Repository navigation
feat(OMN-19968): the tenant credentials writer runs on the local SQLite store - #3210
Conversation
…te store node_projection_tenant_credentials was the last writer the ticket names with no SQLite path: its three writes were asyncpg SQL with $n, ::TEXT and NOW(), and the local schema had neither of its tables. - handlers/handler_tenant_credentials_store.py: apply_credential_registered and apply_credential_revoked write the catalog row and the routing overlay through the store-neutral upsert_returning, keeping every rule the runner's SQL encodes: register never touches created_at or revoked_at, the route is minted only for a key that is not revoked, a revoke keeps the earliest revoked_at and leaves a tombstone for an unknown key, a revoke blanks only the route that points at that key, and an undeclared provider is catalogued but unrouted. The deployed asyncpg runner is unchanged. - projection/sqlite_database.py: tenant_inference_credentials and delegation_routing_tenant_overlay, declared from the node migrations 0000/0001 and the overlay migrations 0001/0004. - contract.yaml: both tables declare access read_write instead of write. The runner already reads them (the overlay's WHERE NOT EXISTS revoke guard and every RETURNING) and the local path reads before a revoke; the projection contract-access gate requires the declaration to say so. The checked-in relation inventory is regenerated (the overlay gains this node as a reader), and the OMN-17372 contract-shape test now pins that the overlay write is declared, as write or read_write. - tests/test_omn19968_writer_store_parity.py: six scenarios compared between the SQLite store path and the REAL asyncpg runner on PostgreSQL, the SQLite path checked for Postgres-only tokens, and the tombstone, revoke and secret-field rules on SQLite alone.
…ant-credentials-sqlite
✅ Architectural Review — PASSEDErrors: 0 What this checks
No architectural violations found. Static architectural lint — no model inference (OMN-14176). |
✅ Hostile Reviewer — PASSEDBlocking findings (critical/error): 0 Gate semantics
Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524) |
…omnimarket#3210 OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head 159f31fc58fe81180060743542a4551da24abf38.
…nimarket#3210 The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited. Ticket: OMN-16859 (AC3b) Onex-Workflow: OCC Receipt Runner Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/36931740454
…market (#12224) * evidence(OMN-19968, OMN-20001): author OCC companion for OmniNode-ai/omnimarket#3210 OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head 159f31fc58fe81180060743542a4551da24abf38. * evidence(OMN-19968, OMN-20001): self-bind OCC#12224 + rebind contract_sha256 * evidence(OMN-16859): executed test_passes receipts for OmniNode-ai/omnimarket#3207 The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited. Ticket: OMN-16859 (AC3b) Onex-Workflow: OCC Receipt Runner Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/36930151590 * evidence(OMN-16859): executed test_passes receipts for OmniNode-ai/omnimarket#3210 The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited. Ticket: OMN-16859 (AC3b) Onex-Workflow: OCC Receipt Runner Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/36931740454 * evidence(OMN-16859): executed test_passes receipts for OmniNode-ai/omnimarket#3207 The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited. Ticket: OMN-16859 (AC3b) Onex-Workflow: OCC Receipt Runner Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/36930788697 --------- Co-authored-by: omnimarket-bot <bot@omninode.ai> Co-authored-by: onexbot-occ-writer[bot] <307849072+onexbot-occ-writer[bot]@users.noreply.github.com> Co-authored-by: jonahgabriel <jonah.gabriel@gmail.com>
…ant-credentials-sqlite
omnimarket#3208 gave ProtocolProjectionRowSource a `selection` on rows() and a walk_origin(); #3212 landed SqliteTableRowSource four minutes later without either. On dev every read_page call against the local store raised TypeError (5 of 11 OMN-20329 tests fail) and mypy rejects handler_projection_read.py:99. - rows() takes `selection`: "walk" windows from the first cursor ascending, "ranked" windows by the contract's order, "newest" is unchanged. - walk_origin() answers one below the tenant's smallest integer cursor, None for any other cursor, and refuses a missing table or store by name.
The release identity gate refuses a packaged-source change on an already published version. 0.4.277 is published; this PR changes packaged source.
|
No reviews or inline comments were left here. The two bot notes passed (architecture lint with 0 errors; the hostile reviewer with 0 blocking findings), so nothing needed a change. Merged as Thank you! |
Summary
Gives
node_projection_tenant_credentialsa SQLite path. It was the last writer named in OMN-19968 without one. This closes Jonah's 09-30 closeout hold on AC1 ("for each writer") by its first option, "land that writer under this ticket".Before this change, the writer's three writes were asyncpg SQL with
$n,::TEXTandNOW(), and the local SQLite schema had neither of its tables.What changed
handlers/handler_tenant_credentials_store.py.apply_credential_registeredandapply_credential_revokedwrite the catalog row and the routing overlay through the store-neutralupsert_returning, which both the SQLite adapter and the Postgres sync adapter implement. They keep every rule the runner's SQL encodes:created_atorrevoked_at;revoked_at, and leaves a tombstone for an unknown key;projection/sqlite_database.py. Addstenant_inference_credentialsanddelegation_routing_tenant_overlay, derived from the node's migrations 0000/0001 and the overlay's 0001/0004.contract.yaml. Both tables now declareaccess: read_writeinstead ofwrite. The projection contract-access gate (OMN-16690) requires this, because the store path reads before a revoke, and the runner itself already reads both tables (the overlay'sWHERE NOT EXISTSrevoke guard and everyRETURNING).writeorread_write).tests/test_omn19968_writer_store_parity.pycompares six scenarios between the SQLite store path and the real asyncpg runner on PostgreSQL: register, register twice, register then revoke, revoke before register, undeclared provider, and re-register with a new ref. It also checks the SQLite path for Postgres-only tokens, and checks the tombstone, revoke and secret-field rules on SQLite alone.How it was verified
Lab first.
tests/test_omn19968_writer_store_parity.pyran on the lakshman lab lane's PostgreSQL 16 on .201, in a throwaway container from the lane's runtime image, against the final tree159f31fc5(2026-10-01T20:38:25Z):delegation_eventsandllm_call_metricscases (invalid input value for enum usage_source_type: "MISSING"). That is the defect omnimarket#3183 fixes; this branch is cut from dev without it.Checks:
ModuleNotFoundError). After it, they give 9 passed locally; the 6 runner cases skip here because no local database runs.test_tenant_credentials_sqlite_tombstone_blocks_the_routewent RED (a route was minted for a revoked key). Restored, it went GREEN.2211ff939gives 606 passed, 31 skipped; the branch gives 615 passed, 37 skipped. The difference is the 9 new tests and 6 new skips.mypy --stricton changed source,ruff check,ruff format --check, the runtime sweep import check, and the node metadata dependency check all pass.Overlap-Reviewed: #3183 — both touch src/omnimarket/projection/sqlite_database.py and tests/test_omn19968_writer_store_parity.py; #3183 (mine, same ticket) changes the llm_call_metrics DDL default and adds usage-source vocabulary cases, this adds two new tables and the tenant-credentials cases. A trial three-way merge (git merge-tree) of both heads is clean; each is needed and they merge in either order.
Overlap-Reviewed: #3172 — both touch docs/evidence/OMN-15423-relation-inventory.json; #3172 (mine, OMN-19969) changes a different relation's entry, this adds this node as a reader of delegation_routing_tenant_overlay. A trial three-way merge of both heads is clean; whichever lands second re-runs the generator's --check in CI.
Failure paths
n/a: this change writes no verdict, receipt or report. It is a store path, two local schemas and tests.
Open defects
none
Local gates
--no-verify, noSKIP=, no--no-gpg-sign, nocore.hooksPathoverride. Every pre-commit and pre-push hook ran.# noqa: E402, so the imports moved to the top of the file. The contract-access gate refusedaccess: writewith reads, so the declaration now saysread_write.Not in this change
public(OMN-15359).Evidence-Ticket: OMN-19968
Evidence-Source: OCC#12224