Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions docs/STYLEGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ rails make "not decided" texturally distinct even in greyscale.
| `--delta-restored` | `#6B7280` | | `--mode-shadow` | `#667085` |
| | | | `--mode-enforce` | `#1570EF` |

### Colour — signing posture (ADR-0020; the Admission signing inventory)
Every image's observed signing posture, always one of these — **never n/a** — each carrying
colour **+ glyph + word** (meaning never by colour alone). `invalid signature` is the loud channel;
plain `not signed` is calm (no baseline yet), never green. The "if enforced" cell is always the
binary would-admit / would-block.
| Token | Value | Glyph | Word |
|---|---|---|---|
| `--sign-signed` (`--cov-present`) | `#067647` | ✓ | signed |
| `--sign-invalid` (`--posture-breach`) | `#D92D20` | ✕ | invalid signature |
| `--sign-notsigned` (`--ink-3`) | `#6B7280` | ○ open | not signed |
| `--sign-checking` (`--posture-awaiting`) | `#9A6B2E` | ◌ dotted | checking… |

### Space (4px base)
`--space-1:4 · --space-2:8 · --space-3:12 · --space-4:16 · --space-6:24 · --space-8:32`

Expand Down Expand Up @@ -97,12 +109,15 @@ Two weights only (400/600). Emphasis via weight + ink value, not a third weight.
| CVE table | `--font-data` `--text-micro`, right-aligned numerics |
| Coverage row | `--cov-*` dot + glyph + label; `weakens_decisions` + absent → amber keyline |
| Reversion log | `--posture-cleared` toned (a self-revert is the system working) |
| Signing inventory | `--sign-*` chip (glyph + word); `invalid` → `--posture-breach` keyline (loud), `not signed` calm; ref/signer single-line ellipsis (never `break-all`), full value in the `<details>` panel + `title=`; "if enforced" → `--cov-present` would-admit / `--posture-breach` would-block |
| Empty states | `--ink-2`; posture-coloured only when honestly earned (model judging) |

## Accessibility gate (test-enforced)
1. **Contrast:** body/status text ≥ **4.5:1** on its surface; chips/rails/glyphs ≥ **3:1**.
2. **Meaning not by colour alone:** every posture / severity / Δ / coverage state renders a
non-empty **glyph + text label** in addition to colour. (Assert each enum→(glyph,label).)
2. **Meaning not by colour alone:** every posture / severity / Δ / coverage / **signing posture**
state renders a non-empty **glyph + text label** in addition to colour. (Assert each
enum→(glyph,label).) The signing posture is always one of signed / invalid signature / not
signed / checking — **never n/a** — and its "if enforced" cell is always would-admit / would-block.
3. **Honest-calm invariant:** the overall green/all-clear resolves to `--posture-cleared`/green
ONLY when the model has affirmatively cleared everything — `model_judging == true` AND not
`warming_up` AND **covered** AND **zero breaches AND zero awaiting AND zero uncertain**. If
Expand Down
49 changes: 44 additions & 5 deletions engine/examples/dashboard_preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,52 @@ fn sample_policy_log() -> Arc<PolicyDecisionLog> {
)
.with_would_admit(false),
);
record_signing_inventory(&log);
Arc::new(log)
}

/// Seed the signing sweep's per-image observation rows (JEF-261 shape) so the Admission tab's
/// signing inventory (JEF-262) renders every posture: a GitHub Actions keyless signature, a
/// human/Google-issued signature, an invalid signature (loud), a plain not-signed (calm), and a
/// transient checking. Keyed `Image/<ref>` with the posture in the `signature` word + `reason`
/// prose, exactly as `engine::signing_sweep` records them.
fn record_signing_inventory(log: &PolicyDecisionLog) {
let sweep = |image: &str, status: &str, reason: &str| {
log.record(PolicyDecisionRecord::now(
"image-signature",
"allow",
format!("Image/{image}"),
image,
status,
"",
"",
reason,
));
};
sweep(
"ghcr.io/acme/api-gateway@sha256:1a2b3c4d5e6f70819293a4b5c6d7e8f90112233445566778899aabbccddeeff0",
"signed",
"signed by https://github.com/acme/api-gateway/.github/workflows/release.yaml@refs/tags/v1.8.2 \
via https://token.actions.githubusercontent.com",
);
sweep(
"ghcr.io/acme/export:3.0.0",
"signed",
"signed by releng@acme.example via https://accounts.google.com",
);
sweep(
"docker.io/library/storefront:latest",
"invalid-signature",
"signature present but does not verify (untrusted/tampered chain)",
);
sweep("docker.io/library/postgres:16", "not-signed", "");
sweep(
"registry.k8s.io/pause:3.9",
"checking",
"signing posture not yet known (registry/log unreachable)",
);
}

/// A representative bake/coverage summary used by the covered scenarios.
fn covered_bake() -> BakeStats {
let mut bake = BakeStats::default();
Expand Down Expand Up @@ -826,11 +869,7 @@ fn preview_readiness(state: &DashboardState) -> view_model::props::ReadinessView

/// Build the Admission view props through the public render path.
fn preview_admission(state: &DashboardState) -> view_model::props::AdmissionViewProps {
view_model::build_admission_view(
preview_strip(state),
state.policy_log.tallies(),
&state.policy_log.snapshot(),
)
view_model::build_admission_view(preview_strip(state), &state.policy_log.snapshot())
}

/// Render the full page for a tab through the dashboard's PUBLIC render path (all four real).
Expand Down
Loading
Loading