Put the policy-swap story in the web console, and stop masking failed runs - #27
Merged
Merged
Conversation
… runs
The console showed enforcement and proof but not tampering, which is the
argument for why the proof has to exist. That story lived in a separate
terminal demo, so nobody saw both together.
Add a policy bundle selector to the Assessment tab:
- Approved: the example's bundle, unchanged
- Tampered: a copy generated at runtime with two edits an operator who
wanted a loan booked would actually make -- delegated-authority ceiling
raised from EUR 500k to EUR 5m, concentration guardrail inverted
Nordwind Logistik (EUR 750k) is denied at the write under the approved bundle
and allowed under the tampered one. cmcp verify is now always pinned to the
approved bundle hash, so the tampered record fails policy_bundle.hash and no
edit to the record can make the two agree.
The gateway measures its bundle at startup, so the tampered bundle gets its own
process on :8444, started lazily and stopped with the console. The approved
gateway on :8443 is untouched.
Also fixed:
- A crashed or partial agent run rendered as a green "Assessment recorded"
banner, because the UI inferred success from the absence of a denied write.
An empty step list is not a pass. The API now reports the exit code and
output tail, and the UI shows it as a failure.
- A write that only succeeded because the bundle was edited was styled with
the same green as a clean pass. It is now an amber warning.
- demo-02-policy-swap printed two different hashes both labelled "v1" three
lines apart -- step 0 showed the demo's own policies-v1 bundle, step 1 read
the hash off demo-01's claim, which is a different bundle. Step 1 now
computes it from the same bundle step 5 pins.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The console showed enforcement and proof, but not tampering — which is the whole argument for why the proof has to exist. That story lived in a separate terminal demo (
demo-02-policy-swap), so nobody saw both together.What
A policy bundle selector on the Assessment tab:
Run Nordwind Logistik AG (€750k) under each:
403 denied— EBA/GL/2020/06policy_bundle.hashPASS200 allow— the write landspolicy_bundle.hashFAILcmcp verifyis now always pinned to the approved bundle hash, so a tampered record fails and no edit to the record can make the two agree.The tampered bundle is generated from the approved one at runtime, so it cannot drift from the submodule. If the example's policy changes shape,
build_tampered()raises rather than silently producing a no-op tamper.The gateway measures its bundle at startup, so the tampered bundle needs its own process: it starts lazily on
:8444on first use and stops with the console. The approved gateway on:8443is untouched, so this does not change the launcher's process ownership.Bugs fixed along the way
CMCP_BEARER_TOKENset in the environment, the gateway required auth the example agent does not send, the agent crashed at step 1, and the console reported a clean success. The API now returns the exit code and output tail, and the UI renders it as a failure.demo-02-policy-swapprinted two different hashes both labelled "v1", three lines apart — step 0 showed the demo's ownpolicies-v1bundle, step 1 read the hash off demo-01's claim, which is a different bundle. Step 1 now computes it from the same bundle step 5 pins.Testing
Ran end to end on Windows, software-only TEE:
deny, verifypolicy_bundle.hash PASSallow, verifypolicy_bundle.hash FAILpolicy_variants.bundle_hash()matches thetrace.policy.bundle_hashthe runtime writes into the record (6ed4ecc2…)🤖 Generated with Claude Code