8.6 KiB
8.6 KiB
Implementation Plan: Landing Page and Login/Register Modal 1.00
1. Architectural Reconnaissance
- Status: The landing page, login/register modal, bootstrap payload flow, and Markdown helper are present, but Job 849 is not fully implemented: the reported runtime-function string proves the welcome binding is not receiving the intended rendered HTML at runtime. Existing source currently derives
welcomeHtmlinfrontend/src/app/features/landing/landing.component.ts:46and binds[innerHTML]="welcomeHtml"infrontend/src/app/features/landing/landing.component.html:9; this integration needs to be corrected and covered by a focused component-level regression test. - Codebase style & conventions: Node.js npm workspace monorepo; Angular 17 standalone components with signals,
OnPush, Angular control-flow blocks, reactive forms, andinject()services. The landing container owns bootstrap-derived state and delegates blog HTTP calls toLandingService. - Data Layer: No database or schema change is required. Backend
SystemService.bootstrapexposes the persistedwelcomeMarkdownsetting, andBootstrapServicestores it in its signal payload. Blog data is separately fetched fromGET /api/v1/blog/posts. - Markdown and security path:
markdown.pure.ts:9-11converts Markdown usingmarked.parseand sanitizes with DOMPurify;MarkdownService.renderwraps that output for Angular HTML binding. Preserve sanitization and ensure the template receives the computed signal value, not a signal/function object. Avoid introducing new CSP inline handlers or unsafe dynamic execution; the existing CSP console error should be investigated only insofar as it is caused by the rendering integration, without weakening CSP. - Test Framework & Structure: Root Jest 29 multi-project configuration in
tests/jest.config.js; frontend tests usets-jestandjsdom, live exclusively undertests/frontend/, and run from the root withnpm testor the focusednpm run test:frontendcommand. Existinglanding-markdown.spec.tstests the pure renderer only; no current test mountsLandingComponentor verifies its[innerHTML]output. - Required Tools & Dependencies: No new runtime or system dependency is expected. Existing
@angular/core,@angular/platform-browser,marked,dompurify, Jest/jsdom, and ts-jest are sufficient. The implementer should use the existingsetup.sh(npm ci/fallback install plus Angular and Nest builds); do not add a package solely for this fix unless repository inspection during implementation demonstrates an unavoidable Angular testing requirement.
2. Impacted Files
- To Modify:
frontend/src/app/features/landing/landing.component.ts— correct the component-side value passed to the HTML binding while retaining bootstrap signal reactivity and the existing MarkdownService sanitization boundary.frontend/src/app/features/landing/landing.component.html— update the binding expression if needed so Angular unwraps/consumes the computed signal value correctly and never renders the function object/source.frontend/src/app/core/services/markdown.service.ts— only if needed by the confirmed root cause; keep the public render contract and sanitization behavior stable rather than bypassing Angular security.tests/frontend/landing-markdown.spec.ts— extend with the smallest regression coverage if a pure helper contract is changed; retain the existing XSS/link sanitization assertions.tests/frontend/landing.component.spec.ts— add a dedicated focused component test under the existing dedicated frontend test folder to mount the standalone landing component and verify the rendered welcome card.
- To Create:
tests/frontend/landing.component.spec.ts— focused success-path and key safety/error regression tests, unless the implementer chooses to place equivalent coverage in an existing landing test without expanding scope.
3. Proposed Changes
Explain the exact implementation logic step-by-step:
- Database / Schema Migration: No migration. Confirm the existing bootstrap response contract remains
welcomeMarkdown: string; use the value already loaded byBootstrapService.payload()and preserve the backend setting/default behavior. - Backend Logic & APIs: No backend route or service change. Continue relying on
GET /api/v1/bootstrap, which already returns the welcome Markdown, and do not alter/api/v1/blog/posts, authentication routes, login/register modal behavior, or CSP headers unless root-cause investigation proves the CSP message is independently generated by an existing Angular event-handler configuration. - Frontend UI Integration:
- Trace Angular template expression semantics for
computed()values and verify whether the current[innerHTML]="welcomeHtml"passes the computed signal object rather than its value in this Angular 17 setup. The likely correction is to consume the signal (welcomeHtml()) in the property binding, matching the component’s other signal accesses (pageTitle(),logo(),landing.posts(), etc.). - Keep
welcomeHtmlas a computed value derived frombootstrap.payload()?.welcomeMarkdown ?? '', so it updates automatically after bootstrap completes and renders an empty sanitized result when the payload is unavailable. - Continue routing Markdown through
MarkdownService.renderandrenderMarkdownToHtml; do not substitute raw interpolation, unsanitizedinnerHTML,eval,Function, or a security bypass around untrusted content. If the current helper’s return type or sanitizer wrapper must change to make Angular accept the binding, make the narrowest compatible change and preserve DOMPurify’s HTML profile. - Leave the existing landing title, login button, empty blog state, and modal forms unchanged except where template compilation requires a minimal adjacent adjustment. The expected welcome DOM for the supplied payload must contain an
<h1>withWelcomeand paragraph textCreate the first admin to get started.rather than the Angular runtime helper source. - Check the reported CSP error after the binding fix during automated verification. Do not weaken
script-src-attr 'none'; if a separate source-level inline-handler issue is identified, replace it with Angular event bindings or document it as unrelated rather than adding an unsafe CSP exception.
- Trace Angular template expression semantics for
- Test Strategy Integration: Add only minimal automated frontend logic tests: one component test that supplies a mock
BootstrapServicepayload containing the job’s Markdown, renders the standalone component with minimal providers/mocks, and asserts the welcome element contains the heading and paragraph and does not contain the runtime-function text; one safety/error-focused assertion may verify empty/null Markdown produces no runtime source and that the existing pure renderer remains sanitized. MockLandingService.refresh()and any unrelated auth/router dependencies as resolved stubs so the test does not perform HTTP, navigation, or UI/browser automation. Keep tests intests/frontend/and make them pass through the existing rootnpm testcommand.
4. Test Strategy
- Target Unit Test File:
tests/frontend/landing.component.spec.tsfor the component/template regression; retain/updatetests/frontend/landing-markdown.spec.tsonly if the renderer contract is touched. No visual, screenshot, browser, network, database, or persistent/datafixture is needed. - Mocking Strategy: Configure the standalone component through Angular
TestBed; provide a deterministicBootstrapServicestub with a signal-backed payload, aLandingServicestub whoserefreshis a resolved promise and whose posts/loading/error signals represent the empty blog state, plus minimalAuthService,Router, andMarkdownServicestubs or real pure Markdown service as appropriate. If HTTP providers are required by transitive dependencies, use Angular’s testing providers rather than manual HTTP mocks and ensure no request is left outstanding. Assert through stabledata-testidattributes or a small harness/query abstraction, not CSS classes. Verify both the expected sanitized HTML content and absence of the Angular runtime source string. - Verification commands for the implementer: Run the focused frontend test, then root
npm test, frontend production build, lint, and typecheck using the repository’s available scripts/configuration. Since no lint/typecheck scripts are present in the inspected root or frontendpackage.json, inspect any project tooling before implementation; if no commands exist, record that limitation rather than inventing dependencies.setup.shalready installs dependencies and builds both packages, so no update is planned.