fix(demo): refuse publishing the homepage hero (DM21)
All checks were successful
PR Checks / bot-tests (pull_request) Successful in 47s
PR Checks / client-build (pull_request) Successful in 54s
PR Checks / server-tests (pull_request) Successful in 12m42s

Settings stay open on the demo (DM2), so the hero editor's Publish wrote
hero_layout, the hero every visitor sees. hero_layout joins the protected
settings keys: PUT /admin/settings naming it answers 403 DEMO_LOCKED with
keys: ['hero_layout']. The editor's draft autosave and Preview write only
hero_layout_draft and stay open; its uploads were already refused by the
multipart lock. Server lock only, as decided: the editor needs no change,
since its status line and the toast already show the demo sentence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-10-26 09:35:03 -05:00
parent 69998ec548
commit c87563bc32
2 changed files with 16 additions and 2 deletions

View File

@@ -184,6 +184,18 @@ test('PUT /admin/settings is open for theme and nav', async () => {
})
})
// DM21: the hero editor's autosave and Preview write only the draft; Publish
// writes both, and the live key refuses the whole body.
test('the hero draft is open, publishing the hero is refused', async () => {
await withLock(undefined, async (req) => {
await expectReached(await req('PUT', '/admin/settings', { hero_layout_draft: '{"v":1}' }))
const body = await expectLocked(
await req('PUT', '/admin/settings', { hero_layout: '{"v":1}', hero_layout_draft: '{"v":1}' }),
)
assert.deepEqual(body.keys, ['hero_layout'])
})
})
test('PUT /admin/settings naming a protected key is refused whole, with the keys named', async () => {
await withLock(undefined, async (req) => {
for (const key of ['site_mode', 'site_mode_changed_by', 'module_source_hosts', 'teams_voice_enabled', 'demo_state']) {