Skip to content

docs(seal): PIV hardware-signer plan — the final CROSS-3 pass#8

Closed
gesh75 wants to merge 1 commit into
feat/llm-seal-servefrom
feat/piv-signer-plan
Closed

docs(seal): PIV hardware-signer plan — the final CROSS-3 pass#8
gesh75 wants to merge 1 commit into
feat/llm-seal-servefrom
feat/piv-signer-plan

Conversation

@gesh75

@gesh75 gesh75 commented Jun 1, 2026

Copy link
Copy Markdown
Owner

The PIV hardware-signer plan (docs-only, stacked on the seal-serve PR)

The execution-ready plan for the one remaining piece: swapping the CROSS-3 seal's software Ed25519 signer for a YubiKey-PIV (ECDSA-P256) signer with attestation-chain verification, and binding max_authorized to the same hardware root. No code — it needs the physical token to provision/sign/verify against; everything it plugs into (the Signer/Verifier protocol, the G0–G6 verifier, the /api/seal/* endpoints) already ships and is property-tested.

docs/PIV_HARDWARE_SIGNER_PLAN.md covers:

  • Decisions up front — slot 9c (distinct from the 9a SSH key), ECCP256, on-device key generation (attestable), the raw r‖s → DER gotcha, touch/PIN posture, CA+serial pinning.
  • New modulespiv.py (PivSigner/PivVerifier), attestation.py (chain → pinned Yubico Root CA), pins.py (compiled-in fingerprint + key, not file-loaded), and verify_seal gates G1a/G1b layered before G2 (Ed25519 path unchanged).
  • Ceiling tamper-proofingload_max_authorized() verifies a PIV-signed ceiling policy so it can't be raised by editing env (the #5-ceiling follow-up).
  • D6–D7 sequencing with hardware-gated steps (⚡) marked, and the hw-free vs hw-gated test split — software-EC + a checked-in attestation fixture so CI validates the chain logic tokenless, with the real C_Sign exercised once behind @needs_yubikey.
  • Threat model — closes T6 (software-key impersonation) structurally via attestation; documents the residuals (PIN/coercion) honestly.
  • Rotation runbook + acceptance criteria.

This closes out the AEGIS upgrade arc: the plan is ready to execute the moment a YubiKey is in hand.

Summary by Sourcery

Documentation:

  • Add a detailed PIV hardware-signer plan describing how to introduce a YubiKey-backed ECDSA-P256 signer for seals, including attestation, configuration, testing strategy, threat model, and rotation runbook.

Execution-ready plan to swap the seal's software Ed25519 signer for a YubiKey-PIV
(ECDSA-P256) signer with attestation-chain verification, and to bind max_authorized to the
same hardware root. Lives next to core/seal. No code change — it needs the physical token.

Covers: the slot/algorithm decisions (9c, ECCP256, raw->DER, touch/PIN), the new modules
(piv.py / attestation.py / pins.py + verify_seal gates G1a/G1b), D6-D7 sequencing with the
hardware-gated steps marked, the hw-free vs hw-gated test split (software-EC + a checked-in
attestation fixture so CI runs tokenless), threat-model deltas (closes T6 structurally), the
rotation runbook, and acceptance criteria.
@sourcery-ai

sourcery-ai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a new documentation file that provides a detailed, execution-ready plan for replacing the CROSS-3 seal’s software Ed25519 signer with a YubiKey-based PIV ECDSA-P256 hardware signer, including attestation-chain validation, ceiling-policy binding, sequencing, testing strategy, and operational runbook, without changing existing code or wire formats.

Sequence diagram for verify_seal with PIV ECDSA-P256 path

sequenceDiagram
    participant Caller
    participant verify_seal
    participant AttestationModule
    participant PivVerifier
    participant Pins

    Caller->>verify_seal: verify_seal(seal)
    alt signature.alg == piv-ecdsa-p256
        verify_seal->>Pins: access pinned_root_ca_fingerprint
        verify_seal->>Pins: access serial_allowlist
        verify_seal->>AttestationModule: [G1a attestation chain check]
        AttestationModule-->>verify_seal: [attestation ok / fail]
        verify_seal->>Pins: access pinned_key_id
        verify_seal->>PivVerifier: [G1b key_id match]
        PivVerifier-->>verify_seal: [match / mismatch]
        verify_seal->>PivVerifier: [G2 signature verify]
        PivVerifier-->>verify_seal: [valid / invalid]
    else signature.alg == ed25519
        verify_seal->>Verifier: [existing Ed25519 path]
        Verifier-->>verify_seal: [valid / invalid]
    end
    verify_seal-->>Caller: verification_result
Loading

File-Level Changes

