Blueprint Protocol
The normative cross-package contract is the Blueprint Protocol Contract. This page documents the Dart DTO package that implements that stable instruction set.
vyuh_blueprint_protocol defines the wire vocabulary used by clients, servers, agents, and simulators to exercise a blueprint-backed app.
The protocol separates:
- Queries: read entity data through a named projection such as
list,summary,detail, orpicker, using the sharedcdx_querygrammar. - Action requests: carry intent from UI, API, agents, simulators, workflows, or systems.
- Action commands: executable units carried by or derived from an action request. A single request may contain or produce many commands.
- Action records: durable truth of what happened, including per-command, rule, effect, integrity, result, and failure records.
- Simulation scenarios: replay ordinary query/action requests with
RequestSource.simulatorand produceSimulationRecordtranscripts. - Agent loops: propose ordinary query/action operations with
RequestSource.agent, run simulations, and report generated operations and simulation records. - Projections: stable DTO contracts describing which fields, actions, query capabilities, and payload shape a client can expect.
Runtime manifests expose these protocol projections so UI and agents do not guess which fields to fetch or render.
At the protocol edge the model is requests in, records/effects out. Queries and actions are the two primary request shapes. Subscriptions and realtime connections are delivery surfaces over records, projections, outbox rows, and runtime effects; they do not invent a separate action API.
An entity projection is the public read contract. Internally, it is assembled from the matching projection contribution of each facet. For example, equipment:list may include identity.code from the identity facet and cleaning.state from the cleaning facet, while equipment:picker may include the cleaning facet with no fields. Empty facet contributions are meaningful: they preserve the fact that the projection was considered facet-by-facet, even when a facet does not contribute fields to a particular read shape.
Action Runtime Vocabulary
| Concept | Purpose |
|---|---|
Actor | Runtime participant represented in RequestContext: user, system, workflow, simulator, API client, or agent. |
RequestContext | Actor, scope, time, reason, device, source, and correlation envelope for the request. |
BlueprintProtocolOperation | Common executable operation boundary for query and action requests. |
BlueprintProtocolRecord | Common durable-result boundary for query, action, simulation, and agent-loop records. |
BlueprintProtocolExecutor | Storage-agnostic executor contract for protocol operations and event streams through executeOperation(...). |
BlueprintQueryRequest | Query operation for one entity projection using Vyuh Query. |
QueryRecord | Durable query result carrying exactly one typed ProjectionResult. |
ProjectionResult | Sealed result root. Cardinality and payload shape come from its concrete subtype. |
ProjectionResultShape | Structural wire envelope only: collection, item, or custom. It is not a semantic type tag. |
ProjectionResultSchema | Stable schemaType, name, and title plus ordered columns; schemaType is the only semantic discriminator. |
ProjectionResultColumn | Stable name, human-facing title, wire-safe value kind, and nullability. |
CollectionResult | Many ProjectionObject values plus typed paging state. |
ItemResult | One ProjectionObject, or null when the exact item is not visible. |
CustomProjectionResult | Extensible base result whose semantic shape is identified by the standard projection schemaType. |
ProjectionObject | Schema-governed runtime object. Generated domain clients may decode it into a domain-specific Dart type. |
ActionRequest | Incoming orchestration boundary for one attempted user/system intent. |
ActionCommand | One executable action unit against an entity facet. |
ActionRecord | Durable result for the whole request. |
ActionCommandRecord | Durable result for one command attempt. |
ActionRuleRecord | Explainable result for one rule or condition evaluation. |
ActionEffectRecord | Durable record of an outbox/workflow/realtime/system effect. |
ActionIntegrityRecord | Runtime integrity finding such as command cycles or budget violations. |
ActionResult | Factual output produced by an action record or command record. |
ActionFailure | First-class typed failure attached to the action record or command record. |
BlueprintProtocolError | Transport-safe error envelope with an explicit protocol/domain layer, stable kind, status, retryability, recoverability, details, and typed remedies. |
SimulationScenario | Scenario made of ordinary query/action request ids. |
SimulationRecord | Replayable simulation outcome with produced records and protocol events. |
AgentLoopRequest | Agent-driven operation generation and testing loop; not a runtime entity operation. |
AgentLoopRecord | Durable record of generated operations and simulation outcomes. |
Requests carry RequestLineage and ExecutionLimits so outbox-driven action chains can be bounded. If an outbox effect creates another action request, that request includes the causal command path. The runtime can then deny recursive commands before they become unstable loops.
ActionResult is separate from ActionFailure. A record can be denied and only contain failures, committed and contain results, or partially committed and contain both. Results describe facts the rest of the system can use: entity state changes, named projection material, evidence links, audit facts, report rows, dashboard measures, downstream effect facts, and domain-specific derivatives.
Failure is explicit. ActionFailureKind separates generic, network, condition, constraint, conflict, integrity, access, policy, evidence, validation, system, adapter, timeout, and domain failures. There is one successful path, but many failure paths; records make those paths inspectable.
create, update, and delete are ordinary actions owned by the effective entity's identity facet. A transport may accept an entity-level alias for convenience, but capability resolution, planning, recording, and execution use the real identity facet. These standard actions do not bypass policies, validation, evidence, audit, or replay.
System of Record Loop
The protocol is intentionally command/query shaped:
QueryRequest -> EntityProjection data
-> QueryRecord
Actor
-> ActionRequest
-> ActionCommand[]
-> ExecutionPlan
-> PlannedInvariantCheck[]
-> PlannedRuntimeEffect[]
-> ActionRecord
-> ActionResult[]
-> ActionFailure[]
-> ActionEffectRecord[]
-> projections, reports, dashboards, UI, and derivative requests
Simulator
-> ActionRequest(source: simulator) / QueryRequest(source: simulator)
-> QueryRecord[] / ActionRecord[]
-> SimulationRecord
Agent
-> AgentLoopRequest
-> GeneratedProtocolOperation[] (query/action)
-> SimulationRecord[]
-> AgentLoopRecordThe server is the authority for records. Clients, UI renderers, agents, and simulators can query projections and request actions, but they do not invent facts locally. They consume action records, action results, and named entity projections published by the runtime.
Server Protocol Ledger
The server-side protocol executor records both read and write traffic:
BlueprintQueryRequestreads a named entity projection through the shared Vyuh Query grammar and produces a durableQueryRecordcarrying one sealedProjectionResultplus schema metadata.ActionRequestcarries one or moreActionCommandvalues and produces a durableActionRecordwith command records, rule decisions, effects, failures, and results.
That keeps simulation, UI, API, and agent traffic replayable. A simulator can send ordinary query/action operations with RequestSource.simulator; an agent can do the same with RequestSource.agent. The source changes, but the protocol vocabulary and record shape stay the same.
Typed projection results
The transport is JSON, but JSON is not the application API. The HTTP client decodes the response immediately into a QueryRecord; the query cache and UI only see that typed record. The result discriminator is encoded as kind:
{
"result": {
"kind": "collection",
"schema": { "columns": [] },
"data": [],
"paging": {
"totalCount": 0,
"hasMore": false,
"current": { "kind": "offset", "offset": 0, "limit": 25 }
}
}
}An exact entity query returns kind: "item" and data is one object or null; it is never wrapped in a one-element list. A custom projection returns kind: "custom", a stable schema.schemaType, and one ProjectionObject. schemaType is the single semantic discriminator for every projected object; there is no parallel custom-result type vocabulary. Because CustomProjectionResult is a base class, packages may derive concrete final, base, or sealed result classes from it. Projection names determine field shape, never cardinality. Consumers exhaustively pattern match the sealed result family instead of inspecting maps or guessing from a projection name.