• Status: decided deployment contract before the Storybook build exists; commands and routes below describe the future realized delivery.
  • Dependencies: 30-first-delivery defines the component and browser contract; 10-topology-options defines renderer/CSS separation; 20-fleet-evidence records source provenance.

Build runtime

LayerRequired or accepted versionBasis and boundary
Nodev22.23.1Existing owner-probed runtime; retained for building and the static server
npm10.9.8Existing owner-probed package manager; installs and lockfile confined to stbk
Storybook10.6.0Chosen version, not a dependency already present in the fleet projects
Framework@storybook/svelte-vite 10.6.0One native Svelte renderer per instance
Svelte5.57.0Common resolved version in the three selected Svelte projects
ViteMajor 8 accepted by the framework peer rangeThe exact installed patch will be recorded in stbk’s lockfile; source locks contain both 8.2.2 and 8.3.0
Svelte Vite plugin@sveltejs/vite-plugin-svelte 7.3.0Source-resolved integration version, within the framework’s accepted plugin range
Tailwindtailwindcss and @tailwindcss/vite 4.3.3CSS-first pipeline; external source discovery must be explicit
daisyUI5.7.38Fleet preview only, with four replicated custom themes
Bits UIbits-ui 2.19.0Separate bits preview; not a replacement for the source ink stylesheet
Flow@xyflow/svelte 1.6.6Real StudioNode fixture and required Flow stylesheet
Icons@lucide/svelte 1.37.0Dependency of the three selected bits demonstrations
Chat MarkdownNot installedNot installed. Formatted display cases use recorded, pre-sanitized block fixtures; local edit results use escaped Svelte text rendering. No runtime Markdown conversion or sanitizer equivalence is claimed.
  • Compatibility evidence:
    • The published framework package metadata includes Svelte 5 and Vite 8 in its peer ranges.
    • Peer acceptance is not a performed install/build proof. The owner will verify the resolved dependency graph and browser execution under the retained runtime.
    • The two Storybooks will use standalone Svelte/Vite configuration, not import SvelteKit application bootstraps or sibling package-install workflows.
  • Runtime fence:
    • No Node or Bun replacement is permitted; installed runtime binaries and global configuration will remain untouched.
    • A newly discovered higher runtime requirement will be a blocker, not an upgrade mandate or permission to force an incompatible installation.
    • Package and lockfile changes will belong only to stbk. No sibling install, migration, formatter, or build command will be run as a side effect of component reuse.

Serving model

  • Artifacts:
    • The root fleet instance will build to the deploy root.
    • The separately built bits instance will occupy a bits subdirectory of that same root. Build staging/assembly must prevent the root build from deleting the referenced output.
    • One dependency-free Node static server will serve the entire tree. Composition will not require a second server process or a second backend port.
  • Build and public routes:
    • Storybook 10.6.0’s Vite builder defaults to base: './', and its manager emits relative asset and index URLs. Build both instances normally into separate staging outputs, then assemble the deploy tree; no required viteFinal base override or custom preview URL is needed. Redirect /bits to /bits/ while preserving the query string. The standalone manager is /bits/?path=/story/<story-id>, its preview is /bits/iframe.html?id=<story-id>&viewMode=story, and the composed manager link is /?path=/story/bits_<story-id>. Missing files must not fall back to either manager HTML.
    • Use normal storybook build with separate --config-dir and --output-dir values and independent staging, then assemble the output trees. Keep manager assets relative; avoid root-absolute custom media.
    • --preview-url and --test builds are forbidden. The CLI build implementation skips the local preview when --preview-url is used unless explicitly forced; getRefs removes refs in --test mode.
    • Version-pinned basis: Vite builder configuration, manager template, and preview URL routing.
  • Process:
    • One systemd unit, stbk.service, will run the Node static server as the operator account.
    • The server will bind only to the selected loopback endpoint and serve only the assembled Storybook output, not arbitrary sibling source paths.
    • It will support the HTML, JavaScript, CSS, story indexes, and local media assets required by both instances; unknown assets will return genuine missing-resource responses rather than the root HTML document.
    • /bits will resolve consistently to /bits/; direct loading and refresh of the referenced instance must work independently of root composition.
  • Endpoint selection:
    • The primary and two documented substitutions were owner-probed free. Occupancy must still be checked immediately before staging the final service/proxy configuration.
    • Use the first available candidate in the recorded order; a substitution must be recorded and applied to both unit/server configuration and nginx’s upstream. The server must not silently select a different endpoint.
