Skip to content

LicenseService

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-28 Marketplace Acquisition & Licensing
Platform / plane Marketplace / Capability & Tools
Deployment granularity module of host · host MarketplaceHost
Status target · ConnectSoft.Factory.Marketplace.Licensing
Built from connectsoft-saas-billing · libraries: connectsoft-extensions-saas-abstractions, connectsoft-extensions-messaging-model, connectsoft-extensions-persistence-model-nhibernate
Decisions ADR-0015, ADR-0020
Traceability FR-04 FUX-08 NFR-13 NFR-15 XL-03 XL-13

Purpose and responsibilities

LicenseService is the commercial side of the marketplace, built on the same SaaS foundations as the Factory's own commercial context (BC-34, D34). A pricing plan says how a listing is priced (free, included in an edition, per seat, per usage metered through the Factory's metering, one-time) and what the publisher's revenue share is; an entitlement is a tenant's acquisition against its active Factory subscription — spend above the threshold needs an approval of class spend (D21) — with validity, seats and license terms, following the subscription's state (suspended, restored, expired); a publisher is certified by Platform admin with an agreement before it may list publicly, and collects reviews from entitled tenants. Billing lines land on the tenant's Factory invoice; the marketplace never bills separately.

It absorbs the June-2026 pricing, publisher-portal and review-rating rows.

Context and boundaries

flowchart LR
    S["LicenseService"]
    MarketplaceCatalogService["MarketplaceCatalogService"] -->|grpc| S
    StudioBff["StudioBff"] -->|sync-http| S
    S -->|grpc| FactoryCommercialService["FactoryCommercialService"]
    S -->|grpc| RunControlService["RunControlService"]
    S -->|sync-http| ext_saas_templates["ext-saas-templates"]
    S -->|grpc| ArtifactService["ArtifactService"]
    S -. "PricingPlanChanged" .-> E_PricingPlanChanged(("event"))
    S -. "EntitlementGranted" .-> E_EntitlementGranted(("event"))
    S -. "EntitlementStateChanged" .-> E_EntitlementStateChanged(("event"))
    S -. "PublisherCertified" .-> E_PublisherCertified(("event"))
Hold "Alt" / "Option" to enable pan & zoom

Entitlement state is enforced by the registry and policy: a suspended entitlement leaves installations in place but refuses new runs using the asset until restored.

Domain model

PricingPlan — The price of a listing: model, amount and currency, included editions, metering dimension for usage pricing, trial terms, and the publisher's revenue share. (catalog entry)

Field Type Required Description
pricingId guid yes
tenantId string yes
listingId guid yes
model enum:PricingModel yes
amountUsd decimal no
includedEditions list:string yes
meteringDimension string no e.g. runs, tokens, instances
trialDays int no
revenueSharePct decimal yes
active bool yes

Invariants:

  • Usage pricing meters through the Factory's metering (BC-34) and is billed on the tenant's Factory invoice; the marketplace never bills separately.

Events: PricingPlanChanged · Tables: PricingPlans · Repository: PricingPlanRepository

Entitlement — A tenant's right to install and use a listing: the acquisition (plan, seats or usage terms), state, validity, the Factory subscription it bills to, and the license record with terms and provenance. (catalog entry)

Field Type Required Description
entitlementId guid yes
tenantId string yes
listingId guid yes
pricingId guid yes
subscriptionId guid yes Factory subscription (BC-34).
seats int no
state enum:EntitlementState yes
validFrom datetime yes
validTo datetime no
licenseTermsRef string yes
acquiredBy string yes

Invariants:

  • An entitlement is granted only against an active Factory subscription whose edition allows the listing kind (D34).
  • Suspension of the subscription suspends entitlements; installations stay but new runs using the asset are refused by policy.
stateDiagram-v2
    Pending --> Active : AcquisitionConfirmed
    Active --> Suspended : SubscriptionSuspendedOrPaymentFailed
    Suspended --> Active : Restored
    Active --> Expired : ValidToPassed
    Active --> Revoked : ListingRevokedOrViolation
Hold "Alt" / "Option" to enable pan & zoom

Events: EntitlementGranted, EntitlementStateChanged · Tables: Entitlements · Repository: EntitlementRepository

Publisher — A publisher (ConnectSoft, a partner organization or a tenant) with certification state, identity, payout details by reference, agreements, and the ratings and reviews of its listings. (catalog entry)

