# Heimdall Heimdall is the shared auth authority taking shape for GameCult-hosted experiments. The point is painfully simple: - stop rebuilding Discord/Patreon login glue in every app - keep provider OAuth, linked identities, grants, entitlements, and session issuance in one place - let app runtimes verify signed claims locally so "shared auth" does not become "everything phones home for every request" - keep app-domain data separate so "shared auth" does not become "shared swamp" ## Front Door - **Value:** one shared auth authority: provider OAuth (Discord, Patreon, GitHub, Twitch, YouTube, Spotify), linked identities, grants, entitlements and session issuance, with Ed25519-signed claims that app backends verify locally. - **Problem:** every GameCult app was rebuilding Discord/Patreon login glue. Heimdall centralizes identity authority and keeps app-domain data in the apps. - **Entry points:** - `src/index.ts` and `src/app.ts`: the Fastify service. `src/signing.ts` and `src/claims.ts` issue JWTs and serve `/.well-known/jwks.json`; `src/oauth.ts` and `src/providers.ts` own provider flows. - `src/verifier.ts`: the local verifier helper an app backend imports to validate Heimdall JWTs without phoning home. - `src/odin-publication.ts` and `plugins/gamecult.heimdall.access`: the redacted Odin/Eve provider advertisement and the `gamecult.heimdall.access` plugin (`docs/eve-access-plugin.md`). - `docs/architecture.md`, `docs/service-contract.md`, `docs/verse-service-contract.md`, `docs/app-profiles/`: the contracts. - `pnpm install`, `pnpm dev`, `pnpm test` (see Dev Commands). - **Live:** a stateful first slice: signing and JWKS, OAuth state for six providers, in-memory and Postgres stores, a real Discord callback path for the Repixelizer flow, sealed provider tokens, the loopback CultNet operation boundary, Idunn health publication, and the deployed Ghostlight Eve host consuming the discovered boundary. - **Planned:** the two-account and eight-account Ghostlight human canaries, refresh and revocation flows, admin surfaces, and broader inspection projections beyond the redacted access boundary. ## Current Shape This repo now has a stateful first slice instead of a decorative skeleton. Landed right now: - a TypeScript/Fastify service scaffold under `src/` - Ed25519 JWT signing plus `/.well-known/jwks.json` - file-backed signing-key loading/bootstrap so restart does not vaporize the service identity when you configure a real key path - signed OAuth start-state scaffolding for Discord, Patreon, GitHub, Twitch, YouTube, and Spotify - durable auth/control-plane storage with in-memory and Postgres backends - account, linked-identity, session, persistent OAuth attempt, grant, entitlement snapshot, and audit persistence - a real Discord OAuth callback path for the first Repixelizer access flow - direct backend callback handoff for same-host or Yggdrasil-reachable app backends - AES-256-GCM sealing for managed provider tokens at rest - a one-time browser completion exchange kept as fallback for opener `postMessage` handoff - app profile surfaces for Repixelizer, StreamPixels, and Spotiverse - signed claim issuance for app-local verification experiments - a local verifier helper in `src/verifier.ts` so app backends can validate Heimdall JWTs without phoning home on every guarded request - a read-only Odin/Eve provider advertisement export that names redacted CultCache witness document shapes and paths without touching live secrets - a daemon-owned CultCache boundary witness at `GC_ACCESS_CULTCACHE_PATH` containing the Heimdall provider advertisement, command boundary, transport profile, and Idunn daemon-health summary - optional Idunn daemon-health publication over `cultnet.transport.rudp.v0` when `GC_ACCESS_IDUNN_RUDP_HEALTH` is configured - the `gamecult.heimdall.access` Eve plugin with executable `describe`, `validate`, and `project` operations plus a browser reference adapter - a loopback-only CultNet operation boundary on port `4101` for authenticated `heimdall.auth.begin` and `heimdall.auth.complete`; app payloads and completion claims are AES-256-GCM wrapped and HMAC-bound to expiry, nonce, operation, runtime, and idempotency identity - redacted provider, command-boundary, plugin, and transport records published through Odin under unique typed catalog keys; secret-bearing auth state never enters the catalog - the deployed Ghostlight Eve host consumes that discovered boundary and keeps routine app-session verification local Remaining work: - the two-account and eight-account Ghostlight human canaries - refresh/revocation flows and admin surfaces - broader admin and inspection projections beyond the redacted access boundary Canonical docs: - `docs/architecture.md` - `docs/implementation-plan.md` - `docs/service-contract.md` - `docs/verse-service-contract.md` - `docs/app-profiles/repixelizer.md` - `docs/app-profiles/streampixels.md` - `docs/app-profiles/spotiverse.md` - `state/map.yaml` - `notes/fresh-workspace-handoff.md` ## Dev Commands ```powershell pnpm install pnpm dev pnpm test pnpm build pnpm export:provider-advertisement ``` ## Working Loop 1. Rehydrate from canonical state. 2. Keep identity authority central and app-domain data local. 3. Prefer a Yggdrasil-hosted shared service over duplicated per-app provider stacks. 4. Let app backends verify signed claims locally instead of begging Heimdall on every guarded route. 5. Commit finished passes before the notes start breeding.