Skip to content

GeneratedSaasFoundations

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-31 Generated Tenant & Commercial Foundations
Platform / plane Generated SaaS / Generated SaaS pack
Deployment granularity standalone host
Status target · ConnectSoft.Factory.Generated.Saas
Built from connectsoft-saas-tenants · libraries: connectsoft-extensions-saas-abstractions, connectsoft-extensions-saas-asp-net-core, connectsoft-extensions-messaging-model, connectsoft-extensions-persistence-model-nhibernate
Decisions ADR-0015, ADR-0020
Traceability FR-06 FR-09 FUX-08 NFR-14 NFR-15 XL-13

Purpose and responsibilities

GeneratedSaasFoundations is the representative instance of the five ConnectSoft SaaS templates (Tenants, ProductsCatalog, Entitlements, Billing, Metering) inside a generated product. It gives the product its own tenants (customers of the product, with canonical ADR-0100 isolation modes and residency), its editions and entitlements from the Agentic SaaS Product Blueprint, subscriptions the product sells to its customers and metered usage the product bills. The one bridge to the Factory is the tenant mapping: every product tenant carries an opaque customer-tenant id the fleet uses for instances, rollouts, incidents and off-boarding — never customer identity. The Factory's own commercial context (BC-34) bills the product owner for the Factory; the product bills its customers itself.

Context and boundaries

flowchart LR
    S["GeneratedSaasFoundations"]
    GeneratedProductHost["GeneratedProductHost"] -->|grpc| S
    FleetInventoryService["FleetInventoryService"] -->|sync-http| S
    S -->|sync-http| ext_identity_platform["ext-identity-platform"]
    S -->|sync-http| ext_saas_templates["ext-saas-templates"]
    S -. "ProductTenantProvisioned" .-> E_ProductTenantProvisioned(("event"))
    S -. "ProductTenantStateChanged" .-> E_ProductTenantStateChanged(("event"))
    S -. "ProductSubscriptionChanged" .-> E_ProductSubscriptionChanged(("event"))
    S -. "ProductUsageMetered" .-> E_ProductUsageMetered(("event"))
Hold "Alt" / "Option" to enable pan & zoom

The same templates serve the Factory's own tenancy and commerce (BC-33, BC-34) and the marketplace's licensing (BC-28): one foundation, three instances with different subjects.

Domain model

ProductTenant — A customer tenant inside the generated product (SaaS Tenants template) with its mapping to the Factory's customer-tenant id used by fleet operations, its isolation mode, region and state. (catalog entry)

Field Type Required Description
productTenantId string yes
factoryTenantId string yes The Factory tenant that owns the product.
customerTenantId string yes Opaque id the fleet uses; never carries customer identity.
name string yes
isolationMode string yes
region string yes
state enum:ProductTenantState yes
createdAt datetime yes

Invariants:

  • Identity and authorization of customer users live in the product (ADR-0101 through the Authorization Server); the Factory sees only the opaque customer-tenant id.
  • A tenant's region satisfies the product owner's residency rule (D31).
stateDiagram-v2
    Provisioning --> Active : Provisioned
    Active --> Suspended : SubscriptionLapsed
    Suspended --> Active : Restored
    Active --> Offboarding : OffboardingRequested
    Offboarding --> Deleted : DeletionCompleted
Hold "Alt" / "Option" to enable pan & zoom

Events: ProductTenantProvisioned, ProductTenantStateChanged · Tables: ProductTenants · Repository: ProductTenantRepository

ProductSubscription — The customer's subscription to an edition of the product (SaaS Billing and Entitlements templates): entitlements, seats, metering dimensions and state; for managed products the product's editions map to the owner's Factory subscription for fleet objectives, never for billing the customer (the product bills its own customers). (catalog entry)

Field Type Required Description
subscriptionId guid yes
productTenantId string yes
factoryTenantId string yes
edition string yes
entitlements json yes
seats int no
meteringDimensions list:string yes
state string yes
changedAt datetime yes

Invariants:

  • Editions and entitlements come from the Agentic SaaS Product Blueprint and the ProductsCatalog template; the product never invents entitlements at run time.

Events: ProductSubscriptionChanged, ProductUsageMetered · Tables: ProductSubscriptions, ProductUsage · Repository: ProductSubscriptionRepository

erDiagram
    ProductTenant {
        string productTenantId PK
        string factoryTenantId
        string customerTenantId
        string name
        string isolationMode
        string region
        enum_ProductTenantState state
        datetime createdAt
    }
    ProductSubscription {
        guid subscriptionId PK
        string productTenantId
        string factoryTenantId
        string edition
        json entitlements
        int seats
        list_string meteringDimensions
        string state
        datetime changedAt
    }
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
Generated product store (representative) primary azure-sql / nhibernate-sqlserver ProductTenants, ProductSubscriptions, ProductUsage
Table Owner Columns Indexes
dbo.ProductTenants ProductTenant 8 1
dbo.ProductSubscriptions ProductSubscription 9 0
dbo.ProductUsage ProductSubscription 6 0

Full DDL: appendix.

APIs

