Add daw_field_type/v1 contract -- declarative field type definitions #3

Closed
opened 2026-08-11 14:50:30 +02:00 by michael · 1 comment
Owner

Goal

Add daw_field_type/v1 as a new ecosystem-wide contract in
daw-contracts, replacing the hardcoded field type list
(M.PRIMITIVES: text, textarea, number, boolean, select, date) in
DAW/daw-modul-berhtjan-core#types.lua.

A daw_field_type/v1 object describes a field type declaratively --
its value semantics and the ways its value may be acquired -- so that
Core and any adapter (CLI, web, API) can handle a field type without
knowing its name in code. A new field type is introduced purely as
data; no change to Core or any adapter is required.

Background

M.PRIMITIVES in daw-modul-berhtjan-core hardcodes the six known
field types directly in Lua code. Adding a new field type today
requires a code change and a release. This was identified as a
blocker during the 2.1 daw_error/v1 migration of
daw-modul-berhtjan-core (feature/daw-error-v1-migration branch)
and traced back to the same anti-pattern described in
"Festgelegt heißt nicht einprogrammiert" -- a closed, fixed vocabulary
does not need to be hardcoded in program code, only the shape of the
contract does.

The proposed model was calibrated against real cases, not designed
up front:

  • the six existing primitives (text, textarea, number, boolean,
    select, date)
  • a new domain-specific value kind with no existing UI mechanism
    (lattenzaun_orientation, as a deliberately unfamiliar test case)
  • file/resource acquisition needed by steurjan (receipts),
    raidjan (incoming invoices, bank statements)
  • dual acquisition for one field type -- openbookregister cover
    images need both fresh upload and selection from an existing
    library, producing the same reference value either way
  • multi-value acquisition (tags, entered freely or chosen from a
    resolved vocabulary)

Model summary

daw_field_type/v1
  schema
  value
    kind          -- open vocabulary
    cardinality   -- closed: single | multiple, no default
  acquisition[]
    kind          -- closed: direct | selection | resource
  collection       -- required if any acquisition entry has kind=selection
    source        -- closed: static | resolved
    values        -- required if source=static
    capability    -- open, required if source=resolved
  resource          -- required if any acquisition entry has kind=resource
    kind          -- open
    media_types   -- open (external/IANA)
    max_size_bytes
  constraint        -- optional, closed vocabulary, NOT YET SPECIFIED in this version
  hint              -- optional, open vocabulary, presentation-only

Key invariants:

  • All acquisition entries of the same field type must produce the
    same value form.
  • value.cardinality applies to the field type as a whole, not per
    acquisition path.
  • An unrecognized constraint key must not be silently treated as
    satisfied -- unlike hint, which is safe to ignore when unknown.

Full draft (contract.json, specification.md, rationale.md,
CHANGELOG.md, examples/valid + examples/invalid) is attached to this
issue / available in the linked session artifact -- ready to drop
into daw_field_type/v1/ following TEMPLATE.md.

Acceptance criteria

  • daw_field_type/v1/{contract.json,specification.md,rationale.md,CHANGELOG.md} added, status: draft
  • examples/valid/ covers: text, textarea, unrecognized value.kind, multi-value tags, dual-acquisition cover image
  • examples/invalid/ covers: missing cardinality, selection without collection, unrecognized (closed) acquisition kind
  • Open/closed vocabulary classification reviewed by team (see table in specification.md) -- proposed by Claude per TEMPLATE.md's criterion, not yet independently verified
  • Team decision recorded on where the ecosystem's six base primitives are shipped from at runtime (berhtjan-core's own contribution vs. required per host program vs. separate shared vocabulary module) -- tracked as follow-up, not blocking this contract
  • daw-modul-berhtjan-core#types.lua migration (M.PRIMITIVES removal) tracked as separate follow-up issue in DAW/daw-modul-berhtjan-core, referencing this one

Open questions (not blocking, tracked for later)

  • Purely resource-based interactions with no prior value semantics
    (e.g. live signature capture, map-based location picking) -- not
    yet worked through against a real case.
  • constraint key vocabulary itself is unspecified in this version.

Refs: DAW/daw-modul-berhtjan-core (M.PRIMITIVES blocker, feature/daw-error-v1-migration branch)

