{ "description": "Incoming-webhook events (issue #610, docs/webhooks.md): the shape the hooks sidecar emits, and the platform contract that UNCLAIMED typed events are silently ignored on every client.", "app": "webhooks", "source": "internal/hooks/hooks.go buildEvent (emitter); web/static/apps.js foldEvent/isAppType (web ignore gate); ios MessagePayload.isRenderableChat (native ignore gate)", "state_shape": "none — the webhooks management app deliberately claims NO wire types; webhooks. events belong to future CONSUMER apps (e.g. a CI dashboard claiming webhooks.github)", "notes": [ "The sidecar posts one event per inbound HTTP request, encrypted to the target thread's key: { type: 'webhooks.', name, uid, ts, hook: {id, ns}, req: {method, path, query, headers, body[, body_b64]} }.", "name/uid are the webhook's roster identity — the same attribution fields as chat messages, so mute-by-person and roster labels apply.", "req.headers carries only the sidecar's allowlisted subset (Content-Type, User-Agent, provider event/signature headers); Authorization and other sender credentials never enter the log.", "req.body is the raw body string; body_b64: true marks a non-UTF-8 body carried base64url-encoded. req.path is the sub-path AFTER the secret segment — the secret itself never rides inside an event.", "CONTRACT — unclaimed types are ignored: until some app registers the exact type string in its events map, web's foldEvent returns null / isAppType is false (the message renders nothing, notifies nothing), and native's MessagePayload.isRenderableChat is false (no bubble, no notification). Old clients degrade to exactly this behaviour.", "Space-thread deliveries additionally never push (push.go skips kind='space' entirely)." ], "vectors": [ { "name": "github-workflow-run", "description": "A GitHub Actions delivery: the full event shape as the sidecar builds it. Unclaimed by any shipped app — web fold must return null, native must treat it as non-renderable.", "event": { "type": "webhooks.github", "name": "CI runs", "uid": "hookuser123", "ts": 1752710400000, "hook": { "id": "wh-abc123", "ns": "github" }, "req": { "method": "POST", "path": "/", "query": {}, "headers": { "Content-Type": "application/json", "X-Github-Event": "workflow_run", "X-Github-Delivery": "72d3162e-cc78-11e3-81ab-4c9367dc0958" }, "body": "{\"action\":\"completed\",\"workflow_run\":{\"status\":\"completed\",\"conclusion\":\"success\"}}" } }, "expected": "ignored" }, { "name": "binary-body-custom-namespace", "description": "A non-UTF-8 delivery under a member-chosen namespace: body rides base64url with body_b64 set. Same ignore contract.", "event": { "type": "webhooks.sensor-net", "name": "Greenhouse", "uid": "hookuser456", "ts": 1752710500000, "hook": { "id": "wh-def456", "ns": "sensor-net" }, "req": { "method": "PUT", "path": "/readings", "query": { "site": ["7"] }, "headers": { "Content-Type": "application/octet-stream" }, "body": "AAECAwQF", "body_b64": true } }, "expected": "ignored" } ] }