You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(spec,service-automation): ADR-0087 — wire conversions into the runtime flow-load seam + conflict guard
Close two third-party-facing risks in the P1 conversion layer.
Risk 1 (data-loss regression) — retiring the executor's `filters` fallback
while the conversion only ran on the build/validate seam meant a stored flow
rehydrated from the DB (engine.registerFlow → FlowSchema.parse, which bypassed
the conversion) kept carrying `config.filters`; with the fallback gone the
executor saw an empty `filter` and a `delete_record`/`update_record` widened to
the whole table. Fix: run the D2 conversion in registerFlow BEFORE parse (new
applyConversionsToFlow), the runtime load seam ADR-0087 D2 calls for. Stored
old-shape flows (`filters`, `webhook`/`http_request` callouts) are canonicalized
on rehydration; the executor only ever sees the canonical shape. This is the
gap config-aliases.ts already described (graph-lint can't reach never-republished
prod flows) — now closed for `filters` by the conversion, not a fallback.
Risk 2 (silent third-party clobber) — `flow.node.type` is an OPEN namespace
(ADR-0018 removed the enum gate), so a retired official name could be
re-registered by a third party. The node-type rename is now conflict-aware:
the runtime seam passes its live executor registry as reservedNodeTypes; if a
retired alias (`http_request`/`http_call`/`webhook`) is a live custom node, the
rewrite is REFUSED and a loud, structured OS_METADATA_CONVERSION_CONFLICT
diagnostic (node path, conversion id, rename hint) is emitted instead of a
silent clobber (ADR-0078). The pure build/validate seam has no registry, so the
historical alias converts as before.
Mechanism/policy split kept clean: spec provides the conflict-aware conversion
(reservedNodeTypes context on apply); service-automation supplies the data. The
crud-config-aliases test is rewritten to prove the stored-`filters` flow now
keeps its filter (the risk-1 fix); a new flow-load-conversion test covers the
rehydration rename and the conflict guard. New exports are additive.
Refs #2643, #2645 (ADR-0087 D2), ADR-0078.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YA9vjVpDrKLuaK6nbm1s37
0 commit comments