Milestone 1 of the Static Pages Module sprint.
- StaticPageConfig / ContentPage / ContentPageBootstrapInput gain: explicit
editable route (defaults from slug, independently overridable), enabled
(master on/off), status: 'draft'|'published' (per-page publish lifecycle,
independent of the whole-bootstrap draft/publish cycle), customTemplate,
heroImage/thumbnail/gallery, and seo.robots.
- ContentPageService: normalizePage/normalizePages default missing
enabled/status to enabled+published so existing bootstrap data never gets
silently un-published; only the editor's createPage() opts a brand-new page
into 'draft'. Legacy array-format pages get the same treatment.
- resolvePage now returns null (storefront 404) for a disabled or draft page,
regardless of whether the surrounding bootstrap itself is published -
affects the storefront static-page route AND the auto-generated footer nav
group (both go through this same resolver), which is the correct behavior.
- validatePages extended: duplicateRoutes (route can now diverge from slug),
invalidHtml, invalidSeo (canonical/ogImage URL shape, known robots tokens).
- New schema/validators/primitives.validateHtml: stack-based tag-balance
check (void/self-closing elements skipped, comments stripped). Caught and
fixed a real bug during its own spec run: the initial implementation popped
the stack back to the nearest matching ancestor on a mismatched closing
tag, which silently swallowed a genuinely unclosed inner tag instead of
flagging it - now a closing tag must match the top of the stack exactly.
- toBootstrapRecord serializes the new fields; visible mirrors enabled so any
reader of the older field name stays truthful.
- Specs: content-page.service.spec.ts (new), primitives.spec.ts (validateHtml).
Gate: tsc --noEmit, npm test (57/57), arch:check, build all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Milestone 4 of the Configuration Engine sprint.
- Add schema/history.util: pure undo/redo reducer (commit/undo/redo, depth cap)
with full spec coverage.
- Facade: debounced snapshot history (~300ms coalesce so a typing burst = one
undo step); undo()/redo() route through the draft-save path so autosave never
desyncs; canUndo/canRedo; history cleared on load/publish/resetDraft.
modifiedFields (schema-diff vs original) + modifiedSections computeds.
- save-bar: Undo/Redo buttons. Page: Ctrl/Cmd+Z / Shift+Z / Y shortcuts
(skipped while a text field is focused so native text undo is preserved);
beforeunload guard already present.
- nav: amber modified-field dot per section (when no blocking badge).
- i18n: builder.undo / builder.redo in interface + en/ru/hy.
Gate: tsc --noEmit, npm test (33/33), arch:check, build all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Milestone 2 of the Configuration Engine sprint.
- Add schema/validators/primitives: pure isValidHexColor/HttpUrl/Email,
validateJson, validateCss, extractStyleBlocks, normalizeRoute. One function
per concern, no duplicated validator logic.
- Refactor ProjectValidator to compose the primitives and tag every issue with
section + fieldKey + severity ('error' blocks publish, 'warning' advisory).
Preserves all existing codes/messages; adds duplicate-routes, invalid-css,
invalid-widget-config checks.
- Facade: issuesByField, issuesBySection, blockingIssues, hasBlockingIssues;
publish() now gates on severity==='error' instead of any issue.
- i18n: add validationInvalidJson/Css/DuplicateRoutes/InvalidWidgetConfig to
the Translations interface + en/ru/hy.
- Specs: primitives + ProjectValidator (25 passing total).
Gate: tsc --noEmit, npm test (25/25), arch:check, build all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Milestone 1 of the Configuration Engine sprint.
- Add schema/ registry: FieldSchema model, SECTION_FIELD_SCHEMAS covering
every editable field per section, and EditorSchemaService (getFields,
getField, all, getByPath). Single source of truth for labels, defaults,
and validator references; sections stay hand-authored (metadata-augmented).
- Stand up Karma + Jasmine (ng test) with a headless, sandbox-free Chrome
launcher; add tsconfig.spec.json, karma.conf.js, angular.json test target,
and npm "test" script. First spec: editor-schema.service.spec (7 passing).
No behavior change. Gate: arch:check, tsc --noEmit, npm test (7/7), build all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>