Repository navigation
fix(reporting-storage): allow shared row sets across SDKs - #3651
Conversation
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean diff, no blocking or medium findings.
Checked:
- Drops the
obligation_idFK from sharedadcp_reporting_row_setsso another SDK's ledger can write row sets without a JS-core obligation row. Both migration pathways covered — inlineALTER ... DROP CONSTRAINT IF EXISTSafterCREATE TABLE IF NOT EXISTS(deprecated direct-apply) and sequential numbered migration 0011. obligation_idstays NOT NULL; composite self-FK and chunk FK reference theUNIQUE(row_set_id, account_id, obligation_id)constraint, not the dropped FK, so they are unaffected.- Tests cover fresh DDL, legacy-key removal, idempotency, and a cross-SDK insert.
- Changeset is
minorfor the pre-1.0@experimental @adcp/reporting-storagepackage with a migration note — correct type; not a wire change, so DR-0033 pathway rules do not apply.
No critical/high/medium findings. gated_paths is false, high_risk is false, no no-auto-approve team match. Decision table falls through to row 9.
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean pass, no blocking or medium findings.
This PR (91 lines across 4 files) drops the obligation_id → adcp_reporting_obligations foreign key from the shared adcp_reporting_row_sets table so a second SDK with its own core ledger can write rows. Migration 0011 and the DDL both DROP CONSTRAINT IF EXISTS the default-named key (idempotent); the NOT NULL column and the self-referential composite FK remain, so tenant integrity holds while obligation ownership moves to each SDK's ledger. Changeset is minor (correct for the experimental reporting-storage package) and includes a migration note covering the deprecated direct-apply path and the custom-named-FK caveat. Test coverage exercises fresh DDL, legacy-FK upgrade, 0011 run twice, and an insert against a non-existent obligation.
Decision trace: no critical/high findings (row 1 n/a); gated_paths false and review_decision APPROVED (row 2 n/a); high_risk false (rows 3, 5 n/a); no medium findings (rows 4, 8 n/a); prior decision was approve (row 6 n/a); no no-auto-approve team match (row 7 n/a). Falls through to row 9 → approve.
When JavaScript creates the shared row tables first, its foreign key to the JavaScript-only obligations table prevents Python from writing its own row sets. Remove that key from fresh row-storage DDL and add migration 0011 for databases that already applied the old migration; reapplying the deprecated DDL also removes the default-named key.
The key had no delete cascade: period retirement explicitly deletes row chunks and row sets before deleting the obligation. JavaScript ledger writes create row sets inside their ledger transactions; the shared tables retain their row-set/chunk tenant keys and digest checks. Direct external SQL no longer gets a core-obligation existence check, which is necessary for cross-SDK writers. Custom-named constraints need manual removal.
Testing: reporting-storage build and 44 focused migration, row-storage, and retirement PostgreSQL tests; Python main and next row-storage tests (28 each); live cross-SDK interop (4 each); JavaScript-first migration followed by Python writes and JavaScript reads.
Related: adcontextprotocol/adcp-client-python#1495, adcontextprotocol/adcp-client-python#1880 (main), adcontextprotocol/adcp-client-python#1879 (next).