From e20669e42a9d387865e0520e65338cb114048ece Mon Sep 17 00:00:00 2001 From: Kyle J Turpin Date: Sat, 23 May 2026 18:01:57 -0500 Subject: [PATCH] feat: Add project revision lifecycle details and clarify versioning model in documentation --- docs/ARCHITECTURE.md | 15 +++++++++++++++ docs/OPEN_QUESTIONS.md | 9 +++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 8609bdb..c401eae 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -40,6 +40,21 @@ Current product definition: - Materials are also an extensible entity: the core material record captures display name, quantity, and unit; domain-specific attributes (yarn weight, fibre content, filament diameter/material, wood species/grade, electronics component value/package) are carried in extension payloads on the material entry, using the same extension mechanism as project-level extensions. - A federated material catalog is a long-term goal: community-defined material types and shared taxonomy entries could be federated as ActivityPub objects, allowing instances to reference a common vocabulary without requiring central authority. +### Project Revision Lifecycle + +FeDIY uses a hybrid draft + immutable revision model: + +- **Drafts are mutable working copies.** Authors edit a draft until they publish it. +- **Publishing creates an immutable numbered revision.** A publish action snapshots the complete project state: materials, tools, steps, media references, canonical links, extension payloads, and any referenced sub-project pointers. +- **Revisions are append-only.** Once published, a revision never changes. Corrections or updates are made by creating a new draft from the latest published revision. +- **Revision numbering is monotonic per project.** Revision 1 is the first published snapshot; later publishes increment the number. +- **History is first-class.** The API and UI expose the full revision history by default, with the latest published revision presented as the canonical current view. +- **Draft visibility is restricted.** Drafts are visible only to the author and explicitly authorized collaborators; they are not part of public history until published. +- **Supersession is explicit.** A newly published revision supersedes the previous published revision, but the older revision remains addressable for audit, attribution, and history browsing. +- **Project references are recursive by graph, not by inline body embedding.** A project may reference another project as a sub-process or prerequisite (for example taco recipe -> taco meat recipe). The reference resolves to a specific published revision, so downstream recipes remain stable even if the referenced project is later updated. +- **Cycle detection is required.** The system must prevent or safely collapse cyclic project-reference graphs so recursive composition cannot create infinite expansion in the API or UI. +- **Extension payloads are versioned with the revision.** A revision snapshot includes extension data as it existed at publish time so clients can render or compare historical states accurately. + ## Client and Front-End Strategy The server exposes a stable, documented HTTP API as its primary interface. The bundled web UI is a first-party client of that same API — it receives no privileged server-side access that a third-party client could not also use. diff --git a/docs/OPEN_QUESTIONS.md b/docs/OPEN_QUESTIONS.md index 7442258..b0de403 100644 --- a/docs/OPEN_QUESTIONS.md +++ b/docs/OPEN_QUESTIONS.md @@ -16,8 +16,8 @@ Each question is tagged with the phase it blocks or most affects: [P0], [P1], [P - Materials are also extensible entities. The core material record (name, quantity, unit) can carry domain-specific extension payloads using the same mechanism as project extensions. Community-defined material type schemas (e.g. yarn, filament, PCB component) can be layered on without modifying the core model. - **Database: PostgreSQL is the primary persistence target.** JSONB, native full-text search, transactional consistency under concurrent federation fan-in, and broad managed hosting support make it the clear long-term fit. The persistence layer is behind a repository abstraction (trait-based interfaces), which keeps business logic independent of the database driver and leaves SQLite viable as a future lightweight self-hosting option without requiring changes to domain logic. See [ADR TBD: Persistence Layer Architecture]. - **Baseline content prohibitions (hardcoded, not operator-configurable):** CSAM, doxxing, and non-consensual intimate imagery (NCII) are prohibited on any FeDIY instance regardless of operator policy. The guiding principle is **consent**: minors cannot consent to sexual content; individuals have not consented to having their private identifying information published; subjects of intimate imagery have not consented to its distribution. Enforcement is in-code as far as technically feasible (hash-matching for CSAM and NCII; upload-time pattern detection and mandatory human-review tooling for doxxing). Weapons, violence, and similar dual-use content are **not** hardcoded prohibitions — legitimate DIY projects (fireworks, blacksmithing, knife-making) are indistinguishable at the software level and are handled by operator content policy and community moderation. -- **Baseline content prohibitions (hardcoded, not operator-configurable):** CSAM, doxxing, and non-consensual intimate imagery (NCII) are prohibited on any FeDIY instance regardless of operator policy. The guiding principle is **consent**: minors cannot consent to sexual content; individuals have not consented to having their private identifying information published; subjects of intimate imagery have not consented to its distribution. Enforcement is in-code as far as technically feasible (hash-matching for CSAM and NCII; upload-time pattern detection and mandatory human-review tooling for doxxing). Weapons, violence, and similar dual-use content are **not** hardcoded prohibitions — legitimate DIY projects (fireworks, blacksmithing, knife-making) are indistinguishable at the software level and are handled by operator content policy and community moderation. - **Personal data register (Q38):** Full register in ARCHITECTURE.md. Required registration fields: email, password hash, handle, display name, minimum-age-verified boolean (raw DOB discarded after age check). IP addresses never stored — ephemeral only. Optional profile fields (bio, avatar, header image, location, preferred crafts, pronouns, external links, locale, display preferences) all under contract. Analytics must be truly aggregate/anonymised — per-user event streams require consent. Handles are changeable with a redirect from old to new URL. +- **Project revision model (Q1):** Use immutable numbered revisions plus mutable drafts. Projects may reference other projects as reusable sub-processes or prerequisites, but recursive content is represented as a graph of project references rather than inline embedding of entire project bodies. Each publish action snapshots materials, tools, steps, media references, canonical links, extension payloads, and any project references as-of publish time. Full history is visible in the API and UI, with the latest published revision as the default view. ## Upfront Clarification Plan (P0 -> Early P1) @@ -51,12 +51,9 @@ The goal is to remove ambiguity before implementation while keeping scope realis ## Domain Model -**Q1 [P1]** What should the explicit versioning model look like? +**Q1 [P1]** ~~What should the explicit versioning model look like?~~ **RESOLVED — see Resolved Decisions and ARCHITECTURE.md Project Revision Lifecycle.** -- Immutable numbered revisions, mutable drafts, or both? -- Does each version snapshot materials, tools, steps, media references, and extension data? -- What is the publish workflow for a new version (draft -> published -> superseded)? -- How should old versions be exposed in API and UI (full history vs selected milestones)? +Decision: immutable numbered revisions plus mutable drafts. Projects may reference other projects as reusable sub-processes or prerequisites, but recursive content is represented as a graph of project references rather than inline embedding of entire project bodies. Publishing freezes a revision snapshot; later edits create a new draft and then a new numbered revision. Full history is visible in API and UI, with the latest published revision as the default view. **Q2 [P1]** How are materials modelled?