# Website system design

## Context and boundary

The website is a static handbook in the separate private repository `devSatym/gcp-security-handbook`, with newly initialized Git history on its own main branch. It describes the preserved GCP implementation at `cbbc807c0c150e106affa89fbb1b9e8349005749` in `devSatym/gcp-supply-chain-security`, whose reviewed main revision is Azure. This handbook work leaves the original local application's tracked infrastructure, release workflows and root README unchanged and makes no source-project push. Separately observed community/documentation and README commits advanced source remote main; those changes are not incorporated here. Source preservation is not a claim that another actor cannot advance that remote. The handbook repository contains `website/` and documentation-only workflows; it has no application release graph. Browser interaction is local presentation, not a query of live cloud state.

Current hosting is native Git-integrated Cloudflare Pages Free. The owner authorized the public handbook and its approved originals while retaining private GitHub source. Production is verified at `https://security.devsatym.xyz/`; provider deployment, custom-domain HTTPS and hosted website results are recorded separately in excluded `engineering/audits/` receipts. These website observations do not establish a running GCP environment.

```mermaid
flowchart LR
  Baseline[Pinned historical source] --> Records[Reviewed catalogues]
  Evidence[Reviewed original images and transcripts] --> Inputs[Website build inputs]
  Records --> Inputs
  MDX[Trusted Markdown and MDX] --> Inputs
  Reports[Explicit report allowlist] --> Inputs
  Inputs --> Validate[Schema and reference checks]
  Validate --> Astro[Astro and Starlight static rendering]
  Astro --> HTML[HTML CSS SVG and small scripts]
  HTML --> Search[Pagefind production index]
  Search --> Audit[Output audit and static asset limits]
  Audit --> Dist[dist publication artifact]
  Dist --> Pages[Native Git Cloudflare Pages]
  Inputs --> CI[Independent GitHub browser validation]
  CI --> Review[Preview and check review before merge]
```

Cloudflare's native build checks the static artifact; the complete Playwright matrix runs independently in GitHub CI. The review step is a maintainer responsibility, not an automatic dependency of the native Pages build.

## Component responsibilities

Astro owns content collection loading, MDX execution, build-time component rendering, and static routes. Starlight supplies layout, navigation, themes, table of contents, code-block affordances, and integrated Pagefind search. Custom Astro components expose baseline context, source references, security contracts, diagrams, architecture stages, reading paths, the release journey, and evidence records. No global application framework is introduced.

`src/data/catalogue.ts` aggregates immutable checked-in catalogue records and supplies fail-fast ID lookups. `src/lib/schemas.mjs` validates catalogue records and their relationships. `src/lib/urls.mjs` centralizes base-path prefixing, route URLs, and commit-pinned source URLs. Site-specific CSS remains in `src/styles/theme.css` while Starlight owns its standard controls and layout.

## Data ownership and processing

The baseline manifest identifies the implementation repository, source SHA, tag resolution, inspection/review dates, and evidence-source context. Its `currentMainCommit` describes the canonical source project rather than handbook main. `documentation.json` separately owns handbook repository/branch/visibility and hosting defaults; selected build-time coordinates determine the emitted origin/base. Revision tooling records real documentation repository/main/head/dirty state. Sources have snapshot hashes and full-SHA URLs. Controls have explicit scope, exclusions, failure behavior, dependencies, and limits. Evidence records have provenance, category, observation/revision uncertainty, expected/actual results, original reference, transcript, publication approval, and limitations. The site never fills unknown evidence dates from file mtimes.

Original project evidence is untouched. All fourteen reviewed source PNGs are copied unchanged into the handbook's approved static asset set and published on Cloudflare, alongside five retained selected-output transcripts. Eight evidence records display an image; the complete gallery adds six other/contextual captures, preserving fourteen unique original images. Internal work ledgers, privacy-mask proposals and raw audit logs remain in `engineering/` and are not copied wholesale. A publication allowlist selects sanitized engineering reports under `public/reports/`. Reports are website documents, not proof that cloud operations were executed.

