Name the concept owner and lifecycle first
A generated form supplies no meaning, invariants, authority, migration, retention, integrations, or reporting. The schema contract must assign them.
Short answer
Choose a field, configurable entity, domain module, or external authority by ownership and behavior
Use a field for a low-risk attribute on the right existing record; a configurable entity for a simple governed register; a module or extension entity for consequential behavior; and an external authority when another system owns the record while Open Mercato references or synchronizes it. Generated screens and storage do not replace domain design.
- Reviewed
- 2026-07-14
- Current source
- 01911d00e28f44cf484d0b1d04860dcfef5370bf (v0.6.5-1202-g01911d00e)
- Latest reviewed tag and package
- v0.6.5 · 0.6.5
This editorial method supports planning. It does not provide a complete schema, migration, security review, data-governance approval or production acceptance.
Evidence states and manager glossary
Keep released evidence, this develop revision, pathway conditions, absent proof and broad narrative documentation separate.
- 1. released
- 2. reviewed current develop
- 3. pathway or implementation dependent
- 4. not established
- 5. documentation drift
- system entity
- ORM-backed domain entity
- custom field
- configurable entity
- custom record
- extension entity
- definition
- EAV
- JSON document
- field kind
- fieldset
- dictionary
- relation
- source of truth
- schema owner
- migration
- backfill
- compatibility
- tombstone
- stable key
Four storage shapes and their consequences
ORM table
Storage: Module-owned explicit schema and domain APIs
Manager implication: Strong behavior and contracts; code, migration and module ownership required
EAV custom values
Storage: Definitions plus typed values extend an existing entity
Manager implication: Low-risk attributes can follow the existing record lifecycle; consumers must integrate the entity id and field utilities
Custom entity JSON documents
Storage: Generic custom_entities_storage records plus definitions
Manager implication: Useful for simple governed registers; generic CRUD does not provide domain behavior
Linked extension entity
Storage: A code-owned table links to another module entity
Manager implication: Preserves module ownership for consequential data without altering another module table
A ce.ts declaration alone does not provide generic custom-record storage. Current classification is ORM-first: module-owned system records stay in their tables and domain APIs, while the generic record route rejects them.
Execution-time field-kind inventory
Record manager use, single or multiple cardinality, options or dependency, generated editor, storage format, filter, sort, search, export and one acceptance example. Availability and parity vary by pathway.
- 1. text
- 2. multiline
- 3. integer
- 4. float
- 5. boolean
- 6. select
- 7. currency
- 8. relation
- 9. attachment
- 10. dictionary
- 11. date
- 12. datetime
Configuration pathway matrix
admin UI
- entity registration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- field definitions: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- defaults: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- validation: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- fieldsets: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- dictionaries: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- relations: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- encryption: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- indexing: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- lifecycle and migration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
authenticated API
- entity registration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- field definitions: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- defaults: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- validation: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- fieldsets: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- dictionaries: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- relations: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- encryption: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- indexing: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- lifecycle and migration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
entities CLI
- entity registration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- field definitions: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- defaults: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- validation: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- fieldsets: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- dictionaries: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- relations: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- encryption: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- indexing: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- lifecycle and migration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
code-first ce.ts
- entity registration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- field definitions: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- defaults: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- validation: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- fieldsets: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- dictionaries: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- relations: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- encryption: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- indexing: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- lifecycle and migration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
app or module code
- entity registration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- field definitions: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- defaults: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- validation: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- fieldsets: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- dictionaries: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- relations: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- encryption: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- indexing: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
- lifecycle and migration: record one source-backed status (current, partial, dependency-specific, implementation-dependent, not exposed, or not established).
The UI, API, CLI, ce.ts and app code do not expose identical options. Current generated custom-entity surfaces include metadata, optional sidebar registration, definitions, record list, forms when fields exist, search, filters, sort, export and APIs. They do not automatically supply dashboards, workflows, commands, approvals, notifications, transactions, specialist permissions, integrations, reconciled reports or migrations. Owning CRUD pages display custom fields only when they integrate the entity id and field utilities.
Classification matrix
1. Use a custom field
An additional low-risk attribute belongs to an existing record with the right owner and lifecycle. Stop if it introduces a new independent object, consequential state or cross-record invariant.
- ownership
- lifecycle
- state transitions
- validation
- relations
- transactionality
- permissions
- volume
- performance
- integrations
- reporting
- migration
- retention
- maintenance
2. Use a configurable custom entity
A simple organization-scoped register is mostly create, view, edit, filter, search and export. Stop if generic permissions, JSON records or generated CRUD cannot satisfy the whole lifecycle.
- ownership
- lifecycle
- state transitions
- validation
- relations
- transactionality
- permissions
- volume
- performance
- integrations
- reporting
- migration
- retention
- maintenance
3. Build a domain module or extension entity
The object has transactions, state transitions, invariants, complex relations, specialist authority or a long-lived contract. Stop until code, operations, migrations and acceptance ownership are funded.
- ownership
- lifecycle
- state transitions
- validation
- relations
- transactionality
- permissions
- volume
- performance
- integrations
- reporting
- migration
- retention
- maintenance
4. Keep or reference an external authority
Another system must own specialist, regulated, high-scale or authoritative data. Stop until synchronization, identity, acknowledgement and reconciliation are defined.
- ownership
- lifecycle
- state transitions
- validation
- relations
- transactionality
- permissions
- volume
- performance
- integrations
- reporting
- migration
- retention
- maintenance
Stop configuration for an unclear owner, duplicate concept, unknown source, unstable meaning, required uniqueness, cross-record rule, multi-step transaction, consequential state, complex many-to-many relation, specialist authorization, high write volume, regulated retention, frozen history, or unplanned migration.
Schema contract
Define meaning, owner, compatibility and acceptance evidence before configuration becomes a contract.
- 1. business question
- 2. plain-language meaning
- 3. business owner
- 4. source of truth
- 5. entity owner
- 6. stable entity id and field key
- 7. display label and translations
- 8. data type
- 9. cardinality
- 10. required, default and null rule
- 11. allowed values or dictionary
- 12. validation rules
- 13. cross-field and domain rules
- 14. relation target and deletion behavior
- 15. tenant and organization scope
- 16. read roles
- 17. write roles
- 18. sensitivity and encryption
- 19. search, filter and sort needs
- 20. list and form needs
- 21. indexing
- 22. import, export and API consumers
- 23. reporting grain
- 24. history, audit and undo
- 25. volume and retention
- 26. migration and backfill
- 27. compatibility
- 28. change approver
- 29. deprecation and removal
- 30. reconciliation
- 31. acceptance owner and evidence
Structural example to adapt
Assumption: one abstract controlled attribute belongs to an existing record. Its key remains stable while label, translation and display order may evolve. The contract still needs type, null and empty rules, dictionary ownership, scope, roles, import, reporting, backfill, reconciliation and removal evidence. No real key or value is provided.
Entity id, field key, display label, translation, display order and stored value are different. Keys are integration contracts; renaming is a migration decision. Decide null versus empty, single versus multiple, defaults, units, currency, precision, date versus datetime and timezone explicitly.
Controlled values, relations and validation
Static options, dictionaries and dynamic options need source ownership, aliases, translations, inline-creation policy, retirement and historical labels. Relations need a target, label field, cardinality, target permission and scope, missing-target and deletion behavior, import mapping, search and API tests. Current relation options cap results at 200; named tests do not prove every target-domain permission case.
Current rules
- required
- date
- integer
- float
- less than
- less than or equal
- greater than
- greater than or equal
- equal
- not equal
- regular expression
Not established by the generic validator
- conditional requiredness
- cross-field rule
- cross-record rule
- uniqueness
- aggregate invariant
- temporal invariant
- external validation
Writes reject undeclared keys and cap present custom-field keys at 128. Fieldsets group presentation or variants; they are not entity types, schemas, authorization boundaries or lifecycle state machines.
Scope, access, deletion and concurrency
Definitions can resolve global, tenant and organization candidates by specificity and time; scoped tombstones can hide inherited definitions and restoration can expose them again. Test wrong tenant, wrong organization, selected organization, global fallback, inherited fields and tombstones. Definition view/manage, generic record grants, target-module features, relation lookup, generated screen, record CRUD, export, search, import and API-key paths are separate authorization surfaces.
Fields, entity definitions and records have separate soft-delete behavior. A deleted entity definition can leave stored records. Optional expected-version headers can reject stale schema, entity and record edits; without a version header current additive locking can proceed. Test concurrent field order, definition, metadata, record update and record delete separately.
Schema change and encryption lifecycle
Record discovery, compatibility, backfill, dual read or write, validation, reconciliation, rollback, communication and retirement evidence. entities install synchronizes declarations only. It does not perform general data migration or destructive schema diffs.
- 1. additive field
- 2. required or default change
- 3. option change
- 4. validation tightening
- 5. type change
- 6. key rename
- 7. relation change
- 8. encryption or scope change
- 9. removal
Selected-field encryption protects future writes when configured with working tenant encryption services. It does not provide database-wide encryption, access control, residency or compliance. Existing plaintext needs resave or backfill. Test KMS health and fallback, key rotation, deterministic hash lookups, search, sort, filter, indexes, exports, backups, logs, integrations and recovery.
Name inputs, owner, evidence, rollback and downstream consumers.
- 1
propose
- 2
classify
- 3
model
- 4
review
- 5
configure or code
- 6
install
- 7
migrate or backfill
- 8
validate
- 9
publish
- 10
monitor
- 11
change
- 12
deprecate
- 13
retire
- business concept owner
- data owner
- schema owner
- domain or module owner
- security and access approver
- migration owner
- integration owner
- reporting owner
- acceptance owner
- change approver
Three synthetic modeling decisions
Load the structural row to inspect candidate shape, rationale, contract excerpt, evidence, escalation and stop without customer data.
Hypothetical only
Synthetic controlled customer attribute
Hypothetical only
Synthetic organization equipment register
Hypothetical only
Synthetic consequential regulated object
Local planning tool
Data-model decision register
Starts empty and stays local to this browser. Use a complete row for planning. The register does not approve a schema or accept a migration.
Do not enter real data: Use structural labels only. Do not enter real company concepts, field keys, values, personal data, credentials, tenant or organization ids, sensitive classifications, production URLs or copied schemas.
Privacy: The page does not send worksheet content, put it in the URL, or store it in cookies.
Acceptance pack and state distinctions
Include normal, edge, failure and adversarial input, scope, authority, output, evidence, cleanup, owner and repeatable pass criterion.
- 1. create
- 2. read
- 3. update
- 4. delete
- 5. required, default and null
- 6. every used kind
- 7. multiple values
- 8. validation
- 9. static options
- 10. dictionary
- 11. relations
- 12. fieldsets
- 13. tenant and organization scope
- 14. definition ACL
- 15. record ACL
- 16. search
- 17. filter
- 18. sort
- 19. export
- 20. encryption
- 21. concurrency
- 22. representative volume
- 23. history
- 24. audit and undo
- 25. import
- 26. API and integrations
- 27. schema change
- 28. backfill
- 29. rollback
- 30. entity deletion with surviving records
- 31. tombstone and restore
- 32. downstream schema refresh
- empty value
- invalid type
- undeclared key
- more than 128 present custom-field keys
- duplicate business identifier
- deleted option
- missing relation target
- wrong scope
- denied role
- stale version
- KMS unavailable
- old plaintext value
- spreadsheet-formula prefix
- high volume
- downstream stale schema
Expose and test this state independently from empty and unavailable states.
- field absent
- field hidden
- field denied
- definition inactive
- definition tombstoned
- dependency unavailable
- record empty
- record deleted
- true null
- true zero or false
Representative volume and query tests are required before claiming search, filter, sort, list, export or relation selectors suit the intended scale.
Stop or defer
- unclear business concept.
- no accountable owner.
- unsettled tenant or organization scope.
- unknown source authority.
- unresolved security or sensitivity.
- incompatible downstream consumers.
- missing migration and rollback.
- untestable history or retention.
- consequential domain forced into generic storage.
Practical questions
When is a custom field enough?
Use a field for an additional attribute of an existing record. Separate identity, workflow, permissions or relationships may justify a custom entity or a module with developer-owned behavior.
Can I change a field’s type or key later?
Treat this as a data change. Inventory stored values, imports, filters and integrations, then rehearse conversion and rollback. A renamed label does not migrate references to a different key.
Does field encryption replace access control?
Selected-field encryption needs working tenant encryption services and configuration. Existing plaintext may require backfill. Check permissions, exports, search indexes and logs individually.
Does deleting an entity definition erase its records?
Definitions, fields and records have separate soft-delete behavior in the reviewed source. Plan record cleanup, retention and recovery explicitly instead of assuming one deletion removes every copy.