bind-address: 127.0.0.1
operator-port-band: 51000-53000
port-order:
  - 51945
  - 51955
  - 51965
primary-endpoint: 127.0.0.1:51945
  • Edge:
    • Both stbk.loca.zone and wiki.stbk.loca.zone already resolve to the operator host according to owner preflight; that observation does not establish application readiness.
    • One nginx site file will contain the two hostname server definitions.
    • The application hostname will proxy to the single static server, preserving paths for the root and /bits/ output.
    • The wiki hostname will serve the shared wiki release root wikis/stbk/current directly; it will not proxy through the Storybook process.
    • One certbot run will request a certificate covering both names.
  • Composition:
    • The root instance’s main.ts will reference the app origin plus /bits; the standalone referenced browser entry is /bits/.
    • The following is a decided configuration fragment, not a claim that the file has already been built or deployed.
refs: {
  bits: {
    title: 'bits',
    url: 'https://stbk.loca.zone/bits',
  },
}
flowchart LR
  B["Browser"] --> A["stbk.loca.zone"]
  B --> W["wiki.stbk.loca.zone"]
  A --> N["One nginx site file"]
  W --> N
  N -->|"App proxy"| S["stbk.service: one Node static process"]
  S --> F["Deploy root: fleet build"]
  S --> R["bits subdirectory: separate build"]
  N -->|"Wiki static root"| Q["wikis/stbk/current"]
  V["stbk/q5vault source"] --> K["Shared wiki build script and lock"]
  K --> Q

Privilege budget

  • Boundary: exactly four uses of sudo, reserved for the owner during realization. There is no privileged implementation work delegated to story or plan authors.
  • Counting rule: each row is one invocation; compound operations must remain inside that bounded invocation rather than expanding into additional privileged calls.
UseAuthorized operationRequired scope
1Unit installInstall the staged stbk.service definition; no edits or restarts to existing fleet units
2Nginx site install plus enableInstall/enable the single dual-host site file, validate nginx, and reload within this invocation; unrelated sites remain unchanged
3One certbot runRequest both hostnames together, once; preserve a usable HTTP-only dual-host configuration if issuance fails
4Unit enable/restartReload systemd’s unit definitions, enable and restart only stbk.service, then observe readiness
  • Before privilege:
    • Build outputs and stage the unit/site definitions inside stbk.
    • Confirm the selected endpoint and both hostname targets; retain the necessary rollback material without touching unrelated host configuration.
    • Builds, source reads, local artifact assembly, and wiki publication will not consume additional sudo calls.
  • Certbot failure:
    • No retry loop, second certificate request, or hidden fifth sudo invocation.
    • Leave an HTTP-only dual-host vhost and record TLS pending; if the certbot operation partially changes the site, retain or restore the staged HTTP configuration within the same authorized invocation.
    • The owner may continue the fourth step so the HTTP application can serve. HTTP reachability is an operational fallback, not completed HTTPS publication.
    • Any later privileged recovery beyond this budget requires a new owner decision; it is not implicit authority to alter another unit, site, or runtime.

