feat: add Nobulex conformance implementation (Python, Ed25519) - #12
feat: add Nobulex conformance implementation (Python, Ed25519)#12arian-gogani wants to merge 2 commits into
Conversation
4/4 vectors pass: signatures verified, chain integrity verified, decisions match expected (allow/allow/deny/allow). Nobulex is credit scores for AI agents. The action_ref formula is normative implementation guidance in OWASP Agentic Skills Top 10 (AST09, PRs #35/#38). Cited as third independent issuer in x402. PyPI: pip install nobulex npm: @nobulex/core GitHub: github.com/arian-gogani/nobulex
|
Updating this rather than letting it keep sitting, since the reason it has not moved turned out not I went back through the suite from a clean clone and opened #13. The part that matters here is that This PR emits v1 flat, so it is on the side that fails check 2. A driver emitting Separately, |
|
This is a considerable favour and I want to be clear about that before anything else. You went looking, found six real things, measured all of them, and held a working driver rather than push a change that would have quietly decided what the suite accepts. That last part is the bit most people would not have done. I reproduced everything I checked from a clean clone. You were right on all of it. The decision you are blocked onBuild against The schema is what is wrong here, not your driver and not the reference receipts. If you want to send the schema and check 1 change alongside the driver, please do. You are not deciding it unilaterally at that point, I am asking for it. If you would rather keep the PR to the driver, say so and I will do the schema separately and you can rebase. You are also right that the verifier reports Fixed in #14Findings 1, 3 and 5, with your reproductions:
Check 2 passes Check 3 now reads Demonstrated rather than asserted: on a receipt set that allows the destructive Bash fixture the policy forbids, the old check 3 exits 0 and the new one exits 1. Finding 2 is separate and also correct. There is no On your last paragraphYou wrote that a suite whose checks pass on receipts nobody evaluated is the same failure the receipts are meant to prevent, one level up. That is the correct criticism and it is the one I should have caught myself. A conformance suite that reports green while nothing conforms is worse than no suite, because it converts an open question into a false answer. Thanks for going after it properly rather than working around it. |
…hape in check 1 Per the maintainer's request in ScopeBlind#12: build against decision_receipt, and send the schema and check 1 change alongside the driver. Driver ------ Evaluates fixtures/policy/autoresearch-safe.cedar and never reads expected_decision. cedar_lite.py is a small evaluator for the subset of Cedar that policy uses, not a Cedar implementation, and says so at the top of the file. A driver that reads the fixture's expected answer copies the answer key, which is finding 6 in ScopeBlind#13. The parent-hash canonical form is byte-identical to the one conformance check 3 computes, so a mismatch means disagreement about decisions rather than disagreement about bytes. No inline public key. draft-farley-acta-signed-receipts says a verifier must not accept a key carried inside the envelope unless it is independently anchored, so kid names the key and resolution is the verifier's. kid is the RFC 7638 thumbprint of the shared conformance seed's public half, which is why it matches the kid on the aps-gateway-enforcement receipts. Output is deterministic: the four receipts hash byte-identically when generated on Linux and on macOS. Schema and check 1 ------------------ expected/receipt-schema.json gains a decisionReceipt branch, and its description is corrected. It previously claimed @veritasacta/verify accepts both the v1 flat and v2 envelope shapes; it accepts neither and returns unknown_format for both. That sentence is where finding 4 in ScopeBlind#13 comes from, and the consequence was that the schema rejected this repository's own aps-gateway-enforcement receipts. They validate now. check 1 in conformance/verify.sh recognises the same shape, kept dependency-free in the existing style. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GSeQ2tJWZkD5NwQkr6J5iC
|
Pushed. Built against What is in the pushThe driver. Its parent-hash canonical form is byte-identical to the one No inline public key. Schema and check 1. What it does on each tree
So this PR is green once #14 lands, and I would rather it merged in that order than have you work around check 2 for me. The suite still catches a bad driverAdding a shape to check 1 could easily have made it permissive, so I planted seven failures and measured the exit code directly rather than through a pipe: Output is deterministic. The four receipts hash byte-identically generated on Linux and on macOS. Finding 7, and it is in check 2Getting that matrix is how I found it. On the first run, three of the four tampered-signature cases passed. Check 2 hands the verifier a glob: npx --yes @veritasacta/verify --key "$CONFORMANCE_KEY" "$RECEIPTS_DIR"/*.jsonIts usage line takes a single It prints exactly one The consequence is the same shape as the others. An implementation can forge three of its four receipts and check 2 reports "all signatures verify." This is on The fix is a loop, one invocation per file, with the pass line moved after it. I have it working locally and left it out of this PR because check 2 is yours in #14 and I did not want to conflict with you. Say the word and I will send it as a separate PR, or take it into #14 yourself, whichever you prefer. I have added it to #13 as finding 7 with the position-by-position numbers. On the
|
Adds Nobulex as an implementation of draft-farley-acta-signed-receipts, per the invitation in
arian-gogani/nobulex#21 by @tomjwxf.
Where this stands, stated plainly: this PR does not pass the suite, and I would rather say so
than let it keep sitting. The driver here emits the v1 flat shape, which passes check 1 on all four
fixtures and comes back
unknown_formatfrom check 2.Chasing that turned into #13. The short version is that the two checks accept disjoint sets: both
shapes
expected/receipt-schema.jsondefines are unknown to@veritasacta/verify, and thedecision_receiptshape the verifier does recognize is rejected by the schema, including on thisrepository's own reference receipts. The measurement is in the issue and it reproduces from a clean
clone.
So the shape this PR should emit is not mine to pick. I have a driver ready that emits
decision_receiptand comes back clean from the verifier, and I will force-push it here the momentthe schema question in #13 has an answer. If you would rather I push it now and let the schema catch
up afterwards, say so and it goes up today.
What the driver produces: four receipts, one per fixture, Ed25519 over JCS-canonical bytes
(RFC 8785), chain-linked via
parent_receipt_hash.Where this canonicalizer has been checked by other people, since that is the part that matters
for a conformance registry and it is better coming from them than from me:
aeoess/agent-passport-systemrecords 14 of 14 byte-match checks passing on 2026-05-02, ten APSJCS vectors plus four CTEF vectors, run through this canonicalizer against their own pinned
canonical_sha256values. Their write-up istests/fixtures/BYTE-MATCH-VERIFICATION.md.AgentAvow/AgentAvowv0.3.2 lists@nobulex/cryptoamong the byte-match validatedimplementations of the CTEF v0.3.1 envelope.
FransDevelopment/open-agent-trust-registrycarries an issuer entry with the Ed25519 key.aeoess/agent-governance-vocabularycarries a crosswalk mapping the primitives to their canonicalvocabulary.
The
action_refconstruction is merged normative implementation guidance in the OWASP AgenticSkills Top 10 under AST09.
Correction to the original description of this PR: it claimed a citation in an x402 conformance
spec. That was wrong. The 14 of 14 figure is from
aeoess/agent-passport-systemas described aboveand has nothing to do with x402. I have removed the claim rather than leave it standing.