Skip to content

fix(OMN-17447): extend the grant gate to SEQUENCES and deliver all 10 - #3113

Merged
github-actions[bot] merged 2 commits into
devfrom
jonah/omn-17447-sequence-grant-delivery
Sep 1, 2026
Merged

github-actions[bot] merged 2 commits into
devfrom
jonah/omn-17447-sequence-grant-delivery

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Sep 1, 2026 •

Copy link
Copy Markdown
Collaborator

STACKED on #3108 (OMN-17440). This branch contains #3108's commit as its
parent. Merge #3108 first; this will then reduce to its own commit. Do not
merge this ahead of #3108.

OMN-17447

A delivered TABLE grant does not make a BIGSERIAL-keyed relation writable. PostgreSQL rewrites a SERIAL/BIGSERIAL column into a nextval() DEFAULT over a standalone sequence and checks that sequence's own ACL on every INSERT — a privilege GRANT INSERT ON TABLE does not reach.

OMN-17379 proved the consequence live: pr_merged_events sat 24 days behind its topic at consumer LAG 0 while every write raised InsufficientPrivilege on the sequence and the offset was committed anyway. OMN-17377 independently found three more of these relations at zero rows.

This gate could not see that half at all. _GRANT_RE reads a relation-and-role pair; GRANT USAGE ON SEQUENCE <name> TO <role> does not parse as one — so sequence grants were invisible rather than merely filtered, and no ratchet movement could ever have revealed them.

What this delivers

The requirement is derived, not hand-listed. The topology models no object_type: SEQUENCE anywhere, so every declared TABLE grant carrying INSERT is resolved against the corpus's own column shapes. GENERATED ... AS IDENTITY columns are excluded — their sequence is owned by the column and rides the table's INSERT privilege.

10 sequence grants, MAX_UNDELIVERED_SEQUENCES → 0, each in its owning node's lineage.

Two corrections to the ticket, both proven

1. Three of the listed ten are NOT sequence-backed. node_projection_baselines/0002 DROPs and recreates baselines_breakdown, baselines_comparisons and baselines_trend with id TEXT PRIMARY KEY. The filed list read only the CREATE TABLE in 0001.

Had those three been written as filed, each would have hit its own AC3-mandated RAISE EXCEPTION and broken every lane's deploy. Demonstrated by running that guard:

ERROR:  OMN-17447: public.baselines_breakdown.id is not backed by a sequence.
        Refusing to grant a privilege on an object that does not exist.

So the checker derives column shapes from the applied end state, replaying the corpus in apply order so a later DROP+recreate wins. test_recreated_tables_are_not_reported_as_sequence_backed is the regression guard.

2. Three gaps the ticket's omninode_runtime-only scope never looked at — tenant_projection_writer on capability_scores, delegation_routing_tenant_overlay and dep_health_findings. (The middle one is the same relation OMN-16436 already fixed once for TABLE-grant drift; the sequence behind its key was never granted.)

Net: same count, different set.

dod_evidence

Scratch Postgres, real bytes:

  • 7/7 runtime sequences usage=false BEFORE, true AFTER
  • the decisive isolation — revoke only the sequence privilege on receipt_gate_rows, leaving the TABLE grant fully intact: has_table_privilege INSERT reads true and nextval() still fails permission denied for sequence receipt_gate_rows_id_seq; re-applying the migration makes the same nextval() return 1. That is the defect isolated to the one privilege this PR is about.
  • fail-loud guard verified to actually fire (output above)
  • check_topology_grant_delivery.py → sequence grant delivery: 0 undelivered (bound 0), exit 0
  • tests/ci/test_topology_grant_delivery.py → 37 passed, including a RED control (--max-undelivered-sequences -1 → exit 1)
  • source↔vendor byte-identical, sha256-verified; sync-node-migrations.sh --check → in sync
  • governed pre-push passed on a lab host; no PREPUSH_* override, no --no-verify, no override grant

No live lane touched; scratch container destroyed.

Ordering

Source half is omnimarket and lands after this, per node-migration-vendor-parity-gate. The ownership-manifest prerequisite is a separate omnimarket PR that lands before #3108.

Refs: OMN-17447, OMN-17440, OMN-17379, OMN-17377, OMN-15423

Evidence-Ticket: OMN-17447
Evidence-Source: OCC#7952

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

⚠️ Hostile Reviewer — DEGRADED (informational)

Blocking findings (critical): 0
Total findings: 0
Models succeeded: none

