-
Notifications
You must be signed in to change notification settings - Fork 0
feat: content model, state machine, admin UI, and test infrastructure #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
15e2b12
feat(admin): overhaul CMS dashboard UI and fix API integration
flyingrobots 538e3c7
refactor(test): replace git subprocess tests with InMemoryGraphAdapter
5b6f135
merge: bring in overhauled admin UI from git-stunts-ui
12155e9
docs: add CHANGELOG covering git-stunts branch work
9241843
docs: fix remaining PR review nits
4fe6fa9
Merge remote-tracking branch 'origin/main' into git-stunts
3645920
chore: clean up InMemoryGraphAdapter vitest alias
dbcb406
fix: address PR #3 review feedback (XSS, atomicity, guards, test clea…
188f17a
fix: address remaining PR #3 review comments
d649fe0
fix: address PR #3 feedback — trailer casing, existence guard, escAtt…
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Changelog | ||
|
|
||
| All notable changes to git-cms are documented in this file. | ||
|
|
||
| ## [Unreleased] — git-stunts branch | ||
|
|
||
| ### Added | ||
|
|
||
| - **Content Identity Policy (M1.1):** Canonical slug validation with NFKC normalization, reserved word rejection, and `CmsValidationError` contract (`ContentIdentityPolicy.js`) | ||
| - **State Machine (M1.2):** Explicit draft/published/unpublished/reverted states with enforced transition rules (`ContentStatePolicy.js`) | ||
| - **Admin UI overhaul:** Split/edit/preview markdown editor (via `marked`), autosave, toast notifications, skeleton loading, drag-and-drop file uploads, metadata trailer editor, keyboard shortcuts (`Cmd+S`, `Esc`), dark mode token system | ||
| - **DI seam in CmsService:** Optional `graph` constructor param enables `InMemoryGraphAdapter` injection for zero-subprocess tests | ||
| - **In-memory test adapter:** Unit tests run in ~11ms instead of hundreds of ms (no `git init`/subprocess forks) | ||
| - **E2E test separation:** Real-git smoke tests in `test/git-e2e.test.js`, excluded from default `test:local` runs | ||
| - **`test:git-e2e` script:** Run real-git integration tests independently | ||
| - **`@git-stunts/alfred` dependency:** Resilience policy library (wired but not yet integrated) | ||
| - **`@git-stunts/docker-guard` dependency:** Docker isolation helpers | ||
| - **ROADMAP.md:** M0–M6 milestone plan with blocking graph | ||
| - **Formal LaTeX ADR** (`docs/adr-tex-2/`) | ||
| - **Onboarding scripts:** `setup.sh`, `demo.sh`, `quickstart.sh` with interactive menus | ||
| - **Dependency integrity check:** `check-dependency-integrity.mjs` prevents `file:` path regressions | ||
|
|
||
| ### Changed | ||
|
|
||
| - CmsService now uses `@git-stunts/git-warp` `GitGraphAdapter` and `@git-stunts/plumbing` `GitRepositoryService` instead of raw plumbing calls | ||
| - All `repo.updateRef()` calls routed through `CmsService._updateRef()` for DI/production dual-path | ||
| - `listArticles()` supports both plumbing (`for-each-ref`) and in-memory (`graph.listRefs`) paths | ||
| - Server endpoints return structured `{ code, field }` errors for validation failures | ||
| - Swapped all `file:` dependency paths to versioned npm ranges (PP3) | ||
|
|
||
| ### Fixed | ||
|
|
||
| - Symlink traversal hardening in static file serving | ||
| - Slug canonicalization enforced at all API ingress points | ||
| - Admin UI API calls aligned with server contract (query params, response shapes) | ||
| - Server integration test environment stabilized for CI | ||
| - **(P1) Stored XSS via markdown preview:** Sanitize `marked.parse()` output with DOMPurify | ||
| - **(P1) Unpublish atomicity:** Reorder `unpublishArticle` so draft ref updates before published ref deletion | ||
| - **(P2) XSS via slug/badge rendering:** Use `textContent` and DOM APIs instead of `innerHTML` interpolation | ||
| - **(P2) SRI hashes:** Add `integrity` + `crossorigin` to marked and DOMPurify CDN script tags | ||
| - **(P2) Null guards:** `revertArticle` and `unpublishArticle` throw `no_draft` when draft ref is missing; `_resolveArticleState` throws `article_not_found` when both draft and published refs are missing | ||
| - **(P2) uploadAsset DI guard:** Throw `unsupported_in_di_mode` when `cas`/`vault` are null | ||
| - **(P2) Trailer key casing:** Use camelCase `updatedAt` in `unpublishArticle` and `revertArticle` (was lowercase `updatedat` which broke `renderBadges` lookups); destructure out decoded lowercase key before spreading to avoid `TrailerInvalidError` | ||
| - **(P2) XSS in `escAttr`:** Escape single quotes (`'` → `'`) to prevent injection into single-quoted attributes | ||
| - **(P2) Supply-chain hardening:** Vendor Open Props CSS files locally (`public/css/`) instead of `@import` from unpkg, eliminating CDN dependency and SRI gap | ||
| - **(P2) Monkey-patch safety:** E2E test restores `plumbing.execute` in `finally` block | ||
| - Unknown `draftStatus` in `resolveEffectiveState` now throws `unknown_status` instead of silently falling through to draft | ||
| - Removed double-canonicalization in `_resolveArticleState` | ||
| - Replaced sequential `readRef` loop with `Promise.all` in `listArticles` DI path | ||
| - Admin UI: fixed `removeTrailerRow` redundant positional removal, FileReader error handling, autosave-while-saving guard, Escape key scoped to editor panel, drag-and-drop scoped to drop zone | ||
| - Test cleanup: extracted `createTestCms()` helper, converted try/catch assertions to `.rejects.toMatchObject()`, added guard-path tests | ||
| - `TRANSITIONS` Sets now `Object.freeze`d to prevent mutation via `.add()`/`.delete()` | ||
| - DI-mode `_updateRef` now performs manual CAS check against `oldSha` | ||
| - Server tests assert setup call status codes to surface silent failures | ||
| - Vitest exclude glob `test/git-e2e*` → `test/git-e2e**` to cover future subdirectories | ||
|
|
||
| [Unreleased]: https://github.com/flyingrobots/git-cms/compare/main...git-stunts | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"markdown" is a proper noun — capitalize it.
markdown preview→Markdown preview. Flagged by LanguageTool; tiny but this is a user-facing changelog.📝 Committable suggestion
🧰 Tools
🪛 LanguageTool
[uncategorized] ~34-~34: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ...abilized for CI - (P1) Stored XSS via markdown preview: Sanitize
marked.parse()ou...(MARKDOWN_NNP)
🤖 Prompt for AI Agents