Draft Proposal: Workflow-Governed Process Data and FEC UI Overhaul¶
Status: Draft for product/architecture review
Owner: LeadArchitect
Inputs: Product Owner feedback, DISC-02 team design discussion
Scope: Proposal only; no implementation commitment
1. Executive Summary¶
The eFEC engine is converging on the right architecture: all business mutations flow through process_event, actions are workflow-governed, event history is verifiable, and the universal action dialog can construct signed events from workflow/server output. The current UX, however, exposes engine pieces directly rather than presenting a coherent platform to analysts, auditors, and admins. Pages such as Workbench, Customers, Cases, and Screening overlap, repeat data, and do not clearly map to user jobs.
The root cause is not only frontend layout. The platform does not yet have a formal, enforced process data model. Customer data currently feels arbitrary because process data is effectively a loose JSON object, while workflows contain only partial/de-facto schema metadata.
This proposal has two parts:
- FEC-independent process data structure definition: formalize workflow-owned process data schema, using the existing
$fieldsand$displayconventions as the starting point, and enforce it inside the engine. - FEC-specific UI overhaul: redesign navigation and presentation around user personas and schema-governed process instances rather than hardcoded customer/case/screening pages.
Key recommendation: extend and enforce the existing workflow $fields model instead of inventing a parallel data_schema syntax. $fields already appears in most seeded workflows and already functions as de-facto process schema/display metadata. Formalizing it reduces migration risk and keeps schema attached to immutable workflow versions.
2. Goals and Non-Goals¶
Goals¶
- Make process data structure explicit, workflow-governed, versioned, and enforceable.
- Keep the model generic: applicable to any workflow namespace, not specific to customers or FEC.
- Preserve eFEC guardrails:
- all mutations through
process_event; - canonical
inputenvelope; - no frontend workflow evaluation;
- no raw writes;
- immutable event history;
- Rust/WASM parity.
- Enable schema-driven process views, forms, tables, and detail pages.
- Simplify FEC UX around personas and primary jobs.
- Separate analyst operational UX from auditor/admin diagnostic UX.
Non-Goals¶
- Do not design a full low-code UI builder.
- Do not introduce frontend-only validation as a substitute for engine validation.
- Do not make customer data a separate application model outside process data.
- Do not change canonical event hash formula.
- Do not require per-state process schemas in the first iteration.
- Do not implement automatic child-process spawning as part of this proposal; model it as a related but separate workflow/process graph capability.
3. Part A: FEC-Independent Process Data Structure Definition¶
3.1 Current State¶
Current workflows already contain schema-like metadata:
$fieldsdescribes fields using attributes such astype,label,section,required,system, andoptions.$displaydescribes presentation metadata such aslabel,icon,list_columns, anddefault_sort.- Action
setrules commonly map frominput.fields.*into processdata.
This is already a de-facto process data schema. The missing pieces are:
- formal syntax and validation semantics;
- deploy-time validation of workflow schema;
- runtime enforcement during
process_event; - clear distinction between consensus validation metadata and UI display metadata;
- schema-driven frontend rendering.
3.2 Recommendation: Formalize $fields¶
Use workflow-level $fields as the authoritative process data schema for a workflow version.
Example draft shape:
json
{
"$schema_enforce": true,
"$display": {
"label": "Corporate Customer",
"icon": "building",
"list_columns": ["legal_name", "jurisdiction", "state", "risk_score"],
"default_sort": [{ "field": "updated_at", "direction": "desc" }]
},
"$fields": {
"legal_name": {
"type": "string",
"label": "Legal Name",
"section": "identity",
"required": true,
"readonly": false,
"audit_sensitivity": "pii"
},
"jurisdiction": {
"type": "string",
"label": "Jurisdiction",
"section": "identity",
"required": true
},
"risk_score": {
"type": "number",
"label": "Risk Score",
"section": "risk",
"readonly": true,
"computed": true,
"audit_sensitivity": "internal"
},
"kyc_case": {
"type": "reference",
"label": "KYC Case",
"section": "related",
"reference": { "namespace": "case/review", "workflow": "kyc-review" },
"readonly": true
},
"raw_screening_payload": {
"type": "json",
"label": "Screening Payload",
"section": "screening",
"audit_sensitivity": "restricted"
}
},
"$sections": {
"identity": { "label": "Identity", "order": 10 },
"risk": { "label": "Risk", "order": 20 },
"related": { "label": "Related Processes", "order": 30 },
"screening": { "label": "Screening", "order": 40 }
}
}
Notes:
$fieldsis consensus-relevant schema metadata because it controls process mutation validity.$displayand$sectionsare presentation metadata. They may live in the immutable workflow snapshot, but the engine should only depend on validation-relevant parts.$schema_enforceallows opt-in rollout per workflow version.
3.3 Field Types¶
Start with a small deterministic type set:
| Type | Meaning | Validation |
|---|---|---|
string |
UTF-8 JSON string | value must be JSON string |
number |
JSON number | value must be finite JSON number |
boolean |
JSON boolean | value must be boolean |
date |
ISO date string | strict YYYY-MM-DD string |
datetime |
ISO/RFC3339 timestamp string | strict timestamp string |
enum |
one of configured options | value must match option value |
reference |
process reference | process id string initially; later structured reference object |
json |
opaque object/array/scalar | accepted as JSON, optionally constrained later |
object |
declared nested object | only if a nested field model is explicitly needed |
Avoid expanding the type system too early. money, country, identifier, etc. should initially be display/widget hints over canonical primitive types unless they require consensus validation.
3.4 Field Attributes¶
Initial attributes:
| Attribute | Owner | Purpose |
|---|---|---|
type |
engine | deterministic field validation |
label |
frontend | human-readable display |
section |
frontend | grouping/detail layout |
required |
engine | required presence constraint |
default |
engine | create/init default, applied deterministically |
options |
engine/frontend | enum values and labels |
readonly |
engine | rejects analyst/action writes unless system-derived path is allowed |
computed |
engine/frontend | indicates derived field, not submitted by users |
system |
engine/frontend | backwards-compatible alias/flag for engine-owned fields |
audit_sensitivity |
frontend/policy | redaction and visibility hints |
reference |
engine/frontend | allowed target namespace/workflow for process references |
description |
frontend | help text |
widget |
frontend | rendering hint only, not validation logic |
3.5 Engine Responsibilities¶
The engine owns deterministic, workflow-versioned validation:
- Deploy-time validation during workflow registration/update:
- parse
$fields; - reject invalid types/options/attributes;
- reject
setpaths targeting undeclared fields when$schema_enforceis true; - type-check
setsource references such asinput.fields.doc_countagainst target$fieldstypes, not only literal values; - reject self-contradictory input schemas that ask users to provide
readonly/computedfields; - warn or reject unsupported schema/display combinations;
-
preserve schema in immutable workflow version snapshot.
-
Runtime validation during
process_event: - resolve workflow/action/state/guard as today;
- validate action
inputif/when action input schema exists; - construct the process data delta from
set/merge/appendrules; - validate the resulting delta/final data against
$fields; - reject unknown fields, invalid types, missing required fields, and forbidden user-input writes to
readonly/computedfields; - allow workflow-authored deterministic
setrules to write derivedreadonly/computedfields when those rules pass deploy-time validation; -
only after validation succeeds, proceed to canonical event persistence.
-
Canonical errors:
- return stable error codes and field paths;
- avoid frontend-specific phrasing in engine semantics.
3.6 Frontend Responsibilities¶
The frontend owns presentation only:
- render list columns from
$display.list_columns; - render detail sections/cards from
$fields.sectionand$sections; - select controls/widgets from
type,options, and widget hints; - show required/readonly/computed/sensitivity indicators;
- render allowed actions from server/Rust-WASM flow output;
- submit canonical
inputenvelopes through the shared event builder/dialog.
The frontend must not:
- decide action availability;
- bypass engine validation;
- infer hidden workflow semantics;
- write directly to process data;
- treat customer/case/screening data as separate models outside workflow process data.
3.7 Validation Ordering and Hash Integrity¶
Validation must not alter canonical event hash semantics.
Recommended order:
- Receive canonical action envelope with
input. - Verify actor/signature/roles/workflow/state/guard.
- Build data delta from workflow action rules.
- Validate delta/final process data against
$fields. - If invalid: reject; no event is appended.
- If valid: append the original signed event using the existing canonical hash formula.
Important principle: schema validation is a pre-commit gate. It rejects invalid mutations; it does not rewrite the event payload.
3.8 Requiredness and Defaults¶
Open design choice: requiredness can mean either:
- lifecycle required: field must exist after create/init; or
- eventually required: field must exist before particular transitions.
Recommendation for first iteration:
- Process-wide
requiredmeans required after create/init when$schema_enforceis true. - Transition-specific requiredness remains in action guards/input requirements.
- Defaults apply only during create/init or deterministic schema initialization.
- Defaults never mutate historical events retroactively.
- A default added in workflow version
N+1must not backfill process data created under workflow versionNduring replay.
3.9 Readonly, Computed, and System Fields¶
System-derived data should be explicit.
Examples:
state: system/readonly, engine-owned.risk_score: computed/readonly if produced by rules/automation.kyc_result: readonly if written only by a linked child process result event or automation actor.
Initial rule:
readonlymeans "not user-submitted" rather than "never changed";- analyst/action
inputmust not directly providereadonlyorcomputedfields; - workflow-authored deterministic
setrules may writereadonly/computedfields, because that is how derived/system fields are produced; - deploy-time validation must reject action input schemas that request readonly/computed fields from users;
- deploy-time validation must still type-check workflow
setrules that write readonly/computed fields; - automation writes require explicit actor/workflow semantics before broadening this rule.
This precedence avoids a contradiction where a field such as risk_score is correctly marked readonly for analysts but still needs to be written by approved workflow logic.
3.9.1 set, merge, append, and Nested Data¶
The first schema-enforced version should avoid a full nested schema language.
Recommended v1 rule:
- scalar
settargets are validated against declared$fieldstype and attributes; setvalues that referenceinput.fields.*must be type-compatible with their target fields at deploy time and runtime;mergetargets must be declared as an opaquejsonfield unless/until a nested schema extension is approved;appendtargets must be declared as an opaquejsonor array-compatiblejsonfield in v1;- v1 does not validate array element schemas or nested object member schemas;
- future nested schemas can be added after the flat field contract is proven.
This keeps consensus validation deterministic and small while still blocking accidental writes to undeclared top-level process data.
3.10 References and Process Graphs¶
KYC, screening, investigations, accounts, and cases should be modeled as process instances, not duplicated JSON fields on the customer.
First iteration reference model:
json
{
"kyc_case": {
"type": "reference",
"reference": {
"namespace": "case/review",
"workflow": "kyc-review"
},
"readonly": true
}
}
A reference field initially stores a process id. Later it may become a structured object:
json
{
"process_id": "...",
"namespace": "case/review",
"workflow": "kyc-review",
"relationship": "kyc_case"
}
Related but separate future work:
- explicit child process creation action semantics;
- process graph query API;
- relationship events between processes;
- UI graph of parent/customer and child KYC/screening/case branches.
3.11 Migration and Compatibility¶
Recommendation:
- Introduce
$schema_enforce: trueas opt-in per workflow version. - Existing workflows/processes continue without enforcement until migrated.
- Convert current
$fieldsmetadata into formal schema in seeded workflows. - Add missing
$fieldsto workflows that currently lack them. - Run reconcile/dry-run tooling against existing process data before enabling enforcement.
- A clean dev reset is acceptable if Product Owner approves, but the architecture should not depend on resets long term.
3.12 Consensus and Parity Risks¶
High-risk areas:
- schema validation becomes consensus logic;
- Rust/WASM parity must be exact;
- canonical error semantics should be stable;
- validation must not mutate submitted events or alter hash formula;
- display metadata must not become hidden consensus logic accidentally.
Mitigations:
- implement schema parser/validator in shared
governed-eventscore; - expose the same logic to WASM;
- test Rust and WASM parity with shared fixtures;
- add a dedicated
schema_validation_testsfixture set covering valid schemas, invalid schemas, every supported field type, required/default/readonly/computed attributes, input-ref-to-target type compatibility, and invalid-submission rejection before hashing/persistence; - keep initial type system small;
- keep validation deterministic and independent of database lookups except where explicitly designed, such as reference existence validation.
4. Part B: FEC-Specific UI Overhaul¶
4.1 Current UX Problem¶
The current UI exposes implementation pieces rather than a coherent product:
- Workbench, Customers, Cases, Screening, Processes, Events, and diagnostics overlap.
- Users see repeated process data without a clear task model.
- Customer detail mixes arbitrary JSON, workflow actions, related processes, screening/case concepts, and audit timeline.
- Some pages are unclear: are they operational surfaces, diagnostics, or admin tools?
- Child-process concepts such as KYC are not represented clearly.
The UI should be rebuilt around personas and jobs-to-be-done, with process schema as the rendering source.
4.2 Personas¶
Analyst¶
Primary user for day-to-day compliance work.
Needs:
- know what requires attention now;
- open an entity/case;
- see current state and key data;
- perform allowed workflow actions;
- review related KYC/screening/case processes;
- avoid audit/admin noise unless needed.
Investigator / Compliance Manager¶
Needs:
- escalations and approvals;
- queue oversight;
- exception/risk views;
- ability to inspect linked cases and decision rationale.
Auditor¶
Needs:
- immutable event history;
- hash chain/signature verification;
- exact submitted event payloads;
- workflow version/snapshot at decision time;
- read-only access, minimal operational UI.
Admin / Workflow Owner¶
Needs:
- workflow deployment/versioning;
- actor/role management;
- automation/scheduler configuration;
- diagnostics and health checks;
- schema/display review.
4.3 Proposed Navigation¶
Recommended top-level navigation:
- Inbox
- Processes
- Audit
- Admin
Optional shortcuts can appear under Processes, but should not become separate data models.
Inbox¶
Primary analyst landing page.
Purpose:
- show available work across process types;
- group by priority, SLA, state, workflow, assignment, or risk;
- drive users to the next allowed action.
Data source:
- server/Rust flow projection and process metadata;
- not hardcoded action lists.
Rows could show:
- process type/workflow label;
- process display name from
$display/schema fields; - current state;
- available action count/action labels;
- risk/SLA indicators;
- assigned actor/team where available.
Processes¶
Unified process browser.
Purpose:
- replace fragmented Customers/Cases/Screening pages with one schema-driven browser;
- provide saved filters for common domains.
Saved filters/shortcuts:
- Customers
- KYC Reviews
- Screening Alerts
- Investigations
- Accounts
These are filters over process namespace/workflow/state, not separate frontend models.
List rendering:
- columns from
$display.list_columns; - labels from workflow
$display; - field formatting from
$fields; - no hardcoded customer table columns except temporary migration fallback.
Process Workspace¶
Detail page for any process instance.
Purpose:
- single operational workspace for an entity/case/screening process.
Recommended layout:
- Header
- workflow label/icon;
- process id truncated with copy/full view;
- state/status;
-
key badges from schema display metadata.
-
Summary
-
key fields from
$display.summary_fieldsor first important$fields. -
Allowed Actions
- rendered from server/Rust flow output;
-
submit through universal
ActionDialog. -
Data Sections
- generated from
$fieldsand$sections; - readonly/computed/sensitive indicators;
-
schema-driven formatting.
-
Related Processes
- references/process graph: KYC case, screening alert, investigation, account, etc.;
-
no duplicated child data unless shown as a summary card.
-
Timeline
- process-local event timeline from create event onward;
- action, date, process id, event hash;
-
click opens audit event detail.
-
Evidence/Notes
- only when represented by workflow-governed process data or linked processes/events;
- avoid side tables that bypass
process_event.
Audit¶
Read-only audit explorer.
Purpose:
- event detail;
- hash chain verification;
- signature verification;
- workflow snapshot/version at event time;
- replay/lineage views;
- process graph and event graph diagnostics.
Audit should not be the analyst default experience. It is for proof and investigation.
Admin¶
Purpose:
- workflows and schema review;
- actors/roles;
- automation and schedules;
- namespace registries;
- diagnostics/health;
- seed/bootstrap state.
Admin is where raw tables/diagnostics belong, clearly separated from operational UX.
4.4 Pages to Remove, Merge, or Reframe¶
| Current Concept | Proposed Treatment |
|---|---|
| Workbench | Rename/reframe as Inbox if task/action-driven; otherwise remove as redundant. |
| Customers | Saved filter under Processes + schema-driven customer workspace. |
| Cases | Saved filter under Processes, not separate model. |
| Screening | Saved filter or queue only if it has distinct alert workflow; otherwise related process tab. |
| Processes | Keep as unified process browser. |
| Events | Move under Audit. |
| Raw diagnostics | Move under Admin/Diagnostics. |
4.5 Customer Data Model in FEC¶
A customer should be a process instance governed by its workflow. There should be no separate customer data model that competes with process data.
Corporate customer example:
- namespace:
customer/corporate - workflow:
corporate-customer - data governed by
$fields - related KYC/screening/investigation/account processes linked via reference fields or process graph relationships
Example sections:
- Identity
- Registration
- Ownership
- Risk
- KYC
- Screening
- Relationships
- Audit Summary
System fields:
staterisk_scorekyc_resultscreening_statuslast_reviewed_at- references to child process ids
Analyst-facing customer view should show curated schema sections and allowed actions. Auditor-facing view should show event lineage and exact submitted events.
4.6 KYC, Screening, and Cases¶
The current spawn_kyc behavior demonstrates the need for clearer modeling:
- an action named
spawn_kycrecorded intent but did not create a KYC process; - users then had no way to find the expected KYC process.
Recommendation:
- model KYC review as a real child/related process using
case/review/kyc-review; - create/link child processes through explicit signed events;
- store the child process id as a
referencefield or relationship event; - show child processes in the parent Process Workspace under Related Processes;
- avoid duplicating child status except as read-only summary fields derived from linked process state.
The exact child-process creation mechanism should be specified separately, but the UI model should assume linked process graph support.
5. Implementation Sequence¶
Phase 0: Product/UX Inventory¶
No engine changes.
Deliverables:
- map current pages to personas and jobs;
- identify duplicated data and unclear surfaces;
- decide final top-level navigation labels;
- define minimum analyst, auditor, and admin workflows.
Phase 1: $fields Schema Specification¶
No implementation until approved.
Deliverables:
- formal
$fieldsgrammar; - type semantics;
- required/default/readonly/computed rules;
setsource/target type-checking rules, includinginput.fields.*indirection;merge/appendv1 rule for opaquejsonfields;$schema_enforcesemantics;- validation order in
process_event; - canonical error model;
- Rust/WASM parity fixtures;
- relationship/reference semantics v1.
Decision required:
- confirm extending
$fieldsinstead of adding paralleldata_schema; - confirm no per-state schemas in v1;
- confirm opt-in enforcement.
Phase 2: Schema-Driven UI Prototype¶
Frontend prototype only; may use static/sample schemas.
Deliverables:
- schema-driven process list;
- schema-driven process detail sections;
- schema-driven action input rendering using existing
ActionDialog; - prototype navigation: Inbox / Processes / Audit / Admin;
- no frontend workflow evaluation.
Purpose:
- validate UX before making schema enforcement consensus-critical.
Phase 3: Engine Schema Parser and Deploy-Time Validation¶
Deliverables:
- parse
$fieldsin shared Rust core; - validate workflow schema during deployment/registration;
- validate
settarget paths andinput.fields.*source type compatibility; - validate readonly/computed input-vs-workflow ownership rules;
- expose parsed schema through WASM/API;
- reject invalid schemas;
- parity tests.
No runtime process mutation enforcement yet unless behind a test flag.
Phase 4: Runtime Enforcement Behind $schema_enforce¶
Deliverables:
- validate action input, resulting data deltas, and final process data before commit;
- reject unknown fields and invalid types;
- enforce readonly/computed/required/default semantics;
- validate opaque-json behavior for
merge/appendv1; - ensure invalid submissions append no event;
- preserve canonical event hash formula;
- add Rust/WASM/SQL integration tests, including a reject-before-hash/persistence fixture.
Phase 5: Seed Workflow Migration¶
Deliverables:
- update all seeded workflows to formal
$fields; - add missing schemas for KYC, screening, accounts, and other workflows;
- reconcile/dry-run existing process data;
- reset dev seed data if approved.
Phase 6: UI Consolidation¶
Deliverables:
- Inbox replaces current scattered Workbench behavior;
- Processes browser replaces standalone Customers/Cases/Screening as primary model;
- process workspace becomes universal detail shell;
- Audit Explorer owns events/hash/signature views;
- Admin owns workflow/actor/diagnostic views;
- old redundant pages removed or converted to saved filters.
6. Open Decisions¶
- Schema syntax: extend
$fieldsas recommended, or introduce a newdata_schemablock? - Enforcement rollout: opt-in
$schema_enforceper workflow version, or mandatory after migration? - Per-state schemas: defer as recommended, or support state-specific field requirements early?
- References: store process id string initially, or structured reference object from v1?
- Child process creation: specify now, or handle in a separate process-graph proposal?
- Navigation labels: should analyst home be called Inbox, Workbench, or Queue?
- Role-specific navigation: separate analyst/auditor/admin navigation roots, or same nav with role-gated pages?
- Dev reset: is a clean seed reset acceptable when schema enforcement lands?
7. Proposed Immediate Next Steps¶
- Product Owner reviews this draft and confirms direction on open decisions.
- LeadArchitect converts this into two approved specs:
$fieldsprocess data schema enforcement spec;- FEC UX information architecture spec.
- Team prototypes schema-driven process list/detail using current
$fieldsbefore engine enforcement. - Team writes shared schema validation fixtures before modifying
process_event.
8. Team Input Incorporated¶
Developer input:
- proposed workflow-level process schema separate from action input schemas;
- emphasized engine validation vs frontend rendering separation;
- recommended queue/entity/case/audit/admin UX organization;
- warned against overloading schema as both validation and layout.
SeniorDeveloper input:
- identified
$fieldsas existing de-facto process schema; - recommended extending/enforcing
$fieldsinstead of inventing parallel syntax; - proposed
$schema_enforceopt-in migration; - emphasized validate-before-hash ordering and Rust/WASM parity;
- recommended collapsing Customers/Cases/Screening into unified Processes browser with saved filters;
- recommended Inbox-first analyst UX and separate Audit/Admin surfaces.