Skip to content

StoreProfileService

Target

This page describes intended behaviour or structure. No implementation is claimed unless a section is explicitly marked Current implementation or Evidence.

Bounded context BC-42 Data & Event Foundations
Platform / plane Data & Event Platform / Data & Event
Deployment granularity module of host · host DataEventFoundations
Status target · ConnectSoft.Factory.DataEvent.Stores
Built from connectsoft-microservice · libraries: connectsoft-extensions-persistence-model-nhibernate, connectsoft-extensions-persistence-model, connectsoft-extensions-saas-abstractions, connectsoft-extensions-messaging-model
Decisions ADR-0006, ADR-0012, ADR-0013, ADR-0017
Traceability FR-12 FUX-11 NFR-05 NFR-06 NFR-16 XL-09

Purpose and responsibilities

StoreProfileService keeps the original design's §54 separation — operational relational, worker durable, cache, artifact, vector, graph, event transport, audit, analytics, secrets — as store classes, the engine profile each class runs on each topology (NHibernate on SQL Server or PostgreSQL per ADR-0006, Qdrant or Azure AI Search per ADR-0013, Azure Blob, Redis, the messaging transport per ADR-0012), and the binding of every logical store in the stores catalog to its owning service, tenant-selected region, customer-managed key and backup class. It answers ResolveBinding for hosts at start-up and for provisioning, and reconciles bindings against observed state every six hours.

Context and boundaries

flowchart LR
    S["StoreProfileService"]
    ControlPlaneApi["ControlPlaneApi"] -->|grpc| S
    StudioBff["StudioBff"] -->|sync-http| S
    S -->|grpc| SecretBrokerService["SecretBrokerService"]
    S -. "StoreProfileActivated" .-> E_StoreProfileActivated(("event"))
    S -. "StoreBindingChanged" .-> E_StoreBindingChanged(("event"))
Hold "Alt" / "Option" to enable pan & zoom

Two rules are enforced here, not just documented: one owning service per store (other services go through its API or events), and two services may share a server but never a schema. A binding whose region violates the tenant's residency rule is refused through RetentionResidencyService.EvaluateResidency.

Domain model

StoreProfile — One engine profile for one store class on one topology: engine, adapter library, migration convention, backup class (RPO, RTO), encryption, and whether it is authoritative or derived. (catalog entry)

Field Type Required Description
profileId string yes e.g. nhibernate-sqlserver, vector-qdrant, azure-blob-immutable
storeClass enum:StoreClass yes
topology string yes
engine string yes
adapterLibrary string yes Library id from the libraries catalog.
migrationConvention string yes FluentMigrator per service schema; TenantId column by default
rpoMinutes int yes
rtoMinutes int yes
encryption string yes
authoritative bool yes False for derived stores (vector, cache, projections).

Invariants:

  • A derived store (cache, vector, projection) is never the authoritative state of anything and must be rebuildable from an authoritative one.
  • The pilot backup class (D30: RPO 15 min, RTO 4 h) is the minimum for authoritative stores; derived stores may be looser.

Events: StoreProfileActivated · Tables: StoreProfiles · Repository: StoreProfileRepository

StoreBinding — The binding of one logical store (the stores catalog id) to its owning service, profile, tenant-selected region, encryption key and state; the runtime truth of where data lives. (catalog entry)

Field Type Required Description
storeId string yes Logical store id from the stores catalog.
tenantId string yes Platform tenant for shared stores; a tenant id for per-tenant stores in the on-prem profile.
ownerService string yes
profileId string yes
region string yes Tenant-selected region (D31): westeurope default, israelcentral available
keyReference string yes Customer-managed key reference in the secret store.
state enum:BindingState yes
schemas list:string yes Database schemas owned per service on a shared server.

Invariants:

  • Exactly one owning service per store; other services reach its data through that service's API or events, never the store (ownership rule).
  • Two services may share a server but never a schema.
  • A binding's region must satisfy the tenant's residency rule.
stateDiagram-v2
    Planned --> Provisioned : Provisioned
    Provisioned --> Active : MigrationsApplied
    Active --> Draining : DecommissionRequested
    Draining --> Decommissioned : DataMovedOrDeleted
Hold "Alt" / "Option" to enable pan & zoom

Events: StoreBindingChanged · Tables: StoreBindings · Repository: StoreBindingRepository

erDiagram
    StoreProfile {
        string profileId PK
        enum_StoreClass storeClass
        string topology
        string engine
        string adapterLibrary
        string migrationConvention
        int rpoMinutes
        int rtoMinutes
        string encryption
        bool authoritative
    }
    StoreBinding {
        string storeId PK
        string tenantId
        string ownerService
        string profileId
        string region
        string keyReference
        enum_BindingState state
        list_string schemas
    }
Hold "Alt" / "Option" to enable pan & zoom

Entities and value objects

None modelled

No entities or value objects are modelled for this item yet.

Data model and storage

