ZDDC/zddc/internal/handler/default-project-mdl.form.yaml
ZDDC 3b2280de7f test(handler): coverage for record audit + history flows
Adds history_test.go with eight cases exercising the record-write
orchestration path:
- CreateStampsAuditFields: PUT to a fresh mdl path → audit fields
  injected; response echoes the stamped YAML; no history dir yet.
- UpdateIncrementsRevisionAndArchivesPrior: second PUT archives
  the prior bytes under .history/<base>/<ts>-<sha8>.yaml, bumps
  revision, preserves created_*, chains previous_sha.
- ConflictPreservesHistory: 412 from stale If-Match leaves the live
  file untouched and writes NO history entry (the failed write must
  be a true no-op).
- ClientAuditFieldsStripped: client-supplied created_by / revision
  are silently overwritten by server values — anti-forgery test.
- FilenameMismatch: URL says ...-0002 but body composes to ...-0001
  → 422.
- LockedFieldRejected: posting type=SPC to an rsk row → 422 with
  /type error (rsk/ locks type=RSK via cascade).
- SSRHistoryAtPartyLevel: writes to archive/<party>/ssr.yaml put
  history at archive/<party>/.history/ssr/, NOT at
  archive/.history/<party>/.
- RollupCreate_AssignsRowAndComposesFilename: three POSTs to
  /project/rsk/form.html in two table-scope groups demonstrate the
  server picks up filename_format + row_field+row_scope_fields from
  the cascade, auto-assigns sequence row numbers per group, and
  composes the canonical filename.

Bug fix surfaced by the first test: composeFilename was eliding TWO
separators around an optional placeholder when one was correct.
"ACM-{phase?}-PRJ" with phase="" was producing "ACMPRJ" instead of
"ACM-PRJ". Now drops only the trailing separator from output and
lets the next iteration emit the connector.

Default-project-{mdl,rsk}.form.yaml updated: project-rollup MDL +
RSK schemas gained the six readOnly audit fields and the project-
rsk schema picked up the full table-tracking component shape (+
row) plus an enum-locked type=RSK. The required: list no longer
includes type for rsk schemas — the cascade's field_defaults
injects it after schema validation, and requiring it would 422
well-behaved clients.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 10:08:52 -05:00

122 lines
3.6 KiB
YAML

# Default project-rollup MDL row schema, served by zddc-server when
# no operator-supplied form.yaml exists at <project>/mdl/.
#
# Identical to the per-party MDL schema (default-mdl.form.yaml)
# except for one extra required field: `party`. That field is the
# routing key — the server reads it on POST <project>/mdl/form.html,
# finds the matching <project>/archive/<party>/ folder, and writes
# the row inside its mdl/ subfolder. The `party` value is stripped
# from the YAML on write (folder name IS the identity); on read the
# dispatcher injects it back so the rollup table can show the
# Package column.
#
# To customize: drop your own form.yaml at <project>/mdl/form.yaml.
# Keep the `party` field shape unless you also customize the rollup
# create handler — the server's routing depends on it.
title: Deliverable (project rollup)
description: One deliverable across all parties. The first field (Package) routes the row to the matching archive/<party>/mdl/ folder; the rest mirrors the per-party MDL schema.
schema:
type: object
required: [party, originator, project, discipline, type, sequence, title]
additionalProperties: false
properties:
party:
type: string
title: Package (party folder)
description: Routing key — must match an existing <project>/archive/<party>/ folder. Typical naming = MasterFormat 4-digit code + C|P + sequence digit (e.g. 0330C1).
pattern: "^[A-Za-z0-9][A-Za-z0-9.-]*$"
minLength: 1
originator:
type: string
title: Originator
description: Organizational unit responsible for this deliverable (e.g. ACME).
minLength: 1
phase:
type: string
title: Phase
description: Optional project phase code (e.g. ECI, EPC).
project:
type: string
title: Project
description: Project identifier, or your corporate placeholder for non-project deliverables.
minLength: 1
area:
type: string
title: Area
description: Optional area / budget code (e.g. B02).
discipline:
type: string
title: Discipline
description: Engineering or functional group code (EL, ME, CV, PM, ...).
minLength: 1
type:
type: string
title: Document type
description: Document category code within the discipline (SPC, DWG, RPT, ...).
minLength: 1
sequence:
type: string
title: Sequence
description: Zero-padded integer (0001, 0042, 2623). Stored as a string so leading zeros survive YAML.
minLength: 1
suffix:
type: string
title: Suffix
description: Optional structural-part suffix.
title:
type: string
title: Deliverable title
minLength: 1
plannedRevision:
type: string
title: Planned revision
plannedDate:
type: string
title: Planned date
format: date
status:
type: string
title: Current status
enum: [DFT, IFR, IFA, IFC, AFC, AB]
owner:
type: string
title: Owner
notes:
type: string
title: Notes
# --- Audit fields (server-managed; read-only).
created_at:
type: string
title: Created
format: date-time
readOnly: true
created_by:
type: string
title: Created by
format: email
readOnly: true
updated_at:
type: string
title: Updated
format: date-time
readOnly: true
updated_by:
type: string
title: Updated by
format: email
readOnly: true
revision:
type: integer
title: Revision
minimum: 1
readOnly: true
previous_sha:
type: string
title: Previous SHA
readOnly: true
ui:
notes:
ui:widget: textarea