`src/data/screenshots.json` and its typed `screenshots.ts` adapter record all fourteen source/display hashes, dimensions, collection/review dates, revision context, control/evidence associations, expected/recorded result, direct/context relation and privacy notes. `ScreenshotGallery.astro` renders the complete collection at `failure-cases/screenshots`, while image-bearing `EvidencePanel` records retain their detailed transcripts and link into the gallery. Contextual captures are not silently upgraded into the same release observation as their related record.

## Rendering, assets, and search

Diagrams are accessible SVG rendered at build time from `diagrams.json`. Their titles, captions, semantics, and ordered text equivalents carry meaning independently of visual arrows. No Mermaid browser runtime or external diagram service is required. Evidence PNGs retain explicit dimensions; full-image links expose readable detail. Favicon and robots output accompany static routes.

Pagefind indexes generated pages during the production build. Tests use production preview at the actual project base. The development server is useful for authoring but cannot establish that production search chunks, deep links, or asset prefixes work. Static output supports direct refresh and reading without a cloud backend.

## Publication authority

The owner's later Cloudflare instruction authorizes publication of this handbook and its existing approved assets. The Cloudflare Workers & Pages GitHub App connects the private documentation repository to the native Pages project. Production builds follow relevant pushes to `main`; other branches receive native previews. Both the website and previews are public unless separately protected. Repository privacy is not a website access control. [Git integration](https://developers.cloudflare.com/pages/get-started/git-integration/), [preview access](https://developers.cloudflare.com/pages/configuration/preview-deployments/)

Read-only `docs-validate.yml` checks website content and runs the complete browser matrix without application-cloud credentials. The separate native build command, `npm run build:cloudflare`, runs lint, Astro/type checks, unit/content tests, static rendering, output auditing and Free asset-limit checks. It does not run Playwright or automatically wait for GitHub CI. Review native previews and passing GitHub checks before merging into production.

The unused `docs-pages.yml` retains the historical manual GitHub Pages option: separate contents-read build and Pages/id-token publication jobs, a private-repository guard and `dist`-only upload. Those permissions are not the current Cloudflare publication mechanism. No GCP/Azure identity, paid plan, repository visibility change, nameserver migration or unrelated DNS mutation is introduced.

## Hosting profiles and domain ownership

Production uses `DOCS_SITE=https://security.devsatym.xyz` at `/`, with the same fallback in the preview environment. The native Cloudflare root is `website`, build command is `npm run build:cloudflare`, output directory is `dist`, and Node is pinned to `22.20.0`. Production auto-deployments and all-branch previews are enabled. Native non-main builds derive their origin from validated `CF_PAGES_URL` and emit preview noindex/robots metadata. GitHub subpaths remain compatibility tests, not the current hosting destination.

| Profile | Site origin | Base path | Purpose |
| --- | --- | --- | --- |
| Cloudflare production | `https://security.devsatym.xyz` | `/` | Current published handbook |
| Cloudflare preview | Validated native `CF_PAGES_URL` | `/` | Non-main branch preview with indexing controls |
| Custom local profile | `https://security.devsatym.xyz` | `/` | Default local/compatibility artifact |
| Standalone GitHub domain | `https://devsatym.github.io` | `/gcp-security-handbook` | Historical GitHub compatibility test |
| Legacy compatibility | `https://devsatym.github.io` | `/gcp-supply-chain-security` | Requested historical-prefix compatibility check |

`src/lib/deployment.mjs` exposes `resolveDeployment(env)` for `cloudflare|custom|github|legacy`. The Cloudflare wrapper selects `cloudflare`, requires an explicit stable production `DOCS_SITE`, and restricts the base to `/`; native non-main preview detection uses Cloudflare's branch and URL variables. Other named profiles accept validated HTTPS-origin and clean-base overrides. Legacy `SITE_URL`/`SITE_BASE` aliases remain accepted for earlier tooling; conflicting old/new values fail. Canonical/sitemap/social URLs, Pagefind navigation, internal routes and public evidence/report/favicon URLs derive from the resolved profile.

A production artifact belongs to one origin/base. `scripts/validate-profiles.mjs` (`npm run test:profiles`) independently builds/audits/browser-tests the three compatibility profiles, retains outputs under `.profile-builds/{custom,github,legacy}`, and records their own artifacts/screenshots under `engineering/audits/profiles/`. It restores custom-domain output to `dist` at the end; a Cloudflare publication still requires its own fresh native-profile build. Root-path success does not establish subpath success or portability to arbitrary roots.

