Wendy Certificates
How principals in the Wendy ecosystem get, renew, and lose certificates. pki-core is the sole issuer — every cert it mints binds a client-held key, never a bare identity claim. Which cert type a flow needs depends on where authorization will be enforced: the cloud-facing cert stays identity-only because cloud authorizes live against its own mutable state, while any cert used where there is no live authority to consult offline — an operator's cert for direct field/USB device access — must carry entitlements; device certs are identity-only, and entitlements ride on operator certs only (§4.2). Full flow-level detail — including how the two credential shapes interact with the rest of the AAA contract — lives in the wendy-aaa-interop skill; this skill is the certificate-request/renewal/revocation slice of it.
Decision Table: Which Cert / Which Path
| Need | Path |
|---|---|
| Identity-only operator cert (steady-state login/session) | Direct pki-core endpoint — no cloud in this path |
| Entitlement-bearing cert (direct field/USB device access) | Operator-signed request + CSR → cloud attaches a grant → relayed to pki-core |
| Device cert (enrollment, first touch, recovery) | Enrollment flows — see the wendy-device-enrollment skill |
| Service account / machine user | Identical operator flow, through a different wendy-auth front door (§5.2, D17) |
(§5.2, D17)
Key Rules (non-negotiable)
- Client-generated keys only. Private keys are always generated on the client; pki-core's engine-side
GenerateKeyAndIssueCertis prohibited for principal certs. The sole exception is the server-keygen-over-USB fallback, for a device that genuinely cannot generate its own key, with in-memory zeroization after use (§5.2). extractable:falseis the floor. The Wendy frontend holds the signing key as a WebCrypto key withextractable:falseexplicitly set (§4.1/§7) — not a platform default; high-assurance operators use a FIDO2/passkey hardware authenticator instead, so signing happens inside the device and malware can only use the key while resident, never exfiltrate it (§7).- No pure bearer PATs. Only sender-constrained tokens exist in this system — a copy-pasteable secret is rejected outright, for humans and service accounts alike (D17).
- Request-signing is JWS/COSE with ML-DSA, not RFC 9421. Proof-of-possession is a signature over a canonical request descriptor, algorithm ML-DSA per RFC 9964 (default leaf ML-DSA-65), enveloped as JWS (HTTP/cloud) or COSE_Sign1 (edge/gRPC) — not RFC 9421 HTTP Message Signatures, whose registry has no ML-DSA algorithm (§4.1).
Service Accounts & CI
A service account is a normal user behind a different wendy-auth front door, flagged and privileged by cloud exactly like a human — same §5.2 cert flow (issuance + renewal + in-flight status check), no weaker path. It gets its own service SPIFFE kind (spiffe://wendy.sh/tenant/<uuid>/service/<name>) so audit and offline enforcement can tell human and machine principals apart.
CI never holds a long-lived secret: wendy-cloud-action federates the job's IdP OIDC token into wendy-auth, which mints a wendy-auth token bound to an ephemeral in-job key; the job then calls the same identity-cert endpoint for a short-lived cert. No PAT ever exists at any point in this flow (D17).
Self-Hosted Rule (mandatory)
The wendy stack (wendyos / wendy-agent) must ALWAYS be able to run without the SaaS stack. Before shipping any interop change, consult the wendy-self-hosted skill: keep the self-hosted path intact, or create it where it doesn't exist yet. A SaaS-only feature is an incomplete feature.
Source of Truth
This skill distills the AAA Contract v0.21 (Approved 2026-08-29). The living contract lives in Linear: AAA Contract — Authentication, Authorization, Accounting. It is versioned and evolving: check it for flow-level detail, and if it disagrees with this skill, the contract wins — then update this skill.
Related Skills
wendy-aaa-interop— the full contract this skill distills a slice ofwendy-device-enrollment— device certs: first touch, tiers, post-expiry recoverywendy-security-baselines— the invariants any interop change must respectwendy-self-hosted— the standing dual-path rule


