130 lines
3.4 KiB
Markdown
130 lines
3.4 KiB
Markdown
# Revisions and audit
|
|
|
|
## Distinction
|
|
|
|
**Revisions** preserve content state and support comparison/restoration.
|
|
|
|
**Audit events** preserve security- and operation-relevant attribution.
|
|
|
|
They are related but not interchangeable.
|
|
|
|
## Page revisions
|
|
|
|
A revision is immutable and includes:
|
|
|
|
- page ID;
|
|
- monotonically increasing revision number;
|
|
- title and slug;
|
|
- parent/order snapshot;
|
|
- Markdown;
|
|
- typed metadata snapshot;
|
|
- content hash;
|
|
- author/source;
|
|
- change summary;
|
|
- timestamp.
|
|
|
|
The current `pages` row is a projection of the newest published revision plus operational
|
|
fields.
|
|
|
|
### When to create a revision
|
|
|
|
- content publish;
|
|
- title/slug change;
|
|
- document type/status change;
|
|
- structural move when it changes meaning/breadcrumb;
|
|
- restore;
|
|
- import;
|
|
- API mutation.
|
|
|
|
Purely personal favorite/recent state does not create a page revision.
|
|
|
|
### Restore
|
|
|
|
Restoring revision N creates revision N+1 (or later) containing that snapshot. It does not
|
|
delete intervening history. The restore action itself is audited.
|
|
|
|
### Diff
|
|
|
|
Provide:
|
|
|
|
- line-based Markdown diff;
|
|
- metadata field diff;
|
|
- safe rendered comparison where useful;
|
|
- author/time/change summary.
|
|
|
|
Do not render removed unsafe HTML as active content.
|
|
|
|
## Project history
|
|
|
|
Project lifecycle changes and current-state mutations create an immutable project-state
|
|
revision or equivalent history record. Timeline entries are immutable; corrections append
|
|
a linked correction.
|
|
|
|
ADR supersession and runbook validation are explicitly audited.
|
|
|
|
## Audit event requirements
|
|
|
|
Audit events are append-only application records:
|
|
|
|
- actor kind: user, service account, import, system;
|
|
- actor ID and safe display snapshot;
|
|
- source channel;
|
|
- action;
|
|
- target type and stable ID;
|
|
- workspace;
|
|
- result;
|
|
- correlation ID;
|
|
- timestamp;
|
|
- safe changed-field names/summary;
|
|
- optional network/client metadata under policy.
|
|
|
|
No page body diff, password, token or raw attachment content is stored in the audit event.
|
|
|
|
## Atomicity
|
|
|
|
A published mutation succeeds only when current state, revision, audit and required
|
|
outbox record commit together. A failed transaction creates none of them.
|
|
|
|
Authentication failures may need audit/security logging outside a content transaction,
|
|
with rate limiting and privacy controls.
|
|
|
|
## Retention
|
|
|
|
- Revisions: retained by default until explicit administrative policy.
|
|
- Audit: configurable long retention, minimum recommended one year for a personal system.
|
|
- Diagnostic logs: much shorter operational retention.
|
|
- Trashed content: configurable grace period.
|
|
- Purge: explicit, audited and blocked while legal/operational holds exist (future-ready).
|
|
|
|
## Audit access
|
|
|
|
Administrator only by default. Search/filter:
|
|
|
|
- time range;
|
|
- actor;
|
|
- action;
|
|
- target;
|
|
- source;
|
|
- correlation ID;
|
|
- result.
|
|
|
|
Audit export excludes sensitive request data.
|
|
|
|
## Integrity and tamper evidence
|
|
|
|
PostgreSQL permissions prevent ordinary application paths from updating/deleting audit
|
|
rows. A future hash chain may be added, but v1 must not claim tamper-proof logging against
|
|
a database administrator. Backups and restricted DB roles provide practical protection.
|
|
|
|
## Tests
|
|
|
|
- concurrent publish produces exactly one accepted revision;
|
|
- restore appends;
|
|
- failed mutation creates no partial audit/revision;
|
|
- service-account attribution;
|
|
- import attribution;
|
|
- disabled user attribution remains readable;
|
|
- audit UI authorization;
|
|
- sensitive-field redaction;
|
|
- retention and purge boundaries.
|