Skip to content

CAP-WEB-WEB-012Preserve website edits as attributable revisions

Markdown

CAP-WEB-WEB-012

Preserve website edits as attributable revisions

Markdown
  • DocumentDraft
  • Product intentProposed
  • ImplementationObserved

KindCapabilityProduct areaWebsitesModuleWebsites, content and the portal runtimeRevision1

Read atservices-websites 5fc6823c

The Formal Contract

The narrative above explains; the sections below are authoritative — the rules, scenarios and tests this document binds.

Outcomes
Preserve website edits as attributable revisions.
Surfaces
consoleapi
Intent sources
services-websites:docs/milestones/rebaseline-2026-10-19.md#1. Approval register (2026-10-15 12:08, 2026-10-18 18:26)services-websites:modules/changes/README.md#Decisions (10, 17)

Controls

52 controls apply, from the corpus control catalogue.

TC-AI-001 TC-AI-003 TC-AI-004 TC-AVL-002 TC-AVL-003 TC-AZ-001 TC-AZ-002 TC-AZ-003 TC-AZ-004 TC-AZ-006 TC-CHG-001 TC-CHG-002 TC-CHG-003 TC-CHG-004 TC-CHG-005 TC-CHG-006 TC-CHG-007 TC-CRY-001 TC-CRY-002 TC-CRY-003 TC-CRY-004 TC-DAT-001 TC-DAT-002 TC-DAT-003 TC-DAT-005 TC-DAT-007 TC-IAM-001 TC-IAM-002 TC-IAM-004 TC-IAM-005 TC-LOG-001 TC-LOG-002 TC-LOG-003 TC-LOG-004 TC-LOG-005 TC-MON-001 TC-MON-003 TC-MON-004 TC-PI-001 TC-PI-003 TC-PI-005 TC-SEC-001 TC-SEC-002 TC-SEC-003 TC-SEC-004 TC-TEN-001 TC-TEN-002 TC-TEN-003 TC-TEN-004 TC-VEN-001 TC-VEN-002 TC-VEN-003

Permissions

KeyChecked atScope
websites.website-changes.changeapitenant
websites.website-changes.readapitenant
websites.website-changes.sourceservicetenant

Business Rules

15 rules, 14 to be proved before approval. A rule's product intent is derived from its origin: 0 confirmed by a product decision, the rest inheriting this capability's proposed.

IdRuleKindEnforced atProvenance
01must prove
Proposed
A website change starts Queued for one workspace site or template, with an objective up to 4,000 characters, a full starting commit and a branch named for the change.
validationapi, service, databasetest
02must prove
Proposed
Foreign-workspace sites and changes are indistinguishable from missing records, and rejected creation writes in neither workspace.
invariantservice, databasetest
services-websites:modules/changes/tests/integration/services/persistence/website-changes.integration.spec.js#refuses a site of another tenant as not found, exactly as a site nobody holds
03must prove
Proposed
Revision saving requires the current parent revision, or the starting commit for the first save, and concurrent saves from that parent produce one winner.
invariantservicetest
04must prove
Proposed
Revision saves accept at most 50 regular files of 512 KB within the customer's folder and reject traversal, absolute or backslash paths, duplicate paths, package or source-control folders, symlinks and submodules.
validationservicetest
05must prove
Proposed
Saving revisions moves only the website change's branch and leaves the release branch untouched.
invariantservicetest
06must prove
Proposed
A refused revision save records no branch, commit or revision before returning its refusal.
invariantservicetest
services-websites:modules/changes/tests/integration/services/revisions/persist-revision.integration.spec.js#creates no branch, commit or revision for a refused path, and leaves the change queued
07must prove
Proposed
Saving again during initial preview preparation replaces the current revision, clears the obsolete preview and leaves the change Persisted.
origin: services-websites:modules/changes/README.md#Decisions (17, confirmed by Andrew on 2026-10-18)
lifecycleservicetest
services-websites:modules/changes/tests/integration/services/persistence/website-changes.integration.spec.js#clears the preview of the earlier revision from the record, the new revision superseding it
08must prove
Proposed
A save is rejected after the lifecycle enters an in-flight pull request, check, build or review stage that no longer accepts revisions.
lifecycleservicetest
services-websites:modules/changes/tests/integration/services/revisions/persist-revision.integration.spec.js#refuses a persist once the change has moved past where a revision is taken
09must prove
Proposed
A change rejects its 101st revision rather than discard earlier revisions.
validationdatabase, servicetest
10must prove
Proposed
State transitions preserve their prior state, actor and context in history and reject the transition that would exceed 1,000 entries.
origin: services-websites:docs/milestones/rebaseline-2026-10-19.md#1. Approval register (2026-10-18 18:26: Refuse at the limit)
invariantdatabase, servicetest
services-websites:modules/changes/tests/integration/services/persistence/website-changes.integration.spec.js#refuses the transition that would write the 1001st, naming the limit, and keeps the oldest
11must prove
Proposed
Revision authors distinguish people, identified AI runs, staff acting as staff and system-authored template-operation commits.
validationserviceobserved
12must prove
Proposed
Only declared lifecycle transitions are accepted; Rolled Back and Superseded are final, while Failed can restart.
lifecycleservicetest
services-websites:modules/changes/tests/unit/services/state-machine.spec.ts#moves queued to persisted on a manual or automated persist
13
Proposed
Change detail includes revisions and the first history page, and diffs compare the current revision with its start, predecessor or a selected revision.
policyapi, servicetest
14must prove
Proposed
Opening changes requires change authority, while read authority permits listing and inspection only.
permissionapitest
services-websites:modules/changes/tests/e2e/changes-routes.e2e.spec.js#answers 403 to a reader opening a change, which takes websites.website-changes.change
15must prove
Proposed
An unrecorded commit remains on the branch and causes a later parent mismatch refusal; the branch is never forced backwards.
policyservicedocumented

Scenarios

IdGivenWhenThenProvenance
01Two designers edit the same current revision.They submit competing saves.One revision is stored and the other designer must reload after a conflict.test

Edge Cases

IdGivenWhenThenProvenance
02The stylesheet-only pilot receives a script-file save.The designer submits that save.The service rejects it before creating a commit.test

The Markdown files under specs/ in rhythmsoftware/rhythm-v2-docs are the canonical source of truth. This reader is a generated, read-only projection of them.