Skip to content

Record the first per-service compose baseline: cn-20's twelve services - #98

Open
HONGJICAI wants to merge 2 commits into
mainfrom
claude/gateway-broker-verify-allowlist-y9184x
Open

Record the first per-service compose baseline: cn-20's twelve services#98
HONGJICAI wants to merge 2 commits into
mainfrom
claude/gateway-broker-verify-allowlist-y9184x

Conversation

@HONGJICAI

Copy link
Copy Markdown
Collaborator

The baseline mechanism has existed since #94 with nothing in it, so every pcverify -provider run reported the containers as "not compared" and exited 3. This fills it from provider 0x4870CbC4D07d6Ac2EE5aA865588e5985FE77a4E9, compose_hash 720530b4…, read 2026-08-28.

What is recorded

Twelve services. Nine pin the image exactly as the deployment has it — including the four pinned only by tag. Three run 0G's own broker image and pin the image-held-out block plus a repository rule, so a broker release does not force a gateway release; that is the one case the recorded text cannot express, and it is used nowhere else.

Every block was split mechanically out of that provider's own -blocks output, and each of the twelve fingerprints was then checked back against the same output. So the recorded text reduces to the authenticated text rather than to a transcription of it. That round trip also exercised the canonicalizer on two real literal block scalars — the config bootstrap script and the Prometheus config generator — which no fixture had covered.

Recording is not approval

The review still reports ten blocking findings on this manifest and recording silences none of them: four tag-only images, privileged plus /, /proc and /sys on prometheus-node-exporter, SYS_ADMIN on dcgm-exporter, and the container runtime's socket held by 0g-controller.

What the baseline buys is that the set cannot grow unseen. From here a service added, removed, renamed or otherwise changed in a way that changes what runs is a mismatch, named with the first differing line. Before this file had an entry, an operator could have given the model server docker.sock overnight and nothing in the chain would have noticed.

Each entry carries a note recording why it stands as it does. 0g-controller's records its docker.sock mount as an open question rather than an accepted risk — it is our own image, nobody has established the controller needs the socket, and a container holding it can start any container it likes. The header states the consequence: this baseline must not be wired into the sealing path as a refusal while that entry stands. That decision is the blocker on the follow-up, not this PR.

Two consequences the header now states rather than leaving to be discovered

  • It records one provider, so every other provider is a mismatch, not a skipped check. pcverify -provider exits 0 only against a recorded deployment and 1 against any other, where before it exited 3 against all of them. Nothing in CI runs that command, so no automation changes behaviour.
  • Convergence on one fleet-wide manifest is constrained by what a block contains. 0gm-sglang's carries --model-path and --revision, so a provider serving a different model cannot match however correct its deployment is. That argues for recording several baselines, not for pinning less — dropping the model path would leave the weights answering a sealed prompt unpinned.

Format hardening

Matters much more now the file is non-empty: the decode refuses unknown keys and trailing content. A top-level key misspelled servcies previously decoded into zero entries, zero entries mean NOT CONFIGURED, and the reports then say the comparison did not run — a typo that silently turns the adjudicating check off. _comment and the new per-entry note are declared so the file keeps explaining itself; neither is ever read by the comparison.

Tests

Four guards on the shipped file, which until now had none that read it:

  • the recorded service names and count;
  • that each entry records the form its rule compares — a repository rule against a block that still carries an image line can never match, and pasting the wrong one of the two printed forms is the likeliest transcription error;
  • that every entry carries its audit note;
  • and the only test here that exercises the file rather than the mechanism: the whole baseline against a manifest reassembled from the same provider's full blocks. It matches 12 of 12 and still reports the docker.sock finding as blocking. The fixture carries the real image references while the baseline stores the held-out form for three services, so it is independent in the dimension that can actually go wrong.

Both new guards were mutation-checked: each fails when the thing it protects is removed.

gofmt, go vet and the full client suite are clean. Only pcverify reads this baseline — client/route and cmd/gateway do not — so populating it cannot change sealing behaviour.

Not verified here

I have no network route to cn-20 from this environment, so the live confirmation is one command:

