Application and Storage Boundary¶
Hubuum has one application-facing storage boundary. A selectable storage backend implements that boundary in full; it is not a collection of optional features.
PostgreSQL and the experimental process-local memory adapter are selectable complete backends. The separate focused in-memory resource model remains a test tool.
Choose a Reading Path¶
- Start here for the invariants and the overall shape.
- Read the normative storage contract for the guarantees every selectable backend and application caller must preserve.
- Use the semantic capability group map to find the trait that owns an operation and the groups it collaborates with.
- Use storage query semantics for the common paging contract and the exhaustive method-specific rules.
- Use the backend author guide to implement or evaluate a backend.
- Use the maintainer guide to trace a call, locate its implementation, and change the boundary safely.
- Use transactions and side effects when a use case spans several resource operations or must define audit behavior.
- Use testing and compatibility to understand what the test layers prove and where confidence remains limited.
- Use the storage adapter SDK policy for the published crate graph, versioning, MSRV, features, enum evolution, releases, and upgrades.
- Track deliberately deferred work in the storage-boundary follow-up issues.
- Inspect the machine-checked semantic coverage inventory for the exact methods, tracked input variants, and test evidence.
- Inspect the machine-checked method contract registry for exact page, candidate, batch, and complete-collection behavior.
The Boundary in One Page¶
HTTP handlers / workers / administration
|
v
application services and policy
|
v
opaque StorageContext
|
v
StorageHandle
common dispatch + observation
|
v
complete StorageBackend
| operation traits |
| audited StorageTransaction
|
v
PostgreSQL adapter
|
v
Diesel / SQL / pools / transactions
Dependencies point down the diagram. Calls and errors return upward through the same layers.
Values crossing the boundary are backend-neutral DTOs. An application consumer must never recover a pool, receive a Diesel row, build SQL, or handle a driver error.
The boundary has five responsibilities:
- The application owns use cases, public API models, authorization-policy selection, persistence-independent validation, and conversion from
StorageErrortoApiError. - The storage contract owns operation-shaped traits, composable transaction-scoped resource APIs, backend-neutral requests and results, and the bounded storage error taxonomy.
- The opaque handle owns exhaustive backend dispatch plus common tracing and metrics. Callers do not select an adapter for each operation.
- Each adapter owns persistence rows, queries, native transactions, locking, driver errors, notifications, and explicit conversion to contract DTOs and
StorageError. - Certification combines reusable semantic conformance, complete-backend compatibility, native failure tests, and a sealed application registry. Implementing the Rust trait shapes alone does not make an adapter selectable.
Complete Means Complete¶
StorageBackend is the aggregate trait in crates/hubuum-storage-core/src/backend.rs. Its supertraits are the complete compile-time contract, including the mandatory TransactionStorage unit-of-work capability.
An adapter opts in structurally only after it implements every required
operation trait and all six family bounds. Rust rejects the implementation if
any method or bound is missing. The
application then admits it through the sealed CertifiedStorageBackend
registry only after its shared and native behavioral evidence passes.
The documentation organizes those traits into 20 semantic capability groups:
- lifecycle and identity foundations;
- permission-aware reads and computed data;
- relations, history, inventory, and search;
- tasks and long-running workflows;
- event administration and event workers; and
- operational state, retention, and execution context.
These groups are a documentation map over one indivisible contract. They are neither a second runtime contract nor feature flags. The semantic capability group map names every group, maps it to its required traits, and explains its relationships.
Adapters are statically linked Rust crates. Trait checking and crate versions are therefore the compatibility mechanism; Hubuum has no duplicate runtime contract version or dynamic capability negotiation.
The server and administrator CLI select one registered adapter through the
typed HUBUUM_STORAGE_BACKEND setting. The only current value is
postgresql; an empty value selects that default, while every other unknown
value fails configuration parsing. Startup logs, metrics, and the administrator
configuration endpoint report the selected backend and the same non-sensitive
effective settings.
Services Depend on Exact Operation Traits¶
Collection, class, object, class-relation, and object-relation services use the specific traits that own their operations:
CollectionService -------> CollectionStorage
ClassService ------------> ClassStorage
ObjectService -----------> ObjectStorage
ClassRelationService ----> ClassRelationStorage
ObjectRelationService ---> ObjectRelationStorage
^
|
PostgreSQL or focused model
ResourceStorage is the method-free resource family bound,
but focused services depend on the exact operation traits above rather than on
that aggregate. There is no default "unsupported" behavior. A focused model
implements only the operation traits it can perform. Tests may inject it
through those traits, but it cannot satisfy StorageBackend and cannot be
selected for the application.
Production composition projects exact observed trait objects from a complete StorageHandle.
Application workflows that must compose several resource mutations use
TransactionStorage. The callback receives an opaque StorageTransaction
whose collections(), classes(), class_relations(), objects(), and
object_relations() accessors return discoverable operation types. Every
transactional mutation inherits one required EventContext.
Boundary Rules¶
The following rules are architectural invariants:
- Application code accepts
StorageContext,AuthorizationContext, an application service, or a backend-neutral capability trait. - Only an authorization-aware context may select the configured permission backend. A storage handle cannot silently substitute local authorization for an external policy backend.
- Adapter inputs and results are crate-owned or storage-owned DTOs with private representation where practical.
- A use case may compose safe resource primitives through
TransactionStorage. The adapter owns the native transaction and exposes neither a connection nor a query language. - Invariant-heavy state machines remain one operation-shaped trait method. Task completion, restore application, retention, permission mutation, and similar workflows must not be reconstructed from lower-level calls.
- Transaction-scoped mutations always inherit the transaction's
EventContext. State and durable audit events commit or roll back together. - Ordinary audited mutations require
EventContextand returnStorageMutationOutcome: committed changes carry a durableStorageAuditReceipt, while genuine no-ops carry no receipt and append no event. - Imports and restores are restricted to the explicit
ImportStorageandRestoreStoragecapabilities. Those typed surfaces preserve or reconstruct history and are not unaudited shortcuts for ordinary writes. - Native mechanisms such as SQL cursors, statement timeouts, advisory locks, task-local database settings, and notification listeners remain private to the adapter.
- Backend errors move upward exactly once:
- Every storage call uses bounded, static capability and operation labels. Entity IDs, names, queries, URLs, credentials, and payloads never become log or metric labels.
- A backend is selectable only after it passes the shared compatibility suite and six-part conformance verifier plus its own native consistency, concurrency, recovery, and failure tests.
Architecture tests enforce these rules for the current source tree. The maintainer guide locates those checks; the testing guide explains what they do and do not prove.
The transactions and side-effects guide defines the decision rule, event guarantee, cancellation semantics, and adapter obligations in detail.
Current Workspace Shape¶
The application, reusable contracts, and native adapter are distinct:
hubuum application
|-- hubuum-domain
|-- hubuum-query
|-- hubuum-events-core
|-- hubuum-task-core
|-- hubuum-storage-core
|-- hubuum-storage-conformance
`-- hubuum-storage-postgres
hubuum-domainowns backend-independent validated identifiers, revisions, patches, and policy values extracted from the root application.hubuum-queryowns bounded query options, filters, sorts, cursors, scalar inference, and parsing. It describes query intent and does not expose SQL or database type names.hubuum-events-coreowns typed event identity, envelopes, mutation provenance, and event integration traits. Its public identifiers reusehubuum-domainnewtypes instead of raw database integers.hubuum-task-coreowns task values shared by storage and worker code.hubuum-storage-coreowns the complete storage contract, private-field DTOs, and semantic errors. It has no Actix, Diesel, global configuration, orApiErrordependency. Resource lifecycle, revision, metadata, and principal boundaries use domain IDs and revisions rather than persistence-shaped strings and integers.hubuum-storage-conformanceowns the reusable six-part behavioral verifier for receipts, no-ops, rollback, fan-out to a recording sink, telemetry, and exact revision-conflict propagation. It also owns the retention retry verifier for durable claim identity and idempotent completion, deterministic delivery, restore-coordination, and lease-loss protocol expectations, and the common application, service, readiness, and authenticated HTTP expectations. It is an experimental public development dependency for adapter authors.hubuum-storage-postgresowns the native pool, TLS, endpoint diagnostics, generated schema, migrations, JSONB validation, query instrumentation, and all production PostgreSQL operations.- The root crate owns application services and static composition. It constructs the PostgreSQL adapter with telemetry and dedicated operational pools, then places it behind the opaque handle.
- The root crate has no PostgreSQL module tree. Adapter-specific integration
fixtures are typed, feature-gated APIs owned by
hubuum-storage-postgres.
The backend-neutral contracts needed by an out-of-tree adapter form the experimental public seven-crate storage adapter SDK. External-crate integration tests nevertheless implement all 44 complete-backend traits and their 250 methods, compile every transaction port, exercise representative typed query APIs, and name public construction paths for all current adapter-returned values without crate-private access. Backend registration remains explicit, exhaustive, and application-owned. Hubuum does not load storage plugins dynamically.
The SDK is a supported pre-1.0 Rust source contract for statically linked adapters. It is not a promise that the PostgreSQL adapter, server composition, or a dynamic plugin ABI is public. Remaining follow-up work validates the boundary with an independent adapter and standardizes neutral audit-document construction before a stable 1.0 designation.
Moving a file does not by itself improve the boundary. Dependencies must continue to point from the application to contracts and from adapters to contracts, never from a contract or adapter back into the application.
Current Confidence¶
The PostgreSQL path is exercised against a real migrated database by shared backend contracts, PostgreSQL-specific tests, service tests, HTTP integration tests, destructive restore tests, query-budget tests, platform and feature builds, production-container tests, and benchmarks. CI also migrates representative data from the adjacent stable release, starts the new application, and restarts the previous application against the migrated schema.
The contract's methods, effects, selected input variants, and collection-shaped method semantics are inventoried mechanically. Every registered backend runs the reusable six-part audit verifier plus compact service, readiness, and authenticated HTTP point/list scenarios. Adapter-private deterministic failpoints prove rollback at representative compound-write and task-state-machine seams.
This is strong practical coverage, not a formal proof of portability. PostgreSQL is the only complete production adapter. The portable six-part, retention-retry, delivery-fault, restore-coordination, and lease-loss expectations are extracted, while backend provisioning and the broader application compatibility fixtures remain application-owned.
The testing guide gives the detailed assessment and the highest-value remaining improvements.