Strata architecture and SDDMenu
On this page

Server Component hydration observations (0.10.0 candidate)

Candidate and dependency tuple

Starting origin/main SHA: efd14e2d1375e1762846c3ee6ab6bb49d5440609, package @strata-sc/server-components 0.9.0. Candidate branch: feat/server-components-hydration-observability-v010.

The fixture lockfile tuple is Analog platform / Angular Vite plugin 2.7.2, Analog Router 2.8.1, Angular core/compiler/compiler-cli 22.1.7, common/platform-browser 22.2.3, platform-server/router 22.2.2, Angular build 22.1.8, Nitro 2.13.4, H3 1.15.11, Vite 8.3.0, TypeScript 6.0.3, Node 22.23.1 and Wrangler 4.135.0. These mixed lockfile resolutions are a fixture tuple, not a compatibility promise.

Public API and event

import { provideStrataHydrationObserver } from "@strata-sc/server-components";

provideStrataHydrationObserver((event) => {
  applicationLogger.info("strata-host", event);
});

StrataHydrationObservation is readonly and frozen at delivery:

FieldContract
hostSelectorPublic selector of the generated Server Component host element.
outcomecommitted, preflight-refused, or commit-failed.
discoveredBoundariesNumber of boundary elements discovered for this host.
committedBoundariesAll discovered boundaries on success; zero on refusal or rollback.
failureCategoryExisting BoundaryFailureCategory on a classified preflight refusal only.
buildMismatchTrue only for StrataBuildMismatchError from two valid, different identities.
recoveryOutcomeExisting bounded recovery result, present only for confirmed mismatch.
elapsedMsMonotonic duration of discovery, preflight, commit, and rollback if needed.

Provider scope is the Angular application injector. There is no server request context or required initialization call. With no provider, the event and clock read are skipped. The existing boundary discovery remains the sole scan.

Outcome semantics

One afterNextRender callback owns one host attempt. A successful event follows all roots being created, inputs assigned, views attached, and hydrated markers written. An empty host is a successful zero-boundary transaction and reports committed with both counts zero. Preflight is all-or-nothing; a refusal is reported before the existing error throw and before component creation. Commit failure is reported only after created roots have been destroyed and SSR nodes restored, then the original error is thrown unchanged. Each eligible attempt reports at most once. A host destroyed before its scheduled callback starts reports nothing; destroy after an attempt does not emit another event.

preflight-refused may contain an existing category. Arbitrary errors during root creation or input assignment use commit-failed without a fabricated category. No event means successful completion of all later Angular change detection, event handlers, requests or deferred rendering.

ErrorHandler and skew recovery

Strata still registers no ErrorHandler, calls no ErrorHandler and does not wrap a component error. Angular receives the exact error once through the same afterNextRender error path. Observer sync throws are caught. Returned promises and thenables are not awaited and have rejection handlers attached immediately. Their failures cannot alter rollback, sibling hosts, ErrorHandler delivery or recovery.

Only a confirmed StrataBuildMismatchError is passed to SkewRecovery; malformed/missing identities, protocol errors and all other boundary categories are not eligible. The event reads the error's existing recovery outcome after handle(). Recovery stays disabled unless opted in, keeps its existing per-tab bound, and invokes the existing onMismatch callback. A synchronous reload request may begin before application telemetry side effects finish; no external delivery is promised during navigation. Multiple mismatched hosts remain under the existing document-level reload decision.

Confidentiality and timing

The flat event contains no props, component values, URL, query, cookies, authorization, request body, resource or tenant ID, exception, DOM node, injector or Angular reference. Build labels are not copied into the event. elapsedMs covers Strata's boundary discovery, validation, component creation, input assignment, view attachment, marker update and any rollback. It excludes network time and later Angular work. This is not a measure of Angular's full hydration lifecycle.

@defer

The host event means Strata's explicit client roots committed. Angular continues to own @defer, including viewport / interaction triggers, lazy chunks and event replay. A deferred child may still be dehydrated when the host is reported; its later hydration does not create another Strata host event. Deferred blocks remain unsupported in server-owned templates.

Evidence matrix

Evidence levelStatus
ImplementedProvider, readonly type, host outcome integration, failure isolation.
Unit testedProvider scope, no-observer path, frozen shape, sync throw, rejected Promise and thenable (354 pass).
Locally integratedNode, Analog live dev, workerd, failure/recovery, deployment-skew and @defer suites passed.
Packed-consumer qualifiedPacked tarball install, TS 5.9/6, Node production, external dev and Cloudflare/workerd passed.
Hosted-CI qualifiedPR #143 CI is running; no main-push release-gate transition is established by this PR run.
Deployed qualifiedNot run; no real deployment was authorized.
Production adoptedUnknown / not evidenced.

The Changeset is one minor bump for @strata-sc/server-components; no version files were edited. One Node fixture observation reported 1.10 ms for one host attempt, including boundary scan, preflight and commit. This is one noisy sample, not a comparative overhead benchmark. The disabled path skips event allocation and clock reads; its comparative cost has not been measured. Full workspace build, typecheck and tests passed; the performance-tools subset passed 163 checks with loopback access. A full lint run completed with zero errors and four import-order warnings. Two warnings were in changed files and have been corrected; a final full lint rerun is still pending. One existing warning remains in tools/analog/observability.ts.

Release safety and remaining limits

The current release workflow is a workflow_run workflow and calls tools/release/authorize.ts before any version or publish action. verify-run.ts requires a completed successful CI run for a main push, a single successful aggregate Verify job, and that main still points at that exact SHA. The helper tests cover successful, failed, cancelled, pending, missing/duplicate Verify and GitHub's reported workflow path. Issue #117 remains open. Recent hosted the current PR CI runs are available and in progress, but main-push release runs and live pending/failure/cancelled/stale-main transitions are not established by this PR. Do not claim release workflow qualification or close the issue based on helper tests or PR checks alone. No package was published.

This feature does not complete M3, M4, M5 or Strata 1.0. Browser Router subtree navigation, protocol stability, deployed qualification, full supported-version matrix, production application adoption and the remaining release safety evidence are still separate gates.

Source: docs/research/server-component-hydration-observability-v010.md

Generated by Entwine · Markdown remains the source of truth.