Spaces:
Running
Running
File size: 7,422 Bytes
da0ce7b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | # Aureon website release tooling
This directory is the single automated release stack for the static site in
[`website/`](../../website/):
`audit -> commit-bound build -> fresh backup gate -> non-pruning FTPS upload -> exact read-back`
An upload is not publication proof. The release is complete only when the
read-back comparison passes for the exact package.
## 1. Audit
```powershell
python -m scripts.website.audit_site --root website
```
The deterministic audit fails on broken internal links/assets, invalid JSON or
JSON-LD, sitemap/canonical drift, and the static accessibility/SEO contracts it
implements. It is not a substitute for the separate claim, browser, a11y, or
Core Web Vitals gates.
## 2. Build an exact release
The source commit is mandatory. In a Git worktree it must equal checked-out
`HEAD`, and the bounded `website/` tree must be clean. An uncommitted public file
cannot be described as belonging to a commit.
```powershell
$sourceCommit = (git rev-parse HEAD).Trim()
python -m scripts.website.build_package `
--root website `
--out artifacts/website-releases `
--source-commit $sourceCommit
```
The build writes:
- `website_package/` with `index.html` at its root;
- `website_package/HOMEPL_PACKAGE_MANIFEST.txt`, which names the exact source
commit and package contract;
- `website_package/HOMEPL_FILE_HASHES.json`, a sorted SHA-256 record for every
other package file, including the summary manifest;
- `aureon-zorza-website.zip`, produced with deterministic ordering and
timestamps; and
- `aureon-zorza-website.zip.sha256.txt`, the external companion containing the
ZIP hash and the hash of `HOMEPL_FILE_HASHES.json`.
`HOMEPL_FILE_HASHES.json` intentionally excludes itself to avoid recursive
self-hashing. Its own SHA-256 is in the external companion.
For byte-identical reproduction, also pass the same `--created-at` value. A
standalone test fixture outside Git can build with an explicit valid commit, but
the manifest labels that binding `declared-only-isolated-source`; a real
repository build is labelled `verified-git-head-clean-site`.
## 3. Create and verify a fresh backup
Before any remote write, map the authenticated Home.pl served root and create a
fresh recursive backup with a non-zero manifest. The audited backup tool is
[`website/backup-homepl-ftps.ps1`](../../website/backup-homepl-ftps.ps1). It
emits an `aureon.homepl-backup-transfer.v1` receipt only after a complete,
read-only transfer and manifest verification.
Do not assume that the root is `/` or `/public_html`. The exact current provider
mapping controls. If the existing backup tool's strict root/preflight contract
does not match the current provider mapping, stop and use the Home.pl provider
backup as a named human host gate; do not weaken the mapping check or fabricate
a receipt.
## 4. Plan and deploy without pruning
The Python deployer and the audited PowerShell tools use one environment-name
contract:
| Variable | Required | Meaning |
|---|---:|---|
| `HOMEPL_FTPS_HOST` | yes | FTPS hostname only |
| `HOMEPL_FTPS_USER` | yes | temporary or approved FTPS account |
| `HOMEPL_FTPS_PASSWORD` | yes | process-only secret; never logged |
| `HOMEPL_FTPS_REMOTE_ROOT` | yes | exact authenticated served root |
| `HOMEPL_FTPS_PORT` | yes | exact authenticated port; never inferred from mode |
| `HOMEPL_FTPS_MODE` | yes | exactly `explicit` or `implicit` |
| `HOMEPL_FTPS_CERT_THUMBPRINT` | PowerShell only | optional pinned certificate thumbprint |
Retained Home.pl configuration evidence points to implicit FTPS on port 990.
The Python uploader supports that transport and explicit FTPS as two separate,
fail-closed modes. Both use the operating system trust store with certificate
and hostname verification and require `PROT P`; implicit mode wraps the control
socket before reading the server welcome and never sends `AUTH TLS`, while
explicit mode negotiates TLS after the welcome. Mode and port remain mandatory
and are never inferred from one another. The exact provider hostname, served
root, and approved credentials are still unresolved operator gates, and no live
Home.pl connection or publication is claimed here. Do not silently substitute
explicit port 21.
Dry-run still requires the target binding and process-only credentials because
it prints the exact authenticated-account plan, but it performs no network
operation:
```powershell
python -m scripts.website.ftp_deploy `
--package artifacts/website-releases/website_package `
--dry-run
```
A live upload additionally requires the fresh backup transfer receipt:
```powershell
python -m scripts.website.ftp_deploy `
--package artifacts/website-releases/website_package `
--backup-receipt C:\absolute\path\to\backup-transfer.json
```
The deployer verifies the local package against its per-file manifest before
opening a connection. It also verifies that the backup receipt was produced by
the checked `website/backup-homepl-ftps.ps1`, that its deterministic CSV
`Path,Bytes,Sha256` manifest matches the exact downloaded directory, and that
its counts, byte totals, root and freshness agree. A hand-authored receipt or a
manifest detached from the backed-up files is refused. The deployer
creates/overwrites package files only. Pruning and remote deletion are disabled;
`--prune` is always refused.
## 5. Compare exact read-back
Capture the served-root files through the authenticated operator or fetch the
public paths into an isolated directory, then compare without credentials or
network access:
```powershell
python -m scripts.website.readback `
--package artifacts/website-releases/website_package `
--readback-dir C:\absolute\path\to\captured-served-root
```
The directory helper verifies `HOMEPL_FILE_HASHES.json` itself, every listed file
by size and SHA-256, and the absence of unexpected files in the downloaded
served-root mirror. This exact-mirror rule prevents a mixed release from passing
when non-pruning upload leaves stale public files.
`compare_http_observations()` verifies every expected package path from already
captured status/body objects. It cannot discover an unknown stale URL that was
not requested, so it is expected-path evidence, not proof of an exact served-root
file set. Reports never contain bodies, URLs, headers, cookies, or credentials.
TLS, cache headers, public route rendering, visual regression, accessibility,
claim lint, and Core Web Vitals remain separate mandatory release evidence.
## Manual provider alternatives
Home.pl WebFTP ZIP upload/unzip is a manual host-gate alternative, not a second
release stack. It must use the exact audited ZIP, the same fresh backup gate,
the exact served root, and the same per-file read-back comparison. The legacy
`website/publish-homepl-ftps.ps1` CSV flow and
`website/build-homepl-package.ps1` are not the canonical V45 automated path.
Do not mix their legacy manifests with `HOMEPL_FILE_HASHES.json`.
## Focused verification
```powershell
$env:PYTHONDONTWRITEBYTECODE = '1'
python -m pytest -p no:cacheprovider tests/test_website_tooling.py -q
python -m ruff check scripts/website tests/test_website_tooling.py
python -m mypy --strict scripts/website/build_package.py scripts/website/ftp_deploy.py scripts/website/readback.py
```
|