From 03e05673418d3676569183075b5a0da098577a2aa6ee2a29afac5cb6e95f1046 Mon Sep 17 00:00:00 2001 From: Tyler J King Date: Fri, 15 May 2026 15:05:03 -0400 Subject: [PATCH] docs: add CLAUDE.md for guildhall project context Covers architecture, auth flow, database schema, gRPC services, routes, schematic templates, and K8s manifests so future sessions can orient without re-discovering the codebase. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Tyler J King --- CLAUDE.md | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f5e92cf --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,130 @@ +# Guildhall — Claude Context + +## What this is + +Phoenix umbrella app — ceremony orchestrator + governance UI for the Guildhouse platform. Onboards guilds (MSP/ISV/NSP organizations), deploys founding schematics via gRPC, and manages membership with ceremony-engine approval flows. + +## Architecture + +``` +guildhall/ +├── apps/ +│ ├── guildhall_ops_db — Ecto schemas + contexts (Postgres) +│ ├── guildhall_orchestrator — gRPC clients, GenServers, template engine +│ ├── guildhall_web — Phoenix LiveView UI + OIDC auth +│ ├── guildhall_chronicle — Chronicle event consumer (stub) +│ └── guildhall_graph_bridge — Microsoft Graph reconciler (stub) +├── config/ — dev.exs, runtime.exs (env-var driven) +└── k8s/ — Kubernetes manifests (00-93, numeric order) +``` + +## External services (gRPC) + +| Service | Port | Proto | Client module | +|---------|------|-------|---------------| +| ceremony-service (Rust) | 50053 | `ceremony.v1.CeremonyService` | `Guildhall.Orchestrator.CeremonyClient` | +| ffc-schematic-server (Rust) | 9091 | `schematic.v1.SchematicsService` + `FfcSchematicService` | `Guildhall.Orchestrator.SchematicClient` | + +Env vars: `CEREMONY_SERVICE_URL`, `SCHEMATIC_SERVICE_URL`, `FFC_SCHEMATIC_SERVICE_URL`. In-cluster DNS: `.guildhall.svc.cluster.local:`. + +## Auth + +Keycloak OIDC at `auth.guildhouse.dev/realms/guildhouse`, client `guildhall-web`. Env vars: `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`, `OIDC_REDIRECT_URI`. + +- `GuildhallWeb.Plugs.Auth` — `fetch_current_user/2` plug (reads session) +- `GuildhallWeb.AuthController` — login/callback/logout controller +- `GuildhallWeb.AuthHooks` — LiveView `on_mount(:require_auth)` +- User stored in session as map: `%{"did" => "did:web:...", "email" => ..., "name" => ..., "sub" => ..., "preferred_username" => ...}` +- DID format: `did:web:guildhouse.dev:user:` +- Hub operator DID: `did:web:guildhouse.dev:user:tking` + +## Database tables (guildhall_ops_db) + +Pre-existing: `governed_artifacts`, `deployment_states`, `verification_results` + +New guild tables: +- **guilds** — `guild_id` (10-bit, 0x010–0x3FF), `slug`, `guild_type` (msp/isv/nsp), `status` (pending_approval/approved/denied/active/suspended), `registration_ceremony_id`, `trust_domain`, `registrant_did`, `contact_did` +- **guild_schematics** — FK to guilds, `template_name`, `schematic_name`, `schematic_version`, `realization_id`, `status` (pending/forked/binding_created/realizing/realized/failed), `realization_snapshot` (map) +- **guild_memberships** — FK to guilds, `user_did`, `role` (apprentice/journeyman/master), `status` (pending/approved/denied/active/suspended/removed), `membership_ceremony_id`, unique on (guild_id, user_did) + +## Key flows + +### Guild registration +1. User fills form at `/guilds/register` → creates guild row (status: pending_approval) + ceremony via `CeremonyClient.create_guild_registration_ceremony` +2. Hub operator (tking) sees pending guild at `/guilds/:slug`, clicks Approve → `CeremonyClient.approve_ceremony` + `Guilds.approve_guild/1` (Ecto.Multi: updates guild to "approved" + creates registrant as guild master) + +### Schematic deployment +1. Guild master visits `/guilds/:slug/schematic` → loads TOML template for guild type from `priv/schematic_templates/` +2. Click Deploy → `SchematicClient.fork_schematic` → `create_deployment_binding` → `realize_ffc_schematic` +3. Creates `guild_schematics` row, starts `RealizationPoller.watch/2` +4. `/guilds/:slug/realization` shows 7 reconciler sections via PubSub live updates + +### Member onboarding +1. User visits `/guilds/:slug/join` → creates membership (pending) + ceremony for guild master approval +2. Guild master at `/guilds/:slug/members` → approve/deny via ceremony engine, manage roles + +## Routes + +All guild routes are under authenticated `live_session :authenticated`: +``` +/ DashboardLive +/guilds GuildLive.Index +/guilds/register GuildLive.Register +/guilds/:slug GuildLive.Show +/guilds/:slug/schematic GuildLive.Schematic +/guilds/:slug/realization GuildLive.Realization +/guilds/:slug/join GuildLive.Join +/guilds/:slug/members GuildLive.Members +/ceremonies CeremonyLive.Index +/artifacts ArtifactLive.Index +``` + +Public: `/auth/login`, `/auth/callback`, `/auth/logout`, `/health` + +## Orchestrator supervision tree + +- `Guildhall.Orchestrator.CeremonyOrchestrator` — existing ceremony workflow coordinator +- `Guildhall.Orchestrator.RealizationPoller` — GenServer, polls realization status every 5s for watched IDs, broadcasts on `"realization:#{guild_slug}"` PubSub topic + +## Schematic templates + +TOML files in `apps/guildhall_orchestrator/priv/schematic_templates/`: +- `msp-founding.toml` — attestation tier 2, MFA, single_approval +- `isv-founding.toml` — attestation tier 1, no MFA, single_approval +- `nsp-founding.toml` — attestation tier 3, MFA + hardware, multi_party quorum 2 + +`SchematicTemplate.render_template/2` substitutes `{{guild_slug}}`, `{{guild_name}}`, `{{trust_domain}}`, `{{registrant_did}}`. + +## Generated protobuf modules + +In `apps/guildhall_orchestrator/lib/guildhall/orchestrator/proto/`: +- `ceremony/v1/ceremony.pb.ex` — `Ceremony.V1.CeremonyService.Stub` +- `schematic/v1/schematics.pb.ex` — `Schematic.V1.SchematicsService.Stub` +- `schematic/v1/ffc_schematic.pb.ex` — `Schematic.V1.FfcSchematicService.Stub` + +These were generated with `protoc --elixir_out=plugins=grpc`. Re-generate if protos change. + +## K8s manifests + +Files in `k8s/` applied in numeric order. Key additions: +- `90-ceremony-service-deployment.yaml` + `91-*-service.yaml` — ClusterIP on 50053 +- `92-schematic-server-deployment.yaml` + `93-*-service.yaml` — ClusterIP on 9091 +- `70-guildhall-deployment.yaml` — includes OIDC + gRPC env vars +- Secrets created imperatively (see `50-guildhall-secrets-template.yaml`) + +## Commands + +```bash +mix deps.get # fetch deps +mix ecto.migrate # run migrations +mix compile # verify compilation +mix phx.server # start dev server (localhost:4000) +mix test # run tests +``` + +## Commit convention + +Sign commits as `tking@guildhouse.dev`: +```bash +git -c user.email=tking@guildhouse.dev commit -s -m "message" +```