Repository navigation
feat(OMN-20329): the projection read node serves the local SQLite store - #3212
Merged
Merged
Conversation
node_projection_read_effect now answers contract-declared exposures from the local SQLite store when the runtime projection binding's database_url is a sqlite: or file: DSN (local MVP mode 1). Decision D1 (a) routes local dashboard reads through this node (OMN-20159). SqliteTableRowSource (the node's ports/sqlite_row_source.py) serves the same window, tenant scoping, row shape and named refusals as the Postgres TableRowSource, in SQLite's dialect. It opens the file read-only per read and never creates a missing file (projection_database_unavailable). Before reading, it checks the table and every column the read names against pragma_table_info. SQLite reads a double-quoted unknown column as a string literal, so without the check a missing column is served as its own name. It answers projection_column_missing instead. Postgres bindings resolve to TableRowSource unchanged; other schemes are still refused as projection_binding_unsupported, and no binding is still projection_binding_unconfigured. sqlite_path_from_dsn moves to the shared projection/sqlite_database.py, and the delegate orchestrator's evidence DB resolver imports it instead of keeping a private copy. The real-Postgres integration test gains a case proving a Postgres binding still reads and that close() still drains the source's pools.
✅ 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) |
Moved marker comment from closing-paren line to sqlite3.connect( line in src/omnimarket/nodes/node_projection_read_effect/ports/sqlite_row_source.py to satisfy imperative-contract-guard (CI run 36924302867). Verified locally: live 0, ruff format clean, sqlite unit test file passes (11 tests). No behavior change. Ticket OMN-20329. Bumped project.version in pyproject.toml and uv.lock from 0.4.276 to 0.4.277 to satisfy release-identity gate (failing at a14ebdb).
Patel230
added a commit
that referenced
this pull request
Oct 2, 2026
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.
jonahgabriel
added a commit
that referenced
this pull request
Oct 2, 2026
dev was excluded from the CI push triggers, and dev is not strict and has no merge queue. #3212 merged on CI graded against a base older than #3208, so dev head d471dcb broke typecheck and Tests (Split 14/20) with no check run on it until the release fast-forward to main. This adds dev to push.branches, matching omnibase_infra, omnibase_core and omniclaude; the push concurrency group is ref-scoped and never cancels.
jonahgabriel
added a commit
that referenced
this pull request
Oct 2, 2026
dev was excluded from the CI push triggers, and dev is not strict and has no merge queue. #3212 merged on CI graded against a base older than #3208, so dev head d471dcb broke typecheck and Tests (Split 14/20) with no check run on it until the release fast-forward to main. This adds dev to push.branches, matching omnibase_infra, omnibase_core and omniclaude; the push concurrency group is ref-scoped and never cancels.
Patel230
added a commit
that referenced
this pull request
Oct 2, 2026
…te store (#3210) * feat(OMN-19968): the tenant credentials writer runs on the local SQLite 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. * fix(OMN-20329): the SQLite row source speaks the OMN-20327 walk protocol 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. * chore(OMN-19968): bump version to 0.4.278 past the published 0.4.277 The release identity gate refuses a packaged-source change on an already published version. 0.4.277 is published; this PR changes packaged source.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
OMN-20329.
node_projection_read_effectnow serves contract-declared exposures from the local SQLite store when the runtime projection binding'sdatabase_urlis asqlite:orfile:DSN (local MVP mode 1). Decision D1 (a) routes the local dashboard's reads through this node (OMN-20159), so this is the read path for that mode. Before this change the resolver refused every non-Postgres binding withprojection_binding_unsupported.ports/sqlite_row_source.py:SqliteTableRowSourceserves the same window, tenant scoping, row shape and named refusals as the PostgresTableRowSource, in SQLite's dialect. It opens the file read-only per read and never creates a missing file (projection_database_unavailable).pragma_table_info. SQLite reads a double-quoted unknown column as a string literal, so without the check a missing column is served as its own name. It answersprojection_column_missinginstead.resolve_projection_read_source:postgres/postgresqlresolve toTableRowSourceunchanged;sqlite/fileresolve toSqliteTableRowSource; any other scheme is still refusedprojection_binding_unsupported; no binding is stillprojection_binding_unconfigured(no fallback).sqlite_path_from_dsnmoves to the sharedprojection/sqlite_database.py, and the delegate orchestrator's evidence DB resolver imports it instead of keeping a private copy, so the writer and the reader resolve a DSN to the same file.dod_evidence
tests/unit/nodes/node_projection_read_effect/(incl. newtest_projection_read_effect_sqlite_omn20329.py),test_evidence_db_resolution_omn14015.py,test_golden_chain_projection_read_effect.py: 39 passed on lab host h202.tests/integration/nodes/node_projection_read_effect/test_projection_read_effect_real_postgres_omn20159.py: 5 passed against a disposable postgres:16-alpine on h202, including the new case proving a Postgres binding still reads andclose()still drains its pools.~/.omninode/delegation/delegation.sqlite, 22delegation_eventsrows, one tenant), read through the node with asqlite:binding: before the catalogue check the decisions exposure answered ok with 5 rows; after it,ok=False 503 projection_column_missing. That store lacksid,authority_source,score_source,cost_tier_nameandcost_tier_type, which the exposure declares. Making the local writers declare those columns is the plan's T3.0 store-neutral writer work, not this change.Evidence-Ticket: OMN-20329
Evidence-Source: OCC#12231