Skip to content

ci: delegate gate-attestation to the fleet reusable - #9

Merged
forkwright merged 1 commit into
mainfrom
ci/gate-attestation-caller
Jul 8, 2026
Merged

forkwright merged 1 commit into
mainfrom
ci/gate-attestation-caller

Conversation

@forkwright

Copy link
Copy Markdown
Owner

Replaces the inline gate-attestation (no release-please waiver — every release PR failed with "No Gate-Passed trailer found") with a thin caller of the canonical reusable, pinned past the branch-shaped RP waiver (forkwright/.github#10). Note: the check context becomes gate / gate-attestation; branch protection (where present) is updated in lockstep.

Replace the inline copy (which lacked any release-please waiver, failing every
release PR with 'No Gate-Passed trailer found') with a thin caller of the
canonical reusable, pinned past the branch-shaped release-please waiver
(forkwright/.github#10). One fact, one place.

Gate-Passed: kanon 0.1.6 +stages:fmt,check,clippy,nextest,lint sha:f37359ad8909afc24d679265586d080fd00a793d
@forkwright
forkwright merged commit 94afe5c into main Jul 8, 2026
10 checks passed
@forkwright
forkwright deleted the ci/gate-attestation-caller branch July 8, 2026 14:33
forkwright added a commit that referenced this pull request Aug 15, 2026
… the adapter seam (#32)

## Summary

sphragis#23 asks Sphragis to earn authority as a versioned,
multi-recipient
content-key envelope — not as a generic X-Wing/KEM primitive library —
by
hiding `HybridKem`, `EncapsulationKey`, `DecapsulationKey`,
`SharedSecret`,
and `derive_wrap_key` from the normal public API, and by defining the
seam
for an eventual upstream-X-Wing adapter.

**What this PR does:**

- Adds a `hazmat` feature (the RustCrypto/rustls convention for exactly
this
shape of surface) that gates the generic hybrid-KEM primitive:
`HybridKem`,
direct `EncapsulationKey::encapsulate`/`DecapsulationKey::decapsulate`,
and
`derive_wrap_key`. Off by default; carries no stability promise; exists
  only so this crate's own known-answer/conformance tests can reach the
  primitive directly.
- Adds `generate_recipient_keypair()` — the new stable, profile-level
entry
  point for device-key creation, replacing `HybridKem::generate()` for a
  normal consumer.
- Keeps `EncapsulationKey`/`DecapsulationKey` and their key-management
  operations (`to_bytes`/`from_bytes`, `from_seed`/`to_seed`,
`encapsulation_key`) public — `seal_for`/`unseal` require them in their
own
  signatures, and publishing/persisting a device key is a profile-level
  operation, not a primitive one.
- `DECISION.md` #9 documents the module boundary (`src/hybrid.rs` is now
the
  *only* place that performs a raw KEM operation) as the adapter seam a
  future migration would use, and is explicit that this PR does **not**
  perform that migration: upstream `x-wing` is still a release-candidate
stack (`DECISION.md` #6), so the local X-Wing transcription remains the
  implementation until a stable, audited release meets the existing
  migration gate. Building the seam now and gating the migration on
  upstream stabilizing is the honest scope here, per the task brief.
- New `tests/profile_api.rs`: a normal-consumer round-trip
  (`generate_recipient_keypair` → `seal_for` → `unseal`) compiled with
`preview-pq` alone, `hazmat` off — the proof that narrowing the API did
not
  also narrow what a normal consumer can *do*.
- A `compile_fail` doctest on `HybridKem`'s non-hazmat declaration
proves the
  hiding: it fails to compile under `--features preview-pq` (pre-fix
behaviour: `HybridKem::generate()` was reachable and this snippet would
have compiled) and is entirely absent — so never even attempted — under
`--features preview-pq,hazmat`, since that cfg arm doesn't exist there.
- CI (`ci.yml`) and the local gate (`.kanon-ci.toml`) both gain a
`preview-pq,hazmat` check/clippy/test lane so
`tests/known_answer_vectors.rs`
  keeps compiling and running unmodified (see below) instead of silently
  going unbuilt.

## Sequencing (sphragis#17, sphragis#18)

Per the task brief, this rebases onto current `origin/main` and stays
off
files those two sibling lanes are actively editing:

- **`src/lib.rs` / `src/envelope.rs`**: zero overlap — neither #17 nor
#18
  touches these files.
- **`src/hybrid.rs`**: #17 (unmerged, no PR yet) touches two disjoint
regions
  — the `EncapsulationKey` doc comment and `encapsulate_deterministic`'s
  signature/body, appending an inline KAT test at EOF. This PR's edits
  (`SharedSecret`'s doc, `HybridKem`, `HybridKem::generate`,
  `EncapsulationKey::encapsulate`, `DecapsulationKey::decapsulate`) sit
  outside those hunks. **Deferred**: `encapsulate_deterministic`'s own
visibility is left exactly as on `main` (`#[doc(hidden)] pub fn`) — #17
is
  already privatizing it directly; touching the same lines here would be
  fighting for the same file for no benefit, since #17 lands a strictly
  tighter result (fully private, not hazmat-gated).
- **`tests/known_answer_vectors.rs`**: #17 removes/relocates one test
there;
  #18 (PR #27, mid-rebase) rewrites ~270 lines of it (ACVP vectors,
provenance-lock helpers). This PR does not touch that file at all —
instead,
`Cargo.toml` gains a `[[test]] required-features = ["preview-pq",
"hazmat"]`
  entry for it, so it silently skips under `--features preview-pq` (no
  hazmat) instead of failing to compile, and keeps compiling/running
  byte-for-byte unmodified under `--features preview-pq,hazmat` — its
  existing calls to `HybridKem::generate()`, `.encapsulate()`,
  `.decapsulate()`, `derive_wrap_key()` all still resolve because those
  items are genuinely `pub` in that feature combination.
- **`DECISION.md`**: #18 edits section 7 (lines ~185-199, inside its own
hunk). This PR's new section 9 is appended after section 8, at the
file's
  end — disjoint from that hunk.
- **`Cargo.toml`**: #18 appends two `[dev-dependencies]` (`serde_json`,
`hex`) after `proptest = "1"`. This PR's `hazmat` feature line sits in
the
`[features]` block near the top, and the new `[[test]]` block sits right
  before `[lints.rust]` — both disjoint from #18's dev-dependency hunk.
