From 357a0f0dc1036d39a50f871dcd07598bc756e48e Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 4 Sep 2026 01:17:42 -0400 Subject: [PATCH] Use slash-free CMS pilot branch --- docs/decap-cms-gitea-setup.md | 14 +++++++++++--- docs/decap-cms-pilot.md | 31 +++++++++++++++++-------------- public/admin/config.yml | 2 +- scripts/verify-decap.mjs | 2 +- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/docs/decap-cms-gitea-setup.md b/docs/decap-cms-gitea-setup.md index 05c0486..d201e0d 100644 --- a/docs/decap-cms-gitea-setup.md +++ b/docs/decap-cms-gitea-setup.md @@ -9,13 +9,21 @@ The repository implementation targets these fixed public values: | Setting | Value | | --- | --- | | Gitea repository | `SloanOps/3031023-xyz` | -| Decap write branch | `cms/pilot` | +| Decap write branch | `cms-pilot` | +| Planned live write branch | `cms` | | Gitea base URL | `https://git.sloanops.com` | | Gitea API root | `https://git.sloanops.com/api/v1` | | Stable CMS origin | `https://cms-pilot-3031023-xyz-www.ksloan90.workers.dev` | | Exact OAuth redirect URI | `https://cms-pilot-3031023-xyz-www.ksloan90.workers.dev/admin/` | | Required status context | `CMS content validation / cms-content-validation (pull_request)` | +The pilot and planned live branch names are intentionally slash-free. Decap +CMS 3.15.1 inserts the configured Gitea branch directly into its tree-API URL; +a slash-named branch such as `cms/pilot` is split as an API path and its 404 is +presented as an empty collection. The permanent `cms` branch is still a +non-production staging branch: changes reach `main` only through the protected +pull-request flow. + The Workers alias was confirmed after the first approved preview deployment. If Cloudflare later assigns a different stable origin, update the repository configuration, CORS origin, and OAuth redirect URI @@ -140,7 +148,7 @@ directly into the flat uploads directory, and the local verifier rejects nested media paths. Gitea file patterns are case-insensitive; CI verifies actual file signatures and the 500 KiB limit before a preview can upload. -Everything not listed is protected from CMS/client pushes on `cms/pilot` and +Everything not listed is protected from CMS/client pushes on `cms-pilot` and on every differently named branch, including: ```text @@ -169,7 +177,7 @@ altered by choosing another branch name. ## Verification before an editor invitation 1. Run `npm ci`, `npm run verify:cms`, and both site build/verifier pairs. -2. Create `cms/pilot` from the reviewed baseline only after approval. +2. Create `cms-pilot` from the reviewed baseline only after approval. 3. Apply both protection rules together and confirm `main` is priority 1 and `*` is priority 2. 4. Use the same non-operator account intended for Decap to prove allowed diff --git a/docs/decap-cms-pilot.md b/docs/decap-cms-pilot.md index e821317..8d42ba9 100644 --- a/docs/decap-cms-pilot.md +++ b/docs/decap-cms-pilot.md @@ -1,6 +1,6 @@ # Decap CMS Gitea pilot -Status: preview-only pilot infrastructure is active on `cms/pilot`: the stable +Status: preview-only pilot infrastructure is active on `cms-pilot`: the stable preview, narrow Gitea CORS policy, public PKCE OAuth application, and two repository protection rules are configured. Nothing has been merged to `main`, and production remains unchanged. @@ -62,7 +62,7 @@ the pilot: configuration for both site builds. - The shell pins Decap CMS `3.15.1` by exact URL and verified SHA-384 integrity value rather than a floating release range. -- The backend is fixed to `SloanOps/3031023-xyz` and `cms/pilot` and contains +- The backend is fixed to `SloanOps/3031023-xyz` and `cms-pilot` and contains only the public client ID for the non-confidential Gitea PKCE application. - All four Markdown collections and every persisted frontmatter field are modeled with the current Astro/Zod bounds. Markdown controls are text-first; @@ -78,9 +78,8 @@ the pilot: now prove preview robots rules and page metadata stay no-index and that the admin response has a no-index header rule. -This preparation does not make the CMS usable yet: the placeholder public -client ID, unapplied CORS setting, absent `cms/pilot` remote branch, and absent -branch rules are intentional review gates. +The pilot dependencies are active: the public client ID, exact-origin CORS +policy, `cms-pilot` branch, and both protection rules have been verified. ## Proposed pilot architecture @@ -89,7 +88,7 @@ Decap at /admin/ | | Gitea PKCE OAuth and content/media commits only v -cms/pilot branch +cms-pilot branch | +--> primary no-index Worker preview | @@ -110,7 +109,7 @@ is acceptable because both sites belong to the same root-domain repository and the same owner. One Decap configuration exposes clearly labeled Primary Site and Journal collection groups. -Expected preview URLs for branch `cms/pilot`: +Preview URLs for branch `cms-pilot`: - `https://cms-pilot-3031023-xyz-www.ksloan90.workers.dev/admin/` - `https://cms-pilot-3031023-xyz-www.ksloan90.workers.dev/` @@ -213,10 +212,14 @@ Preview deployment remains branch-specific and may use the existing Worker workflows. Cloudflare credentials stay scoped to the deployment step; content validation does not need them. -Because Decap writes to a fixed `cms/pilot` branch, SloanOps creates the pull +Because Decap writes to a fixed `cms-pilot` branch, SloanOps creates the pull request in Gitea. After an approved merge, synchronize the CMS branch with `main` before the next editing cycle. Do not automate production merge. +If the pilot is accepted, replace the disposable branch with a permanent, +slash-free `cms` branch. It remains a preview/staging branch and retains the +same pull-request, validation, and approval path into `main`. + ## Gitea and Decap setup 1. Add a non-confidential Gitea OAuth application for the exact preview @@ -224,11 +227,11 @@ request in Gitea. After an approved merge, synchronize the CMS branch with 2. Enable Gitea API CORS for the exact approved preview origin or origins. Allow only required methods and headers, including `Authorization` and `Content-Type`; do not use a wildcard origin. -3. Create `cms/pilot` from the reviewed repository baseline. +3. Create `cms-pilot` from the reviewed repository baseline. 4. Review the pinned Decap admin assets beneath `public/admin/`. Do not replace the exact version and integrity value with a floating range. 5. Configure the Gitea backend for `SloanOps/3031023-xyz` and branch - `cms/pilot`. + `cms-pilot`. 6. Model every persisted frontmatter field with limits matching `src/content.config.ts`. Do not let a CMS save silently remove an existing field. @@ -249,7 +252,7 @@ not record OAuth tokens or Cloudflare credentials. | DC-02 | Open each preview `/admin/` route | Admin shell loads and remains no-index. | | DC-03 | Authenticate with the approved operator account | PKCE login succeeds and the configured collections load. | | DC-04 | Authenticate with an account without repository write access | Repository editing is unavailable. | -| DC-05 | Edit an existing draft journal post | One content-only commit lands on `cms/pilot`; the blog preview rebuilds. | +| DC-05 | Edit an existing draft journal post | One content-only commit lands on `cms-pilot`; the blog preview rebuilds. | | DC-06 | Create, edit, and delete a disposable journal post | Filename, dates, tags, body, draft state, and cleanup remain schema-valid. | | DC-07 | Edit a primary FAQ | Only the primary preview rebuilds and displays the change. | | DC-08 | Edit service ordering and featured state | YAML types remain correct and the primary verifier passes. | @@ -259,10 +262,10 @@ not record OAuth tokens or Cloudflare credentials. | DC-12 | Attempt to modify `.gitea/workflows/**`, source, package, script, schema, Wrangler, and site-manifest paths with the CMS account | Gitea rejects every push. | | DC-13 | Attempt to create a differently named branch and change a protected file | The fallback rule rejects the push; branch naming cannot bypass protection. | | DC-14 | Attempt a direct push to `main` | Gitea rejects it. | -| DC-15 | Open a pull request from `cms/pilot` to `main` | Both sites validate; required review and merge controls are present. | +| DC-15 | Open a pull request from `cms-pilot` to `main` | Both sites validate; required review and merge controls are present. | | DC-16 | Attempt to merge without status or approval | Gitea blocks the merge. | | DC-17 | Inspect both preview responses | Expected routes work; preview metadata/headers prevent indexing; production remains unchanged. | -| DC-18 | Revert the disposable CMS changes on `cms/pilot` | Preview returns to baseline without changing either public site. | +| DC-18 | Revert the disposable CMS changes on `cms-pilot` | Preview returns to baseline without changing either public site. | | DC-19 | Refresh, sign out, reauthenticate, and let a session expire | Session behavior is understandable and no unsaved-content loss is observed. | | DC-20 | Review commit attribution and audit history | Gitea identifies the editor and the exact content/media changes. | @@ -292,7 +295,7 @@ account control over executable deployment files. If the pilot is rejected or paused: -1. Revert or delete disposable changes on `cms/pilot`. +1. Revert or delete disposable changes on `cms-pilot`. 2. Delete the two disposable preview aliases/versions if desired; do not delete production Workers or retained legacy rollback resources. 3. Revoke/delete the Decap OAuth application. diff --git a/public/admin/config.yml b/public/admin/config.yml index c21c390..427db1a 100644 --- a/public/admin/config.yml +++ b/public/admin/config.yml @@ -1,7 +1,7 @@ backend: name: gitea repo: SloanOps/3031023-xyz - branch: cms/pilot + branch: cms-pilot app_id: c07dba05-eb09-48f0-8da4-6df775a13995 api_root: https://git.sloanops.com/api/v1 base_url: https://git.sloanops.com diff --git a/scripts/verify-decap.mjs b/scripts/verify-decap.mjs index 8672cc5..2db55c6 100644 --- a/scripts/verify-decap.mjs +++ b/scripts/verify-decap.mjs @@ -21,7 +21,7 @@ const expectedOrigin = 'https://cms-pilot-3031023-xyz-www.ksloan90.workers.dev'; const expectedBackend = { name: 'gitea', repo: 'SloanOps/3031023-xyz', - branch: 'cms/pilot', + branch: 'cms-pilot', api_root: 'https://git.sloanops.com/api/v1', base_url: 'https://git.sloanops.com', auth_endpoint: 'https://git.sloanops.com/login/oauth/authorize',