No description
  • TypeScript 92.2%
  • C++ 5.6%
  • Python 2.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Meta Vens 726dd56e7d Honour the Idunn process write lease, and stop claiming active while warming
During a deployment two Heimdall processes exist at once under distinct
UIDs and namespaces, and both are configured with the same CultCache store
path. Exactly one may write it. Idunn decides which by publishing a lease
record naming an incarnation; nothing in Heimdall read it, so both
generations would have written heimdall.service.cc.

src/process-write-lease.ts answers one question -- may this process write
state right now -- by reading the lease and the runtime bundle's
expected.cc, and comparing incarnation identity. It grants nothing and
throws nothing outward: every failure is a decision of mayWrite:false with
a reason, because for a warming candidate "not yet my turn" is the
expected condition and crashing would turn it into a failed deployment.
Records are decoded as the canonical positional MessagePack Idunn writes
(14 fields for the lease, schema-checked), and the tests build the same
envelope bytes rather than convenient objects.

publishHeimdallVerseState is the single writer, so that is the only place
gated. Outside Idunn no lease path is configured and writes proceed
unconditionally, which keeps developer runs and the current plain unit
working.

Second defect found while wiring it: health publication hardcoded
state "active". A candidate would have claimed active from its first
pulse, which is both untrue and structurally broken -- Idunn must observe
`warming` presence before it fences the incumbent, so a candidate that
never reports warming cannot be promoted. State is now derived from the
lease: warming until held, active after, with the reason carried in the
detail string.

49 tests across 11 files; tsc clean under exactOptionalPropertyTypes.

The recipe's status banner now records the contract as implemented, with
the honest caveat that none of it has been through a live `idunn up` --
the daemon on yggdrasil is still the previous generation, so the first
deployment remains the real verification.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 02:25:38 +02:00
.voidbot/state Seed Heimdall social interpretation biases 2026-05-24 20:39:24 +01:00
assets Add Heimdall profile avatar 2026-05-20 18:52:21 +01:00
deployment/idunn Honour the Idunn process write lease, and stop claiming active while warming 2026-09-06 02:25:38 +02:00
docs Retire the Spotiverse profile; keep the spotify provider intact for restore 2026-09-06 01:47:10 +02:00
notes Record Odin-discovered access deployment 2026-08-22 04:08:36 +02:00
plugins/gamecult.heimdall.access Resume Heimdall auth from browser return witness 2026-08-22 11:42:28 +02:00
schemas Bind auth completions to their attempt handles 2026-08-22 12:01:56 +02:00
src Honour the Idunn process write lease, and stop claiming active while warming 2026-09-06 02:25:38 +02:00
state Record Odin-discovered access deployment 2026-08-22 04:08:36 +02:00
tests Honour the Idunn process write lease, and stop claiming active while warming 2026-09-06 02:25:38 +02:00
tools Rename repo to Heimdall 2026-04-26 11:41:27 +01:00
vendor Vendor CultLib as a gitlink so Heimdall's source can be sealed 2026-09-06 00:42:45 +02:00
.env.example Add Eve access plugin and private auth plane 2026-08-22 00:44:57 +02:00
.gitignore Ignore local secret files 2026-04-29 12:23:45 +01:00
.gitmodules Vendor CultLib as a gitlink so Heimdall's source can be sealed 2026-09-06 00:42:45 +02:00
AGENTS.md Make AGENTS.md paths repo-relative so a drive move stops rotting it 2026-09-06 01:13:19 +02:00
CLAUDE.md Drop the Codex framing from the doctrine import 2026-09-06 00:39:45 +02:00
LICENSE Add MIT license 2026-09-05 21:54:09 +02:00
package.json Vendor CultLib as a gitlink so Heimdall's source can be sealed 2026-09-06 00:42:45 +02:00
pnpm-lock.yaml Vendor CultLib as a gitlink so Heimdall's source can be sealed 2026-09-06 00:42:45 +02:00
README.md Record Odin-discovered access deployment 2026-08-22 04:08:36 +02:00
tsconfig.json Resume Heimdall auth from browser return witness 2026-08-22 11:42:28 +02:00
vitest.config.ts Limit Vitest to source test tree 2026-04-26 12:25:53 +01:00

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"

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

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.