- **`README.md`**: #18 inserts a paragraph after the "Testing" code
block
(~line 56+). This PR edits the earlier "Usage" example and the
"Features"
  list (~lines 31-51) — disjoint.
- **Deferred, not touched**: `AGENTS.md`, `llms.txt` — both list
`tests/`
  contents in a region #18 is actively rewriting for its own new files
(`provenance_lock.rs`, `vectors/`, `crypto-provenance.toml`). Left for a
  follow-up doc-sync pass once #17/#18/#23 have all landed, rather than
  risk a three-way collision on the same lines.

## Deliberate scope limit: `SharedSecret`'s alias name

`SharedSecret`'s type-alias visibility stays exactly as it is today
(public,
reachable at `sphragis::hybrid::SharedSecret`) rather than being
hazmat-gated
like `HybridKem`/`derive_wrap_key`/direct encaps-decaps. Reason:
`EncapsulationKey::encapsulate_deterministic` (pre-existing,
`#[doc(hidden)]`,
unrelated to this issue and explicitly left untouched per the sequencing
above) returns `SharedSecret` **unconditionally** — narrowing the
alias's own
visibility would leak a private type through that method's
still-fully-public
signature (`private_interfaces`, denied under `-D warnings` in CI),
without
ever touching the method causing it. This is inert: no operation
reachable
without `hazmat` (`HybridKem::generate`, direct
`encapsulate`/`decapsulate`,
`derive_wrap_key`) can produce a real X-Wing-derived value of it, and
`Zeroizing<[u8; 32]>` — the concrete type this aliases — carries no
capability
a consumer couldn't already construct directly from the public `zeroize`
crate. Documented inline in `src/hybrid.rs` at the declaration site.

## Blast radius

Verified zero: akroasis pins `sphragis` via `tag = "v0.1.1"` in
`[workspace.dependencies]`, but no member crate depends on it
(`grep -rln sphragis --include Cargo.toml` finds only the root pin) and
no
`.rs` file references it.

## Test plan

- [x] `cargo fmt --all -- --check` — clean.
- [ ] CI: `cargo check`/`clippy`/`test` × {default, preview-pq,
preview-pq+hazmat}
— this box's local `vgate` admission is under heavy contention from
concurrent sessions and did not complete a full local pass before push;
per this repo's build-reality guidance, CI is the reliable verifier
      here and a prior agent on this exact repo correctly withheld a PR
rather than ship unverified crypto without it — this PR relies on the
      GitHub Actions run rather than a claimed-clean local build.
- [x] New `tests/profile_api.rs` proves the narrowed API is still fully
      usable end-to-end without `hazmat`.
- [x] New `compile_fail` doctest proves `HybridKem` is unreachable
without
      `hazmat` (fails pre-fix behaviour, passes post-fix).

Closes #23

---------

Co-authored-by: forkwright <cody@forkwright.com>
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