You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+19Lines changed: 19 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,13 @@ All notable changes to git-cms are documented in this file.
6
6
7
7
### Added
8
8
9
+
-**Version History Browser (CE3):** Browse prior versions of an article, preview old content, and restore a selected version as a new draft commit
10
+
-`CmsService.getArticleHistory()` — walk parent chain to list version summaries (SHA, title, status, author, date)
11
+
-`CmsService.readVersion()` — read full content of a specific commit by SHA
12
+
-`CmsService.restoreVersion()` — restore historical content as a new draft with ancestry validation and provenance trailers (`restoredFromSha`, `restoredAt`)
13
+
-`GET /api/cms/history`, `GET /api/cms/show-version`, `POST /api/cms/restore` server endpoints
14
+
- Admin UI: collapsible history panel with lazy-fetch, version preview, and restore button
15
+
9
16
-**Content Identity Policy (M1.1):** Canonical slug validation with NFKC normalization, reserved word rejection, and `CmsValidationError` contract (`ContentIdentityPolicy.js`)
10
17
-**State Machine (M1.2):** Explicit draft/published/unpublished/reverted states with enforced transition rules (`ContentStatePolicy.js`)
@@ -40,6 +47,9 @@ All notable changes to git-cms are documented in this file.
40
47
-**(P2) SRI hashes:** Add `integrity` + `crossorigin` to marked and DOMPurify CDN script tags
41
48
-**(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
42
49
-**(P2) uploadAsset DI guard:** Throw `unsupported_in_di_mode` when `cas`/`vault` are null
50
+
-**(P1) Path traversal in upload handler:** Sanitize user-controlled `filename` to `path.basename()` preventing writes outside tmpDir
-**(P1) readVersion published fallback:**`readVersion` checks both draft and published refs (consistent with `getArticleHistory`)
43
53
-**(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`
44
54
-**(P2) XSS in `escAttr`:** Escape single quotes (`'` → `'`) to prevent injection into single-quoted attributes
45
55
-**(P2) Supply-chain hardening:** Vendor Open Props CSS files locally (`public/css/`) instead of `@import` from unpkg, eliminating CDN dependency and SRI gap
@@ -53,5 +63,14 @@ All notable changes to git-cms are documented in this file.
53
63
- DI-mode `_updateRef` now performs manual CAS check against `oldSha`
54
64
- Server tests assert setup call status codes to surface silent failures
- Admin UI: reset history panel state (versions list, preview, selection) when creating a new article to prevent stale data
67
+
- Defensive `|| {}` guard on `decoded.trailers` destructuring in `unpublishArticle` and `revertArticle` (prevents TypeError if trailers is undefined)
68
+
-`readVersion` now returns `trailers: decoded.trailers || {}` ensuring callers always receive an object
69
+
- Upload handler: moved tmpDir cleanup to `finally` block preventing temp directory leaks on failure
70
+
-**(P1) sendError info leak:** 500 responses now return generic 'Internal server error' instead of raw `err.message` (prevents leaking file paths, git subprocess details, or internal state)
71
+
-**(P2) readBody O(n²):**`readBody` now accumulates chunks in an array and uses `Buffer.concat` instead of repeated string concatenation
72
+
- Admin UI: `loadArticle` unconditionally resets `historyVersions` and `selectedVersion` to prevent stale history state when switching articles with the panel closed
73
+
- Admin UI: `selectVersion` guards against out-of-order async responses (prevents stale preview flash from rapid clicks)
74
+
-**(P2) walkLimit divergence:** Extracted `HISTORY_WALK_LIMIT` as a shared exported constant used by both `_validateAncestry` and the server's history limit clamp
0 commit comments