## Goal Add `daw_field_type/v1` as a new ecosystem-wide contract in `daw-contracts`, replacing the hardcoded field type list (`M.PRIMITIVES`: text, textarea, number, boolean, select, date) in `DAW/daw-modul-berhtjan-core#types.lua`. A `daw_field_type/v1` object describes a field type declaratively -- its value semantics and the ways its value may be acquired -- so that Core and any adapter (CLI, web, API) can handle a field type without knowing its name in code. A new field type is introduced purely as data; no change to Core or any adapter is required. ## Background `M.PRIMITIVES` in `daw-modul-berhtjan-core` hardcodes the six known field types directly in Lua code. Adding a new field type today requires a code change and a release. This was identified as a blocker during the 2.1 `daw_error/v1` migration of `daw-modul-berhtjan-core` (`feature/daw-error-v1-migration` branch) and traced back to the same anti-pattern described in "Festgelegt heißt nicht einprogrammiert" -- a closed, fixed vocabulary does not need to be hardcoded in program code, only the *shape* of the contract does. The proposed model was calibrated against real cases, not designed up front: - the six existing primitives (text, textarea, number, boolean, select, date) - a new domain-specific value kind with no existing UI mechanism (`lattenzaun_orientation`, as a deliberately unfamiliar test case) - file/resource acquisition needed by `steurjan` (receipts), `raidjan` (incoming invoices, bank statements) - dual acquisition for one field type -- `openbookregister` cover images need both fresh upload and selection from an existing library, producing the same reference value either way - multi-value acquisition (tags, entered freely or chosen from a resolved vocabulary) ## Model summary ```text daw_field_type/v1 schema value kind -- open vocabulary cardinality -- closed: single | multiple, no default acquisition[] kind -- closed: direct | selection | resource collection -- required if any acquisition entry has kind=selection source -- closed: static | resolved values -- required if source=static capability -- open, required if source=resolved resource -- required if any acquisition entry has kind=resource kind -- open media_types -- open (external/IANA) max_size_bytes constraint -- optional, closed vocabulary, NOT YET SPECIFIED in this version hint -- optional, open vocabulary, presentation-only ``` Key invariants: - All `acquisition` entries of the same field type must produce the same value form. - `value.cardinality` applies to the field type as a whole, not per acquisition path. - An unrecognized `constraint` key must not be silently treated as satisfied -- unlike `hint`, which is safe to ignore when unknown. Full draft (contract.json, specification.md, rationale.md, CHANGELOG.md, examples/valid + examples/invalid) is attached to this issue / available in the linked session artifact -- ready to drop into `daw_field_type/v1/` following `TEMPLATE.md`. ## Acceptance criteria - [ ] `daw_field_type/v1/{contract.json,specification.md,rationale.md,CHANGELOG.md}` added, `status: draft` - [ ] `examples/valid/` covers: text, textarea, unrecognized value.kind, multi-value tags, dual-acquisition cover image - [ ] `examples/invalid/` covers: missing cardinality, selection without collection, unrecognized (closed) acquisition kind - [ ] Open/closed vocabulary classification reviewed by team (see table in specification.md) -- proposed by Claude per TEMPLATE.md's criterion, not yet independently verified - [ ] Team decision recorded on where the ecosystem's six base primitives are shipped from at runtime (berhtjan-core's own contribution vs. required per host program vs. separate shared vocabulary module) -- tracked as follow-up, not blocking this contract - [ ] `daw-modul-berhtjan-core#types.lua` migration (`M.PRIMITIVES` removal) tracked as separate follow-up issue in `DAW/daw-modul-berhtjan-core`, referencing this one ## Open questions (not blocking, tracked for later) - Purely resource-based interactions with no prior value semantics (e.g. live signature capture, map-based location picking) -- not yet worked through against a real case. - `constraint` key vocabulary itself is unspecified in this version. Refs: DAW/daw-modul-berhtjan-core (M.PRIMITIVES blocker, feature/daw-error-v1-migration branch)
Author
Owner

Resolved.

daw_field_type/v1 added: contract.json, specification.md,
rationale.md, CHANGELOG.md, examples/valid + examples/invalid,
status: draft. Calibrated against the six former berhtjan-core
primitives, a new domain-specific value kind (lattenzaun_orientation),
file/resource acquisition (steurjan, raidjan, openbookregister),
dual acquisition for one field type (cover image: upload or select
existing), and multi-value acquisition (tags).

Open/closed vocabulary decided per field: value.kind, resource.kind,
collection.capability, hint keys open; acquisition[].kind,
collection.source, value.cardinality, constraint keys (closed,
7-key set: min, max, step, integer_only, min_length, max_length,
pattern) closed.

Consumed in daw-modul-berhtjan-core 2.1.0 -- types.resolve() is now
pure registry lookup, M.PRIMITIVES removed entirely.

Refs: DAW/daw-modul-berhtjan-core#11

Resolved. daw_field_type/v1 added: contract.json, specification.md, rationale.md, CHANGELOG.md, examples/valid + examples/invalid, status: draft. Calibrated against the six former berhtjan-core primitives, a new domain-specific value kind (lattenzaun_orientation), file/resource acquisition (steurjan, raidjan, openbookregister), dual acquisition for one field type (cover image: upload or select existing), and multi-value acquisition (tags). Open/closed vocabulary decided per field: value.kind, resource.kind, collection.capability, hint keys open; acquisition[].kind, collection.source, value.cardinality, constraint keys (closed, 7-key set: min, max, step, integer_only, min_length, max_length, pattern) closed. Consumed in daw-modul-berhtjan-core 2.1.0 -- types.resolve() is now pure registry lookup, M.PRIMITIVES removed entirely. Refs: DAW/daw-modul-berhtjan-core#11
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
DAW/daw-contracts#3
No description provided.