Sprint G: audited every BootstrapConfig field for a real runtime consumer (docs/DEAD-CONFIG-AUDIT.md). Wired 3 previously-dead editable fields: footer.logoUrl, company.address.street/contacts.phone, catalog.suggestionsEnabled. Remaining dead fields needing a business/design decision tracked in PRODUCT_BACKLOG.md/KNOWN-ISSUES.md, not silently left. Sprint H: 6 new spec files (test count 57 -> 83), covering ProjectEditorFacade (undo/redo, draft persistence, publish gating), AdminAnalyticsFacade (never-fabricate-a-number contract), and regression coverage for this session's carousel/hero/profile-toggle fixes. Sprint I: widget settingsSchema (declared in widget-manifest.json, never validated) now enforced via a new lightweight schema check in ProjectValidator, surfaced through the existing issuesByField pipeline. Same check reused in diagnostics so editor and diagnostics can't disagree. Verification: tsc clean, ng build clean, 83/83 tests pass, barry-cache validate clean (2 pre-existing unrelated warnings only). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
6.2 KiB
Dead-Config Audit (Sprint G)
Mechanical sweep of every field in BootstrapConfig and its sub-models
(src/app/shared/models/config/*.model.ts), cross-referenced against
src/app/features/project-editor/schema/editor-schema.ts (SECTION_FIELD_SCHEMAS)
to find fields that are editable in the Project Editor but have no real runtime
consumer — the same bug class as HeaderConfig.showProfile and layout.columns
(both fixed earlier this cycle). Non-editable fields are listed for completeness
but were not a priority (nothing in the editor lets a client set them, so there's
no ghost-setting UX to fix).
Status legend: live (read, has effect) / dead (never read outside the editor) / inert (read, but the effect is unreachable or a stub) / n/a (not client-editable today, lower priority per sprint scope).
Editable fields (client-facing — checked first)
| Field | Status | Recommendation | Outcome |
|---|---|---|---|
header.show* (8 flags) |
live | none | header.component.html reads every one |
theme.palette.* (12 colors) |
live | none | theme-css-vars.mapper.ts |
theme.mode |
inert | needs decision | already tracked in PRODUCT_BACKLOG.md |
layout.type ("Site Layout") |
dead | needs decision | see below — not fixed this pass |
branding.brandName/logoUrl/logoCompactUrl/faviconUrl |
live | none | header/footer/meta consumers |
seo.default.title/description |
live | none | seo.service.ts |
localization.defaultLocale/supportedLocales |
live | none | language switching |
tenant.host/websiteBaseUrl |
inert by design | none | frontend never resolves its own tenant (ADR-001) — this is backend routing metadata, not something the SPA is meant to read back |
company.companyName |
dead | needs decision | see below — not fixed this pass |
company.address.street |
dead → fixed | wire | now shown in footer bottom bar |
company.contacts.phone |
dead → fixed | wire | now shown in footer bottom bar (tel: link) |
company.contacts.email |
live | none | ui-runtime.facade.ts fallback chain |
footer.copyrightText/paymentIcons/socialLinks/columns |
live | none | footer-resolver.service.ts |
footer.logoUrl |
dead → fixed | wire | LogoComponent gained srcOverride, footer passes it |
catalog.navigationMode |
inert (deliberate placeholder) | leave as-is | renders a labeled placeholder card + catalog.navigationPlaceholder i18n string; the alternate nav UIs (mega-menu, top-carousel, left-nav) don't exist yet — building them is a real feature, not a wiring fix |
catalog.suggestionsEnabled |
dead → fixed | wire | SearchFacade.autocomplete() now short-circuits to no suggestions when false |
catalog.searchHistoryEnabled |
live | none | catalog-container.component.ts |
productPage.questions.* |
live | none | product-details-container.component.ts |
userExperience.recentlyViewed.enabled |
live | none | multiple consumers |
navigation.header |
dead | needs decision | see below — not fixed this pass |
navigation.footer |
live | none | footer-resolver.service.ts fallback tier |
pages / staticPages |
live | none | core rendering pipeline |
Non-editable fields (lower priority — n/a)
branding.legalName/slogan/supportPhone/appIconUrl/galleryUrls,
company.registrationNumber/taxId, tenant.defaultCurrency/supportedCurrencies/timezone,
featureFlags.blog/chat/coupons/loyalty/giftCards/invoices,
features.brands/manufacturers, permissions.definitions/roles (used elsewhere,
not via this config path), userExperience.recentlyViewed.widgetEnabled,
catalog.showBreadcrumbs/showCategoryBanner/showSubcategoryChips/enabledFilters/availableSorts/defaultSort
— none of these have an editor control today, so no client can create a false
expectation by setting them. Flagged here for completeness; no action taken.
Fixed this pass (trivially wireable)
footer.logoUrl—LogoComponent(src/app/components/logo/logo.component.ts) gained an optionalsrcOverrideinput;FooterResolverService/FooterComponentnow resolve and passfooter.logoUrl, falling back to the brand logo exactly as before when unset.company.address.street/company.contacts.phone—UiRuntimeFacadegainedcontactPhone()/companyAddress()(same fallback pattern as the existingcontactEmail()); footer bottom bar now renders atel:link and the address next to the existing email link when present.catalog.suggestionsEnabled—SearchFacade.autocomplete()now reads the bootstrap snapshot and returns no suggestions when the flag isfalse, instead of always running autocomplete regardless of the toggle.
Left dead, tracked (needs a decision, not a mechanical fix)
layout.type("Site Layout" selector, Theme section) — top-levelBootstrapConfig.layoutis edited but never applied to any page; page layout comes entirely from eachPageConfig.layout(seeSectionEngineService.resolveLayoutType), which this global selector doesn't touch. Wiring it requires deciding which page(s) it should drive (homepage only? every page without its own override?) — a product decision, not a mechanical fix. Tracked indocs/PRODUCT_BACKLOG.md.company.companyName— Footer editor has a "Company Name" field with zero runtime consumers. The footer already has a copyright fallback (© {year} {brandName},footer.component.html) usingbranding.brandName, notcompany.companyName— these are meant to be distinct (brand vs. legal entity name), so blindly reusing one for the other would be a content decision, not a safe mechanical fix. Tracked indocs/PRODUCT_BACKLOG.md.navigation.header— editable list of header nav items in the Navigation section, butHeaderComponentnever readsNavigationConfig.headerat all; the header's own category menu comes fromCategoryFacade, not this list. Rendering an actual configurable top-nav (positioning, active-state, children/dropdowns) is real feature work, not a one-line wire. Tracked indocs/KNOWN-ISSUES.md.
Not touched
theme.mode (dark mode) stays exactly as already tracked in docs/PRODUCT_BACKLOG.md — no new information found, confirmed still inert.