Field Type Required Description
publisherId guid yes
tenantId string yes
name string yes
state enum:PublisherState yes
agreementRef string yes
payoutRef string no
ratingAverage decimal no
certifiedAt datetime no

Invariants:

  • Only Certified publishers may list publicly; certification is a Platform admin decision with evidence.
  • Reviews come from tenants with an active or past entitlement; one review per tenant per listing.

Events: PublisherCertified · Tables: Publishers, Reviews · Repository: PublisherRepository

erDiagram
    PricingPlan {
        guid pricingId PK
        string tenantId
        guid listingId
        enum_PricingModel model
        decimal amountUsd
        list_string includedEditions
        string meteringDimension
        int trialDays
        decimal revenueSharePct
        bool active
    }
    Entitlement {
        guid entitlementId PK
        string tenantId
        guid listingId
        guid pricingId
        guid subscriptionId
        int seats
        enum_EntitlementState state
        datetime validFrom
        datetime validTo
        string licenseTermsRef
        string acquiredBy
    }
    Publisher {
        guid publisherId PK
        string tenantId
        string name
        enum_PublisherState state
        string agreementRef
        string payoutRef
        decimal ratingAverage
        datetime certifiedAt
    }
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
Marketplace store primary azure-sql / nhibernate-sqlserver PricingPlans, Entitlements, Publishers, Reviews
Table Owner Columns Indexes
dbo.PricingPlans PricingPlan 10 1
dbo.Entitlements Entitlement 11 1
dbo.Publishers Publisher 8 0
dbo.Reviews Publisher 6 0

Full DDL: appendix.

APIs

Method Path Operation Scope Side effects Idempotency Gateway Summary
GET /factory/marketplace/listings/{listingId}/pricing GetPricing factory.marketplace.read read natural GW-03 Pricing plans of a listing with the caller's edition applied.
PUT /factory/marketplace/listings/{listingId}/pricing SetPricing factory.marketplace.publish shared-write natural GW-03 Set a pricing plan (publisher; public plans reviewed by Platform admin).
POST /factory/marketplace/listings/{listingId}/acquire AcquireListing factory.marketplace.acquire spend key-header GW-03 Acquire an entitlement against the tenant's Factory subscription (spend class above the threshold needs an approval).
GET /factory/marketplace/entitlements ListEntitlements factory.marketplace.read read natural GW-03 The tenant's entitlements with state, validity and terms.
POST /factory/marketplace/publishers ApplyAsPublisher factory.marketplace.publish shared-write key-header GW-03 Apply for publisher certification (agreement, identity).
POST /factory/marketplace/publishers/{publisherId}/certify CertifyPublisher factory.marketplace.admin publication natural GW-03 Certify or suspend a publisher (Platform admin; publication class).
POST /factory/marketplace/listings/{listingId}/reviews ReviewListing factory.marketplace.read shared-write natural GW-03 Rate and review a listing the tenant is or was entitled to.
gRPC service Method Streaming Visibility Side effects Summary
Licensing CheckEntitlement none internal read Is the tenant entitled to install or use a listing now?

Messages

Event Topic Scope / v Aggregate Consumers Summary
PricingPlanChanged licensing.pricing.v1.pricing-plan-changed integration / 1 PricingPlan MarketplaceCatalogService, StudioBff, AuditService A pricing plan was set or changed.
EntitlementGranted licensing.entitlements.v1.entitlement-granted integration / 1 Entitlement MarketplaceCatalogService, FactoryCommercialService, StudioBff, AuditService A tenant is entitled to a listing.
EntitlementStateChanged licensing.entitlements.v1.entitlement-state-changed integration / 1 Entitlement MarketplaceCatalogService, AgentRegistryService, StudioBff, AuditService Suspended, restored, expired or revoked.
PublisherCertified licensing.publishers.v1.publisher-certified integration / 1 Publisher MarketplaceCatalogService, StudioBff, AuditService A publisher was certified or suspended.

PricingPlanChanged payload:

Field Type Required Description
pricingId guid yes
listingId guid yes
model enum:PricingModel yes

EntitlementGranted payload:

Field Type Required Description
entitlementId guid yes
tenantId string yes
listingId guid yes
subscriptionId guid yes
validTo datetime no

EntitlementStateChanged payload:

Field Type Required Description
entitlementId guid yes
tenantId string yes
listingId guid yes
fromState enum:EntitlementState yes
toState enum:EntitlementState yes

PublisherCertified payload:

