- Add Rust provider adapter types and delivery outcome model in
k2mx-core. - Normalize provider policy parsing for throttle, HTTP, token cache, retry, mail, and terminal policy.
- Define queue status transitions and richer delivery-attempt fields in
k2mx-api-contract. - Add helper queries in
k2mx-api-serverto load provider, mailbox, and active provider secret records. - Add helper logic in
k2mx-api-serverto build an internal provider send command from a queued item. - Port Office365 Graph token acquisition flow from
ext/MXinto Rust. - Port Office365 Graph send payload mapping from
ext/MXinto Rust. - Port Office365 Graph timeout, throttle, and token-cache behavior into Rust.
- Port Office365 Graph retry and terminal-failure classification into Rust.
- Define and implement a deterministic provider secret unwrap contract for encrypted provider credentials.
- Replace the placeholder worker dispatch path with real provider execution.
- Persist one durable delivery-attempt record per real provider attempt.
- Patch queue items into explicit terminal states:
sent,retry_wait, orfailed. - Record provider message ids and provider error details on attempts where available.
- Surface real delivery status and attempt details in the k2mx operator console.
- Add worker tests for sent, queued-by-provider, retryable failure, and terminal failure outcomes.
- Add route regression tests to preserve current send-admission behavior while delivery execution changes underneath.
- Add integration-style tests with a mocked Office365 endpoint.
- Validate Milestone A end-to-end under Rally with
k2db-api,ringtail, andk2mxrunning together.
- Add queue delete and bulk delete API parity with legacy MX.
- Add queue redrive operations.
- Add retained failure records as a first-class persisted collection.
- Surface retained failures and redrive controls in the k2mx operator console.
- Add durable telemetry rollups for k2mx delivery outcomes.
- Add telemetry read routes.
- Add operator telemetry views in the shared shell.
- Add durable audit visibility for admin and delivery actions.
- Move permission and provider-selection logic out of
k2mx-api-serverroute handlers and into reusable helpers. - Define a safe multi-instance claim strategy for queue workers instead of best-effort polling plus patching.
- Add tests for claim races and retry scheduling.
- Assume Terraform substrate and lower-layer Ansible platform lift already exist outside this repo.
- Define this repo's infra handoff as layer 3 only: install and initialize the constellation app layer on top of an already-ready cluster.
- Keep the current deploy-script path as the live baseline until the new layer-3 bootstrap can reproduce a working stack end to end.
- Treat published Docker Hub images as the canonical app artifacts for layer-3 install.
- Define the inputs the new Ansible layer-3 playbook must own per service: image tag, public domain, upstream URLs, API keys, JWT secrets, signup flags, and any Nomad var or Vault paths.
- Define the deterministic install order for the core constellation: edge prerequisites already present, then
k2db-api,k2rbac-api,k2login,k2hello, and any other required base services. - Make the app-install contract explicit about what remains infra-owned versus what stays app-owned in this repo.
- Add a repo-side example vars file for the future layer-3 playbook.
- Add a dedicated Ansible playbook or role that renders Nomad jobs for the core services and submits them to the existing cluster.
- Make the layer-3 playbook write Nomad vars or integrate with existing Vault-backed secret delivery without inventing a parallel secret path.
- Reuse the current Nomad job templates and deployment assumptions instead of creating a second deployment model.
- Make the layer-3 deploy idempotent so reruns reconcile image tags, vars, and submitted jobs cleanly.
- Add post-deploy checks for
/ready, service registration, public route reachability, and the critical auth path.
- Define the zero-to-usable bootstrap actions after the jobs are live: first admin bootstrap, default config, and any required seed data.
- Split one-time bootstrap actions from repeatable reconcile actions so reruns do not clobber a live system.
- Add a single core-init entrypoint that can take an already-provisioned cluster to a minimally usable constellation install.
- Add smoke tests that prove login, handoff, and core operator flows work on a fresh layer-3 install.
- Document the layer-3 bring-up contract so frontend apps can assume a stable base constellation model.
Architecture note:
k2loginis the public auth boundary for browser and third-party identity-provider traffic.- Third parties such as GitHub and Google terminate at
k2login, not at RBAC. - RBAC should only consume normalized first-party auth input such as
provider,providerSub,email, andemailVerified. - Anything beyond
k2loginis constellation-internal and should not carry provider-specific browser flow or third-party secret handling.
- Confirm
OAuthRequestremains the canonical provider-agnostic contract shape ink2rbac-api-contract. - Re-export
OAuthRequestcleanly fromk2rbac-api-contractso server and client use the same type. - Add
rbac-api-clientsupport for postingOAuthRequesttoPOST /auth/oauthand returningTokenResponse. - Add a new
oauth_login_or_link(...)capability to theRbacApitrait ink2rbac-api-server. - Expose
POST /auth/oauthin the RBAC runtime router. - Make the RBAC
/auth/oauthroute useoptional_ticket, because anonymous login must work while explicit linking should still require a session. - Port the legacy TypeScript
oauthLoginOrLinkbehavior intok2rbac-api-serverwith the current account-rooted Rust model. - Implement explicit external-provider linking for an already authenticated user via
linkToUserId. - Implement lookup by existing external credential using
provider + providerSub. - Implement safe fallback matching by verified email only when no external credential match exists.
- Implement new account-plus-user creation when no safe match exists.
- Attach the external provider credential to the resolved or newly created user before issuing tokens.
- Keep external-provider identity matching keyed by
provider + providerSub, using verified email only as a secondary safe match hint. - Reject external-provider linking when the same
provider + providerSubis already attached to a different user. - Add router tests proving
POST /auth/oauthexists and wrong methods are rejected. - Add RBAC tests for external-provider login create.
- Add RBAC tests for provider-sub reuse returning the same user.
- Add RBAC tests for verified-email hint reuse when safe.
- Add RBAC tests proving unverified email does not match an existing user.
- Add RBAC tests for explicit account linking.
- Add RBAC tests proving explicit linking requires an authenticated session.
- Add provider-agnostic external auth plumbing in
k2login-serverso GitHub is the first adapter instead of a hardcoded one-off. - Define a normalized external-identity result shape in
k2login-serverwithprovider,providerSub,email, andemailVerified. - Add provider configuration types in
k2login-serverfor enabled providers, client ids, client secrets, scopes, and callback origin. - Add provider start and callback routes in
k2login-serverwith a shape that can support more than one provider. - Add OAuth state storage in
k2login-serverfor provider,next, locale, issued-at, and expiry. - Add OAuth state validation in
k2login-server, preserving currentnextand locale handling. - Add expiry and one-time-consumption behavior for OAuth state entries.
- Preserve current
nextdestination validation rules for external-provider login starts and callbacks. - Preserve current locale propagation rules for external-provider login starts and callbacks.
- Add a provider-agnostic completion path in
k2login-serverthat exchanges a normalized external identity for RBAC tokens. - Reuse the existing
redirect_with_token(...)handoff flow ink2login-serverfor external-provider login completion. - Add structured callback error handling in
k2login-serverfor invalid state, denied consent, token exchange failure, and profile lookup failure. - Add
macrunconfig for provider client ids, client secrets, and callback origin without embedding secrets in static args. - Add Nomad config for provider client ids, client secrets, and callback origin without embedding secrets in static args.
- Add
k2login-servertests for OAuth state issuance, single-use redemption, expiry,nextpreservation, and locale preservation.
- Add a GitHub provider adapter in
k2login-serverthat plugs into the provider-agnostic external-auth path. - Add GitHub authorize redirect generation with callback URL, scopes, and CSRF state.
- Add GitHub callback code exchange in
k2login-server. - Add GitHub user-profile fetch in
k2login-server. - Add GitHub email-list fetch in
k2login-serverso verified email can be used when available. - Normalize GitHub identity into
provider = github,providerSub = github user id, plus optional verified email. - Handle the GitHub case where no verified primary email is available without breaking provider-sub-based login.
- Add login-page GitHub provider buttons in
k2login-serverthat render only when GitHub is configured. - Add GitHub callback error handling for denied consent, missing code, token exchange failure, profile fetch failure, and email fetch failure.
- Add unit tests for GitHub identity normalization and verified-email selection.
- Add route tests for GitHub start and callback flows in
k2login-server. - Add local smoke tests for GitHub login that prove refresh-cookie issuance and relying-app handoff still work.
- Add live smoke tests for GitHub login that prove refresh-cookie issuance and relying-app handoff still work.
- Add a Google provider adapter in
k2login-serverthat plugs into the provider-agnostic external-auth path. - Add Google authorize redirect generation with callback URL, scopes, CSRF state, and OIDC nonce handling where required.
- Add Google callback code exchange in
k2login-server. - Add Google ID-token validation or userinfo fetch in
k2login-server. - Normalize Google identity into
provider = google,providerSub = oidc sub, plus email andemailVerified. - Prefer Google-provided verified-email semantics over ad hoc email heuristics.
- Add login-page Google provider buttons in
k2login-serverthat render only when Google is configured. - Add Google callback error handling for denied consent, missing code, token exchange failure, token validation failure, and userinfo fetch failure.
- Add unit tests for Google identity normalization and verified-email handling.
- Add route tests for Google start and callback flows in
k2login-server. - Add local smoke tests for Google login that prove refresh-cookie issuance and relying-app handoff still work.
- Add live smoke tests for Google login that prove refresh-cookie issuance and relying-app handoff still work.
- Add second-factor policy checks so password, GitHub, and Google can all funnel into MFA or passkey challenges before issuing the final login session.
- Add TOTP authenticator-app enrollment as a separate MFA layer after primary auth succeeds.
- Add TOTP verification challenges for enrolled users before issuing the final login session.
- Add recovery codes for TOTP-based MFA.
- Add backup and reset flows for lost authenticator-app access.
- Add WebAuthn passkey registration as a separate track from provider OAuth.
- Add WebAuthn assertion flow for passkey sign-in or second-factor challenge completion.
- Add support for platform authenticators such as Touch ID under the WebAuthn passkey path.
- Decide whether passkeys act as first-factor sign-in, second-factor completion, or both, and implement the chosen policy explicitly.
- Add UI flows in
k2login-serverfor TOTP enrollment, TOTP challenge, passkey registration, and passkey challenge. - Add
k2login-servertests for TOTP enrollment, challenge success, challenge failure, and recovery-code use. - Add
k2login-servertests for WebAuthn challenge generation, assertion validation, and replay rejection. - Add local smoke tests proving MFA and passkey flows still end in refresh-cookie issuance and relying-app handoff.
-
purgeDeletedOlderThan(): verify whetherwrap(...)should emit. -
drop(): verify whetherwrap(...)should emit.