Skip to content

Retire the legacy sys_webhook.definition_json.headers read path — readLegacyHeaders still accepts the cleartext column with only a warn #9930

Description

@os-warren

Filed by the domain:services seat (session session_01PnJHU45vPJj5UQrxe946Bx) as the scoped-down successor #9756's census pointed at. Unassigned and unlabelled — for triage to grade and route.

Context

#7986 moved webhook custom headers out of the cleartext definition_json.headers blob into headers_secret (secret-backed), and #9927's census re-measured the residue: readLegacyHeaders (packages/plugins/plugin-webhooks/src/auto-enqueuer.ts:579 at the census ref) still reads and honors an un-migrated legacy row's cleartext headers, emitting only a warning. So the cleartext path is retired for writes but alive for reads: a legacy row keeps working forever, and the warn never escalates.

This matters because it is the half of #9756's reachable-cleartext concern that has an actual instrument: #9756's own remedy (enable.apiMethods narrowing) was measured to be a no-op on the reachable surface (see the census in PR #9927), and url masking is settled won't-fix (#8025). The un-migrated-legacy-row read path is what remains actionable.

Related but distinct: #9928 fixes the docs that still point authors at the cleartext column — that is the authoring-guidance half; this card is the runtime acceptance half. Landing #9928 first reduces new legacy rows; it does not retire existing ones.

What retiring would involve (a lead, not a decision)

  1. Measure the population: does anything still produce rows with definition_json.headers (after content/docs/automation/webhooks.mdx still documents custom headers as living in sys_webhook.definition_json, and omits headers_secret entirely — the doc points authors at the cleartext column #7986 moved them out of #9928 fixes the docs, the answer should be "only pre-[security] webhook custom headers are still cleartext in two JSON blobs — the sibling of #7799 that PR #7901 did not close #7986 rows")?
  2. A migration/boot-sweep for existing legacy rows into headers_secretmigrate-webhook-secrets.ts is the precedent shape in the same package (the [security] The webhook signing secret is stored in cleartext in sys_webhook.definition_json #7799 secret sweep).
  3. Flip readLegacyHeaders from warn-and-accept to a loud, dated rejection (or remove it) once the sweep has run — the enforce-or-remove shape.

⚠️ Step 2 touches stored rows (an existing-data migration shape) — under the standing rules that is a maintainer-visibility item: whatever PR lands it must isolate it, document idempotency/reversibility, and flag it prominently rather than riding it in silently.

Re-check commands (premise lines)

  • git grep -n "readLegacyHeaders" origin/main -- packages/plugins/plugin-webhooks/ — the read path still exists
  • git grep -n "definition_json" origin/main -- packages/plugins/plugin-webhooks/src/auto-enqueuer.ts — still consulted for headers

Dedup checked at filing: #7986 (closed — the write-side move), #8118/#8149 (closed — sys_http_delivery/sys_email siblings), #9928 (open — docs half only). No open card owns the legacy read-path retirement.

Refs: #9756 · PR #9927 (census) · #7986 · #9928 · #8025 (url ruling, untouched).

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions