d8a5164f
feat(webhooks): fire on proposal open/merge/reject (Phase 5a)
The firing half — proposal lifecycle events now deliver GraphQL-native webhooks. Verified end to end against a live daemon: an agent REST propose delivers a signed POST whose body is the subscription's stored query executed against the ProposalEvent payload. - service: an EventSink seam (service/events.go). Propose emits PROPOSAL_OPENED for a new proposal, mergeProposal emits PROPOSAL_MERGED (the single merge point — both auto-merge and the human approve reach it), Reject emits PROPOSAL_REJECTED. Nil-safe; a Service with no sink emits nothing. - graph.NewProposalEvent builds the *model.ProposalEvent payload from a service.Proposal (reusing the existing service→graph→model mapping). - cmd webhookEventSink: proposal events happen in the service layer, which has none of core-go's request context, so the sink enqueues a dowork task onto the webhook queue. The task runs in the queue's worker context (server+database+config, from WithQueues), adds the owner's INTERNAL auth, and calls Schedule — which renders each subscriber's query and delivers it Ed25519-signed. Fire-and-forget off the write path: a webhook never blocks or fails a proposal write. Phase 5a (webhooks) is complete: DB, the authn→AuthContext bridge, the GraphQL surface, the core-go server wiring, and firing.
Eugene Blikh <bigbes@gmail.com> — 2026-07-24 09:49:46 UTC
Commit d8a5164f5f1c6ac49b056eb0cb1b9c3d9db338fd —
view raw patch
Parent(s):
021d955a
| File | Status | + | − |
|---|---|---|---|
cmd/specsrht/main.go
|
M | +6 | |
cmd/specsrht/webhooks.go
|
A | +59 | |
go.mod
|
M | +1 | -1 |
graph/webhook_event.go
|
A | +45 | |
service/events.go
|
A | +18 | |
service/events_test.go
|
A | +200 | |
service/merge.go
|
M | +14 | -2 |
service/propose.go
|
M | +8 | |
service/service.go
|
M | +15 |