Add unique index on mcp_proposals(kind, entity_id, status) #88

Closed
opened 2026-07-20 19:44:02 +00:00 by hugo · 1 comment
Owner

Source: Audit section 2.18.

bDS2: ../bDS2/priv/repo/migrations/20260424100817_add_backend_spec_compliance_persistence.exs:30create unique_index(:mcp_proposals, [:kind, :entity_id, :status], ...), preventing duplicate pending proposals for the same entity.

Current behaviour (RuDS): crates/bds-core/migrations/2026-07-19-123029-0000_add_mcp_proposals/up.sql creates only a non-unique mcp_proposals_project_status_idx (project_id, status, created_at) — an MCP client can pile up duplicate pending proposals for one entity.

Task: Add the unique index via a proper Diesel migration (tooling-generated, sqlite semantics; regenerate schema snapshot with the proper tools per AGENTS.md). Handle the NULL entity_id case (draft_post proposals have entity_id NULL; in SQLite NULLs are distinct in unique indexes — mirror bDS2 semantics, check how bDS2 stores draft_post entity_id). Decide conflict behaviour in engine/mcp/tools.rs propose paths: surface a clean "proposal already pending" error instead of a constraint violation. Add a test.

Acceptance: Duplicate propose for same (kind, entity_id) with a pending proposal is rejected gracefully; migration + snapshot committed.

**Source:** Audit section 2.18. **bDS2:** `../bDS2/priv/repo/migrations/20260424100817_add_backend_spec_compliance_persistence.exs:30` — `create unique_index(:mcp_proposals, [:kind, :entity_id, :status], ...)`, preventing duplicate pending proposals for the same entity. **Current behaviour (RuDS):** `crates/bds-core/migrations/2026-07-19-123029-0000_add_mcp_proposals/up.sql` creates only a non-unique `mcp_proposals_project_status_idx (project_id, status, created_at)` — an MCP client can pile up duplicate pending proposals for one entity. **Task:** Add the unique index via a proper Diesel migration (tooling-generated, sqlite semantics; regenerate schema snapshot with the proper tools per AGENTS.md). Handle the NULL entity_id case (draft_post proposals have entity_id NULL; in SQLite NULLs are distinct in unique indexes — mirror bDS2 semantics, check how bDS2 stores draft_post entity_id). Decide conflict behaviour in `engine/mcp/tools.rs` propose paths: surface a clean "proposal already pending" error instead of a constraint violation. Add a test. **Acceptance:** Duplicate propose for same (kind, entity_id) with a pending proposal is rejected gracefully; migration + snapshot committed.
hugo added the bug label 2026-07-20 19:44:02 +00:00
Author
Owner

Implemented in 70503c8. Added a Diesel-generated SQLite migration and regenerated schema snapshot for the named unique (kind, entity_id, status) index; upgraded entity_id to NOT NULL, normalized legacy NULL rows, and retained only the newest invalid legacy duplicate. All proposal paths now generate bDS2-style identities for untargeted writes and surface a clean Conflict for duplicate pending entity proposals. Terminal accept/reject/expiry transitions clean prior same-status history transactionally so the index remains valid across later proposals. Added migration, duplicate, NULL identity, terminal lifecycle, and UI regressions; Diesel migration redo, cargo build --workspace, focused MCP/migration/ORM tests, and cargo test --workspace all pass. Neutral review against #88, bDS2 ProposalStore/migration behavior, and specs/mcp.allium found no remaining gaps.

Implemented in 70503c8. Added a Diesel-generated SQLite migration and regenerated schema snapshot for the named unique (kind, entity_id, status) index; upgraded entity_id to NOT NULL, normalized legacy NULL rows, and retained only the newest invalid legacy duplicate. All proposal paths now generate bDS2-style identities for untargeted writes and surface a clean Conflict for duplicate pending entity proposals. Terminal accept/reject/expiry transitions clean prior same-status history transactionally so the index remains valid across later proposals. Added migration, duplicate, NULL identity, terminal lifecycle, and UI regressions; Diesel migration redo, cargo build --workspace, focused MCP/migration/ORM tests, and cargo test --workspace all pass. Neutral review against #88, bDS2 ProposalStore/migration behavior, and specs/mcp.allium found no remaining gaps.
hugo closed this issue 2026-07-22 16:26:07 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: hugo/RuDS#88