Hostname ownership is one site per repository: `security.devsatym.xyz` is the active handbook; `devsatym.xyz` is the future central portfolio/catalogue; `resilience.devsatym.xyz` and `aks.devsatym.xyz` are future separate project sites. The portfolio is not a dependency of the security site. DNS maps hosts rather than case-study URL paths. Future destinations remain non-clickable planned items until checked; this build does not publish other repositories.

The Pages project associates `security.devsatym.xyz` with its assigned `gcp-security-handbook.pages.dev` hostname. At authoritative provider Spaceship, the owner added `CNAME security → gcp-security-handbook.pages.dev`; direct authoritative/recursive DNS and real verified HTTPS were observed. A subdomain can use external DNS without moving nameservers. Pages association and valid HTTPS preceded promotion of the production `DOCS_SITE`. No repository CNAME file, GitHub account TXT challenge or GitHub Enforce HTTPS setting participates in this native Cloudflare setup. Preserve apex, mail and unrelated records. [Cloudflare custom domains](https://developers.cloudflare.com/pages/configuration/custom-domains/)

## Public assets and reusable identity

Evidence delivery remains a static publication allowlist. The initial three-image selection is historical; the owner's later instructions approve all fourteen reviewed originals under `public/evidence/`, already published unchanged in bytes and dimensions. Terminal/account metadata remains visible and labelled in provenance/privacy notes. No additional pixel redaction was selected or applied. Proposed masks remain private; a future derivative requires owner direction and an accurate display hash, dimensions and disclosure while retaining the original source reference.

Historical gallery-layout checkpoint (2026-10-05): the first gallery functional result and subsequent catalogue Lighthouse score 80/CLS 0.465829 remain preserved. Repair bounded the sticky TOC, allowed the main pane to shrink and reserved image space through block links/aspect ratios. At that checkpoint, ten unit/eighteen content cases and thirty-one browser cases per profile passed, including delayed-image regression, with zero output errors. Repaired Lighthouse scored all four categories 100 on three routes, with maximum CLS 0.008051353. These are the retained local repair measurements, not new tests of a later published artifact. Current hosted results belong to their separate excluded audit receipts.

Editorial assets can be imported from `src/assets` for Astro processing; technical screenshots are copied without automatic optimization. `public/` never appears in a browser URL. [Astro image storage](https://docs.astro.build/en/guides/images/)

The 1200×630 raster social card is original editorial presentation, not recorded execution evidence. Its absolute HTTPS URL follows the selected profile. Diagram SVGs, screenshots, social art and report assets are served by the same static site; no image CDN, bucket or browser-time profile service is required. Local delivery checks alone do not establish an actual sharing-crawler request.

`src/data/author.ts` supplies the typed proposed public name, handle, headline, biography and profile destinations, with destination availability stored separately. Optional avatar, email and resume fields remain null and certifications remain empty without owner-approved details. An initials fallback avoids inventing a headshot. `src/data/projects.ts` records repository and documentation URLs, availability, summary and optional approved preview; availability determines whether a destination becomes a link. `Header`, `AuthorByline`, `AuthorProfile`, `AuthorFooter` and `MoreProjects` components reuse these records. Attribution distinguishes maintained/documented/adapted contributions from upstream original work and recorded historical evidence ownership.

## Failure modes and trade-offs

Invalid metadata or an unknown catalogue ID should stop validation/build. Broken links/assets/anchors should stop the output audit. Browser-only regressions in search, filters, navigation, or themes should stop production E2E. Missing provider objects in the historical baseline are source discrepancies, not website code to repair. Explicit source hashing uses `SOURCE_REPO_PATH` to inspect the original checkout's Git objects; routine website builds do not fetch or copy application history. Network access is only an external setup concern when that separate source checkout lacks the recorded baseline.

Static output limits dynamic dependencies and publishing cost, but content can become stale and client-side search requires downloaded index chunks. MDX provides useful composition but executes at build time and requires code review. Evidence publication improves inspectability but creates disclosure risk; approval and allowlisting reduce that risk without promising automatic secret detection. All performance and accessibility results remain bounded to recorded tests.
