guildhall/apps/guildhall_ops_db/lib/guildhall/ops_db/guild.ex
Tyler J King c0959a5376 feat(guildhall): minimum viable guildhall — OIDC, guilds, schematics, members
Implements the full founding-guild onboarding stack across four phases:

Phase A — Keycloak OIDC auth pipeline (oidcc) + guild registration with
ceremony-engine approval (SingleApproval, hub operator approves via gRPC).
Phase B — Founding schematic templates (MSP/ISV/NSP TOML), gRPC clients
for ceremony-service and ffc-schematic-server, schematic fork/bind/realize
LiveView with DB audit trail in guild_schematics.
Phase C — RealizationPoller GenServer polling realization status every 5s,
PubSub broadcast, live realization dashboard showing 7 reconciler sections.
Phase D — Self-service member onboarding (join request → guild master
approval via ceremony), member management LiveView, auto-create guild
master on guild approval via Ecto.Multi transaction.

Includes K8s manifests for ceremony-service (port 50053) and
ffc-schematic-server (port 9091) as ClusterIP services, plus updated
guildhall deployment with OIDC and gRPC service URL env vars.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Tyler J King <tking@guildhouse.dev>
2026-05-15 15:03:50 -04:00

57 lines
1.5 KiB
Elixir

defmodule Guildhall.OpsDb.Guild do
use Ecto.Schema
import Ecto.Changeset
@type t :: %__MODULE__{}
@min_guild_id 0x010
@max_guild_id 0x3FF
schema "guilds" do
field :guild_id, :integer
field :name, :string
field :slug, :string
field :guild_type, :string
field :description, :string
field :trust_domain, :string
field :contact_did, :string
field :registrant_did, :string
field :registration_ceremony_id, :string
field :status, :string, default: "pending_approval"
field :enrollment_accord_ref, :string
field :metadata, :map, default: %{}
has_many :guild_schematics, Guildhall.OpsDb.GuildSchematic
has_many :guild_memberships, Guildhall.OpsDb.GuildMembership
timestamps(type: :utc_datetime_usec)
end
def changeset(guild, attrs) do
guild
|> cast(attrs, [
:guild_id,
:name,
:slug,
:guild_type,
:description,
:trust_domain,
:contact_did,
:registrant_did,
:registration_ceremony_id,
:status,
:enrollment_accord_ref,
:metadata
])
|> validate_required([:guild_id, :name, :slug, :guild_type, :contact_did, :registrant_did])
|> validate_inclusion(:guild_type, ~w(msp isv nsp))
|> validate_inclusion(:status, ~w(pending_approval approved denied active suspended))
|> validate_number(:guild_id,
greater_than_or_equal_to: @min_guild_id,
less_than_or_equal_to: @max_guild_id
)
|> unique_constraint(:guild_id)
|> unique_constraint(:slug)
|> unique_constraint(:name)
end
end