Store Role Engine / profile Tables
Data & Event foundations store primary azure-sql / nhibernate-sqlserver StoreProfiles, StoreBindings
Table Owner Columns Indexes
dbo.StoreProfiles StoreProfile 11 0
dbo.StoreBindings StoreBinding 8 2

Full DDL: appendix.

APIs

Method Path Operation Scope Side effects Idempotency Gateway Summary
GET /factory/data/stores ListStoreBindings factory.data.read read natural GW-03 Logical stores with owner, profile, region, backup class and state (the storage catalog at runtime).
GET /factory/data/store-profiles ListStoreProfiles factory.data.read read natural GW-03 Engine profiles per store class and topology.
PUT /factory/data/stores/{storeId} SetStoreBinding factory.data.admin production natural GW-03 Bind a logical store to a profile, region and key (Platform admin; applied by provisioning).
gRPC service Method Streaming Visibility Side effects Summary
Stores ResolveBinding none internal read Resolve a logical store to its connection reference and region for a tenant (used by hosts at start-up and by provisioning).

Messages

Event Topic Scope / v Aggregate Consumers Summary
StoreProfileActivated data-foundations.stores.v1.store-profile-activated integration / 1 StoreProfile StudioBff, AuditService An engine profile is active for a class and topology.
StoreBindingChanged data-foundations.stores.v1.store-binding-changed integration / 1 StoreBinding StudioBff, AuditService, RetentionResidencyService A logical store's binding or state changed.

StoreProfileActivated payload:

Field Type Required Description
profileId string yes
storeClass enum:StoreClass yes
topology string yes

StoreBindingChanged payload:

Field Type Required Description
storeId string yes
tenantId string yes
ownerService string yes
region string yes
state enum:BindingState yes
Command Handled by Result events Summary
SetStoreBinding StoreBinding StoreBindingChanged

None modelled

No consumed events are modelled for this item yet.

Workers and jobs

Worker Trigger Output events Retry Idempotency key Summary
BindingReconciler schedule 0 */6 * * * StoreBindingChanged fixed storeId + window Compares bindings with the observed state from provisioning and flags drift (missing schema, wrong region, key rotation overdue).

Actors and grains

None modelled

No grains are modelled for this item yet.

Sagas and long-running flows

None modelled

No sagas are modelled for this item yet.

stateDiagram-v2
    [*] --> Planned
    Planned --> Provisioned: Provisioned (Runtime Cloud)
    Provisioned --> Active: MigrationsApplied
    Active --> Draining: DecommissionRequested
    Draining --> Decommissioned: DataMovedOrDeleted
    Decommissioned --> [*]
Hold "Alt" / "Option" to enable pan & zoom

Options and configuration

Section Key Type Default Reloadable Secret Summary
DataEvent:Stores DefaultRegion string westeurope no no Region for tenants that did not select one (D31).
DataEvent:Stores AllowedRegions string[] [westeurope, israelcentral] yes no Regions a tenant may select.

Metrics and observability

Metric Instrument Unit Dimensions Summary
connectsoft.factory.data_event.store_bindings updown {store} storeClass, region, state Bindings by class, region and state.
connectsoft.factory.data_event.binding_drift counter {store} kind Drift findings from reconciliation.

Security

Authentication client-credentials
Scopes factory.data.read (Read stores and profiles.); factory.data.admin (Bind stores (Platform admin, provisioning).)
Roles PlatformAdmin, Operator, Observer
Tenant isolation row-filter
Data classification internal
Max side-effect class production
Secrets —

Dependencies

Outbound

Target Kind Purpose Failure mode Required
SecretBrokerService grpc Key and connection references; never the secrets. fail-fast yes

Inbound

Target Kind Purpose Failure mode Required
ControlPlaneApi grpc ResolveBinding at tenant creation and host start-up. — yes
StudioBff sync-http Storage views. — yes

Failure and recovery

Scenario Detection Recovery Data impact RTO (min)
Binding violates residency residency rule check on SetStoreBinding refused with 422 and the rule id none 0

NFR targets

Target Class value (pilot-interactive) Override
latency_p95_ms 2000 —
availability_pct 99.5 —
throughput_rps 50 —
rpo_minutes 15 —
rto_minutes 240 —
cost_class low —

Deployment

Granularity module of host · host DataEventFoundations
Topologies saas-default, hybrid, on-prem, hybrid-compute
Runtime —; replicas —–—
Ports —

Current implementation

The storage catalog and model/stores.yaml list the logical stores; templates ship SQL Server, MySQL and PostgreSQL migrations, Orleans AdoNet and Azure Table storage, Audit.NET SQL and an in-memory vector store. No binding registry or reconciliation exists.

Later capabilities

Analytics warehouse profile (usage, cost, BI projections); graph store profile selection; multi-region placement with tracked moves.

Decisions and traceability

Family Ids
FR FR-12
FUX FUX-11
NFR NFR-05, NFR-06, NFR-16
XL XL-09