Concept family 02 · read and write contracts
Open Mercato Data, Query, and Command Architecture
Reads and writes follow different contracts. QueryEngine serves a scoped denormalized read model, while validated and authorized mutations flow through guards, registered commands, DataEngine, audit context, events, and index maintenance. Explicit tenant and organization scope is necessary throughout; encryption adds a separate lookup boundary.
Explicit scope is a mechanism for isolation, not proof that every custom query is secure.
Source snapshot:
ae856df1ecfc · ARCHITECTURE.md sections: 5, 7, 8, 9, 10, 14, 15, 16, 21
Direct answer
Position in the system
This family sits between application/API entry points and persistent data. It explains the platform write/read spine and links outward to deployment-specific security and multitenancy decisions.
Scoped read versus command write
The read path resolves QueryEngine; the write path validates, authorizes, guards, commands, persists, emits, and maintains the read side.
makeCrudRoute composes authentication, validation, scoped reads, command-backed writes, guards, indexing, and enrichment for common API routes.
oss-core
→withScopedPayload injects and validates tenant and organization identifiers instead of relying on ambient scope.
oss-core
→Authorization is feature-based and wildcard-aware, with effective grants resolved for the current user and role context.
oss-core
→DataEngine owns writes that coordinate ORM persistence, declared events, and index side effects, while QueryEngine serves the denormalized read path.
oss-core
→CommandBus executes registered mutations through preparation, execution, audit-log, interceptor, invalidation, and side-effect phases.
oss-core
→Tenant field encryption uses per-tenant material, but non-deterministic ciphertext cannot be queried by plaintext value; lookups need a supported hash or another identifier.
oss-core
→Custom fields use a dynamic overlay, while cross-module relationships are declared as extension links backed by explicit identifiers rather than ORM relations.
oss-core
One mutation from request to read model
The trace exposes the points where scope, policy, auditability, and asynchronous index state can fail.
The route checks access, parses input, and applies explicit scope.
product-factoss-core
Mutation guards may block the operation before execution.
product-factoss-core
CommandBus executes the registered mutation and records its audit context.
product-factoss-core
DataEngine persists the record and schedules declared events or index work.
product-factoss-core
Data contracts and operating limits
| Mechanism | Editorial implication | Limitation | Decision owner |
|---|---|---|---|
| DataEngine owns writes that coordinate ORM persistence, declared events, and index side effects, while QueryEngine serves the denormalized read path. | Treat it as an “oss-core” contract and confirm project-specific fit separately. | The mechanism does not prove performance, security, availability, compliance, or production readiness for a particular deployment. | Application and data owner |
| makeCrudRoute composes authentication, validation, scoped reads, command-backed writes, guards, indexing, and enrichment for common API routes. | Treat it as an “oss-core” contract and confirm project-specific fit separately. | The mechanism does not prove performance, security, availability, compliance, or production readiness for a particular deployment. | Application and data owner |
| External inputs are expected to cross Zod validation boundaries before domain behavior runs. | Treat it as an “documented-convention” contract and confirm project-specific fit separately. | This is a committed engineering convention. A custom application can still violate it and must be reviewed separately. | Application and data owner |
| CommandBus executes registered mutations through preparation, execution, audit-log, interceptor, invalidation, and side-effect phases. | Treat it as an “oss-core” contract and confirm project-specific fit separately. | The mechanism does not prove performance, security, availability, compliance, or production readiness for a particular deployment. | Application and data owner |
| The documented back-office write path uses shared form, table, API-call, and guarded-mutation primitives instead of ad hoc browser writes. | Treat it as an “ui-shared” contract and confirm project-specific fit separately. | This is a committed engineering convention. A custom application can still violate it and must be reviewed separately. | Application and data owner |
| Authorization is feature-based and wildcard-aware, with effective grants resolved for the current user and role context. | Treat it as an “oss-core” contract and confirm project-specific fit separately. | The mechanism does not prove performance, security, availability, compliance, or production readiness for a particular deployment. | Application and data owner |
| withScopedPayload injects and validates tenant and organization identifiers instead of relying on ambient scope. | Treat it as an “oss-core” contract and confirm project-specific fit separately. | The mechanism does not prove performance, security, availability, compliance, or production readiness for a particular deployment. | Application and data owner |
| Tenant field encryption uses per-tenant material, but non-deterministic ciphertext cannot be queried by plaintext value; lookups need a supported hash or another identifier. | Treat it as an “oss-core” contract and confirm project-specific fit separately. | The mechanism does not prove performance, security, availability, compliance, or production readiness for a particular deployment. | Application and data owner |
| Custom fields use a dynamic overlay, while cross-module relationships are declared as extension links backed by explicit identifiers rather than ORM relations. | Treat it as an “oss-core” contract and confirm project-specific fit separately. | This is a committed engineering convention. A custom application can still violate it and must be reviewed separately. | Application and data owner |
Footguns and failure modes
Tenant field encryption uses per-tenant material, but non-deterministic ciphertext cannot be queried by plaintext value; lookups need a supported hash or another identifier.
The mechanism does not prove performance, security, availability, compliance, or production readiness for a particular deployment.
Inspect pinned sourceDataEngine owns writes that coordinate ORM persistence, declared events, and index side effects, while QueryEngine serves the denormalized read path.
The mechanism does not prove performance, security, availability, compliance, or production readiness for a particular deployment.
Inspect pinned sourceSources and method · 13 evidence records
Every fact, node, connector, and flow step has a stable ID, claim class, source locator, scope, limitation, and pinned revision. A local verifier checks every file and locator and ensures sections 1–33 are covered exactly once.
DataEngine owns writes that coordinate ORM persistence, declared events, and index side effects, while QueryEngine serves the denormalized read path.
- ID
section-05-data-paths- Class
- product-fact
- Scope
- oss-core
- Source
- packages/shared/src/lib/data/engine.ts ·
export class DefaultDataEngine
makeCrudRoute composes authentication, validation, scoped reads, command-backed writes, guards, indexing, and enrichment for common API routes.
- ID
section-07-crud-factory- Class
- product-fact
- Scope
- oss-core
- Source
- packages/shared/src/lib/crud/factory.ts ·
export function makeCrudRoute
External inputs are expected to cross Zod validation boundaries before domain behavior runs.
- ID
section-08-validation- Class
- documented-convention
- Scope
- documented-convention
- Source
- ARCHITECTURE.md ·
## 8. Validation
CommandBus executes registered mutations through preparation, execution, audit-log, interceptor, invalidation, and side-effect phases.
- ID
section-09-command-pipeline- Class
- product-fact
- Scope
- oss-core
- Source
- packages/shared/src/lib/commands/command-bus.ts ·
export class CommandBus
The documented back-office write path uses shared form, table, API-call, and guarded-mutation primitives instead of ad hoc browser writes.
- ID
section-10-ui-write-path- Class
- documented-convention
- Scope
- ui-shared
- Source
- ARCHITECTURE.md ·
## 10. Backend UI: CrudForm, DataTable and the Write Path
Authorization is feature-based and wildcard-aware, with effective grants resolved for the current user and role context.
- ID
section-14-rbac- Class
- product-fact
- Scope
- oss-core
- Source
- packages/core/src/modules/auth/services/rbacService.ts ·
export class RbacService
withScopedPayload injects and validates tenant and organization identifiers instead of relying on ambient scope.
- ID
section-15-explicit-scope- Class
- product-fact
- Scope
- oss-core
- Source
- packages/shared/src/lib/api/scoped.ts ·
export function withScopedPayload
Tenant field encryption uses per-tenant material, but non-deterministic ciphertext cannot be queried by plaintext value; lookups need a supported hash or another identifier.
- ID
section-16-encryption- Class
- product-fact
- Scope
- oss-core
- Source
- packages/shared/src/lib/encryption/tenantDataEncryptionService.ts ·
export class TenantDataEncryptionService
Custom fields use a dynamic overlay, while cross-module relationships are declared as extension links backed by explicit identifiers rather than ORM relations.
- ID
section-21-custom-fields-links- Class
- documented-convention
- Scope
- oss-core
- Source
- ARCHITECTURE.md ·
## 21. Custom Fields and Entity Extensions
The route checks access, parses input, and applies explicit scope.
- ID
flow-write-validate- Class
- product-fact
- Scope
- oss-core
- Source
- packages/shared/src/lib/crud/factory.ts ·
export function makeCrudRoute
Mutation guards may block the operation before execution.
- ID
flow-write-guard- Class
- product-fact
- Scope
- oss-core
- Source
- packages/shared/src/lib/crud/factory.ts ·
runMutationGuards
CommandBus executes the registered mutation and records its audit context.
- ID
flow-write-command- Class
- product-fact
- Scope
- oss-core
- Source
- packages/shared/src/lib/commands/command-bus.ts ·
export class CommandBus
DataEngine persists the record and schedules declared events or index work.
- ID
flow-write-effects- Class
- product-fact
- Scope
- oss-core
- Source
- packages/shared/src/lib/data/engine.ts ·
async emitOrmEntityEvent