Skip to content

fix(examples): pin the trusted root in the cross-operator demo, and stop it dying on cp1252 - #140

Merged
imran-siddique merged 1 commit into
mainfrom
fix/cross-operator-example-trust-roots
Aug 25, 2026
Merged

fix(examples): pin the trusted root in the cross-operator demo, and stop it dying on cp1252#140
imran-siddique merged 1 commit into
mainfrom
fix/cross-operator-example-trust-roots

Conversation

@imran-siddique

Copy link
Copy Markdown
Member

The demo was broken on main

Two independent bugs, both of which stopped examples/cross-operator-delegation/demo.py before it reached the thing it exists to demonstrate.

1. The trusted root was only half-threaded through

#132 made verify_chain fail closed when no trusted root issuer is supplied. That is the right call: a self-consistent chain minted by an attacker passes every signature, continuity and attenuation check, so the pinned anchor is what makes this authorization rather than structure-checking.

That change updated the two CLI invocations at the end of this demo to pass --trusted-root-issuer, and missed all three in-process call sites. Result on main today:

  [3] attenuated delegation chain verifies (leaf scope narrows): OK
Traceback (most recent call last):
  ...
ca2a_runtime.errors.UntrustedDelegationRoot: delegation root issuer is not trusted by this peer

Which reads like the example is wrong about delegation, when the example was simply not passing the root it already had in hand.

Fixed at effective_scope and both enforce_peer_call sites, with a comment on why the anchor is load-bearing rather than ceremony.

2. It crashed on a default Windows console

The demo prints the set-intersection sign when reporting scope ∩ policy. A stock Windows console is cp1252, which cannot encode it, so the run died with UnicodeEncodeError at step 4 on any default Windows shell. stdout/stderr are now reconfigured to UTF-8 rather than downgrading the notation, since the intersection sign is the clearest way to write what that step does.

Worth noting the other two demos (rejection-with-proof, trace-dag) were checked and run clean on cp1252 already, so this is specific to this file.

After

  [1] independent channel keys across domains: OK
  ...
  [4] effective scope = delegated ∩ policy = {task:read}: OK
  [5] child ALLOWS task:read (delegated and locally permitted): OK
  [6] child DENIES task:write (delegated but not locally permitted): OK
  [7] task sealed to child's attested key, opened only by child: OK
  [8] silently swapped binary detected (measurement mismatch): OK
  [9] per-hop provenance DAG verifies and binds to the chain: OK
  [10] accepted-call record matches the leaf credential: OK
  [11] ca2a verify-chain accepts chain.json: OK
  [12] ca2a verify-dag accepts dag.json and cross-checks the chain: OK

KEY RESULT: 12/12

Verified on a default Windows console, no PYTHONIOENCODING needed.

Not included

The regenerated chain.json and dag.json. The demo mints fresh keys on every run, so committing them is pure churn and would make every future example run show a spurious diff.

Unrelated observation

ruff format --check examples/ reports examples/trace-dag/demo.py would be reformatted. Pre-existing and untouched here; flagging rather than folding an unrelated reformat into this PR.

…top it dying on cp1252

Two bugs, both of which made `demo.py` fail before it reached its own point.

**The trust root was only half-threaded through.** #132 made `verify_chain` fail
closed when no trusted root issuer is supplied, which is right: a self-consistent
chain minted by an attacker passes every signature and attenuation check, so the
pinned anchor is what makes the call authorization rather than structure
checking. That change updated the two CLI invocations at the end of this demo to
pass `--trusted-root-issuer`, and missed all three in-process call sites. The
demo died at step 4 with `UntrustedDelegationRoot`, which reads like the example
is wrong about delegation when the example was simply not passing the root.

`effective_scope` and both `enforce_peer_call` sites now pass
`trusted_root_issuers=[chain[0].issuer]`, with a comment saying why the anchor is
load-bearing rather than ceremony.

**The demo crashed on a default Windows console.** It prints the set-intersection
sign when reporting scope n policy, and cp1252 cannot encode it, so a run on
stock Windows died with a UnicodeEncodeError partway through the checks. stdout
and stderr are reconfigured to UTF-8 rather than downgrading the notation, since
the intersection is the clearest way to write what that step does.

12/12 checks now pass on a default Windows console, including the sealed task,
the binary-swap rejection, and the offline provenance-DAG verification.

The regenerated chain.json and dag.json are deliberately not included: the demo
mints fresh keys each run, so committing them is pure churn.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P1p7BCjLPmLCw4VcBpcF8J
@imran-siddique
imran-siddique requested a review from a team as a code owner August 24, 2026 23:53
@imran-siddique
imran-siddique merged commit 947290f into main Aug 25, 2026
12 checks passed
@imran-siddique
imran-siddique deleted the fix/cross-operator-example-trust-roots branch August 25, 2026 01:57
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