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 recipes<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]
Recipe[ValidationRecipe<br/>named reusable settings]
Package[ValidationPackage<br/>distributable recipes]
Config[ValidationConfig<br/>resolved runtime config]
Result[ValidationResult]
Package --> Recipe
Recipe --> 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
Future Package Flow
flowchart LR
Registry[validation package registry]
Package[phone package]
Recipe[phone.e164 recipe]
Assignment[column assignment]
Stored[server stored settings<br/>recipe ref + resolved config]
Runtime[server/canvas runtime]
Registry --> Package
Package --> Recipe
Recipe --> Assignment
Assignment --> Stored
Stored --> Runtime
The server may store both the recipe reference and the resolved settings:
field customer_phone uses phone.e164@1.0.0
resolved settings = {...}
That keeps package imports inspectable and versioned while preserving stable backend enforcement even if a package changes later.