# Gitea webhook threat model Status: design gate only. Incoming webhooks are disabled and no webhook is registered by DevRunbook. Periodic PostgreSQL-backed refresh remains the sole automatic freshness mechanism for this release. ## Trust boundary A webhook body, headers, event name, repository identity and delivery ID are untrusted network input. They may request only the same bounded, read-only snapshot job that an authorized refresh already creates. They must never carry forge credentials, select a workspace directly, execute content or mutate a repository. ## Mandatory controls before enabling an endpoint - Authenticate the exact raw body with HMAC-SHA-256 and a per-integration secret; compare the digest in constant time before parsing JSON. - Require a signed timestamp within five minutes and a cryptographically random delivery ID. Persist `(integration_id, delivery_id)` with a TTL and atomically reject replays before enqueueing work. - Resolve workspace and repository exclusively from the authenticated integration and allowlisted remote identity. Never trust workspace IDs or callback URLs supplied by the body. - Limit the raw body before buffering, allowlist push/default-branch and repository-change events, validate content type and reject unknown fields. - Apply independent per-source-IP, per-integration and per-workspace token buckets before database work. Return `429` with bounded jitter and never bypass the normal queue's deduplication or retry limits. - Use the existing snapshot preflight and idempotency contract. A delivery may enqueue work but cannot force full analysis or create a profile revision. - Log only a hashed delivery ID, integration ID, event class and safe outcome. Never log the signature, raw body, token or repository content. - Respond with generic errors so signature, tenant and repository existence cannot be enumerated. Keep last-known-good snapshots on every failure. ## Required verification gate The feature stays disabled until integration tests prove valid/invalid signatures, raw-byte verification, expired/future timestamps, replay races, body limits, event allowlisting, flood limits, queue deduplication and strict cross-workspace isolation. Deployment documentation must also cover secret rotation with an explicitly bounded overlap window and immediate revocation. This keeps the Gitea integration read-only: webhook registration itself is an operator action outside DevRunbook, and the callback can only schedule reads.