Change Details Files
Introduce an execution-ready design for a YubiKey-PIV-backed hardware signer and associated verification/ceiling logic for the CROSS-3 seal system.
  • Describe how a new PivSigner/PivVerifier module would integrate with the existing Signer/Verifier protocol and seal format using ECDSA-P256 and PKCS#11 C_Sign, including raw r‖s to DER conversion and key_id derivation.
  • Specify an attestation module that validates a YubiKey attestation chain (leaf ← f9 intermediate ← pinned Yubico PIV Root CA), checks serial allowlists, and binds the attested public key to verification.
  • Define compiled-in pinning constants for the Yubico Root CA fingerprint, pinned verification key/key_id, and optional serial allowlist instead of file-based trust configuration.
  • Extend the planned verify_seal flow with additional PIV-specific gates (G1a/G1b) ahead of the existing G2, keeping the Ed25519 path unchanged, and document how max_authorized will be enforced via a PIV-signed policy object.
  • Lay out stepwise sequencing, CI vs hardware-gated tests, threat-model deltas, rotation procedures, dependencies/configuration, and acceptance criteria for safely rolling out and operating the hardware signer without changing the current APIs or formats.
docs/PIV_HARDWARE_SIGNER_PLAN.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The plan mentions seals "carrying an attestation chain" while also stating there is no seal format change; it would help to clarify explicitly where the attestation chain is transported (e.g., only via /api/seal/pubkey vs embedded in the seal) and align the acceptance criteria wording with that.
  • For the PIV-signed ceiling policy {max_authorized, not_after_utc, key_id, signature}, please specify the exact serialization format (e.g., JSON with canonicalization rules vs CBOR) and how canonical bytes are produced so that implementations don’t diverge.
  • The CA-only vs CA+serial pinning posture is described conceptually, but it would be useful to call out the concrete configuration surface (env vars / constants) that controls this choice so operators know precisely how to switch between the two modes.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The plan mentions seals "carrying an attestation chain" while also stating there is no seal format change; it would help to clarify explicitly where the attestation chain is transported (e.g., only via `/api/seal/pubkey` vs embedded in the seal) and align the acceptance criteria wording with that.
- For the PIV-signed ceiling policy `{max_authorized, not_after_utc, key_id, signature}`, please specify the exact serialization format (e.g., JSON with canonicalization rules vs CBOR) and how canonical bytes are produced so that implementations don’t diverge.
- The CA-only vs CA+serial pinning posture is described conceptually, but it would be useful to call out the concrete configuration surface (env vars / constants) that controls this choice so operators know precisely how to switch between the two modes.

## Individual Comments

### Comment 1
<location path="docs/PIV_HARDWARE_SIGNER_PLAN.md" line_range="162" />
<code_context>
+
+---
+
+## 10. Acceptance criteria (done = )
+
+- `AEGIS_SEAL_BACKEND=piv` produces seals whose `signature.alg == "piv-ecdsa-p256"`, carrying an
</code_context>
<issue_to_address>
**issue (typo):** The phrase "(done = )" appears incomplete in the section header.

If this is meant to encode something specific (e.g., a status like `done = true`), please spell it out so readers understand the intended meaning of this notation.

```suggestion
## 10. Acceptance criteria (done = all criteria below are satisfied)
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


---

## 10. Acceptance criteria (done = )

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): The phrase "(done = )" appears incomplete in the section header.

If this is meant to encode something specific (e.g., a status like done = true), please spell it out so readers understand the intended meaning of this notation.

Suggested change
## 10. Acceptance criteria (done = )
## 10. Acceptance criteria (done = all criteria below are satisfied)

gesh75 added a commit that referenced this pull request Jun 1, 2026
…authority gate, ceiling, CROSS-3 seal (#9)

Squashed release of the 8-PR stack (#2..#8): the offline, hardware-rootable bounded-autonomy
receipt and everything under it. AUTO disabled by default; the only un-built piece is the
hardware-PIV signer (docs/PIV_HARDWARE_SIGNER_PLAN.md) — software Ed25519 runs the whole demo.

- core/llm: single shared LLM egress + adapter (local-first fallback chain, retry/cooldown,
  4-event hook bus; raw httpx, no anthropic SDK; air-gap fail-closed). [#2]
- evidence: model-identity wedge — change.model_identity sealed into the bundle hash; honest
  UNKNOWN / unattested states, never a faked attribution. [#3]
- core/risk: deterministic AUTO/HITL/HOTL/BLOCK authority model (severity != authority;
  AS/RD/RT -> BLOCK; spine/underlay -> >= HOTL) + the no-self-escalation ceiling. [#4]
- core/promote: gate rule G5 enforces the ceiling from the sealed required tier;
  change.authority sealed (bundle_version 1.1->1.2). [#5]
- core/seal: CROSS-3 detached, offline-verifiable bounded-autonomy receipt (Ed25519; gates
  G0..G6; refuses to seal an unbounded change). [#6]
- serve: /api/preflight/run emits the seal; GET /api/seal/pubkey + POST /api/seal/verify;
  examiner PDF shows the seal. [#7]
- docs: PIV hardware-signer plan — the final, hardware-gated CROSS-3 pass. [#8]

Property-tested safety invariants: no-self-escalation 0-violations, every-seal-is-bounded,
tamper detection, offline-keyless verify, air-gap fail-closed.
@gesh75

gesh75 commented Jun 1, 2026

Copy link
Copy Markdown
Owner Author

Superseded by the squashed release #9, now merged to main. This PR's changes are in main; closing for tidiness (branch kept for history).

@gesh75 gesh75 closed this Jun 1, 2026
@gesh75
gesh75 deleted the feat/piv-signer-plan branch June 1, 2026 18:10
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