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

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.

Scoped read versus command writeThe read path resolves QueryEngine; the write path validates, authorizes, guards, commands, persists, emits, and maintains the read side.
01

makeCrudRoute composes authentication, validation, scoped reads, command-backed writes, guards, indexing, and enrichment for common API routes.

oss-core

02

withScopedPayload injects and validates tenant and organization identifiers instead of relying on ambient scope.

oss-core

03

Authorization is feature-based and wildcard-aware, with effective grants resolved for the current user and role context.

oss-core

04

DataEngine owns writes that coordinate ORM persistence, declared events, and index side effects, while QueryEngine serves the denormalized read path.

oss-core

05

CommandBus executes registered mutations through preparation, execution, audit-log, interceptor, invalidation, and side-effect phases.

oss-core

06

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

07

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.

  1. The route checks access, parses input, and applies explicit scope.

    product-factoss-core

  2. Mutation guards may block the operation before execution.

    product-factoss-core

  3. CommandBus executes the registered mutation and records its audit context.

    product-factoss-core

  4. DataEngine persists the record and schedules declared events or index work.

    product-factoss-core

Data contracts and operating limits

Data contracts and operating limits
MechanismEditorial implicationLimitationDecision 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 source

DataEngine 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 source
Sources 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
  • 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