Enable CMS-managed site images

This commit is contained in:
Kevin
2026-09-04 01:48:38 -04:00
parent 357a0f0dc1
commit d76de0ccb4
26 changed files with 229 additions and 44 deletions
+21 -10
View File
@@ -64,12 +64,16 @@ the pilot:
value rather than a floating release range.
- 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;
image embedding and general file widgets are absent.
- The team image field accepts an existing approved raster path or a bounded
upload. URL insertion and SVG paths are rejected. Builds additionally verify
the extension, raster signature, flat upload path, and 500 KiB limit.
- All four Markdown content collections and every persisted frontmatter field
are modeled with the current Astro/Zod bounds. Markdown controls remain
text-first; embedded images and general file widgets are absent.
- A fixed image-only Markdown record controls the primary home, About,
Services, and Contact page imagery without exposing either `site.json`.
- Team and page-image fields accept optional bounded uploads. Editors can add,
replace, or remove an image reference while retaining accessible image
descriptions and a layout fallback. URL insertion and SVG paths are
rejected. Builds additionally verify the extension, raster signature, flat
upload path, and 500 KiB limit.
- `.gitea/workflows/cms-content-validation.yml` runs on every pull request into
`main`, uses no secrets, and reports
`CMS content validation / cms-content-validation (pull_request)` after
@@ -126,9 +130,10 @@ Allow editing and creation only within these collections:
| --- | --- | --- |
| Primary site FAQs | `sites/www/content/faq/**` | Create, edit, draft, reorder, delete after confirmation |
| Primary services | `sites/www/content/services/**` | Create, edit, draft, reorder, feature |
| Primary team | `sites/www/content/team/**` | Create, edit, draft, reorder, select an approved image |
| Primary team | `sites/www/content/team/**` | Create, edit, draft, reorder, add, replace, or remove a portrait |
| Primary page images | `sites/www/content/page-images/primary.md` | Add, replace, or remove home, About, Services, and Contact images and edit their descriptions |
| Journal posts | `sites/blog/content/posts/**` | Create, edit, draft, date, tag, update |
| Shared pilot media | `public/images/uploads/**` | Upload bounded raster images after text editing is proven |
| Shared pilot media | `public/images/uploads/**` | Select or upload bounded raster images |
Do not expose `sites.json`, either `site.json`, schemas, workflows, Wrangler
configuration, package files, source components, scripts, contact routing, or
@@ -139,6 +144,12 @@ not accept executables, archives, HTML, scripts, or SVG uploads. Asset rights,
alt text, crop, dimensions, and optimization remain operator review items even
when the CMS accepts an upload.
The media gallery lists only `public/images/uploads`, so the pilot seeds that
directory with the images referenced by CMS-controlled fields. Removing an
image from content clears the field and uses the page's text-only or initials
fallback; it does not delete a potentially shared asset. Delete a gallery asset
only after confirming that no content entry references it.
## Repository protection model
### `main`
@@ -256,8 +267,8 @@ not record OAuth tokens or Cloudflare credentials.
| 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. |
| DC-09 | Edit a team entry without changing its image | Existing fields and image path are preserved exactly. |
| DC-10 | Upload a bounded raster image | File lands only in the approved media path and renders on the relevant preview. |
| DC-09 | Add, replace, and remove a team portrait | The selected upload renders in the team card; removal uses the initials fallback. |
| DC-10 | Upload a bounded raster image and select it in the fixed page-image record | File lands only in the approved media path and renders on the relevant primary preview page. |
| DC-11 | Attempt an oversized upload and a disallowed file type | The CMS size limit rejects the oversized file before upload; Gitea's unprotected-extension patterns reject the disallowed path. |
| 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. |