Method Path Operation Scope Side effects Idempotency Gateway Summary
GET /product/tenants ListProductTenants product.admin.read read natural GW-07 Product tenants with state, region and the opaque customer-tenant id (product owner and fleet).
POST /product/tenants ProvisionProductTenant product.admin.write shared-write key-header GW-07 Provision a customer tenant in the product (self-service sign-up or owner action).
GET /product/tenants/{productTenantId}/subscription GetProductSubscription product.admin.read read natural GW-07 Edition, entitlements, seats and metered usage.
PUT /product/tenants/{productTenantId}/subscription ChangeProductSubscription product.admin.write shared-write natural GW-07 Change edition or seats (the product's own commerce).
gRPC service Method Streaming Visibility Side effects Summary
Foundations ResolveTenant none internal read Resolve a request's tenant and entitlements for the product's services (per-request claim).

Messages

Event Topic Scope / v Aggregate Consumers Summary
ProductTenantProvisioned product-tenancy.tenants.v1.product-tenant-provisioned integration / 1 ProductTenant FleetInventoryService, AuditService A customer tenant exists in the product (the fleet gets an instance).
ProductTenantStateChanged product-tenancy.tenants.v1.product-tenant-state-changed integration / 1 ProductTenant FleetInventoryService, FleetIncidentService, AuditService Suspended, restored, off-boarding or deleted.
ProductSubscriptionChanged product-tenancy.subscriptions.v1.product-subscription-changed integration / 1 ProductSubscription FleetInventoryService, AuditService A customer's edition or seats changed.
ProductUsageMetered product-tenancy.usage.v1.product-usage-metered integration / 1 ProductSubscription FleetInventoryService Metered usage for a period (the product's own billing; mirrored to the Factory for managed-product cost attribution later).

ProductTenantProvisioned payload:

Field Type Required Description
productTenantId string yes
factoryTenantId string yes
customerTenantId string yes
region string yes

ProductTenantStateChanged payload:

Field Type Required Description
productTenantId string yes
factoryTenantId string yes
customerTenantId string yes
fromState enum:ProductTenantState yes
toState enum:ProductTenantState yes

ProductSubscriptionChanged payload:

Field Type Required Description
subscriptionId guid yes
factoryTenantId string yes
customerTenantId string yes
edition string yes
state string yes

ProductUsageMetered payload:

Field Type Required Description
subscriptionId guid yes
factoryTenantId string yes
customerTenantId string yes
dimension string yes
period string yes
quantity decimal yes
Command Handled by Result events Summary
ProvisionProductTenant ProductTenant ProductTenantProvisioned
ChangeProductSubscription ProductSubscription ProductSubscriptionChanged

None modelled

No consumed events are modelled for this item yet.

Workers and jobs

Worker Trigger Output events Retry Idempotency key Summary
UsageMeter schedule 0 * * * * ProductUsageMetered fixed subscriptionId + dimension + period Aggregates metered events per dimension and period (the Metering template) and emits period totals.

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
    [*] --> Provisioning
    Provisioning --> Active: Provisioned
    Active --> Suspended: SubscriptionLapsed
    Suspended --> Active: Restored
    Active --> Offboarding: OffboardingRequested (fleet order)
    Offboarding --> Deleted: DeletionCompleted (after acknowledged handover)
    Deleted --> [*]
Hold "Alt" / "Option" to enable pan & zoom

Options and configuration

Section Key Type Default Reloadable Secret Summary
Saas:Tenants IsolationMode string RowFilter no no ADR-0100 mode from the blueprint.
Saas:Editions Catalog json { starter: {}, professional: {}, enterprise: {} } yes no Editions and entitlements from the Agentic SaaS Product Blueprint.

Metrics and observability

Metric Instrument Unit Dimensions Summary
connectsoft.factory.product.tenants updown {tenant} productId, state Product tenants by state.
connectsoft.factory.product.subscriptions updown {subscription} productId, edition Subscriptions by edition.

Security

Authentication oauth2-jwt
Scopes product.admin.read (Tenants and subscriptions (product owner, fleet).); product.admin.write (Provision and change (product owner, self-service flows).)
Roles ProductOwner, FleetOperator, Observer
Tenant isolation per-request-claim
Data classification confidential
Max side-effect class shared-write
Secrets product-sql (key-vault, rotate 90 d)

Dependencies

Outbound

Target Kind Purpose Failure mode Required
ext-identity-platform sync-http Customer identity through the Authorization Server (ADR-0101). fail-fast yes
ext-saas-templates sync-http The SaaS templates this foundation instantiates. fail-fast yes

Inbound

Target Kind Purpose Failure mode Required
GeneratedProductHost grpc ResolveTenant on every request. — yes
FleetInventoryService sync-http Tenants and subscriptions through GW-07. — yes

Failure and recovery

Scenario Detection Recovery Data impact RTO (min)
Subscription lapses billing state tenant Suspended; product refuses tenant requests with a clear state; restore on payment 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 standalone host
Topologies saas-default, hybrid, on-prem
Runtime aks; replicas 2–6
Ports https 9010, grpc 9012, silo 13010, gateway 32010

Current implementation

The SaaS templates exist with the SaaS Control Plane prototype as their UI; DerechHaLev uses the tenancy foundations. No product-to-fleet tenant mapping exists.

Later capabilities

Usage mirrored to the Factory for managed-product cost attribution; customer self-service edition changes through the product's own shell on the SaaS shell template.

Decisions and traceability

Family Ids
FR FR-06, FR-09
FUX FUX-08
NFR NFR-14, NFR-15
XL XL-13