Skip to content

feat(gov): SP3a — egret image-level matrix dimension + enforcement-point framing - #854

Merged
viethqb merged 9 commits into
mainfrom
feat/gov-sp3a-ep-framing
Nov 13, 2026
Merged

viethqb merged 9 commits into
mainfrom
feat/gov-sp3a-ep-framing

Conversation

@viethqb

@viethqb viethqb commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

What

Governance SP3a — the first package of SP3 (enforcement points). Adds an egret image-level (egret.N) dimension to the capability matrix so StarRocks capabilities that depend on the fork image (masks and tag row filters, enforced across every protocol by patches 0002/0003/0004) are gated on the running fork image, and renames "profile" to enforcement point at the UI/API surface (no table/field/route changes).

Why

Today the matrix is keyed on (EpKind, Ranger plugin version) only. A StarRocks engine on an official/old image silently fails to enforce masks and tag row filters over some protocols. SP3a makes that capability gap first-class: below the enabling image level the matrix lowers the capability to a deny (fail-closed); at egret.3+ it enforces normally. All corpus and demo-stack engines run fork images ≥ egret.4, so the compiled Ranger JSON is byte-identical — only an engine on an image that cannot enforce (already forbidden by the "fork image only" rule) changes.

How

  • Parse the egret fork level from the engine image tag (…-egret.N) — egret_perm::starrocks_egret_image_level.
  • Carry it on BoundEngine / EpInput; EpInput::effective_image_level() folds a multi-engine EP to the most restrictive level (None beats Some, else min) — fail-closed, the EP shows whichever engine holds it back.
  • Gate only StarRocks mask / tag-row-filter matrix rows (min_egret_image = Some(3), const STARROCKS_MASK_MIN_EGRET_IMAGE); all other rows ungated.
  • Wire the real effective level into lowering and enforcement (previously the dimension was inert — every caller hardcoded Some(3)). A below-level gated mask / row filter lowers to a Ranger deny (not skipped → never served in cleartext).
  • Rename profile → "enforcement point" in UI copy + utoipa descriptions (display strings only; policy.authz_services, API keys, routes, test ids unchanged).

Scope / limits

Verification

  • cargo test -p egret-perm-ir green incl. new below-level (gated → deny) and at-level (byte-identical) tests.
  • cargo fmt --check + clippy clean.
  • Golden/byte-identical corpus: only G17_several_engines.json re-blessed (official-image fixture → now a deny, as designed); egret.3/egret.4 fixtures byte-identical.
  • SDD final whole-branch review (most capable model): approved, no code must-fix.

Merge gated on green CI (openapi-currency + generated-client digest + DB-gated Rust tests).

Spec + plan: #853

🤖 Generated with Claude Code

viethqb and others added 8 commits November 13, 2026 09:43
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…; mixed EP = least capable

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ement paths

The matrix image dimension was inert: no production path consulted the real
per-engine image level. lower_rules now passes the EP's most-restrictive
effective image level into lower_rule (a StarRocks mask / row filter below
egret.3 is reported as a skip, not lowered), AttachedEngine carries the level
for the NotEnforced reporting, and load_ep reads the engines' image levels
before any rule is lowered. Byte-identical on fork images (effective level
>= 3); fixtures that ran StarRocks on official or unpinned images now pin the
fork image.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…deny, not to nothing

Below egret.3 a missing mask policy served the column in cleartext. The gated
rule now lowers to a withhold of its columns / tables to everyone but the
exemptions, rendered as an access deny attributed to the rule, and is still
reported in the compile summary. The enforcement report uses the same
EP-wide most-restrictive image level as the lowering.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Surface text only: UI labels and help text, OpenAPI descriptions and the
no-tag-service warning. Identifiers, JSON keys, routes and the table are unchanged.
openapi.json and the generated client are regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Task 5's profile->enforcement-point rename lengthened three warning-string
consts past the wrap point; cargo fmt had not been re-run on them. Whitespace
only; no behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@viethqb
viethqb force-pushed the feat/gov-sp3a-ep-framing branch from cb12c4d to e098ce3 Compare November 13, 2026 02:45
…e mask gate

SP3a gates StarRocks column masks and row filters on the egret fork image
level (>= 3). These pre-existing DB-gated fixtures seeded their StarRocks
engine with an official (or absent) image tag, which resolves to no fork
level, so the gate lowered every mask and row filter to a deny — dropping
the MASK_HASH the rename tests assert and hiding the row-filter tie the
boot-pass test asserts. The failures surfaced only now because the
unreachable_code compile break (fixed in #856) had kept the DB-gated rust
job from ever reaching them.

Point the fixtures at the fork image egret runs in production
(ghcr.io/egret-data/egret-starrocks-fe:4.1.7-egret.4, level 4):

- table_hook_db / view_rename_db: renamed table/column/view keep their mask.
- recompile_on_tag_write: assign recompiles the bound profile (mask + deny).
- governance_attention: the tied row-filter rules reach the engine, so the
  compile fails and the boot-pass refusal names both rules. Its k_sr_eng is
  now inserted inline with the fork image; the shared engine() helper seeds
  no image, and the plugin_unmodelled test still needs the floating tag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@viethqb
viethqb merged commit 2423466 into main Nov 13, 2026
9 checks passed
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