Architecture
Architecture
The workbench separates authored Git content from reconstructable Confluence working data.
- Source
docs/architecture.md- Mode
- rendered markdown
- State boundary
- authored documentation; not live state
Architecture
The workbench separates authored Git content from reconstructable Confluence working data.
RWS Confluence
|
| read-only REST API
v
Confluence cache producer
|-- private XHTML snapshot -> local agents or deployment PVC
`-- sanitized public JSON -> nginx /runtime/confluence/
|
v
static Astro portal shell
RWS-ARCH/ -> validators -> static Astro vault routes
Cache producer
.scripts/confluence-cache.mjs implements status, sync, reset, and import. Synchronization paginates CQL discovery for the complete INFRAARCH page set, fetches approved page metadata and storage XHTML with GET requests, applies a bounded concurrency and retry policy, and refuses to publish a partial snapshot.
Each generation receives a content-derived snapshot ID. The producer builds into a temporary directory, validates identities, installs immutable private and public generation directories, and replaces public/current.json last. Failed runs leave the previous pointer untouched. Current and previous generations are retained.
Import copies only a validated public snapshot from another portal cache. It derives every immutable artifact URL locally from the validated snapshot and page IDs, follows redirects only within the source origin, and installs no private storage XHTML. A later direct Confluence sync therefore refetches page bodies before it can build or reuse private cache state.
Portal
The Astro build contains one content-free /confluence/ shell. At runtime the browser reads:
/runtime/confluence/current.json/runtime/confluence/snapshots/<snapshot-id>/navigation.json/runtime/confluence/snapshots/<snapshot-id>/pages/<page-id>.json
Every artifact is strictly validated for schema, numeric page IDs, snapshot identity, tree consistency, source hashes, and inert markup. Numeric /confluence/<page-id>/ routes are served by a narrow nginx fallback to the static shell. There is no site-wide SPA fallback.
Deployment authentication is evaluated on every Confluence shell, artifact, and control request. Responses use private, no-store caching even though snapshot paths are content-addressed.
The shell also exposes deployment-provided sync and copy-main controls. The application sends only the documented same-origin control requests and polls their status; authentication and authorization are deployment responsibilities. The copy control imports the main deployment's sanitized public cache and does not make the preview cache authoritative or shared with main.
.scripts/confluence-cache-control.mjs serves only GET /health, GET /runtime/confluence/control/status.json, and the two corresponding POST action endpoints. It binds to loopback by default. In production, every action requires the configured exact Origin, JSON media type, control header, and an exact {} body; deployment routing must keep the endpoints behind deployment authentication. Work runs asynchronously with one active operation, a startup sync, and periodic refreshes. API status and errors are bounded and never expose credentials, upstream content, or filesystem details.
Deployment
Stable and preview workloads use one replica and a CephFS ReadWriteMany PVC-backed cache. A dedicated worker receives the Confluence Secret, executes the repository sync command on startup and periodically, and shares only <cache-root>/public read-only with nginx. An init container creates the public subpath on a fresh claim. The static site and cache use separate mount paths.
The PVC is disposable. Recovery is an empty portal state followed by a complete refresh. It is not backed up for correctness.
CI evidence
CI never reads live Confluence. Portal tests and browser evidence mount the synthetic cache under test/fixtures/confluence-cache/public/. The evidence bundle records that synthetic mode but does not copy cache content into the artifact.