Read-only fences

  • Fleet:
    • Every sibling project remains read-only, including sflw, svelte-chat, bits, airi, iconmania, click2punch, and wrdp.
    • Direct imports may read permitted source graphs. Where no component file exists, attributed adaptations will be authored inside stbk.
    • No writes to sibling source, manifests, lockfiles, installed dependencies, generated configuration, application state, or service definitions.
  • Operator configuration:
    • No changes to home configuration, global OMP state, package-manager configuration, runtime installation, or unrelated service/vhost files.
    • The four owner-only deployment operations above are the complete privileged exception, not a general host-maintenance allowance.
  • Quartz:
    • stbk/q5vault/ is the plan source and is exposed through the existing wiki content-root symlink.
    • No direct or persistent changes will be made to Quartz engine source, shared wiki infrastructure, or other vaults. The existing locked wikis/build.sh workflow may temporarily stage the stbk config and stylesheet in the engine tree and must restore the prior files on exit.
    • Wiki publication will run only through the shared wikis/build.sh workflow. The script acquires its own shared lock; do not surround it with another independent acquisition of the same lock. The owner will perform the integrated publication after page authors have finished; no competing direct engine build or manual release-tree mutation.
    • The build shell will explicitly use a readable umask rather than inheriting a previous secret-writing shell’s restrictive permissions.
# Run from the development root; the script acquires its own shared build lock.
umask 022
./wikis/build.sh stbk --check-only
./wikis/build.sh stbk

Failure modes and fallbacks

  • Composition ref fails to load:

    • Check the referenced story index, preview HTML, assets, base paths, and frame-loading policy at /bits/ independently from the root manager.
    • Keep the separate instance directly browsable at stbk.loca.zone/bits/ and expose that route as the visible fallback.
    • Do not merge the bits stylesheet into fleet, duplicate its components into the root renderer, or call direct browsing proof of working composition. A failed ref remains an acceptance failure until repaired.
  • Selected port becomes occupied:

    • Apply the fenced substitution order; each substitute is ten above the previous candidate.
    • Record the choice and stage matching server/unit and proxy values. Do not kill the occupying process, choose an undocumented endpoint, or add a second listener for bits.
    • If no candidate remains available, stop with a deployment blocker. If a later race would require extra privileged changes after the four calls, report deployment pending rather than exceeding the budget.
  • Quartz build succeeds but nginx cannot read the release:

    • A restrictive inherited umask can create an unreadable output tree despite a green build.
    • Use the explicit umask before the shared workflow; inspect generated directory traversal and file readability, then request the actual published pages. A successful build command alone does not prove HTTP readability.
    • Retain the previous publish target; recovery must use the established publication workflow rather than edits to the engine or unrelated release trees.
  • Rendered title or frontmatter leaks:

    • Verify the rendered article title against each page’s frontmatter title and inspect the article beginning for literal YAML/frontmatter leakage outside intended code examples.
    • Verify that wikilinks resolve to the five planned pages and that Mermaid fences become visible diagrams; a successful status code or a source file containing the expected title is insufficient.
    • Block publication on a leaked header, raw wiki syntax, missing diagram, or incorrect title; repair the owned vault/configuration input through the existing workflow, not shared Quartz internals.
  • TLS issuance fails:

    • Preserve the HTTP-only dual-host fallback and explicit pending state described in the privilege budget. Do not claim secure deployment or hide the failure behind a certificate retry loop.
  • Runtime or dependency compatibility fails:

    • Report the exact package/runtime requirement and stop that build. Do not replace Node/Bun, force peer resolution, or mutate a sibling project’s lockfile to make the plan appear complete.
  • Static-server readiness or asset delivery fails:

    • Observe the service’s actual listener and request both native Storybook entry points, their indexes, and representative assets through the application hostname.
    • A running unit without working HTTP assets is not ready. Preserve the assembled output and failure evidence; do not substitute an empty landing page or development server for the specified static delivery.
  • Final hosting evidence:

    • Both hostnames will be fetched through nginx; the app will be exercised in a browser at its public origin, including root composition and direct /bits/ navigation.
    • The wiki’s rendered content, not just HTTP status, will be inspected after the shared publish.
    • Record the effective endpoint, TLS outcome, four-call deployment boundary, and unchanged-fleet comparison. These are future completion requirements, not results asserted by this plan.