Field Type Required Description
publisherId guid yes
tenantId string yes
state enum:PublisherState yes
Command Handled by Result events Summary
SetPricing PricingPlan PricingPlanChanged
AcquireListing Entitlement EntitlementGranted
CertifyPublisher Publisher PublisherCertified
ReviewListing Publisher —
Event Producer Handler Purpose
SubscriptionChanged FactoryCommercialService FollowSubscription Suspend, restore or expire entitlements with the Factory subscription.
ApprovalDecided RunControlService ApplySpendApproval Acquisitions above the spend threshold wait for approval.
ListingStateChanged MarketplaceCatalogService FollowListing Delisted or suspended listings suspend or revoke entitlements.
ListingPublished MarketplaceCatalogService TrackListing Pricing plans attach to Listed listings.
ListingInstalled MarketplaceCatalogService CountSeats Seat consumption.
ListingRemoved MarketplaceCatalogService ReleaseSeats Seat release.

Workers and jobs

Worker Trigger Output events Retry Idempotency key Summary
ExpiryAndSeatSweeper schedule 0 1 * * * EntitlementStateChanged fixed entitlementId + day Expires entitlements past validity and reconciles seat counts with installations.
RevenueShareReporter schedule 0 2 1 * * — fixed publisherId + month Produces publisher revenue-share statements from the Factory's reconciled usage and invoices.

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
    [*] --> Pending
    Pending --> Active: AcquisitionConfirmed (spend approval above threshold)
    Active --> Suspended: subscription suspended or payment failed
    Suspended --> Active: Restored
    Active --> Expired: validTo passed
    Active --> Revoked: listing revoked or violation
    Expired --> [*]
    Revoked --> [*]
Hold "Alt" / "Option" to enable pan & zoom

Options and configuration

Section Key Type Default Reloadable Secret Summary
Marketplace:Licensing SpendApprovalThresholdUsd decimal 500 yes no Acquisitions above this need an approval of class spend (D21).
Marketplace:Licensing DefaultRevenueSharePct decimal 70 yes no Publisher share for partner listings.

Metrics and observability

Metric Instrument Unit Dimensions Summary
connectsoft.factory.marketplace.entitlements updown {entitlement} tenant, state Entitlements by state.
connectsoft.factory.marketplace.acquisitions counter {acquisition} model, outcome Acquisitions by pricing model and outcome.
connectsoft.factory.marketplace.publishers updown {publisher} state Publishers by state.

Security

Authentication client-credentials
Scopes factory.marketplace.read (Pricing, own entitlements, reviews.); factory.marketplace.acquire (Acquire (Workspace admin; spend approval above threshold).); factory.marketplace.publish (Pricing and publisher application.); factory.marketplace.admin (Certification (Platform admin).)
Roles WorkspaceAdmin, AssetMaintainer, PlatformAdmin, Observer
Tenant isolation row-filter
Data classification confidential
Max side-effect class spend
Secrets —

Dependencies

Outbound

Target Kind Purpose Failure mode Required
FactoryCommercialService grpc Subscription and edition; billing lines; metering. fail-fast yes
RunControlService grpc Spend approvals. fail-fast yes
ext-saas-templates sync-http ProductsCatalog, Entitlements and Billing foundations. fail-fast yes
ArtifactService grpc License terms and agreements. degrade yes

Inbound

Target Kind Purpose Failure mode Required
MarketplaceCatalogService grpc CheckEntitlement on install. — yes
StudioBff sync-http Pricing, entitlement and publisher views. — yes

Failure and recovery

Scenario Detection Recovery Data impact RTO (min)
Subscription suspended SubscriptionChanged entitlements Suspended; installations stay; new runs refused by policy until restored none 0

NFR targets

Target Class value (pilot-batch) Override
latency_p95_ms 0 —
availability_pct 99.5 —
throughput_rps 10 —
rpo_minutes 15 —
rto_minutes 240 —
cost_class medium —

Deployment

Granularity module of host · host MarketplaceHost
Topologies saas-default
Runtime —; replicas —–—
Ports —

Current implementation

The SaaS Billing, Entitlements and Metering templates exist (scaffold-only usage in the SaaS Control Plane prototype); nothing marketplace-specific exists.

Later capabilities

Partner payouts through a payment connector; enterprise agreements covering many tenants; usage-based pricing for operated products per customer tenant.

Decisions and traceability

Family Ids
FR FR-04
FUX FUX-08
NFR NFR-13, NFR-15
XL XL-03, XL-13