Skip to content

chore(OMN-16702): re-stage the staging-namespace authorization after the 16:00Z expiry - #7731

Merged
jonahgabriel merged 4 commits into
mainfrom
hotfix/omn-16702-restage-staging-grant
Aug 30, 2026
Merged

jonahgabriel merged 4 commits into
mainfrom
hotfix/omn-16702-restage-staging-grant

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Aug 30, 2026 •

Copy link
Copy Markdown
Contributor

Re-stages the OMN-16702 staging-namespace authorization on main — the ref the omninode_infra gate resolves from — after the first entry expired unconsumed.

Why

grant-00ba7b7e-fc60-4938-9a32-70f9df9a9c7a (landed by #7662) carried an approver-set absolute expires_at: 2026-08-30T16:00:00Z. No dispatch was ever performed under it. The blocker was upstream, not authorization: the converge-public-staging job with the staging gate existed only on omninode_infra dev, and the workflow refuses to run off main. That promotion (omninode_infra#1086) merged at 16:59:12Z — 59 minutes after the grant window closed. The grant expired with the run it was minted for still un-dispatched.

Per this file's own LIFECYCLE section an expired entry must be pruned, so grant-00ba7b7e is removed here rather than left to rot, and replaced by a fresh entry.

What changed — three fields, nothing else

field old new
grant_id grant-00ba7b7e-… grant-2840de81-b6de-4963-bb7e-ab022b2d0cc9
created_at 2026-08-30T10:30:00Z 2026-08-30T17:20:00Z
expires_at 2026-08-30T16:00:00Z 2026-08-31T02:00:00Z

cluster, namespaces: [dev, onex-dev], authorization, operator_quote, operator_quote_at, authorization_record and approved_by are byte-identical to the pruned entry.

The quote is still fresh, and the new expiry sits strictly inside its window

"Amend doctrine: in-session operator 'go' counts" — operator, 2026-08-30T05:30:00Z, in-session.

The gate's freshness window is 24h (_DEFAULT_MAX_QUOTE_AGE_HOURS = 24.0), so the quote stays usable until 2026-08-31T05:30:00Z. The new approver-set absolute expires_at is 2026-08-31T02:00:00Z — inside that window, not at its edge. authorization_record: omni_home@e72943be6d7d27e69d00a017511a41fe3a7ac9a6 is unchanged and still an ancestor of omni_home@main; the quote is readable twice in that commit's own diff (CLAUDE.md §2a and §12), which is what the gate's UNRECORDED_QUOTE check resolves against.

approved_by: jonahgabriel still equals the dispatcher on purpose. That relaxation is the whole point of this anchor and applies here only.

Verified live against this exact file, before pushing

Schema validator (onex_change_control, from dev):

$ python3 validate_staging_namespace_grants.py --file grants/staging_namespace_grants.yaml
PASS: grants/staging_namespace_grants.yaml — 1 staging-namespace authorization(s) validated successfully
exit=0

The consuming gate (omninode_infra@main scripts/validate_staging_namespace_grant.py), fed the real scope report rendered from omninode_infra@main 16725bdd by scripts/assert_staging_namespace_scope.py --tree k8s/onex-public --tree k8s/onex-public/runtime --tree k8s/onex-public/network (PASS: 28 object(s) render only into ['onex-dev']):

$ validate_staging_namespace_grant.py --requested-by jonahgabriel \
      --namespaces onex-dev --scope-report /tmp/staging-scope-report.json
[staging-auth] PASS (resolved): grant grant-2840de81-… approved_by=jonahgabriel
  covers ['dev', 'onex-dev'] expires_at=2026-08-31T02:00:00Z

Negative control — this anchor still cannot reach prod:

$ … --namespaces onex-dev,onex-prod
[staging-auth] BLOCKED (scope_exceeded): run requests namespaces ['onex-prod']
  outside the staging-class allowlist ['dev', 'onex-dev']. This gate cannot
  authorize them; prod namespaces require the OMN-13418/OMN-14209
  prod-promotion grant. There is no override.

Blast radius

Unchanged from #7662. This file is read only by omninode_infra's scripts/validate_staging_namespace_grant.py, which matches runtime_lane: staging-namespace and refuses any namespace outside {dev, onex-dev}. scripts/validate_prod_promotion_grant.py reads grants/prod_promotion_grants.yaml and only that path; it is byte-unchanged. The run this authorizes is deploy_target=public-only, which skips promote-to-prod entirely.

Lifecycle

PRUNE this entry once consumed, or set consumed: true. Absolute expiry 2026-08-31T02:00:00Z.

Ticket: OMN-16702 (also unblocks OMN-17153 / OMN-17155)

hotfix-evidence: OCC-7649
backmerge: #7649


Second commit — OCC self-bind (81b2acf7c)

occ-preflight / eligibility and verify / verify both failed the first push with missing_occ_self_bind / pr_ticket_mismatch: OMN-16702's evidence verifies, but no PASS receipt bound to this PR. Fixed exactly as the gate's own detail field prescribed:

  • contracts/OMN-16702.yaml gains one appended dod_evidence entry occ-self-bind-pr-7731;
  • drift/dod_receipts/OMN-16702/occ-self-bind-pr-7731/command.yaml is a PASS receipt with pr_number: 7731.

Hashes recomputed against the post-yamlfmt bytes, not the pre-format draft:

Third + fourth commits — the expired prod grants had to be pruned too

Tests (and Contract Compliance Check) went red on the second push, and not because of anything this PR added. TestGrantFileAtRest::test_grant_file_entries_are_empty_or_well_formed_and_unexpired fails on main for every PR, because six prod-promotion grants were sitting in grants/prod_promotion_grants.yaml past their absolute expiry:

grant-7ebd7674  batch-404af076  sha256:13c96028...   expires_at 2026-08-30T16:00:00Z
grant-7013b49e  batch-404af076  sha256:bc95b9bc...   expires_at 2026-08-30T16:00:00Z
grant-30d406bb  batch-48e48b4c  sha256:13c96028...   expires_at 2026-08-30T16:00:00Z
grant-7f32b169  batch-48e48b4c  sha256:50601f9e...   expires_at 2026-08-30T16:00:00Z
grant-0bb17fe1  batch-48e48b4c  sha256:b4c32554...   expires_at 2026-08-30T16:00:00Z
grant-25d6751a  batch-48e48b4c  sha256:53ae5378...   expires_at 2026-08-30T16:00:00Z

Same 16:00Z cliff that stranded the staging grant, on the prod anchor. All six unconsumed — no deploy-onex-prod.yml dispatch ran under any of them. Tests is not itself a branch-protection context, but it rolls into the required CI Summary, so this was a hard block, not cosmetics.

Pruned to entries: [], which is what this file's own header and OMN-13424 call the at-rest state, and what OCC#7554 did to batch-af8142c0 under exactly these circumstances.

Direction of travel matters here: pruning REMOVES prod authorization and creates none. After this PR, main authorizes zero prod promotions; the next one needs a fresh, CODEOWNERS-approved, digest-pinned entry, unchanged. validate_prod_promotion_grant.py is byte-untouched.

dod-prod-promotion-grant-values-omn16702 asserted the presence of the four batch-48e48b4c ids, so pruning them would have falsified it. Re-pointed at the pruned state (grep -Fq 'entries: []' && grep -Fq 'PRUNED 2026-08-30') — the second time this item has been re-pointed after a batch lapsed, the same operation #7561 performed. Its receipt is rewritten in place with the new contract_entry_sha256 and pr_number: 7731, mirroring #7561's edit of the same file.

$ uv run pytest tests/test_prod_promotion_grants.py -q
..................                                                       [100%]
18 passed in 0.12s

Both live receipts carry contract_sha256: sha256:558244469f..., the hash of contracts/OMN-16702.yaml as it stands after the final yamlfmt pass.

@coderabbitai

coderabbitai Bot commented Aug 30, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 03ed1447-1d97-4dc1-9274-7c8805be9258

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@jonahgabriel
jonahgabriel enabled auto-merge (squash) August 30, 2026 17:24
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