V0.1 Deliverables

Complete list of deliverables expected for the V0.1 (MVP) release, organized by application.

Front-Office (13 deliverables)

#Deliverable
1Repository bootstrapped (Nuxt 3) with dev, build, generate commands
2CSS design tokens (light/dark, RTL-ready), Flowbite with no hardcoded hex
3Layouts: Home, Article, Page
4i18n: fr, en, nl, ar with language switcher and correct <html lang>
5SEO: title/description meta, canonical URL, hreflang, sitemap stub, robots.txt
6Islands: 1 dynamic block (hero)
7Accessibility: skip link, focus management, AA contrast
8Placeholder images with blurhash
9CSP hash-only in report-only mode + CI grep (unhashed inline = build fail)
10Performance budgets CI hard-fail: JS ≤ 180 KB (+20%), CSS ≤ 60 KB (+20%), LCP image ≤ 120 KB, LCP ≤ 2.0s / 2.5s
11Consumes /v1/public/* only (never sends Authorization header)
12Pagination, sort, and filter UI support
13Playwright DNT test: DNT=1 produces zero Matomo hits

Back-Office (12 deliverables)

#Deliverable
1Repository SPA (Nuxt) with dashboard and stub pages (Articles, Pages, Media)
2i18n: fr, en, nl
3UI design tokens with Flowbite overrides
4Real Keycloak auth (OIDC PKCE, short AT 5-10 min, no RT), mock available within 48h. Playwright tests for AT expiration + ITP-like behavior
5Accessible forms
6Unlayer editor with palette locked, client-side sanitization (matched by API)
7CSP hash-only in report-only + Trusted Types in report-only
8OpenAPI hash conformant (/contract-hash) — build fails on mismatch
9ETag/If-Match on PUT/PATCH + UX handling for 412/428 when CONCURRENCY_STRICT=1
10Playwright XSS test: injection attempt produces 0 API calls
11Protected navigation with role-based menus
12BFF V0.2 ticket referenced with deadline (2025-11-15) and assigned owner

API (16 deliverables)

#Deliverable
1Symfony 7 + API Platform repository (Domain/Application/Infrastructure/Security/Voter/State/EventSubscriber/Http/Listener)
2JWT Authenticator RS256 via JWKS + JwtUser (tenantId, roles, userId=sub). Strict validation: iss/aud/azp/sub/typ/skew. id_token forbidden. Circuit breaker + double-KID rollover.
3Entities: Article, Page, Redirect, Media with localized fields. Unicode slugs + slug_ascii. Unique constraint on (tenant_id, locale, slug_ascii).
4Security: Doctrine Filter global (read) + Security expressions. Item-level Voters only (no collection-level).
5State Processor: POST/PUT/PATCH forces tenantId from JWT. Malicious body values ignored.
6QueryFilterEnforcer: HTTP fail-fast (500 if filter OFF). CLI exemptions whitelisted and tested.
7Concurrency: strong ETag + If-Match (PUT/PATCH). CanonicalJsonNormalizer (read groups only). CONCURRENCY_STRICT flag.
8Public /v1/public/*: distinct DTO whitelists, anonymous, cacheable, complete Vary. Authorization present returns 403 + no-store.
9Preview /v1/preview/*: X-Preview-Token header (HMAC-SHA256), Redis one-time (SETNX+TTL), TTL max 5 min, no-store, UA blocklist, X-Robots-Tag.
10Pagination/sort/filter normalized. X-Total-Count + Link (RFC 5988).
11Media: presigned PUT ≤ 10 MiB, HEAD post-upload + backoff, DELETE if out-of-range, metadata, SSE (S3/KMS), tenant quotas.
12OpenAPI /v1 export CI + Spectral lint + contract hash + x-openapi-rev header + /contract-hash endpoint + Problem RFC 7807.
13RateLimiter: auth/public keys RGPD-safe (pepper), Retry-After, whitelists, quotas per role. Pepper rotation tests.
14Cache-Control/ETag + Vary (Origin, Accept-Language, Accept-Encoding). no-store if Authorization present.
15/healthz: ping DB + JWKS cache + clock skew + ICU version exposed.
16PHPUnit ≥ 80% coverage on critical domain paths.