Skip to content

ADR 0025: Module names and shared-object form views

  • Status: Accepted; form views implemented for the local prototype
  • Date: 2026-11-03
  • Extends: ADR 0017 and ADR 0021

Scope refinement, 2026-11-04: V1 supplies Contacts & Relations and Projects & Tasks with the release-scoped target catalog and domain-profile specification process. Documents & Communication and the five other target modules are later scope under PRD section 3. The initial selections below describe the current prototype seed; they do not limit the agreed catalog or establish complete domain delivery. Shared-definition/view/lifecycle architecture must support future contributors without duplicating records.

Stable key Short English name English description German description Initial object selection
contacts Contacts Contacts & Relations Kontakte & Beziehungen Contacts, Distribution lists
projects Projects Projects & Tasks Projekte & Aufgaben Contacts, Projects, Cases, Tasks
documents Documents Documents & Communication Dokumente & Kommunikation Emails, Documents

These are initial selections, not a closed catalog. Additional objects and modules may be supplied later. Contacts can represent customers, suppliers, partners, service providers and other relationships; those roles are not mutually exclusive Contact kinds. Organization, Individual contact and Contact person remain separate Contact kinds.

Objects, field definitions and values are shared across modules. A Contact viewed from Contacts or Projects has the same UUID and storage. Modules contribute protected fields to one common object form without copying records or redefining a shared field. Human-facing names may change without renaming the existing projects key. Earlier references to CRM or Project Management describe Contacts and Projects respectively.

The current dedicated Workspace Modules area reads its three-entry catalog from PostgreSQL, with the full descriptive names above. Contacts & Relations activates its structured Contact/Distribution-list base under ADR 0032; the local V1 Contacts/Distribution-list functional scope is accepted. Documents & Communication is planned and cannot activate yet. Projects & Tasks activation atomically supplies protected base Contacts, Projects, Cases and Tasks with standard fields and fixed Contact → Project → Case UUID roles. No role reassignment is offered through UI/API/MCP. Shared object/field contributions, common object forms and additive template updates are implemented locally. Full domain templates, released migration tooling and Documents capabilities remain separate work. This decision does not bring uploads, attachments or email transport into version 1.

Contact form refinement, 2026-11-04: supplied Contacts have a fixed core per Contact kind, recognized through semantic field/relationship UUID bindings. Creation selects the kind before opening the form; the value is immutable through normal UI/API/MCP updates. A separate conversion workflow is later work. The core contains names/Organization, compact contact collections, addresses, relevant further details, classification, notes and Contacts-owned relationships. Derived Keyword/formatted-name/Organization-name projections and the kind controller are omitted as input fields; the record heading retains the permission-aware display name. Salutation and Academic title are separate optional configurable selects; Additional given names and Name suffix use plain text inputs. All six personal name fields stay visible in Name & organization, ordered as Salutation, Academic title, First name, Additional given names, Last name and Name suffix, followed by Organization when applicable. Name & organization and Photo/Logo share the top row on large screens (two-thirds/one-third). Professional details (Job title, Department and Function) sits beneath Photo for Contact persons and Individual contacts. Further details and Language & time zone share the next row; narrower layouts stack. Record number, birthday, optional configurable Gender (independent of Salutation) and applicable register information belong to Further details; classification contains only Type, Status and Category. Contact details lists telephone numbers, email addresses and websites in that order. Contact details and Addresses share a second row with equal columns on large screens and stack on narrower screens. Their headings use the same section-legend treatment without duplicate titles. Loading uses the same group composition. There is no additional-name disclosure. Address details retain their disclosure. The interchange formatted-address text is not an editable form field; newly entered addresses leave it empty. A complete read-only address preview is available; export remains separate work. Collection Add actions sit beside their field headings; compact rows show a configurable context label, value and direct up/down actions. Entry order determines preference (first entry = 1); separate preferred toggles/numeric preference controls are not offered. Address entries have an unframed header with context and actions; a standard Separator divides consecutive addresses. All contact collection rows use visible usage/value labels. Telephone rows give most width to the number. A short expandable Order = preference explanation replaces the long inline hint. The ordinary editor selects at most one context label, with an explicit No label choice. Supplied context suggestions are Work/Home. Telephone options additionally carry an explicit immutable usage or phone_type group: usage starts with Work/Home; capabilities start with Mobile, Voice calls, Fax, SMS/text, Video, Pager and Textphone. Telephone rows expose two labeled single selects, independently editable and backed by ordinary configurable field options; each includes No label. Usage, Phone type and Telephone number share one row when the collection has enough width; narrower containers place the number below the two selections. Field settings separate the groups and require a group for each new option. Collection entries are reordered with direct up/down buttons; their stable identities and values move together. The stored entry retains its UUID context array for interoperability; group semantics come from option metadata, never translated labels. Multiple API-supplied labels are preserved on unrelated edits and shown as additional badges; choosing a label replaces that dimension. Each name field uses one plain text input; compound given/family names are entered together. Existing structured components are displayed joined with spaces and retained untouched on unrelated saves; editing the text writes one component using the existing first identity. No name-component Add/Remove/Reorder controls are exposed. Shared structured storage remains available to API/MCP.

