# Contabo release operations This site publishes static content through the merged Contabo release manager. It does not run `nixos-rebuild`, reload nginx, change DNS, or write directly to `/srv/www/azinstitute4autism.com/www/dist`. ## Required local tools and private inputs - Node.js 22+, Git, tar, SSH and rsync. - A normal SSH identity accepted by the existing root receiver: `AIA_DEPLOY_SSH_IDENTITY=/absolute/path/to/identity`. - `AIA_DEPLOY_HOST=administrator@host` (or the approved equivalent). - For a real public release, an owner-controlled, regular encrypted payload: `AIA_PORTAL_PRODUCTION_CIPHERTEXT_FILE=/absolute/private/employee-portal/approved-production-ciphertext.json`. The payload remains outside Git and the source snapshot. It is browser ciphertext only; neither access code nor decrypted portal HTML enters an Astro environment variable, public resource directory, build log, or deployment manifest. ## Commands From `www/`: ```sh npm run deploy -- --dry-run ``` Dry-run performs the local production build, tests, artifact verification, manifest creation and source-snapshot preparation. With no private production payload it uses a generated synthetic two-stream fixture and explicitly reports that the result is not production-ready. It never opens SSH or rsync. ```sh AIA_DEPLOY_HOST='root@approved-host' \ AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \ AIA_PORTAL_PRODUCTION_CIPHERTEXT_FILE="$PWD/private/employee-portal/approved-production-ciphertext.json" \ npm run deploy -- --confirm ``` The confirmed command builds with `PUBLIC_ALLOW_INDEXING=true`, Form A live and counters off, then uploads only fresh commit-specific `staging/source-` and `staging/dist-` directories. It runs, in order: ```text aia-website-release verify aia-website-release sync-source aia-website-release promote ``` The VPS verifies the manifest, promotes an immutable release by atomic symlink, and retains the prior release. A successful rsync transfer alone is not success. Rollback requires the reviewed manifest retained at the server’s fixed path: ```sh AIA_DEPLOY_HOST='root@approved-host' \ AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \ npm run deploy:rollback -- FULL_APPROVED_SHA --confirm ``` ## Employee resources: separate one-time operation Approved non-PHI employee files are never part of an ordinary release. After the website release that contains `portal-resource-install.mjs` is promoted and the VPS SOPS-backed Basic Auth material is independently ready: ```sh npm run deploy:portal-resources -- --dry-run AIA_DEPLOY_HOST='root@approved-host' \ AIA_DEPLOY_SSH_IDENTITY="$HOME/.ssh/AIAMarketing" \ npm run deploy:portal-resources -- --confirm ``` The installer reads only the private collection manifest, accepts approved `STAFF-INTERNAL` and `MANAGEMENT-INTERNAL` mappings to `/staff-resources/` and `/management-resources/`, verifies every local hash, rejects links/traversal and uploads a root-controlled temporary tree. It never uses `--delete` for resource directories and refuses to replace a different existing file. The VPS installs regular files as `root:nginx` mode `0640` and reports metadata only. Before public DNS cutover, test the site with approved host-header/SNI methods, including the portal’s noindex response, valid ciphertext unlock, both protected resource namespaces, denial cases, redirects, Form A, IPv4 and IPv6. Portal shared-code rotation is coordinated: update VPS SOPS inputs and privately re-encrypt the browser payload together. This interim portal is non-PHI and is not an employee identity system.