ZDDC/zddc/internal/handler/default-ssr.form.yaml
ZDDC d35809cfd8 feat(forms): cascade-driven filename composition + audit on row create
Schemas:
- default-mdl.form.yaml: declare the six readOnly audit fields
  (created_at/by, updated_at/by, revision, previous_sha) so the form
  UI renders them disabled. additionalProperties: false is preserved;
  WriteWithHistory strips any client-supplied values before validation.
- default-rsk.form.yaml: overhaul to reflect the new shape. Each row
  now carries the table-tracking components (originator/phase?/project/
  area?/discipline/type/sequence/suffix?) plus a server-assigned `row`
  field; type is enum-locked to RSK to mirror the cascade's locked: rule.
  Drops the old `id` field (D-001/R-001-style identifiers are now
  composed from the components and stored in the filename).
- default-ssr.form.yaml: append the six audit fields.

Handlers:
- serveFormCreateSSR routes the write through WriteWithHistory so
  audit fields are stamped on first create (revision=1, created_*=
  updated_*=request principal/now). ssr.yaml's identity stays the
  party folder name; no filename composition runs.
- serveFormCreateRollup now resolves the cascade at the row's parent
  folder and uses the matched records: entry's filename_format to
  compose the row filename from body fields. For RSK rows the rule
  carries row_field+row_scope_fields, so the server auto-assigns the
  next sequence (001, 002, ...) within the table-tracking group and
  injects it into the body before composition. Defaults from
  field_defaults: are injected where the client omitted them
  (type=RSK locks in via the locked: list). Falls back to the
  historical date+email naming only when no records: rule is in
  scope (covers deployments that override defaults.zddc.yaml without
  declaring their own records: entries).

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

110 lines
3.2 KiB
YAML

# Default row schema for a Supplier / Subcontractor Status Report
# entry, served by zddc-server when no operator-supplied form.yaml
# exists at <project>/archive/<party>/ssr.form.yaml.
#
# The `name` field doubles as the party folder name (the row's
# stable identifier). It's required on create (+ Add row materializes
# <project>/archive/<name>/) but is stripped from the YAML on save —
# the folder name IS the identity, so storing it inside the file too
# would just be a denormalization. On read the dispatcher injects
# name back into the row data so this form (and the SSR table)
# can display it.
#
# Pattern excludes leading `.` and `_` to avoid colliding with
# fileapi.go's dot/underscore-prefix guards on file paths.
#
# To customize: drop your own form.yaml into
# <project>/archive/<party>/ (sibling to the party's ssr.yaml).
title: Supplier / Subcontractor Status
description: One party's status report. The party name doubles as the archive folder name and is required when creating a new row.
schema:
type: object
required: [name, vendorType, contractNo, scopeSummary]
additionalProperties: false
properties:
name:
type: string
title: Party (folder name)
description: Becomes <project>/archive/<name>/. Typical naming = MasterFormat 4-digit code + C|P + sequence digit (e.g. 0330C1).
pattern: "^[A-Za-z0-9][A-Za-z0-9.-]*$"
minLength: 1
vendorType:
type: string
title: Vendor type
enum: [subcontractor, supplier, consultant, vendor, other]
contractNo:
type: string
title: Contract / PO number
scopeSummary:
type: string
title: Scope summary
contractValue:
type: number
title: Contract value
awardDate:
type: string
title: Award date
format: date
kickoffDate:
type: string
title: Kickoff date
format: date
scheduleStatus:
type: string
title: Schedule status
enum: [on-track, at-risk, behind, completed, on-hold]
deliverablesStatus:
type: string
title: Deliverables status
enum: [on-track, at-risk, behind, completed]
paymentStatus:
type: string
title: Payment status
enum: [current, overdue, hold, complete]
ownerContact:
type: string
title: Owner contact (email)
notes:
type: string
title: Notes
# --- Audit fields (server-managed; read-only). WriteWithHistory
# strips any client-supplied versions before validation and
# re-injects authoritative values on every write.
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
description: SHA-256 (first 8 hex chars) of the prior revision's bytes.
readOnly: true
ui:
scopeSummary:
ui:widget: textarea
notes:
ui:widget: textarea