Contact form_layouts describe only extensions: additional fields (including Access principals) and custom/Primary relationships outside the Contacts-owned core. The designer displays a protected core explanation and edits only those extensions. The backend rejects attempts to place core fields or module relationship sides in configurable layouts. Core field input aids/labels remain governed by normal field configuration, independent of layout protection. Custom object forms retain their freely editable layout.

Access principals is a protected virtual system field using its existing field UUID in the same layout entries as other fields. Designers can assign its group, order and half/full width. Its default width is full. The designer labels its protected role; placement never changes ownership rules or permits generic field-value writes. When sensitivity is disabled the element is unavailable, while its authored placement remains retained.

The current schema stores sys_object_types.form_layouts as JSONB. The single default form contains ordered groups with stable group IDs, translated labels and ordered form-element entries: scalar field UUIDs, relationship type UUID plus side, or one Primary-chain marker, with layout properties. Width is half or full on desktop; narrow layouts stack fields. No CSS, scripts, business values, rights or physical SQL column positions are stored in the form model.

configure_form_layout is shared by API and MCP. It requires an active object, Administrator/Designer authorization and the opened object version. Field references and relationship sides must belong to the object; General and subordinate Primary links are excluded. Groups and form elements must not be duplicated, and group translations follow the workspace label-language policy. A changed form advances the object version and writes one atomic definition event under form_layout.default. No-ops preserve version and history. Passing null resets the common form to its starter layout.

New custom objects use an editable starter layout: General / Allgemein contains Keyword, other business fields and maximum-one custom relationship sides; Primary association / Hauptzuordnung has its own full-width section immediately before Classification; Classification / Einordnung contains Type, Status and Category with the ordinary half/half/full widths; Relationships / Verknüpfungen contains multi-target relationship lists; Notes / Notizen comes last when a multiline notes field exists. Other than General, groups without elements are omitted. This is an initial proposal based on the available fields, not a required group structure or creation of extra fields. The demo seed uses the same shared proposal instead of a separate General/Details layout. Group IDs and names have no runtime domain meaning. Additional fields and relationship elements remain in an explicit Unassigned / Noch nicht zugeordnet collection until placed; they stay available in record forms, including required elements. All user groups may be renamed, reordered or removed; removing a group moves its elements to Unassigned without deleting definitions or values. All available object fields use the common form. Deleted/inactive and currently inapplicable fields are omitted at render time while their configuration identities remain retained. Empty rendered groups are omitted. Field administration remains alphabetical, and business-table column order stays unchanged.

Workspace settings offers a dedicated Form designer area, separately from object/field definition administration. Its alphabetically ordered selector contains only actual object types in the current workspace, including inactive types for read-only inspection. The inline editor configures the selected object’s standard form: group labels/order and half/full group width, element-group assignment, element order and width, plus visibility and initial table state for relationships. Group deletion unassigns its elements; even the last group may be removed. The designer explicitly labels group, width, visibility and initial table state. Group actions sit beside the heading; elements use the same layout without nested cards. Adding a group retains the entire unassigned draft, including display settings. Save/Reset are rendered into the enclosing dialog footer through form-associated buttons, so keyboard submission and native form validation still apply while actions remain visible. Assigning/unassigning elements does not change business data. Save/Reset, pending guards and discard confirmation apply, including object switches. Read-only workspace members can inspect configuration. Settings-section changes retain the draft, and the enclosing settings dialog protects dismissal.

The common object form is the only supported form configuration. Module contributions track definition ownership and template updates; they do not create separate form views.

Custom relationship sides are regular designer elements alongside scalar and classification fields. Maximum-one sides render as labeled InputGroups with half/full width; multi-target sides render full-width tables. The designer can place and hide optional sides, and choose Automatic/Expanded/Collapsed as the initial table state. Required sides cannot be hidden, and a later change to requiredness or cardinality overrides stale presentation settings at render time. The Primary chain is one full-width element, preserving its ordered levels and inherited/direct behavior. General remains in the header and Dossier, and subordinate Primary links remain in the Dossier; neither becomes a duplicate designer element.

Both metadata and content reads use the same relationship-side projection, including directed self-pairs and symmetric undirected pairs. The designer reads definitions without loading business contents. New applicable sides remain unassigned, like newly added scalar fields; no Relationships or Business details group is created automatically. Hidden optional connections can be temporarily revealed in the record without changing configuration or stored edges; if a discriminator edit is blocked by a hidden connection, that connection is revealed for explicit removal. Initial table state does not prevent users expanding a table or applying a picker. Inactive/unavailable elements retain stored positions while the editor can save unrelated changes; newly forged or altered unavailable references are rejected. Conditional applicability, rights, cardinalities, versions, cycle checks and atomic edge journals remain backend rules, independent of layout. Full module navigation remains future work.

