Let logged-in players manage their transaction-feed webhooks (PAR-151) from economy-explorer instead of raw API calls. Substrate/convenience UI over the same webhook_subscription table the dispatcher drives.
webhook_subscription.api_key_id made nullable — via a new V14 ALTER (V13 is already deployed, do NOT edit it).webhook_delivery rows per webhook.economy-flyway: V14 ALTER TABLE webhook_subscription MODIFY api_key_id INT UNSIGNED NULL.treasury-rest-api: WebhookSubscription.apiKeyId → Long; WebhookService.requireOwned null-safe (explorer rows not manageable via a REST key).economy-explorer: lib/sql/webhook.ts (DAL), lib/actions/webhooks.ts (actions + server-side scope authz), lib/util/ssrf.ts (TS SSRF port), app/me/webhooks/** (page + create form + row actions + delivery view), lib/db.ts (DB interface), /me nav link.Re-validate scope server-side (own personal account / hasFirmFinancialAccess); SSRF guard on URLs (dispatcher re-checks at delivery); secret shown once; owner-scoped ownership on edit/delete; audit; noindex + login/link gate.
Follow-up to PAR-151. Plan: parallel-whistling-swing.md.