Roadmap to 1.0
Baseline: STATE. Milestones are capability gates, not calendar promises or mandatory version numbers. M1–M4 may produce experimental 0.x releases; M5 produces release candidates. Each future slice gets its spec immediately before implementation. SPEC-001 and SPEC-002 were executed and remain Blocked; SPEC-003 is implemented and in review (see specs).
Two tracks (reconciled 2026-09-24). The diagram below was drawn as one sequence. In practice the
M1 blocker belongs to @strata-sc/h3's H3 v2 declarations, and @strata-sc/analog never exposes them. So:
- H3 consumer qualification track (M1): upstream-blocked; stays Blocked and visible. It still
gates any claim that
@strata-sc/h3consumers typecheck strictly, and any M3+ stabilization that relies on@strata-sc/h3. - Analog integration / Server Component feasibility track (M2): proceeds on
@strata-sc/analog, which has its own runtime and bundle evidence. Its experiments do not claim M1, and M1 does not pretend they have not happened.
M0 existing core + H3 GET
→ M1 consumer compilation evidence
→ M2 integration and strict Server Component feasibility (go / no-go)
→ M3 usable HTTP architecture + stable Analog integration
→ M4 production component/navigation contract
→ M5 deployment hardening + real consumer
→ 1.0 release audit
M2 deliberately precedes broad HTTP feature work: the riskiest requirement determines whether the 1.0 destination is viable. M2 has sequential, separately specified experiments, not one large implementation assignment. Baseline prototype endpoints are sufficient to exercise them.
M0 — Existing experimental primitives
Status: implemented baseline, not a stable release.
- Capability: declarative
Controller/Getmetadata executes on a caller-owned H3 v2 app. - Hypothesis already exercised: an independent metadata core can drive a thin runtime adapter.
- Evidence: 34 existing tests pass locally; limitations and missing cases are in STATE.
- Still changeable: all public experimental APIs, metadata/lifecycle details and package policy.
M1 — A consumer can compile and run the primitive
Status: Blocked, partially proven. SPEC-001 executed; strict consumer types still fail.
- Capability: a fresh external consumer uses packed Strata packages and its own standard-decorated controller with a reproducible TypeScript/Vite compilation recipe.
- Hypothesis: internal test transforms have not hidden broken package exports, symbol initialization, metadata emission or consumer build requirements.
- Evidence: SPEC-001 proves packed installation, dependency rewriting/single core, standard-decorator metadata and both Node runtime paths with real H3/native requests. Direct Vite retains decorators and fails in Node; that is successful characterization, not a failure of the reference runtime path.
- Blocker: AC2 remains unsatisfied by H3 declarations (TS4113 lib mismatch and TS2307 optional
peer type leakage). Adding
esnext.erroralone is insufficient. Exact external Rolldown pinning also needs repair; remote CI currently stops at pre-build lint, before consumer qualification. - SPEC-002 result: executed, no eligible closure; upstream-blocked (see STATE). Its original framing follows. SPEC-002 tests one bounded hypothesis: a declared, pinned TypeScript/lib/type-dependency closure can qualify the existing H3 v2 consumer without suppression or dependency patches. If falsified, retain an upstream reproduction and keep M1 Blocked; completed investigation is not gate completion. Primitive semantic gaps remain in STATE.
- Gate: installed tarballs, public declarations, executable production output and route behavior
verified without workspace source aliases. Evidence must distinguish package build from user-code
compilation. A clean strict typecheck remains mandatory; successful emitted JS cannot replace it.
No public compiler package is needed to pass this gate. M2 claims that depend on
@strata-sc/h3remain gated on M1; the Analog-track experiments do not depend on it (see the two-track note). - Still changeable: consumer build recipe, package boundaries, distribution and all framework APIs.
M2 — Prove the integration path and the hardest UI requirement
Status: in progress on the Analog track; prototype-only, not production-ready. M1 remains
Blocked for @strata-sc/h3 (see the two-track note above). Experiment 1 is partially evidenced by the
Analog integration baseline: Nitro 2 / H3 v1 seam,
@strata-sc/analog rather than an H3 bridge, standard decorators in dev and production, and Angular-graph
decorator failures recorded. Base paths, cookies, abort and Workers are still open. Experiment 2 has a
CONDITIONAL GO (SPEC-003,
report). Experiment 3 is next.
Capability: a pinned minimal Analog fixture demonstrates, or falsifies, the route from a Strata controller to request services and from a server-only component to an interactive Angular child.
Experiments, in dependency order:
- Runtime and compiler seam. Resolve exact Angular/Analog/Nitro/H3/TS/Vite versions. Compare a narrow H3 v1 adapter path, an explicit Web Request/Response bridge around H3 v2, and an upstream supported newer runtime if actually available. Verify base paths, headers/cookies, errors and abort behavior. Exercise consumer decorators with Angular AOT in dev and production; prove transform order and metadata retention. Select neither multiple-major support nor a plugin by fiat.
- Angular DI. Trace the request injector as described in ARCHITECTURE; test identity, scopes,
concurrency, cleanup, synchronous
inject()and server-function coexistence. A private hook or fork must be identified, not disguised as stable integration. Result (SPEC-003): no supported Analog seam exposes the SSR or server-function injector. Consumer-ownedcreateApplication()+ per-requestcreateEnvironmentInjector()viacontrollerFactory/onCleanuppasses isolation, identity and cleanup tests on Node. The HTTP composition qualification adds consumer-owned guards, interceptors, Standard Schema input, provider overrides and a 24-request mixed matrix on Node. It remains a separate DI universe from SSR and server functions and needs the JIT compiler in the Nitro bundle. Local workerd refuses Angular JIT factory compilation (Code generation from strings disallowed), so Angular DI on that Worker tuple remains NO-GO; abort cleanup and packed Angular DI remain open. See the cross-runtime lifecycle report. - Component compiler/graph PoC (next bounded step). Build on SPEC-003's lifecycle: one
server-only component/service plus one interactive Angular child, with production bundle
assertions. Server data service plus
ProductDetailsabsent from every browser artifact, interactiveAddToCartComponentpresent and actually hydrated after SSR. Prove template compilation and boundary ownership, direct/transitive import rejection and production bundle assertions. Attempt the same minimal output under a Workers runtime. - Navigation feasibility probe. Exercise a second route with document navigation and assess whether a client-router subtree approach has a supported Angular lifecycle. Record tradeoffs and failures; the final protocol is specified in M4, after these results.
Hypotheses: supported framework extension points can preserve the strict graph split, share request services and hydrate explicit children without a second DI container or shipping server code.
Gate: reproducible fixtures and a go/no-go report for every experiment; one pinned viable runtime path, a documented consumer compilation strategy and strict component graph/hydration evidence. If only SSR works, record no-go and keep 1.0 blocked. If upstream work is required, record its public issue and version dependency and replan before broad API work. Do not turn a prototype into support.
Still changeable: component declaration syntax, compiler/plugin packaging, DI bridge, H3 target for Analog and navigation strategy. Write relevant ADRs only after the evidence exists.
M3 — Usable HTTP domains inside Analog
Status: in progress; the 0.5.0 candidate adds the typed HTTP error and response contracts, and extends real Node/workerd and packed-consumer checks. Broader M3 adoption and lifecycle gates remain open; see the HTTP contract report.
- Capability: controllers and services handle real HTTP domains inside an Analog app with defined request lifetimes and native H3 escape hatches.
- Hypothesis: a small explicit architecture covers those needs without replicating a backend platform.
- Capability delivered in the 0.5.0 candidate: close the initial application error/response gap; existing Post/Put/Patch/Delete, Standard Schema, guards and interceptors compose through one request cleanup scope. The remaining work is qualification and adoption, not another duplicate HTTP error layer.
- Capability delivered in the 0.6.0 candidate: a deterministic HTTP routing and API boundary (JSON 404,
405 with
Allow, derivedHEAD, opt-inOPTIONS) that does not shadow native Nitro routes, Analog pages or server functions (report). - Capability delivered in the 0.7.0 candidate: an explicit, opt-in streaming lifetime (
streamResponse()) that holds the request cleanup scope until the body completes, fails or is cancelled, and a real compiled AnalogserverFnexecuted beside controllers, native routes, the API boundary and Server Component SSR on Node. Client-disconnect cancellation stays NO-GO on the pinned Nitro adapters, Cloudflare Pages buffers the body, andserverFnis NO-GO on workerd (Angular JIT) (report). M3 is not marked complete. - Capability delivered in the 0.8.0 candidate: an opt-in
onRequestSettledobservation of each Strata invocation's end (route template, finite outcome, cleanup state, monotonic durations; streams only at a supported terminal outcome), synchronous and isolated from the response, with no request or error data. It is not an observability SDK; client disconnect and the API boundary's own answers stay unobserved (report). M3 is not marked complete. - Capability delivered in the 0.9.0 candidate: opt-in
validateHeaders(schema)completes the params/query/headers/body Standard Schema input set (lowercase string snapshot, native duplicate combination, safesource: "headers"400, no authentication claim) (report). Request validation is therefore no longer open work; M3 is not marked complete. - Capability in the 0.10.0 candidate: opt-in
readValidatedForm(schema)adds bounded Standard Schema v1 validation for URL-encoded forms. It preserves ordered repeated values and literal keys, rejects malformed percent/UTF-8 input, limits bodies to 1 MiB and fields to 10,000, and shares request-local body ownership with validated JSON. Local unit, real Node/dev/workerd fixture and packed-consumer checks pass; hosted CI evidence is pending (report). This does not complete M3. - Capability in the 0.11.0 candidate: registration preflight rejects equivalent static/named-parameter route templates across Strata-owned registrations, including when Nitro shares parameter names across HTTP methods. This does not inspect native routes, model unsupported Nitro syntax, or complete M3 (report).
- Remaining M3 work: close metadata/member/registration contracts; settle params/query/body/headers and Standard Schema contracts with external consumers; qualify safe errors; Angular providers/lifetimes; guards and interceptors with explicit order, cancellation and logging; stabilize consumer compilation and Analog integration.
- Gate: core/adapter contracts, installed consumers, Analog SSR and existing server functions remain compatible; concurrent request isolation and error/authorization tests pass on Node and Workers. Consumer compilation is a prerequisite to calling Analog integration stable. Request-input and lifecycle decisions must precede their public APIs.
- Still changeable: HTTP names and ergonomics through experimental releases; component protocol remains provisional. Breaking changes require explicit migration notes.
M4 — Server Components with a production rendering contract
The 0.12.0 candidate validates client reference identity at runtime (expected versus actual Angular selector, conflicting selector ownership) inside the existing host preflight. It is an incremental integrity check, not completion of M4; see the candidate evidence.
The 0.13.0 test-only qualification adds a real Chromium unknown-reference refusal on Node and local workerd, and reruns the installed 0.13.0 package consumer. It demonstrates host-local atomic refusal, ErrorHandler/observer delivery, DOM identity and sibling interaction for that selector case. It does not qualify malformed descriptors in a browser, the installed-package reference-negative matrix, warm Vite optimizer cache transitions, or a deployment; M4 remains open. See the browser integrity report.
The 0.11.0 candidate adds per-host browser preflight budgets (128 owned boundaries and 1 MiB of serialized payload UTF-8). This is an incremental bound on hydration work, not completion of M4; see the candidate evidence.
Status: planned; depends on M2 component feasibility and M3 request/security contracts.
The 0.3.0 candidate advances one bounded part of this milestone: structured client-boundary data and protocol v2, with v1 compatibility. It does not close M4: protocol stability, router subtree navigation, streaming, deployment qualification, complete production adoption and the remaining security gates are still open. Evidence is tracked in the boundary v2 report.
The document-navigation candidate makes the one supported navigation path first-class
(StrataDocumentLink, StrataDocumentNavigator, hardened strataDocumentNavigationGuard); it does
not add SPA subtree navigation (report).
Explicitly registered Angular package islands were first explored on a branch whose packed consumer had not yet passed npm installation; that was superseded. They were merged (#107) and released in 0.4.0, and the packed Node/workerd consumer now gates them on every pull request. Bundle cost, production adoption and a deployment of the package shape remain open (report).
The server-only graph hardening candidate (0.6) extends the build-graph firewall to Vite aliases, tsconfig paths, index files, aliased re-export chains, package modules that assert server-only and importer-aware diagnostics; it does not add package crawling, SPA subtree navigation or streaming (report).
The optimizer firewall increment (0.9) closes a reproduced vite dev bypass: Vite 8 pre-bundles dependencies with
Rolldown, so a package module that asserts server-only, or a barrel or dynamic import reaching it, was served to the
browser. The plugin now fails the optimizer run through the public optimizeDeps.rolldownOptions.plugins seam and
keeps [strata] dev errors free of source; it adds no option, no package crawl and no claim for unmarked packages
(report).
The production SSR integrity increment (0.7) turns an intermittent SSR failure into a build-time error: a reproduced Analog multi-environment compilation race is serialized by the plugin and a post-transform gate fails builds that contain uncompiled Angular classes or unlinked partial declarations; qualification suites classify SSR answers instead of trusting HTTP 200. It does not add a render-error response seam, streaming or SPA navigation (report).
The deployment-skew increment (0.8) adds the one piece of "deployment-version skew" the work item below
names that can be qualified locally: an opt-in application build identity, a classified build-mismatch
refusal before islands exist, and an opt-in bounded document reload. It does not close M4: protocol
stability, router subtree navigation, streaming, a deployed qualification and production adoption remain open
(report).
The 0.10 candidate adds an opt-in browser observer for one terminal result per Strata host transaction.
It reports commit, preflight refusal or rollback-complete commit failure without taking over Angular's
ErrorHandler or @defer scheduler. The implementation does not complete M4; Node, dev, workerd, packed
consumer, and hosted CI evidence must be recorded separately (report).
- Capability: strict server-only UI composes Angular interactive descendants under a defined initial SSR and navigation strategy.
- Hypothesis: the PoC remains correct across navigation, nested boundaries, errors and optimization.
- Work: choose document navigation or a justified router protocol; specify serialization, boundary
identity, authorization, caching, error recovery and deployment-version skew. Integrate ordinary
hydration, incremental hydration and
@defer; declare supported composition rules and reject the rest clearly. Add build-time forbidden-import diagnostics and production graph assertions. - Gate: SSR, browser interaction and navigation tests pass; no server implementation or transitive server dependency in any browser output; adversarial leak tests fail closed; selected strategy works on both target runtimes. Freeze the protocol through evidence-backed ADRs, not the example API.
- Still changeable: ergonomics and tuning before RC; security invariants cannot be weakened.
M5 — Production evidence and release candidates
Status: planned; depends on M4.
- Capability: a deployed production fixture and a real application use the complete path.
- Hypothesis: deployment, packaging, upgrades and real traffic do not invalidate fixture guarantees.
- Work: qualify a small exact compatibility matrix; deploy Node and the selected Cloudflare shape; enforce measured bundle/runtime budgets, load/concurrency and cleanup tests; verify published package candidates; exercise upgrade/rollback and safe diagnostics; finish examples and migrations. Adopt in ForgeCMS only after fixtures pass, or document another real consumer.
- Gate: every 1.0 exit criterion has evidence for the same candidate and supported matrix; real consumer uses controllers/services and production Server Components, including the selected navigation path. Agree consumer-specific observation duration and service objectives before trial, record results and regressions, and repeat after material fixes.
- Still changeable: fixes and explicit RC migrations. No new broad platform capabilities.
1.0.0 — Release decision
Astra reviews evidence and architectural coherence; maintainers accept the release audit. A demo, passing unit tests or an unpublished consumer branch cannot substitute for production proof. Anything missing from RELEASE-1.0 keeps the candidate below 1.0. Future milestones may change through new evidence, but 1.0 cannot quietly become “controllers work.”