# Phase 5a — GraphQL-native webhooks (proposal lifecycle) **Mode:** hands-off **Branch:** feat/phase5a-webhooks **Beads:** spec-3m9 (epic), spec-8y4 (conventions), spec-45j (webhook feature) ## Design Emit webhooks on proposal open/merge/reject, GraphQL-native, matching the core-go webhook engine used by pages.sr.ht / lists.sr.ht. spec.sr.ht keeps its own `authn` (owner/agent/anonymous + provenance) as the single auth policy — core-go's auth model has no agent concept — and a thin adapter derives the core-go `auth.AuthContext` the webhook engine consumes. Webhooks are owner-scoped (`gql_user_wh_sub`, one user = the owner); events are PROPOSAL_OPENED / PROPOSAL_MERGED / PROPOSAL_REJECTED; the agent identity that triggered an event rides in the payload (the proposal), not the auth context. Reference: /Users/blikh/data/home/tmp/pages.sr.ht (same fork). ## Plan (phases) 1. **DB foundation** — `user` table + owner seed; `webhook_event` / `auth_method` enums; `gql_user_wh_sub` + `gql_user_wh_delivery` tables. schema.sql + migrations/0003. 2. **AuthContext bridge** — an in-spec adapter mapping `authn.Principal` → core-go `auth.AuthContext` (owner→AUTH_COOKIE+UserID; agent→owner's UserID), factored to lift into a future `sr-ht-ext` module. 3. **Server + context wiring** — install core-go database + webhooks context on /query and the delivery worker; keep spec's surfaces/auth intact (no core-go 401-by-default). 4. **Webhook SDL + models + resolvers** — WebhookEvent/Subscription/Delivery/ Payload types, create/delete mutations, webhooks/webhook queries, the `webhook` payload root field; gqlgen regen. 5. **Firing** — service event hook → webhooks.Schedule on open/merge/reject. ## Conclusion ### Hands-off decisions - make: Mode hands-off (user invoked /up:handsoff). - make: dedicated branch `feat/phase5a-webhooks`; worktree skipped — session is configured for in-place work; isolation via the branch, master untouched. - udesign: keep spec's `authn` as the single auth policy; derive a core-go `auth.AuthContext` for the webhook engine only (core-go auth cannot model agents/provenance without breaking Phases 3-4). - uplan: adopt core-go's webhook ENGINE (queue/delivery/Ed25519 signing/ GraphQL-native Exec) + the pages.sr.ht schema/SDL shape; do NOT rewrite the existing read resolvers onto database.Model — only the webhook models need it. - uplan: webhooks are owner-scoped (`gql_user_wh_sub`), matching pages.sr.ht's user-scoped pattern; the single owner is the only user. ### Deferred (needs user input) - extensions-go / `sr-ht-ext` module — extracting spec's agent model into a shared module (location, name, publish target, CI wiring). User said it's "too early to judge"; building the bridge in-spec, factored for later extraction. Revisit when a second consumer exists or after this ships. - gqlgen regeneration runs `go generate ./graph` (pulls gqlgen at generate-time and rewrites graph/api/generated.go). Will run during phase 4; flagged.