Skip to content

fix: complete revocation — TS HTTP verifier wired, README corrected, tests added#40

Merged
rmhrisk merged 1 commit intomainfrom
feat/revocation-tests
Mar 17, 2026
Merged

fix: complete revocation — TS HTTP verifier wired, README corrected, tests added#40
rmhrisk merged 1 commit intomainfrom
feat/revocation-tests

Conversation

@rmhrisk
Copy link
Copy Markdown
Contributor

@rmhrisk rmhrisk commented Mar 17, 2026

Addresses the gaps that caused an external audit to conclude revocation was not implemented.

Root cause 1 — ts/verifier/main.ts: The TS HTTP verifier service had an independent verification loop that still contained the stub. The SDK verifier (ts/sdk/src/verifier.ts) was fully wired, but the HTTP service was not. Fixed: checkRevocation() and parseRevArtifact() added, revocationURL field added to TrustAnchor, revocCache added.

Root cause 2 — README.md: Line 225 explicitly said "Revocation not implemented." Updated to accurately describe what's done and document the intentional Mode 0 fail-open behavior.

RevocationTest.java: Six behavioral tests covering the full issue → revoke → verify path: notRevokedEntryVerifies, revokedEntryIsRejected, revocationDoesNotAffectOtherEntries, multipleRevocations, revokeZeroThrows, revokeUnissuedThrows. Java total: 39/39.

interop_test.py: Two cross-implementation revocation tests using dedicated fresh service instances (ports 8091/3011 issuers, 8092/3012 verifiers). Cold-cache verify pattern — revoke before first verify so the verifier fetches the updated artifact directly. Interop total: 17/17.

…tests added

The other LLM that audited the repo was correct: two things were incomplete
on main after PRs #38 and #39.

1. ts/verifier/main.ts — TS HTTP verifier service still had the stub.
   The SDK verifier (ts/sdk/src/verifier.ts) was fully implemented, but the
   HTTP service has its own independent verification loop. It was never updated.

   Fixed: Cascade import added. revocationURL field added to TrustAnchor.
   revocCache: Map<string, CachedRevocation> added. checkRevocation() and
   parseRevArtifact() added — mirrors Go HTTP verifier implementation with
   full signature verification, algorithm binding, staleness check (32 entries),
   fail-closed behavior.

2. README.md — line 225 explicitly said 'Revocation not implemented.' This
   is what the other LLM read. Updated to accurately describe the current state:
   all four SDK verifiers are wired, cascade is cross-verified against locked
   test vectors, revocation_url is in trust config. Mode 0 fail-open behavior
   documented as the intentional design for offline deployments.

RevocationTest.java — six behavioral tests added to Java SDK test suite:
   notRevokedEntryVerifies, revokedEntryIsRejected,
   revocationDoesNotAffectOtherEntries, multipleRevocations,
   revokeZeroThrows, revokeUnissuedThrows. All 6 pass. Java total: 39/39.

interop_test.py — two cross-implementation revocation tests added:
   'Revoke: Go issuer → TS verifier rejects' (issuer port 8091, verifier 3012)
   'Revoke: TS issuer → Go verifier rejects' (issuer port 3011, verifier 8092)
   Dedicated fresh service instances used to avoid cache contamination from
   the positive matrix runs. Cold-cache verify: revocation happens before the
   first verify call so the verifier fetches the updated artifact directly.
   Both pass. Interop total: 17/17.
@rmhrisk rmhrisk merged commit e12cb2b into main Mar 17, 2026
7 checks passed
rmhrisk pushed a commit that referenced this pull request Mar 17, 2026
…guages

Addresses eight gaps identified in a cross-language audit:

1. Rust claims type (HashMap<String,String> → HashMap<String,serde_json::Value>)
   Non-string claim values (integers, booleans, nulls, arrays) were silently
   dropped at decode time. Added cbor_to_json() helper preserving all CBOR types.

2. Rust Issuer revocation (revoke(), revocation_artifact())
   Rust Issuer had the cascade but no public revocation API. Added revoke(),
   revocation_artifact(), build_revocation_artifact(), entry_expiry_time(),
   revoked_indices HashSet, latest_rev_artifact Option<String> in State, and
   revocation_url emission from trust_config_json(). Wired into publish_checkpoint.

3. TS SDK Issuer revocation (revoke(), revocationArtifact())
   SDK Issuer had internal state but no public API. Added public revoke(bigint),
   revocationArtifact() methods, buildRevocationArtifact() private method,
   entryExpiryTime() helper, Cascade and decodeTbs imports, and revocation_url
   in trustConfigJson(). Wired into publishCheckpoint.

4. TS SDK Verifier RevocationProvider
   Added RevocationProvider type and 3rd constructor parameter, symmetric with
   Java. Wired into fetchRevArtifact for test injection. Updated all.test.ts to
   pass revocationProvider so smoke tests no longer fail-closed on localhost:0.

5. Rust Verifier RevocationProvider
   Added RevocationProvider type and with_revocation_provider() constructor,
   symmetric with Java and TS SDK. Wired into fetch_revocation_artifact.

6. Mode 0 rejection — TS SDK and Rust verifiers now reject mode=0 payloads
   explicitly before any network work, with a clear 'not implemented' message.
   Go already did this correctly; Java falls through (mode=0 fails at proof
   verification, not at an explicit check — Java gap noted but not fixed here).

7. Behavioral revocation tests:
   - Go: IsRevoked() accessor added; TestRevokeAndArtifact, TestRevokeIndexZeroRejected,
     TestRevokeUnissuedRejected, TestMultipleRevocations (4 tests, log_test.go)
   - TS SDK: revocation.test.ts — 6 behavioral tests + 1 mode=0 rejection test (7 total)
   - Rust: revocation_tests module — un_revoked_entry_verifies, revoked_entry_is_rejected,
     revoke_zero_rejected, revoke_unissued_rejected, mode_zero_rejected (5 tests)
   - Java: unchanged — RevocationTest.java already has 6 behavioral tests from PR #40

8. Documentation:
   - SPEC.md §Deferred Items: 'not yet implemented' → 'specified and implemented'
   - ARCHITECTURE.md: Revocation section (cascade algorithm, wire format, issuer/verifier
     implementation summary, cache semantics). Multi-anchor vs single-anchor design
     decision documented (HTTP services are multi-anchor; SDK libraries are single-anchor).
   - IMPLEMENTERS_GUIDE.md: Three stale 'revocation is stubbed' references fixed.

Test totals after this PR:
  Go:   42 tests (was 38) — 4 new revocation behavioral tests
  TS SDK: 47 tests (was 40) — 7 new revocation + mode0 tests
  Rust: 28 unit + 2 doctests = 30 (was 23+2=25) — 5 new revocation tests
  Java: 39 tests (unchanged — already had RevocationTest from PR #40)
  Interop: 17/17 (unchanged)
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