Documentation Index
Fetch the complete documentation index at: https://docs.automagik.dev/llms.txt
Use this file to discover all available pages before exploring further.
Release signing for
@automagik/genie is cosign keyless only. There is no long-lived private key, no hardware-backed offline key, no public-key fingerprint to pin. “Rotation” here means rotating the certificate-identity pin (workflow-path@ref, OIDC issuer, and provenance source-uri) that operators cross-check across three independent channels.When to rotate
Rotate the pinned certificate identity when — and ONLY when — one of these happens. Routine releases do NOT require rotation.- Workflow path moves.
.github/workflows/release.ymlis renamed or split. The Fulcio certificate SAN embeds the workflow path, so a move changes the certificate identity verifiers must accept. - Repository is renamed.
automagik-dev/geniebecomes something else. Both the signer identity regexp and the SLSA provenancesource-urimust move atomically. - OIDC issuer changes. GitHub Actions’ OIDC token issuer URL changes
(rare; announced upstream). The pinned
certificate-oidc-issuermust change with it. - Keyless trust-root incident. Sigstore / Fulcio announces a trust-root rotation that requires consumers to re-verify against a new root. Operators follow the cosign upstream rotation advisory in addition to this runbook.
Rotation contract (summary)
| Constraint | Detail |
|---|---|
| Minimum approvers | Two Namastex security officers (independent GitHub accounts) |
| Pinning channels | SECURITY.md, /.well-known/security.txt, pinned GitHub issue |
| Grace period | Minimum 72 hours in which the OLD and NEW identities both verify |
| Retirement test | genie sec verify-install against a post-rotation release MUST exit 0 |
| Audit trail | Rotation PR signed by both officers; the pinned issue records the Filed by (GPG fingerprint). |
Step-by-step rotation procedure
Phase 1 — Pre-rotation (before touching anything)
- Open a tracking issue in
automagik-dev/genietitledSIGNING_CERT_IDENTITY_<YYYYMMDD>using the.github/ISSUE_TEMPLATE/signing-key-fingerprint.mdtemplate. - Draft the new values:
certificate-identity-regexpcertificate-oidc-issuer- provenance
source-uri
- Confirm the CURRENT values are byte-identical across all three pinning channels. If they already drift, stop and open an incident — rotation cannot overlay a broken baseline.
Phase 2 — Two-officer ceremony
- Two Namastex security officers (distinct GitHub identities, distinct
hardware keys for commit signing) co-author the rotation PR. The PR MUST:
- Update
.github/workflows/release.yml(if workflow path changes). - Update
src/term-commands/sec.tsSIGNER_IDENTITY_REGEXP/SIGNER_OIDC_ISSUER/PROVENANCE_SOURCE_URIconstants. - Update
SECURITY.mdso its pinned values match the new identity byte-for-byte. - Update
/.well-known/security.txton the project site (or file the site-repo PR in parallel). - Update (or open) the tracking issue created in Phase 1 with the final values.
- Update
- Both officers sign the PR via
git commit -Swith a GPG key that appears on their GitHub profile. CI checks for exactly two distinct co-authors with verified signatures; a single-officer PR must be refused. - After merge, a tagged release runs the real signing workflow against the
new certificate identity. The post-release verify job
(
.github/workflows/release.ymlverifyjob) MUST pass; if it fails, the rotation is aborted and rolled back.
Phase 3 — Grace-period dual-verification
- For at least 72 hours after the rotation lands, verification tooling MUST
accept BOTH the old and new certificate identities. In practice that means
keeping the old entry in
SECURITY.mdunder a## Previous pinningheading so operators running the previous release do not failgenie sec verify-install. - The pinned issue is updated with the old value under its
## Previous pinningsection — never deleted. - Operators running
genie sec verify-install --offlineduring the grace period should seeverified_attimestamps newer than the rotation epoch. Any operator whoseverified_atpredates the rotation is instructed to pull the new release.
Phase 4 — Retirement of the old identity
- 72 hours after Phase 3 begins, and AFTER the post-rotation release has
been verified end-to-end at least once by each of the three channels, the
old identity is retired:
SECURITY.mddrops the## Previous pinningsection.- The tracking issue is marked RESOLVED (but never deleted).
- Verification tooling stops accepting the old identity.
- Retirement is a separate PR. It is NOT bundled with the rotation PR — a bundled retirement eliminates the grace window.
Test-key dry-run recipe
The rotation procedure MUST be practiced at least once per quarter using throwaway test identities. A successful dry-run ends withgenie sec verify-install returning exit 0 against a test-release bundle
signed by the rehearsed identity.
Goal
Simulate Phases 1–4 end-to-end in under one hour, against a disposableautomagik-dev/genie-signing-drill repo (or a local fork pointing at a
fixture workflow), without touching the production signing identity.
Steps
Acceptance
A dry-run is successful when every expected exit code in the recipe above appears. If any step deviates, file an issue taggedsigning-rotation-drill
and do not ship the rotation PR until the deviation is understood.
Anti-patterns
The following have bitten prior rotations and MUST NOT be repeated:- Rotating without updating all three channels. The three-channel pin exists so an attacker must compromise three distribution points to invalidate. Dropping one channel defeats the invariant.
- Single-officer rotation. A rotation touched by one human account means a single compromise can move the pin. CI blocks single-officer PRs.
- Grace-period shortcuts. Reducing the 72-hour window to “speed up” a
rotation makes operators on older releases fail
verify-install. If a rotation is urgent enough to skip the grace window, it is an incident — file it as such, don’t rotate. - Bundling retirement with rotation. Retirement collapses the grace window. Always two PRs.
- “Just amend” fixups. Rotation history is load-bearing. Fix via a new PR that explicitly references the broken rotation; do not rewrite history.
References
.github/cosign.pub— the documented NO-KEY sentinel (keyless-only)..github/workflows/release.yml— the signing + verify pipeline..github/ISSUE_TEMPLATE/signing-key-fingerprint.md— pinned-issue template.src/sec/unsafe-verify.ts— the--unsafe-unverifiedcontract that operators fall back on if a rotation goes sideways.scripts/verify-release.sh— the local verification script that mirrorsgenie sec verify-install.