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>
6.3 KiB
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/2plug (reads session)GuildhallWeb.AuthController— login/callback/logout controllerGuildhallWeb.AuthHooks— LiveViewon_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, 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
- User fills form at
/guilds/register→ creates guild row (status: pending_approval) + ceremony viaCeremonyClient.create_guild_registration_ceremony - 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
- Guild master visits
/guilds/:slug/schematic→ loads TOML template for guild type frompriv/schematic_templates/ - Click Deploy →
SchematicClient.fork_schematic→create_deployment_binding→realize_ffc_schematic - Creates
guild_schematicsrow, startsRealizationPoller.watch/2 /guilds/:slug/realizationshows 7 reconciler sections via PubSub live updates
Member onboarding
- User visits
/guilds/:slug/join→ creates membership (pending) + ceremony for guild master approval - 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 coordinatorGuildhall.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_approvalisv-founding.toml— attestation tier 1, no MFA, single_approvalnsp-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.Stubschematic/v1/schematics.pb.ex—Schematic.V1.SchematicsService.Stubschematic/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 5005392-schematic-server-deployment.yaml+93-*-service.yaml— ClusterIP on 909170-guildhall-deployment.yaml— includes OIDC + gRPC env vars- Secrets created imperatively (see
50-guildhall-secrets-template.yaml)
Commands
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:
git -c user.email=tking@guildhouse.dev commit -s -m "message"