Skip to main content
Stralos publishes immutable candidates before making them live. Dev remains continuous: each repository produces its merged source, and the dev reconciler selects a compatible composition. Test and production use the central release workflows in stralos-core. The release train, gate-test.yml, gate-prod.yml, member prepare-release.yml workflows, and release-event production jobs are retired. Use the current central path to recover a stopped release.

Concepts

Produce — publish a candidate without activating it. Dev uses source commit SHAs. Central test releases use X.Y.Z-rc.N; production promotes the same source to X.Y.Z without rebuilding. Activate — move a controlled pointer to already-produced bytes. API activation runs migrations before moving aliases. The frontend flip updates the selected composition and root documents after the API activation barrier passes. Built-against evidence — a contract-v2 remote records { contract: 2, requires } in built-against.json. The shell records the exact React-family versions it provides. UI and domain packages are bundled separately from each repository’s exact pins; they are not shared by the host. Compatibility gate — validate each selected remote’s React-family requirements against the candidate shell. Missing or incompatible evidence prevents the frontend flip.

Shell production

Dev

A push to stralos-shell/main runs deploy-dev.yml. Manual dispatch can assert the intended source ref. The workflow builds the shell, publishes its deterministic archive and serving candidate under shell/<sha>/, and requires its validation and publication jobs to succeed. Production of the candidate does not replace the root index.html. Dev activation is separate and shares the composition lease with core reconciliation. See Composition lease.

Test

The central release calls the member’s release-create.yml at its annotated vX.Y.Z-rc.N tag. That workflow calls deploy-test.yml with from_dev: true to reuse the archived dev bundle for the selected SHA. Manual test production can build instead; its version input selects the destination, not the source commit. The shell candidate is parked under shell/<version>/. Before upload, the workflow conditionally creates manifest.sha256.json containing the intended keys, digests, sizes, and content types. A repeat produce must match the claim; occupied-by-different-bytes requires a new version. publish-shell.sh checks the index guard before spending the identifier. Under shell/, write-once behaviour is enforced by the publisher’s conditional writes. The test remotes bucket additionally denies unconditional writes and deletes under remotes/. Do not treat the shell claim as proof against every other principal that can write to its bucket.

Central release

Use release-test.yml and release-prod.yml in stralos-core. The shared release-pipeline.yml resolves sources, dispatches each member’s CREATE, activates APIs, then flips frontend pointers. Member release-create.yml workflows report a release-create-result artifact on success and failure; the orchestrator validates those results against the created candidates. Do not dispatch member CREATE workflows as a substitute for the central release. They stage candidates and do not complete the coordinated activation.

Remote test production and promotion

Each feature remote’s central CREATE publishes the archived dev bundle for its source SHA under remotes/<key>/<version>/ on test. Production verifies and promotes the test bytes without rebuilding. built-against.json and completion records accompany the candidate. Manual test rebuilding uses the exact pins and lockfile at the selected ref. Its claim compares repeated production of that test version; it does not establish parity with a separately built dev candidate.

Completion marker and by-commit pointer

Successful test publication writes two conditional records, in order:
  1. remotes/<key>/<version>/complete.json, after the published keys have been verified against the claim.
  2. remotes/<key>/by-sha/<commit>/test-version.json, naming the completed version.
The shell uses equivalent records under shell/. A pointer with its completion marker indicates a finished produce. A pointer without the marker is treated as a partial produce and allowed through for recovery.

Refusal of a second test release for the same commit

Before production, the already-released job checks the by-commit pointer and its completion marker. A completed version refuses a second test produce before build or upload. For a necessary renumbering, manual dispatch supports allow_second_version_for_commit: true. The original pointer remains write-once and continues to name the first completed version. Use a new version when the existing claim is occupied by different bytes.

Prod

The central production CREATE calls frontend-release-promote.yml. It verifies the candidate’s completion marker, source commit, object sizes, and digests, then copies the test bytes to the final X.Y.Z destination without rebuilding. Promotion is distinct from activation. A candidate that has not reached the test release ledger cannot be selected for production. The final tag must identify the same source as the test candidate.

Shell build

The shell builds in a one-member pnpm workspace. Its UI and domain packages are installed from exact pins and bundled into the host. The React-family versions provided to remotes are recorded in the shell sidecar. Owner repository checkouts belong to the isolated integration-fixture job and contribute no files to the production archive. WORKSPACE_CHECKOUT_TOKEN must be able to read those private repositories. Contract-v2 production rejects UI and domain SHA overrides.

Activation sequence

The central sequence is:
  1. Resolve the selected repositories and source identities. Refused members stop the release before tags are cut.
  2. CREATE every candidate. API CREATE stages immutable Lambda versions without migrations or alias moves. Frontends publish or promote parked bytes. Any failed member stops the release before activation.
  3. ACTIVATE APIs and self-activating members. API activation runs migrations, moves aliases, and checks the edge. A failed API can restore its own previous aliases when no cutover marker was armed; it does not roll back every other member.
  4. Flip frontends only after the activation barrier passes. Validate the resulting federation composition and completion markers, then conditionally write the remote manifest, shell documents and sidecars, and static-site root documents.
These are ordered pointer writes, not an atomic transaction across every object. The manifest and shell order preserves a valid composition where such an order exists. Live pointers are served without cache, so the central flip does not require CloudFront invalidation. Production supports the staff and all cohorts. Promote staff first, then select the same versions for all users. Static sites flip on the all run. See Staff cohort.

Rollback

Use the central runbook’s recovery path for a stopped release. Re-run failed jobs recreates or activates only missing work where the recorded identity permits it. Do not revive retired member workflows. For an API rollback, core’s rollback-api.yml moves the stack’s recorded aliases and writes the release record. It refuses to cross a cutover. Pointer rollback cannot undo a contracted database schema. Dev shell rollback selects an earlier compatible composition and activates the earlier candidate under the composition lease. If its candidate is absent, produce that source first. See Deployment for the dev activation controls.

Safety properties

  • CREATE and ACTIVATE are separated by a barrier; a failed CREATE does not activate a partial set.
  • API migrations belong to activation on the central path. Stage-mode Terraform does not move existing aliases.
  • Frontend claims, markers, and source identities are verified before promotion or newly live pointer writes.
  • A incompatible or unreadable federation composition prevents the frontend flip.
  • Live pointer writes use compare-and-swap. Separate objects still have an observable transition interval.
  • A recorded second test produce never rewrites the original by-commit pointer.