2.1 KiB
2.1 KiB
Validation Architecture
Validation is split into three ownership layers.
flowchart LR
Server[server<br/>stores simple settings<br/>binds table fields<br/>enforces writes]
Core[validation-core<br/>owns meaning<br/>resolves sets<br/>runs pure validation]
Canvas[canvas<br/>editor integration<br/>masking while typing<br/>UI feedback]
Common[common/proto<br/>wire format]
Server --> Core
Canvas --> Core
Server --> Common
Canvas --> Common
Rule
server stores dumb, serializable settings. validation-core owns what those
settings mean. canvas uses the resolved result for editing behavior.
flowchart TD
Settings[ValidationSettings<br/>serializable data]
Rule[ValidationRule<br/>named reusable fragment]
Set[ValidationSet<br/>ordered rules]
Config[ValidationConfig<br/>resolved runtime config]
Result[ValidationResult]
Rule --> Settings
Set --> Rule
Set --> Settings
Settings --> Config
Config --> Result
Current Data Flow
sequenceDiagram
participant DB as server DB
participant Server as server
participant Core as validation-core
participant Client as client/canvas
DB->>Server: stored field validation settings
Server->>Core: interpret shared validation primitives
Server->>Client: gRPC validation config
Client->>Core: resolve/use shared primitives
Client->>Client: canvas editing, masks, errors
Set Flow
flowchart LR
RuleA[digits-only rule]
RuleB[phone-length rule]
RuleC[phone-mask rule]
Set[phone set]
Assignment[column assignment]
Stored[server stored settings<br/>set name + resolved config]
Runtime[server/canvas runtime]
RuleA --> Set
RuleB --> Set
RuleC --> Set
Set --> Assignment
Assignment --> Stored
Stored --> Runtime
The server stores reusable rules and sets, and field application stores a resolved snapshot:
field customer_phone uses set phone
resolved settings = {...}
That keeps backend enforcement stable even if the reusable set changes later.