Commit graph

2 commits

Author SHA1 Message Date
d947f616d1 feat(forms): augment served schema with cascade field_codes + locks
Two extension fields added to jsonschema.Schema so server-injected
constraints survive the YAML→Schema→JSON round-trip:
- Pattern: regex hint for the form renderer (server-side validation
  for field_codes already runs via WriteWithHistory).
- ReadOnly: surfaces locked / audit fields as disabled in the UI.
- Labels: x-labels extension carrying human-readable display strings
  paired with enum keys (e.g. ACM → "Acme Inc"), so dropdowns can show
  "ACM — Acme Inc" rather than bare codes.

serveFormRender now calls augmentSchemaFromCascade after loading the
spec: per-field, it injects enum (from field_codes:codes), pattern
(from field_codes:pattern), readOnly (from records:locked), and
default (from records:field_defaults). The augmentation is
per-request and never touches the on-disk *.form.yaml — operators
who declare their own enum/pattern in the spec take precedence
(injection is "if absent").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 09:58:21 -05:00
882d5e4c86 feat(zddc-server): server-stamped audit + history for record YAMLs
Adds cascade-driven schema + immutable audit history for the three table-style
record stores (mdl, rsk, ssr). Two new .zddc top-level keys carry the rules:

- field_codes: discriminated-union vocabulary (kind: enum|pattern|free) for
  the components used to compose tracking-number filenames and constrain
  record bodies. Map-merge across the cascade, mirror of apps: semantics.
- records: per-pattern rules (filename_format, field_defaults, locked,
  row_field, row_scope_fields). Filename-pattern scoping lets the SSR rule
  live at the party-folder level without bleeding onto mdl/rsk siblings.

PUTs to record YAML files route through a new WriteWithHistory orchestrator
(internal/handler/history.go) which:
- strips six client-supplied audit fields (created_at/by, updated_at/by,
  revision, previous_sha) so the client can't forge them
- validates body values against the cascade-resolved field_codes
- enforces filename_format composition (URL basename must match body fields)
- checks locked: defaults (422 mismatch)
- archives prior bytes to <dir>/.history/<base>/<RFC3339Nano>-<sha8>.<ext>
- stamps server-managed audit fields and writes the live file

History-before-live ordering preserves the prior version even on mid-write
crash. previous_sha forms a hash chain across revisions for tamper evidence.

The embedded defaults.zddc.yaml now declares records: entries for mdl, rsk,
and ssr.yaml. RSK rows carry the table-tracking components + row sequence
(filename = <table-tracking>-<row>); MDL rows compose to their own
tracking number; SSR records' identity is the party folder name.

GET <record>.yaml?history=1 returns a JSON list of prior revisions, ACL
gated identically to the live record. dot-segment rejection in
resolveTargetPath protects .history/ from direct client writes.

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