Unassigned entries share the same identity, scope, width and visibility validation as grouped entries. Duplicate identities across both collections are rejected. Unavailable elements retain their configuration, and background metadata refresh adds new elements without replacing a dirty draft.

Layout journal events retain their immutable group labels, element identities, order and display settings. Read-only journal context supplements them with current field/relationship names, including retained definitions. The detail view explicitly distinguishes these current names from the historical layout and keeps original identities/snapshots under Technical details.

Isolated PostgreSQL tests cover current initialization, field identity scope, duplicate rejection, version conflicts, no-ops, atomic journal rollback, API/MCP parity and rejection of module-specific form contexts. Rendering tests cover the common object form, default-form completion of new fields, retained layouts and input rejection, required-visibility/full-width coercion, directed/symmetric side identities and non-mutating defaults. Browser checks cover the settings editor and record forms, draft preservation, field order/width, keyboard behavior and narrow layouts. The current installation and optional seed follow ADR 0028: obsolete disposable development schemas/fixtures are recreated. Retained authored layout identities are ordinary product behavior, not an old-schema adoption path.

All technical object names in the module catalog are reserved for module definitions, including disabled/planned modules. UI shows an associated field error and disables submission; shared API/MCP creation enforces the same database-backed reservation. Display labels may coincide, but custom technical identities cannot occupy module names. Conflicting custom definitions block activation without being repurposed.

Scope refinement, 2026-11-05: Contacts & Relations delivers Contacts and Distribution lists in V1. Its 11 additional catalog objects and their supplied relationships move to the next version. Projects & Tasks delivers Contacts, Projects, Cases and Tasks in V1; its six additional planned objects remain beyond V1. Shared Contacts counts once. The PRD Delivery column owns the release assignment.

Shared contributions and lifecycle — 2026-11-05

Section titled “Shared contributions and lifecycle — 2026-11-05”

sys_module_contributions binds each contributing module to the shared object identity and installed template version. sys_module_field_contributions records its object-owned field selection with composite scope foreign keys. Supplied field recipes reuse canonical bindings; conflicting shared structures fail atomically, and matching custom technical names are never adopted. Projects provisions the same complete Contact core while Contacts activation additionally makes Distribution lists available. Activation order does not create copies.

Disabling a module retains definitions, values, relationships, input-aid configuration and authored forms. A shared object stays active while any contributing module is enabled; otherwise its definition becomes inactive and contents remain inspectable. Reactivation restores the same identities. Module relationships follow endpoint availability. Projects additionally gates Primary and rejects disabling while Primary links remain, including retained recycled links.

The shipped catalog has explicit template versions. Additive template updates install missing definitions and contribution selections while retaining customized labels/options, fields and forms. Structural conflicts roll back; downgrades are rejected. Modules settings offers Update module when the installed version lags. Released application migration/restore tooling remains a separate delivery task under ADR 0028.

Each object type has one common form, independent of module membership. Record pages and the Form designer use this form directly. Available fields from all contributing modules and user-defined additions share the same layout, values and rights. There is no form-context selector or module override in UI/API/MCP. Supplied Contacts retain their fixed core; the common designer arranges only extensions.

Contact presentation refinement — 2026-11-05

Section titled “Contact presentation refinement — 2026-11-05”

Desktop record pages retain direct Recycle/Duplicate actions; narrow screens use a compact Actions menu with the same permission checks, dirty-state guards and confirmation dialog. Contact Function uses a compact checkbox menu that retains multiple selections and the normal record Save/Reset. Phone/messenger type selections receive more width. Partial-date format help opens from a labeled information button rather than repeating permanent text, and Contact time-zone help is an optional disclosure. Media placeholders use one short availability note. While Contact kind is unknown, loading shows a neutral form frame; once values are known, it applies the same field/relationship applicability and read permissions as the form.

Project, Case and Task starter forms place Record number, Responsible and Access principals in that order in a half-width Project details / Projektdetails, Case details / Vorgangsdetails or Task details / Aufgabendetails group next to a half-width Schedule / Zeitplan group. Projects and Cases supply optional Start date / Beginn and Target date / Zieldatum, with an inclusive date-order check. Group widths are stored in the common layout, configurable in the designer and retained in definition journals. Groups stack on narrow screens; element widths remain relative to their group.

Tasks use the same paired Details/Schedule arrangement. Their Schedule & progress group contains Start, Due, Priority, Progress and Completed at, with Priority directly before Progress. Task assignment uses the protected Access principals element below Responsible, without a separate assignment input. These are editable common starter layouts.

Fresh supplied forms reserve the module-gated Primary association group before Classification, even when Projects is not yet enabled during template installation. Normal layout resolution hides unavailable elements and empty groups. Activating Projects preserves an already authored common form; it does not rebuild it.