Skip to content

Contract document types: saving a draft for a published type no longer changes the live type; publishing does (D615, migration 416) #1313

Description

@guillaumelauzier

S1: Saving a draft can change a published contract document type, with no reason and no step-up. Decision D615. Migration 416. Found by #1165's audit (area 7, registry publish).

What is true on main

  • Publishing is guarded. POST /api/admin/contracts/registry/:doc_type/publish (routes/admin_contract_doc_registry.ts) is behind the Super Admin's write bar: a TOTP session, a step-up, and a reason of at least 10 characters. It is audited as registry.type.publish.
  • Saving a draft is not. services/contractDocTypeRegistryStore.ts saves a draft with ON CONFLICT(doc_type) DO UPDATE. That overwrites the row's title, layer, party roles and required fields, and keeps status = 'published' when it was published. So a draft save on a published type changes the live type at once:
    • with no reason, no step-up and no audit;
    • and with no pending copy kept.

The work

  1. A pending draft beside the live values. Migration 416 adds what the store needs to hold a draft for a published type apart from its published values, for example draft_* columns or a draft row keyed apart. Additive only.
  2. Saving a draft never changes a published type's live values. On a type that is only a draft, saving works as it does today.
  3. Publishing applies the pending draft to the live values, under the existing bar and audit, then clears the draft.
  4. The registry reads (doc-types and the hub) return the live values plus the pending draft, so a page can show both.
  5. D615 records the rule. Update the copy on /admin/contracts (frontend/src/pages/hq/ContractsPage.jsx) only if it describes the old behaviour.

Files this task owns

  • cloudflare-worker/sql/migrations/416_*.sql
  • cloudflare-worker/src/services/contractDocTypeRegistryStore.ts
  • cloudflare-worker/src/routes/admin_contract_doc_registry.ts
  • new Worker tests
  • documentation/architecture/decisions/D615.md

Done when

  • Tests cover:
    • a draft save on a published type leaves its live values and status unchanged, and keeps the draft;
    • publishing applies the draft, clears it and is audited;
    • a draft-only type saves as today;
    • the reads return both the live values and the draft.
  • Every new assertion is mutation-checked.

Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    slot:S16Work queue of slot S16state:readyReady for its slot to claim

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions