Follow-up to #4432, verified on main @ a1a855a28 (the rc.3 train tip) as part of the #3909 G1 regression pass.
The two headline harms of #4432 are fixed. Both type spellings now address one namespace (/meta/actions/x and /meta/action/x both report type=action), an overlay no longer shadows the code-authored listing (13 items before and after a PUT), and a saved overlay is dispatchable immediately (#4521). Confirmed by re-running the original repro.
One branch of the original report survives: after DELETE, the listing still returns the deleted overlay while dispatch correctly refuses it.
Repro (clean cycle, fresh name)
PUT /api/v1/meta/action/rg_clean → 200
GET /api/v1/meta/action → rg_clean listed (1)
POST /api/v1/actions/showcase_task/rg_clean → 200 ✅ dispatchable
DELETE /api/v1/meta/action/rg_clean
→ 200 {"success":true,"reset":true,"seq":4,
"message":"Customization overlay deleted — action/rg_clean reset to artifact default. [seq=4]"}
GET /api/v1/meta/action → rg_clean STILL listed (1) ❌
POST /api/v1/actions/showcase_task/rg_clean → 404 ✅ correctly gone
The delete is real — it reports reset: true with a sequence number, and the dispatch path honours it one request later. Only the listing disagrees.
It is not storage: sys_metadata holds no rg_* row, and rg_clean does not appear in dist/objectstack.json. So the listing is serving a cached/registry view that the delete path updates for dispatch but not for enumeration — the mirror image of #4521, which fixed the same seam in the write direction (saved overlays became immediately dispatchable).
Why it still matters
An admin who removes a customization sees it still listed and reasonably concludes the delete failed — the exact confusion #4432 was filed about, just moved from the write side to the read side. Anything that enumerates metadata to decide what exists (Studio's authoring surfaces, a sync/export, a reconciliation job) reads a surface that includes a deleted item.
Expected
DELETE invalidates the enumeration view in the same step it invalidates the dispatch view, so list / get / dispatch agree immediately — the "every surface in agreement" clause of #4432.
Found during the #3909 rc.3 regression pass (G1).
Follow-up to #4432, verified on
main@a1a855a28(the rc.3 train tip) as part of the #3909 G1 regression pass.The two headline harms of #4432 are fixed. Both type spellings now address one namespace (
/meta/actions/xand/meta/action/xboth reporttype=action), an overlay no longer shadows the code-authored listing (13 items before and after a PUT), and a saved overlay is dispatchable immediately (#4521). Confirmed by re-running the original repro.One branch of the original report survives: after DELETE, the listing still returns the deleted overlay while dispatch correctly refuses it.
Repro (clean cycle, fresh name)
The delete is real — it reports
reset: truewith a sequence number, and the dispatch path honours it one request later. Only the listing disagrees.It is not storage:
sys_metadataholds norg_*row, andrg_cleandoes not appear indist/objectstack.json. So the listing is serving a cached/registry view that the delete path updates for dispatch but not for enumeration — the mirror image of #4521, which fixed the same seam in the write direction (saved overlays became immediately dispatchable).Why it still matters
An admin who removes a customization sees it still listed and reasonably concludes the delete failed — the exact confusion #4432 was filed about, just moved from the write side to the read side. Anything that enumerates metadata to decide what exists (Studio's authoring surfaces, a sync/export, a reconciliation job) reads a surface that includes a deleted item.
Expected
DELETEinvalidates the enumeration view in the same step it invalidates the dispatch view, so list / get / dispatch agree immediately — the "every surface in agreement" clause of #4432.Found during the #3909 rc.3 regression pass (G1).