Fix #363: org-level webhooks #372

Merged
crueber merged 1 commit from fix/issue-363 into main 2026-09-12 12:41:50 +00:00
Owner

Org-scoped webhooks fanning out across member repos plus the org membership/team/invite log (docs/features/06 §1.5/§5.4).

What:

  • Owner-gated CRUD: POST/GET /api/v1/orgs/{org}/webhooks (+/{id}, /ping, /deliveries) on both lanes; 401 anon, 403 non-owner, 404 unknown ids; secrets write-only (secret_set).
  • Fan-out: per-hook org-log cursor + per-(hook, member repo) cursors over member collab-activity logs; reuses postEvent verbatim (keepers, HMAC-SHA256, 10s lane); 256/scope/pass, FanoutParallel hooks.
  • Org log: member_added/removed/role_changed, team_created/deleted/member added/removed, invite_created/accepted/cancelled — emitted post-commit via nil-safe identity OrgEvent seam (composition-wired); DeleteOrgInvite added so owner-cancel emits too.
  • Caps mirror repo limits (MaxHooks/org, 409); minute org sweep gated (hooks LIST + org-state GET; member collab_state probes only for orgs with active hooks); retention folds org cursors into the compaction floor.
  • SDK: client.orgs.webhooks (API+SDK only; no org-settings hooks tab — deferred, noted in 06 out-of-scope).
  • No new dependencies.

Out of scope (documented): git pushes stay on the events-bridge TOML sinks; repo creation surfaces via first activity (no synthetic record).

Tests: internal/notify 95.6% / internal/identity 96.4% (≥95 gate), -race clean; table-driven CRUD/gating/validation/caps/fan-out+HMAC/filter/failure-pending/sweep-gate/retention-floor; e2e collab chain passes. Pre-existing failures only: TestUIAssetConcepts (fails on pristine main too) and missing web/dist in fresh worktrees (git-ignored build artifact).

Closes #363.

Org-scoped webhooks fanning out across member repos plus the org membership/team/invite log (docs/features/06 §1.5/§5.4). What: - Owner-gated CRUD: POST/GET /api/v1/orgs/{org}/webhooks (+/{id}, /ping, /deliveries) on both lanes; 401 anon, 403 non-owner, 404 unknown ids; secrets write-only (secret_set). - Fan-out: per-hook org-log cursor + per-(hook, member repo) cursors over member collab-activity logs; reuses postEvent verbatim (keepers, HMAC-SHA256, 10s lane); 256/scope/pass, FanoutParallel hooks. - Org log: member_added/removed/role_changed, team_created/deleted/member added/removed, invite_created/accepted/cancelled — emitted post-commit via nil-safe identity OrgEvent seam (composition-wired); DeleteOrgInvite added so owner-cancel emits too. - Caps mirror repo limits (MaxHooks/org, 409); minute org sweep gated (hooks LIST + org-state GET; member collab_state probes only for orgs with active hooks); retention folds org cursors into the compaction floor. - SDK: client.orgs.webhooks (API+SDK only; no org-settings hooks tab — deferred, noted in 06 out-of-scope). - No new dependencies. Out of scope (documented): git pushes stay on the events-bridge TOML sinks; repo creation surfaces via first activity (no synthetic record). Tests: internal/notify 95.6% / internal/identity 96.4% (≥95 gate), -race clean; table-driven CRUD/gating/validation/caps/fan-out+HMAC/filter/failure-pending/sweep-gate/retention-floor; e2e collab chain passes. Pre-existing failures only: TestUIAssetConcepts (fails on pristine main too) and missing web/dist in fresh worktrees (git-ignored build artifact). Closes #363.
Owner-gated org hook configs (POST /api/v1/orgs/{org}/webhooks,
both lanes) fan out across member repos' collab-activity logs plus a
new org membership/team/invite event log, reusing the repo delivery
and keeper (HMAC) machinery with per-scope cursors. Caps mirror the
repo-hook limits; retention folds org cursors into the compaction
floor. Identity emits post-commit via the nil-safe OrgEvent seam;
owner-cancel of org invites moves through DeleteOrgInvite so both
cancel paths emit. SDK gains client.orgs.webhooks (API+SDK only; no
org-settings hooks tab). No new dependencies.
Sign in to join this conversation.
No description provided.