2026-04-26 05:18:35 +01:00
|
|
|
# Fresh Workspace Handoff
|
|
|
|
|
|
2026-10-19 10:44:24 +02:00
|
|
|
This is the re-entry packet for this repo (path: whatever the checkout is; it has moved drives before).
|
2026-04-26 05:18:35 +01:00
|
|
|
|
|
|
|
|
It is intentionally short. Historical proof belongs in git history and the
|
|
|
|
|
distilled `state/evidence.jsonl` ledger; the shared architecture belongs in
|
|
|
|
|
`docs/architecture.md`; the forward build order belongs in
|
|
|
|
|
`docs/implementation-plan.md`.
|
|
|
|
|
|
|
|
|
|
## Rehydrate
|
|
|
|
|
|
|
|
|
|
From the repo root:
|
|
|
|
|
|
|
|
|
|
```powershell
|
2026-10-19 10:44:29 +02:00
|
|
|
python .\tools\heimdall_state.py status
|
2026-04-26 05:18:35 +01:00
|
|
|
Get-Content '.\state\map.yaml'
|
|
|
|
|
Get-Content '.\notes\fresh-workspace-handoff.md'
|
|
|
|
|
Get-Content '.\docs\architecture.md'
|
|
|
|
|
Get-Content '.\docs\implementation-plan.md'
|
|
|
|
|
git status --short --branch
|
|
|
|
|
git log --oneline -5
|
|
|
|
|
Get-Content '.\state\evidence.jsonl' -Tail 8
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Do not trust this file for the exact live HEAD. Always check git.
|
|
|
|
|
|
2026-10-19 10:44:24 +02:00
|
|
|
## Active Work
|
|
|
|
|
|
2026-10-19 17:56:25 +02:00
|
|
|
Joystick H1 is merged and live (PR GameCult/Heimdall#1; campaign
|
2026-10-19 18:03:17 +02:00
|
|
|
`joystick:campaign:self`). Next: `joystick:follow_up:h1-joystick-consent-round-trip`, then
|
2026-10-19 17:56:25 +02:00
|
|
|
StreamPixels S0/S1 (other sessions). Open Heimdall follow-ups, by id:
|
|
|
|
|
`joystick:follow_up:cross-process-failed-refresh-marker`,
|
|
|
|
|
`joystick:follow_up:connect-start-needs-app-auth`,
|
|
|
|
|
`joystick:follow_up:heimdall-idunn-onboarding`,
|
|
|
|
|
`joystick:follow_up:joystick-viewer-signin-public-bot`. The Ghostlight KLTST
|
|
|
|
|
canaries below stay open, behind them.
|
2026-10-19 10:44:24 +02:00
|
|
|
|
2026-04-26 05:18:35 +01:00
|
|
|
## Current Orientation
|
|
|
|
|
|
2026-10-19 17:56:25 +02:00
|
|
|
Yggdrasil runs Heimdall `d51fa6b`, hand-deployed 2026-10-19 15:51Z;
|
|
|
|
|
gamecult-ops `210a1af` records backup, rollback and provenance. Facts below
|
|
|
|
|
about Odin, Ghostlight and CultLib pins were verified at `1086aee` (2026-08-22)
|
|
|
|
|
and are not re-verified at `d51fa6b`.
|
2026-10-19 10:44:24 +02:00
|
|
|
|
2026-10-19 17:56:25 +02:00
|
|
|
- At `1086aee01169bf60e8a492b2740db1c6f3e8cabf` Heimdall ran with CultLib
|
2026-08-22 04:08:36 +02:00
|
|
|
`5cefa0db0079a8e3ee22f29d7b9e6e5aa60912a9`
|
|
|
|
|
- Heimdall publishes four redacted access records to Odin under unique keys:
|
|
|
|
|
`eve:provider:heimdall`, `heimdall:command-boundary`,
|
|
|
|
|
`eve:plugin:gamecult.heimdall.access`, and `heimdall:transport-profile`
|
|
|
|
|
- Odin `b4f9a2e95f0b41cebdeddc49223781d1d3c7b42a` persists and returns all four;
|
|
|
|
|
it does not proxy private commands or receive claims
|
|
|
|
|
- Ghostlight `b515ca90c25573005a616244143803b37f2d06ec` resolves the boundary through
|
|
|
|
|
Odin and accepted a live canonical anonymous `heimdall.auth.begin`; its unit
|
|
|
|
|
has no direct Heimdall endpoint
|
|
|
|
|
|
2026-08-22 00:44:57 +02:00
|
|
|
- `gamecult.heimdall.access` now has a manifest, advertisement, schemas,
|
|
|
|
|
fixtures, executable `describe`/`validate`/`project` ABI, and browser
|
|
|
|
|
reference adapter
|
|
|
|
|
- Heimdall persists OAuth attempts and serves authenticated
|
2026-08-22 01:53:21 +02:00
|
|
|
`heimdall.auth.begin` / `heimdall.auth.complete` / `heimdall.auth.refresh` /
|
|
|
|
|
`heimdall.auth.logout` through loopback
|
2026-08-22 00:44:57 +02:00
|
|
|
CultNet/RUDP on port `4101`
|
|
|
|
|
- private commands are source-runtime, app-secret, expiry, nonce, and
|
|
|
|
|
idempotency bound; their MessagePack payloads and completion claims are
|
|
|
|
|
AES-256-GCM wrapped
|
|
|
|
|
- the Ghostlight app profile now requires its caller-owned Discord role policy;
|
|
|
|
|
Heimdall evaluates it and Ghostlight remains owner of local sessions,
|
|
|
|
|
memberships, and campaigns
|
2026-08-22 01:53:21 +02:00
|
|
|
- refresh verifies the exact persisted session revision before reissuing a
|
|
|
|
|
claim; logout expires that session and advances its revision, so a stale or
|
|
|
|
|
racing refresh cannot resurrect revoked custody
|
2026-08-22 00:44:57 +02:00
|
|
|
|
2026-04-26 12:50:07 +01:00
|
|
|
- this repo now has a first stateful Heimdall service slice
|
2026-04-26 05:18:35 +01:00
|
|
|
- the canonical shared architecture lives in `docs/architecture.md`
|
2026-04-26 12:25:11 +01:00
|
|
|
- the concrete HTTP/JWKS contract lives in `docs/service-contract.md`
|
2026-04-26 05:18:35 +01:00
|
|
|
- app profiles live under `docs/app-profiles/`
|
|
|
|
|
- the key boundary is explicit:
|
2026-04-26 12:25:11 +01:00
|
|
|
- Heimdall owns OAuth, linking, managed provider credential custody, grants,
|
|
|
|
|
entitlement refresh, and signed claim issuance
|
2026-04-26 05:18:35 +01:00
|
|
|
- app-domain data stays app-owned by default
|
2026-04-26 11:41:27 +01:00
|
|
|
- host apps verify signed claims locally for routine auth instead of calling
|
|
|
|
|
Heimdall on every request
|
2026-04-26 12:50:07 +01:00
|
|
|
- the landed service now exposes:
|
2026-04-26 12:25:11 +01:00
|
|
|
- `/.well-known/jwks.json`
|
|
|
|
|
- `/.well-known/heimdall-configuration`
|
|
|
|
|
- `/v1/oauth/{provider}/start`
|
|
|
|
|
- `/v1/oauth/{provider}/callback`
|
2026-04-26 15:23:04 +01:00
|
|
|
- `/v1/apps/{appSlug}/auth-completions/redeem`
|
2026-05-20 13:43:53 +01:00
|
|
|
- `/v1/apps/{appSlug}/sessions/refresh`
|
2026-04-29 15:00:55 +01:00
|
|
|
- `/v1/apps/{appSlug}/managed-credentials/resolve`
|
2026-04-26 12:50:07 +01:00
|
|
|
- the Discord callback path now performs real code exchange, identity
|
|
|
|
|
resolution, auth persistence, entitlement evaluation, audit logging, and
|
|
|
|
|
claim issuance for the Repixelizer slice
|
2026-04-26 15:23:04 +01:00
|
|
|
- browser-style auth handoff now uses a one-time completion code posted back to
|
|
|
|
|
the opener, with backend redemption instead of fragment-token handoff
|
2026-04-26 17:00:57 +01:00
|
|
|
- same-host or Yggdrasil-reachable app integrations can now ask Heimdall to
|
|
|
|
|
deliver the auth result directly to an app backend callback endpoint, leaving
|
|
|
|
|
the browser with only status/attempt signaling
|
2026-04-26 16:23:29 +01:00
|
|
|
- signing keys can now load from a persisted file path and bootstrap that file
|
|
|
|
|
on first boot when explicitly enabled
|
|
|
|
|
- managed provider tokens are now sealed at rest with AES-256-GCM instead of
|
|
|
|
|
being dumped into "encrypted" columns raw like an insult
|
|
|
|
|
- `src/verifier.ts` now provides a small local JWT verifier seam for app
|
|
|
|
|
backends
|
2026-04-29 11:51:29 +01:00
|
|
|
- Repixelizer has consumed the backend-callback flow in its hosted web layer:
|
|
|
|
|
it creates local auth attempts, asks Heimdall to start OAuth, receives the
|
|
|
|
|
direct backend callback, verifies Heimdall Ed25519 access tokens locally, and
|
|
|
|
|
adopts httpOnly local sessions
|
2026-04-29 12:41:43 +01:00
|
|
|
- Heimdall is now deployed on Yggdrasil at `https://heimdall.gamecult.org`
|
|
|
|
|
behind nginx/TLS with Postgres storage, file-backed signing-key bootstrap,
|
|
|
|
|
configured token custody, and public health/discovery/JWKS checks passing
|
|
|
|
|
- Repixelizer is now deployed on Yggdrasil at
|
2026-04-29 14:39:11 +01:00
|
|
|
`https://repixelizer.gamecult.org` with Heimdall mode enabled, Discord and
|
|
|
|
|
Patreon as public providers, required access enabled, and queue protection
|
|
|
|
|
enabled
|
|
|
|
|
- Repixelizer public auth-start returns Discord and Patreon authorization URLs
|
|
|
|
|
using the Heimdall callback and Repixelizer backend handoff
|
2026-05-20 13:43:53 +01:00
|
|
|
- Repixelizer auth now has a refresh path: Heimdall issues signed refresh
|
|
|
|
|
tokens with access claims, `/v1/apps/{appSlug}/sessions/refresh` reissues
|
|
|
|
|
short-lived access claims, and Discord/Patreon provider tokens refresh inside
|
|
|
|
|
Heimdall before entitlement re-evaluation
|
2026-04-29 15:00:55 +01:00
|
|
|
- Twitch and YouTube now have generic OAuth exchange and identity runtimes
|
|
|
|
|
- GitHub is still catalogued, but its callback runtime is not implemented
|
|
|
|
|
- StreamPixels now delegates viewer and creator Twitch/YouTube OAuth to
|
|
|
|
|
Heimdall, redeems Heimdall completion codes server-side, writes its own
|
|
|
|
|
viewer sessions and connector bindings, and resolves current provider access
|
|
|
|
|
tokens from Heimdall without storing refresh tokens locally
|
2026-06-02 16:25:38 +01:00
|
|
|
- Spotiverse now delegates Spotify OAuth to Heimdall. Heimdall has a
|
|
|
|
|
`spotiverse` app profile and `spotify` provider runtime; Spotiverse stores a
|
|
|
|
|
local Heimdall account binding and resolves current Spotify access through
|
|
|
|
|
`/v1/apps/spotiverse/managed-credentials/resolve` without storing provider
|
|
|
|
|
refresh tokens.
|
2026-06-08 21:04:51 +01:00
|
|
|
- Bifrost now has a `bifrost` app profile for Discord/Patreon member access.
|
|
|
|
|
Bifrost sends caller-owned KTLST Discord role and Patreon tier policies
|
|
|
|
|
through trusted backend-callback OAuth starts; Heimdall owns provider
|
|
|
|
|
OAuth/token custody and configured backend callback allowlisting.
|
2026-06-09 20:22:58 +01:00
|
|
|
- Bifrost patron support sync now reuses Heimdall's existing linked Patreon
|
|
|
|
|
identity and membership reader. `POST /v1/apps/bifrost/patron-support/sync`
|
|
|
|
|
is app-authenticated, refreshes the stored Patreon credential if needed,
|
|
|
|
|
reads active paid Patreon tier evidence, and emits a signed
|
|
|
|
|
`RecurringSupportSnapshot` to Bifrost's
|
|
|
|
|
`/heimdall/patron-support/events` intake.
|
2026-06-02 19:37:06 +01:00
|
|
|
- Public Yggdrasil Heimdall has been deployed with the Spotiverse/Spotify code
|
|
|
|
|
path, Spotify provider credentials, a Spotiverse shared secret, and an
|
|
|
|
|
allowlisted loopback portal callback at
|
|
|
|
|
`http://127.0.0.1:18796/auth/heimdall/callback`.
|
2026-04-29 16:23:21 +01:00
|
|
|
- Heimdall and StreamPixels are deployed on Yggdrasil for the StreamPixels
|
|
|
|
|
migration slice; Twitch callback handling has been patched so provider token
|
|
|
|
|
`scope` can be either a space-delimited string or an array
|
2026-04-29 16:25:35 +01:00
|
|
|
- live StreamPixels Twitch sign-in through Heimdall has succeeded on Yggdrasil
|
|
|
|
|
and Heimdall audit showed callback success, completion creation, and
|
|
|
|
|
completion redemption
|
2026-04-29 15:18:25 +01:00
|
|
|
- the ignored local `secrets/heimdall-service.env` artifact now has
|
|
|
|
|
`GC_ACCESS_PROVIDER_TWITCH_*` and `GC_ACCESS_PROVIDER_YOUTUBE_*` populated
|
|
|
|
|
for the StreamPixels migration slice
|
2026-04-26 11:41:27 +01:00
|
|
|
- the intended first deployment shape is a Heimdall service on Yggdrasil behind
|
|
|
|
|
nginx, not an embedded cross-runtime shared library fantasy
|
2026-06-16 18:01:07 +01:00
|
|
|
- Heimdall now writes a daemon-owned boundary witness store at
|
|
|
|
|
`GC_ACCESS_CULTCACHE_PATH` containing provider advertisement, command
|
|
|
|
|
boundary, transport profile, and daemon-health summary state
|
|
|
|
|
- Heimdall can now publish `heimdall.cultnet-rudp-provider-health` to Idunn
|
|
|
|
|
over `cultnet.transport.rudp.v0` when `GC_ACCESS_IDUNN_RUDP_HEALTH` is
|
|
|
|
|
configured; HTTP `/healthz`, JWKS, discovery, systemd, and nginx routing
|
|
|
|
|
remain compatibility witnesses
|
2026-10-19 17:56:25 +02:00
|
|
|
- Since `1086aee` Heimdall persists its private
|
2026-08-20 20:27:25 +02:00
|
|
|
provider-health identity at `/srv/heimdall/keys/provider-health-identity.cc`
|
|
|
|
|
and publishes canonical signed health independently of the slower Verse
|
|
|
|
|
snapshot cadence. Idunn owns the exact root trust binding, authenticated
|
|
|
|
|
admission, lifecycle decision, and redacted public `.cc` projection.
|
2026-08-22 04:08:36 +02:00
|
|
|
- Odin commit `b4f9a2e95f0b41cebdeddc49223781d1d3c7b42a` retains the RUDP health
|
|
|
|
|
reliability cut and registers Heimdall's command-boundary, plugin, and
|
|
|
|
|
transport schemas so the typed catalog can persist rather than silently drop
|
|
|
|
|
them. Live proof returned all four exact Heimdall records.
|
2026-04-26 05:18:35 +01:00
|
|
|
|
|
|
|
|
## Critical Doctrine
|
|
|
|
|
|
|
|
|
|
- Persistent state is the agent's mind.
|
|
|
|
|
- Cut stale architecture notes as ruthlessly as stale code.
|
|
|
|
|
- Do not mistake "shared auth" for "shared database."
|
2026-04-26 11:41:27 +01:00
|
|
|
- Do not mistake "shared auth service" for "every guarded route must call the
|
|
|
|
|
mothership."
|
2026-04-26 05:18:35 +01:00
|
|
|
- If compaction hits before boundary findings are persisted, that work is gone.
|
|
|
|
|
Re-gather it instead of pretending continuity happened.
|
|
|
|
|
|
|
|
|
|
## Next Real Move
|
|
|
|
|
|
2026-10-19 17:56:25 +02:00
|
|
|
The Active Work follow-ups first. Everything below is the standing queue.
|
2026-10-19 10:44:24 +02:00
|
|
|
|
2026-04-26 05:18:35 +01:00
|
|
|
Do not continue implementation automatically from a rehydrate-only request.
|
|
|
|
|
|
2026-08-20 20:27:25 +02:00
|
|
|
The Idunn/swarm health transport cut is live. Do not regress Heimdall to
|
|
|
|
|
unsigned `idunn.daemon_health`, merge its private key into Idunn, or make HTTP
|
|
|
|
|
health an authority. The next product work is the Bifrost and remaining browser
|
|
|
|
|
verification listed below.
|
2026-06-16 18:01:07 +01:00
|
|
|
|
2026-08-22 04:08:36 +02:00
|
|
|
The active Ghostlight deployment cut is complete. The next Ghostlight work is a
|
|
|
|
|
real separate-account KLTST completion/refresh/logout canary, followed by the
|
|
|
|
|
eight-account Session Zero privacy and actor-binding smoke. Keep port `4101`
|
|
|
|
|
loopback-only and treat any claim, token, completion, app secret, or account
|
|
|
|
|
state in Odin/CultMesh/browser output as a release-blocking fault.
|
2026-08-22 00:44:57 +02:00
|
|
|
|
2026-06-02 19:37:06 +01:00
|
|
|
If the user asks to continue on Spotiverse, the current next move is the real
|
|
|
|
|
browser `/auth/login` flow through public Heimdall. The Yggdrasil SSH tunnel
|
|
|
|
|
must include reverse forward
|
|
|
|
|
`spotiverse-callback:18796:127.0.0.1:8796`, and local Spotiverse must point at
|
|
|
|
|
`https://heimdall.gamecult.org` with the matching `HEIMDALL_APP_SECRET`. Verify
|
|
|
|
|
managed credential resolution after login. Spotiverse should not regain local
|
|
|
|
|
Spotify OAuth token storage.
|
2026-06-02 16:25:38 +01:00
|
|
|
|
2026-04-29 16:23:21 +01:00
|
|
|
If the user asks to continue on StreamPixels, the current next move is real
|
|
|
|
|
browser verification:
|
2026-04-29 15:00:55 +01:00
|
|
|
|
2026-04-29 16:23:21 +01:00
|
|
|
- verify viewer claim/link through `https://streampixels.gamecult.org/auth/connect`
|
2026-04-29 16:25:35 +01:00
|
|
|
- Twitch viewer sign-in has already passed once; continue with YouTube and
|
|
|
|
|
connector attachment verification
|
2026-04-29 15:00:55 +01:00
|
|
|
- verify creator connector attach from an admin creator session
|
|
|
|
|
- confirm StreamPixels persists local profile/connector binding state while
|
|
|
|
|
Heimdall retains provider token custody
|
2026-04-29 16:23:21 +01:00
|
|
|
- if a provider callback fails, inspect Heimdall audit events and StreamPixels
|
|
|
|
|
service logs before touching app/domain boundaries
|
2026-04-29 15:00:55 +01:00
|
|
|
|
|
|
|
|
Repixelizer still needs its real browser OAuth verification:
|
2026-04-29 12:41:43 +01:00
|
|
|
|
|
|
|
|
- open `https://repixelizer.gamecult.org/app/`
|
2026-04-29 13:07:44 +01:00
|
|
|
- start Discord sign-in with an account that has the `KLTST` or
|
2026-04-29 14:39:11 +01:00
|
|
|
Patreon-synced `Inner Sanctum` role, or Patreon sign-in with a currently
|
|
|
|
|
entitled tier titled `Inner Sanctum`
|
|
|
|
|
- confirm Repixelizer sends its app-owned provider policy in the
|
2026-04-29 13:22:01 +01:00
|
|
|
backend-callback OAuth start
|
2026-04-29 14:39:11 +01:00
|
|
|
- confirm Heimdall receives the provider callback and evaluates entitlement
|
2026-04-29 12:41:43 +01:00
|
|
|
- confirm Repixelizer receives the backend callback, verifies the Heimdall
|
|
|
|
|
token, adopts a local httpOnly session, and gates hosted/queue routes
|
|
|
|
|
- confirm the Discord authorization URL requests only `identify
|
|
|
|
|
guilds.members.read`
|
2026-04-29 11:51:29 +01:00
|
|
|
|
2026-04-29 11:54:01 +01:00
|
|
|
Launch policy is role-gated on purpose: the GameCult Discord can remain public,
|
2026-04-29 13:07:44 +01:00
|
|
|
but Repixelizer access is limited to members with either `KLTST` or the
|
2026-04-29 13:22:01 +01:00
|
|
|
Patreon-synced `Inner Sanctum` role. Repixelizer owns that role policy through
|
|
|
|
|
its own runtime env and sends it to Heimdall during backend-callback OAuth
|
|
|
|
|
start; Heimdall owns provider OAuth mechanics and claim issuance, not the
|
|
|
|
|
per-app role list.
|
2026-04-26 05:18:35 +01:00
|
|
|
|
2026-04-29 14:39:11 +01:00
|
|
|
Patreon access is title-gated on the currently entitled tier title
|
|
|
|
|
`Inner Sanctum`; do not use currency amount as the durable policy because
|
|
|
|
|
currencies are weird little traps.
|
|
|
|
|
|
2026-06-08 21:04:51 +01:00
|
|
|
Bifrost needs browser verification after deployment:
|
|
|
|
|
|
|
|
|
|
- configure Heimdall with
|
|
|
|
|
`GC_ACCESS_APP_BIFROST_BACKEND_CALLBACK_URLS=https://bifrost.gamecult.org/auth/heimdall/callback`
|
2026-09-30 14:40:21 +02:00
|
|
|
- configure Heimdall with `GC_ACCESS_APP_BIFROST_SHARED_SECRET_FILE`,
|
2026-06-09 20:22:58 +01:00
|
|
|
`GC_ACCESS_BIFROST_PATRON_SUPPORT_ENDPOINT=https://bifrost.gamecult.org/heimdall/patron-support/events`,
|
2026-09-30 14:40:21 +02:00
|
|
|
and `GC_ACCESS_BIFROST_PATRON_SUPPORT_SECRET_FILE`, each naming a credential
|
|
|
|
|
file
|
2026-06-08 21:04:51 +01:00
|
|
|
- configure Bifrost with `Heimdall__DiscordGuildId`,
|
|
|
|
|
`Heimdall__DiscordAllowedRoleIds__0=<KTLST-role-id>`, and
|
|
|
|
|
`Heimdall__PatreonTierTitle=Inner Sanctum`
|
2026-06-09 20:22:58 +01:00
|
|
|
- configure Bifrost with the matching `Heimdall__PatronSupportIntakeSecret`
|
2026-06-08 21:04:51 +01:00
|
|
|
- start Discord sign-in from `https://bifrost.gamecult.org/` with a user that
|
|
|
|
|
has the KTLST cult-member role
|
|
|
|
|
- start Patreon sign-in with a user that has the configured active tier
|
|
|
|
|
- confirm Bifrost creates/updates a local account and active standard
|
|
|
|
|
membership while Heimdall keeps provider token custody
|
2026-06-09 20:22:58 +01:00
|
|
|
- trigger `/v1/apps/bifrost/patron-support/sync` for that linked Heimdall
|
|
|
|
|
account and confirm Bifrost records a Patreon recurring-support snapshot
|
|
|
|
|
without owning Patreon webhook or token custody
|
2026-06-08 21:04:51 +01:00
|
|
|
|
2026-04-26 05:18:35 +01:00
|
|
|
## Immediate Re-entry Instruction
|
|
|
|
|
|
|
|
|
|
After compaction, first rehydrate and reorient from the listed files and git
|
|
|
|
|
state. Wait for the user's next instruction unless they explicitly say to
|
|
|
|
|
continue.
|