diff --git a/docs/persimmons-shared-cutover.md b/docs/persimmons-shared-cutover.md new file mode 100644 index 0000000..a06ab9b --- /dev/null +++ b/docs/persimmons-shared-cutover.md @@ -0,0 +1,52 @@ +# Persimmons shared-hosting cutover + +`https://persimmons.app` is a second front door for the source-owned +`matcha/persimmons` bytes already composed at +`https://xn--sj8h.teahub.xyz/%F0%9F%8D%8A/`. It is not an application or a +second Gitea. The browser uses the shared Gitea identity and storage at +`teahub.xyz`; browser/API operations terminate at `teahub-mcp` through the +bounded `/tea/site/*` bridge. + +The retired `persimmons-app` and `persimmons-gitea` state is disposable. The +repository contains no Fly manifests, provisioners, launch workflow, preflight +workflow, or operator allowlist entry capable of recreating either app. + +## External cutover (independent operator plane) + +Do not operate this change through Teahub itself. Start from an independently +authenticated Fly/Cloudflare operator and record the current machine, image, +volume, DNS, and certificate state before mutation. + +1. Build the Gitea image from the exact current `matcha/teahub` main SHA. Update + only the canonical `teahub-gitea` machine, preserving its machine ID, volume, + services, IPs, and rollback image. This activates both + `gitea/teahub-nginx.conf` and `GITEA__session__SAME_SITE=none`; do not use the + UI-only refresh script for this config change. +2. On that same independent plane, run the composed Pages projector against the + exact current `matcha/greentea` main SHA: + `ops/pages-project-greentea.sh <40-character-greentea-main-sha>`. Confirm its + recorded `app_persimmons_source_sha` equals the local + `matcha/persimmons.git` `refs/heads/main` and that `current/🍊/index.html`, + `app.js`, and `store.js` are nonempty. +3. Add `persimmons.app` to the `teahub-gitea` Fly certificate set. Replace the + old dedicated-app DNS with DNS-only records pointing at the existing shared + Teahub addresses: `A 66.241.124.48` and + `AAAA 2a09:8280:1::19c:1dd0:0`. Remove the retired + `66.241.124.82` / `2a09:8280:1::1a0:f8e1:0` records. Wait for Fly to report + the hostname certificate ready before treating the cutover as live. +4. Verify `https://persimmons.app/`, `/app.js`, and `/store.js` return 200 and + nonempty bytes; compare their hashes with the files under the composed + `current/🍊` directory. Verify `https://teahub.xyz/api/healthz` and + `https://mcp.teahub.xyz/healthz` remain 200 and one bounded Gitea write path + still succeeds. +5. In a fresh browser, sign in through the Persimmons popup and confirm the + Teahub session cookie is `Secure; HttpOnly; SameSite=None`. Confirm session, + repository discovery, create/list/rotate/revoke/delete, extension connection, + and Juice target `https://teahub.xyz` work. Confirm an unallowlisted origin + receives no credentialed CORS header. +6. After the shared taste test passes, stop/delete the old `persimmons-app` and + `persimmons-gitea` apps and their disposable volumes/IPs/certificates. Do not + copy old dedicated users or vault state into Teahub. + +Rollback changes only the shared Gitea machine back to the recorded image and +restores the prior DNS records. Never replace or detach the Gitea data volume.