Note: All reviewer models failed or were unavailable. Degraded results are informational during the pilot phase (OMN-8468/OMN-8524) and do not block merge. Error: all review endpoints [192.168.86.201:8000 192.168.86.201:8000 ] unreachable — preflight short-circuit (no models available)


Gate semantics (pilot phase)

Verdict Meaning Blocks merge?
passed No critical findings No
blocked CRITICAL findings found Yes
degraded All models unavailable (infra) No (pilot)

Powered by omniintelligence.review_pairing.cli_review — multi-model adversarial review (OMN-8468/OMN-8524)

jonahgabriel pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 1, 2026
#7952)

* evidence: OCC companion pass 1 for OmniNode-ai/omnibase_infra#3113

* evidence: OCC companion self-bind for #7952

---------

Co-authored-by: node-occ-companion-effect <occ-companion-effect@omninode.ai>
A delivered TABLE grant does not make a BIGSERIAL-keyed relation writable.
PostgreSQL rewrites a SERIAL/BIGSERIAL column into a nextval() DEFAULT over a
STANDALONE sequence and checks that sequence's OWN acl on every INSERT --
a privilege GRANT INSERT ON TABLE does not reach. OMN-17379 proved the
consequence live: pr_merged_events sat 24 days behind its topic at consumer
LAG 0 while every write raised InsufficientPrivilege on the sequence and the
offset was committed anyway. OMN-17377 independently found three more of these
relations at zero rows.

This gate could not see that half AT ALL. _GRANT_RE reads a relation-and-role
pair; GRANT USAGE ON SEQUENCE <name> TO <role> does not parse as one, so
sequence grants were INVISIBLE rather than merely filtered -- no ratchet
movement could ever have revealed them.

The requirement is DERIVED, not hand-listed. The topology models no
object_type: SEQUENCE anywhere, so every declared TABLE grant carrying INSERT
is resolved against the corpus's own column shapes. IDENTITY columns are
excluded -- their sequence is owned by the column and rides the table's INSERT
privilege.

TWO CORRECTIONS TO THE TICKET, both from deriving instead of trusting the list:

1. Column shapes must come from the APPLIED END STATE, replaying the corpus in
   apply order so a later DROP+recreate wins. OMN-17447 listed the three
   baselines_* child tables as BIGSERIAL, having read the CREATE in
   node_projection_baselines/0001. 0002 DROPs and recreates all three with
   `id TEXT PRIMARY KEY`. Proven on a scratch Postgres: pg_get_serial_sequence
   returns NULL and pg_attrdef reads `default=NONE`. Had those three migrations
   been written as filed, each would have hit its own fail-loud NULL guard and
   broken every lane's deploy -- demonstrated by running that guard against
   baselines_breakdown and getting the RAISE.

2. Deriving found three gaps the ticket's omninode_runtime-only scope never
   looked at: tenant_projection_writer on capability_scores,
   delegation_routing_tenant_overlay and dep_health_findings.

So the real set is 7 runtime + 3 tenant-writer = 10 -- the same count the ticket
gives, but not the same ten. All 10 are delivered here, taking
MAX_UNDELIVERED_SEQUENCES to 0.

Each migration resolves its sequence via pg_get_serial_sequence rather than
spelling <table>_<column>_seq (a restore or rename must still converge), RAISEs
if the column is not sequence-backed instead of no-oping into another silent
half-grant, and asserts has_sequence_privilege post-grant -- the shape
omnimarket#2256 proved.

PROVEN END TO END on a scratch Postgres against real bytes: 7/7 sequence
usage=false BEFORE, 7/7 true AFTER. Then the decisive isolation -- revoke ONLY
the sequence privilege on receipt_gate_rows, leaving the TABLE grant fully
intact: has_table_privilege INSERT reads true and nextval() still fails
`permission denied for sequence receipt_gate_rows_id_seq`. Re-applying the
migration makes the same nextval() succeed. That is the defect, isolated to the
one privilege this ticket is about.

Refs: OMN-17447, OMN-17440, OMN-17379, OMN-17377, OMN-15423
@jonahgabriel
jonahgabriel force-pushed the jonah/omn-17447-sequence-grant-delivery branch from 4c49ed0 to 5a6b410 Compare September 1, 2026 16:20
@github-actions
github-actions Bot merged commit 0cbda9b into dev Sep 1, 2026
119 checks passed
@github-actions
github-actions Bot deleted the jonah/omn-17447-sequence-grant-delivery branch September 1, 2026 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant