Home / How the site is built

Admin

Two things live under /admin/: how this site is built and released, which exists, and the environment admin pages, which are proposed.

How the site is built

There is no build step and no bundler. The committed tree is the deployed tree. Five generators under admin/build/ write the parts that must not drift (the chrome, the status tables, the release table, the markdown twins, the machine indexes), each with a --check mode, and an eight-check gate in admin/build/validate.js refuses a release that disagrees with itself. The same command, python3 admin/build/gate.py, runs locally and in CI. Every push to dev is a release: the version in admin/build/version.txt is repeated in the commit subject as site vX.Y.Z : what, CI tags it, deploys it, and then polls the live site until it serves that version. The whole procedure is in docs/ops/release.md.

The eight checks

  1. Version agreement. version.txt equals every page badge, the newest row of the versions table, llms.txt, llms-full.txt, index.md and config/environments.json#siteVersion; no version is listed twice.
  2. Internal links and fragments resolve, in every HTML and markdown file.
  3. Canonical host. Every page has rel=canonical and og:url on the host in CNAME.
  4. Leak tripwire on every file in the tree: sgit vault and read keys, AWS and GitHub tokens, API keys, PEM private key blocks, Slack tokens, Google OAuth client secrets, service-account JSON, bare twelve-digit numbers. The fix for a trip is always a redaction, never a wider pattern.
  5. Vendor manifest. Every file under vendor/ matches its SHA-256; no script is loaded from another origin anywhere under app/, components/, admin/ or tests/.
  6. Storage rules in sync. The hash of infra/rules/storage.rules equals the hash recorded in data/features.json, so a rules change without a release note fails.
  7. Reality. docs/reality.md is what data/features.json generates.
  8. No storage of secrets in code. Every localStorage.setItem and sessionStorage.setItem uses a key listed in app/config/storage-keys.js.

The admin pages, proposed

The admin pages will work only when the visitor signs in with a Google account that has IAM on the selected environment's GCP project. There will be no admin role in the app: the project's IAM is the role, and the pages are a client for GCP's own APIs, calling them with the visitor's own token held in memory. Every write action will show the exact request before sending it. None of this exists yet.

AreaFeatureStatusWhereNotes
adminComms page: the asks back to the project lead and the nine build steps with status, from data/steps.jsonshipped v0.1.1admin/comms.htmlgen_versions.py renders the step tracker; a done step must name a release that exists.
adminAdmin sign-in with the visitor's own Google account, token in memory onlyproposedadmin/oauth.jsStep 7. Implicit flow to verify first; PKCE fallback.
adminSetup checklist: every per-project resource as a row, with Fix where fixable client-sideproposedadmin/setup-checklist.htmlStep 3 read-only, step 7 with fixes.
adminAuth config, storage, rules diff and deploy, users, environment exportproposedadmin/*.htmlStep 7. GCP IAM is the role; the pages are a client for GCP's own APIs.
adminRelease history page generated from data/versions.jsonshipped v0.1.0admin/versions.htmlOne row per release; the newest row must equal version.txt.

The pipeline, as it stands

AreaFeatureStatusWhereNotes
pipelineOne version in admin/build/version.txt, repeated in every badge, twin, index and configshipped v0.1.0admin/build/version.txtCheck 1 of the gate fails on any disagreement.
pipelineChrome (head, nav, footer, version badge, CSP, canonical) generated into every page from one definitionshipped v0.1.0admin/build/chrome.pygen_chrome.py --check is part of the gate.
pipelineMarkdown twin of every HTML page, links pointing at markdownshipped v0.1.0admin/build/gen_twins.pyindex.html has index.md beside it; the twin carries the site version.
pipelinellms.txt, llms-full.txt and sitemap.xml generated on every releaseshipped v0.1.0admin/build/gen_llms.pyllms-full.txt concatenates every twin and every design document.
pipelinedocs/reality.md and the status tables generated from data/features.jsonshipped v0.1.0admin/build/gen_features.pyIf the reality document does not list it, it does not exist.
pipelineThe eight-check release gate, no dependenciesshipped v0.1.0admin/build/validate.jsVersion agreement, internal links, canonical host, leak tripwire, vendor manifest, rules in sync, reality, storage keys.
pipelineThe same gate locally and in CI, one commandshipped v0.1.0admin/build/gate.pyThe CI validate job runs gate.py; a release that fails locally fails the same way in CI.
pipelineEvery push to dev is a release: version.txt and the commit subject agree, CI tags itshipped v0.1.0admin/build/tag_release.pyAnchors on the newest commit whose subject is 'site vX.Y.Z : ...', asserts the next minor or patch or major .0, backfills missing tags.
pipelineDeploy to GitHub Pages from the validated treeshipped v0.1.0.github/workflows/deploy-pages.ymlExcludes .git, .github, infra, tests/unit and node_modules. Actions pinned by commit SHA.
pipelineverify-live: the run is red until the live site serves the released versionshipped v0.1.0admin/build/verify_live.pyGreen does not mean live. Polls version.txt and the homepage badge for up to ten minutes.
pipelineEvery third-party file vendored and hashed in vendor/MANIFEST.json; no runtime script from another originshipped v0.1.0vendor/MANIFEST.jsonCheck 5 of the gate. Today the only vendored file is the family design tokens.

The admin section