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 <noreply@anthropic.com>
Signed-off-by: Tyler J King <tking@guildhouse.dev>
This commit is contained in:
Tyler J King 2026-05-15 15:05:03 -04:00
parent c0959a5376
commit 03e0567341

130
CLAUDE.md Normal file
View file

@ -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: `<name>.guildhall.svc.cluster.local:<port>`.
## 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:<preferred_username>`
- 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, 0x0100x3FF), `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"
```