Sub-issue of datum-cloud/enhancements#738. Phase B of the passkey program — this is the original ask on that issue.
Scope
A signup path that needs no social IdP and no password: user gives an email, verifies
it, then enrolls a passkey. Email must be verified before the account can act on the
platform (hard gate). Phase B reuses every ceremony and management surface built in
Phase A and adds the risky surface: backend-sent verification email, the hard gate,
enumeration safety, and bot protection.
What's included
Email pipeline (longest cross-repo path — starts before the rest of Phase B)
Signup rework (auth-ui)
Hard gate (milo, zitadel-provider, cloud-portal)
Enablement (infra)
Passkey-removed notification (moved from Phase A, 31.07.26)
Design and implementation plan are already written and approved — the removal event carries
no passkey name, so auth-ui must persist it at enroll time. Deferred from Phase A because it
spans four repos.
Status
Not started. Phase A had to land first: the shared WebAuthn plumbing, the management
surface, and the org-policy flip are all prerequisites, and shipping the reversible thing
first is the correct risk ordering.
Dependencies and gates
- Blocked on Phase A being live (done on staging).
- The email-templates → OCI bundle → Flux pipeline is the longest lead time in the program: ship templates before the code referencing them.
- GA is gated on: Phase C recovery design sign-off, a bot-protection tooling decision, and enumeration tests passing.
Sub-issue of datum-cloud/enhancements#738. Phase B of the passkey program — this is the original ask on that issue.
Scope
A signup path that needs no social IdP and no password: user gives an email, verifies
it, then enrolls a passkey. Email must be verified before the account can act on the
platform (hard gate). Phase B reuses every ceremony and management surface built in
Phase A and adds the risky surface: backend-sent verification email, the hard gate,
enumeration safety, and bot protection.
What's included
Email pipeline (longest cross-repo path — starts before the rest of Phase B)
emails/user-email-verification.tsx, link-preferred over raw code (email-templates)Signup rework (auth-ui)
CreateUsershowPasskeyfromAUTH_EMAIL_DELIVERY_ENABLED; promoteEMAIL_VERIFICATIONinto the env schemaHard gate (milo, zitadel-provider, cloud-portal)
email_verifiedsynced onto the milo User + authn claim validation + authz-webhook backstopEnablement (infra)
disableLoginWithEmail,AUTH_EMAIL_DELIVERY_ENABLED,EMAIL_VERIFICATION— staging then productionPasskey-removed notification (moved from Phase A, 31.07.26)
user-passkey-removed.tsxtemplate with optionalPasskeyName(email-templates)ListUserMetadataonpkg/zitadel+passkey_removed.gohandler (zitadel-provider)user.human.passwordless.token.removed, staging and production (infra)Browser/Devicevariables from the passkey-added contractDesign and implementation plan are already written and approved — the removal event carries
no passkey name, so auth-ui must persist it at enroll time. Deferred from Phase A because it
spans four repos.
Status
Not started. Phase A had to land first: the shared WebAuthn plumbing, the management
surface, and the org-policy flip are all prerequisites, and shipping the reversible thing
first is the correct risk ordering.
Dependencies and gates