cd client && go run ./cmd/pcverify -provider 0x4870CbC4D07d6Ac2EE5aA865588e5985FE77a4E9

Expected: ✓ baseline all 12 service(s) match the recorded baseline, exit 0, with all ten blocking review findings still printed. A mismatch names the service and the first differing line.


Generated by Claude Code

claude added 2 commits August 28, 2026 10:03
The baseline mechanism has existed since #94 with nothing in it, so every
`pcverify -provider` run reported the containers as "not compared" and exited 3.
This fills it from provider 0x4870CbC4D07d6Ac2EE5aA865588e5985FE77a4E9
(compose_hash 720530b4e2ee997471c59061561606a83aecfb41813b8cb1158b0b979c22b41f).

Nine entries pin the image exactly as the deployment has it. Three run 0G's own
broker image and pin the image-held-out block plus a repository rule, so a broker
release does not force a gateway release — that is the one case the recorded text
cannot express, and it is used nowhere else.

Every block was split mechanically out of that provider's own `-blocks` output
and each of the twelve fingerprints then checked back against the same output, so
the recorded text reduces to the authenticated text rather than to a transcription
of it. That round trip also exercised the canonicalizer on two real literal block
scalars (the config bootstrap script and the Prometheus config generator), which no
fixture had covered.

RECORDING IS NOT APPROVAL, and the file says so at length. The review still
reports ten blocking findings on this manifest and recording silences none of
them: four tag-only images, `privileged` plus `/`, `/proc` and `/sys` on
prometheus-node-exporter, SYS_ADMIN on dcgm-exporter, and the container runtime's
socket held by 0g-controller. What the baseline buys is that the set cannot GROW
unseen — from here a service added, removed, renamed or otherwise changed in a way
that changes what runs is a mismatch, named with the first differing line. Each
entry carries a `note` recording why it stands as it does; 0g-controller's records
its docker.sock mount as an OPEN QUESTION rather than an accepted risk, and the
header states that the baseline must not become a refusal in the sealing path
while that entry stands.

Two consequences the header now states rather than leaving to be discovered. It
records ONE provider, so every other provider is a mismatch, not a skipped check:
`pcverify -provider` exits 0 only against a recorded deployment and 1 against any
other, where before it exited 3 against all of them (nothing in CI runs it, so no
automation changes behavior). And convergence on a single fleet-wide manifest is
constrained by what a block contains — 0gm-sglang's carries `--model-path` and
`--revision`, so a provider serving a different model cannot match however correct
its deployment is. That argues for recording several baselines, not for pinning
less: dropping the model path would leave the weights answering a sealed prompt
unpinned.

TESTS. Four guards on the shipped file, which until now had none that read it: the
recorded service names and count; that each entry records the form its rule
compares (a repository rule against a block that still carries an image line can
never match, and pasting the wrong one of the two printed forms is the likeliest
transcription error); that every entry carries its audit note; and — the only test
here that exercises the file rather than the mechanism — the whole baseline against
a manifest reassembled from the same provider's full blocks, which matches 12 of 12
and still reports the docker.sock finding as blocking. That fixture carries the real
image references while the baseline stores the held-out form for three services, so
it is independent in the dimension that can go wrong. Both new guards were
mutation-checked: each fails when what it protects is removed.

Also hardens the format, which matters much more now the file is non-empty:
the decode refuses unknown keys and trailing content. A top-level key misspelled
"servcies" previously decoded into zero entries, zero entries mean NOT CONFIGURED,
and the reports then say the comparison did not run — a typo that silently turns
the adjudicating check off. `_comment` and the new per-entry `note` are declared
so the file keeps explaining itself; neither is ever read by the comparison.

Docs and package comments that asserted the file ships empty, or wrote the
baseline in future tense, are corrected — including two that a case-sensitive grep
missed on the first pass and one that undercounted provider mode's exit-3 doors as
three rather than four.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GQ4LBXfDT5ptgFtyoPu7p3
…-verify-allowlist-y9184x

# Conflicts:
#	docs/design/trust-chain.md
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.

2 participants