saas-EPIC-TEN — Tenants template gaps¶
Epic ID: saas-EPIC-TEN
Area path: ConnectSoft\SaaS\Tenants
Priority: P1
Status: Not Started
Repository scope: ConnectSoft.Saas.TenantsTemplate
Source gap analysis: Tenants deep analysis
Tenants wave-1 implementation delivers flat ITenant aggregate, five ServiceModel operations, canonical outbound topics, and Orleans grain scaffold — but diverges from DDD blueprint child entities, JSON descriptor, lifecycle saga completeness, architecture tests, and write-path actor wiring. Evidence paths cite ITenant.cs, TenantsConstants, ConnectSoft.Saas.Tenants.json, placeholder architecture tests, and TenantLifecycleSaga create-only stub.
[010] saas-TEN-F01 — Rich tenant aggregate OR formal flat-tenant ADR¶
Type: Feature
Parent: saas-EPIC-TEN
Implementation order: 010
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, aggregate, adr
Priority: P1
Effort: XL
Dependencies: —
Blocks: saas-TEN-F02, saas-TEN-F04
Source gap analysis: Tenants entity model
Description (full):
Canonical DDD blueprint (saas-platform-ddd-entities.md) defines a rich tenant aggregate with value objects and child entities: TenantProfile, TenantRegionResidency, Contact, and TenantConfiguration. Wave-1 code implements a flat ITenant interface with scalar properties only (TenantAggregateId, TenantId, TenantKey, DisplayName, ResidencyRegion, LifecycleStatus, AggregateVersion, timestamps).
Evidence:
ConnectSoft.Saas.TenantsTemplate/src/ConnectSoft.Saas.Tenants.EntityModel/ITenant.cs— no child collections or profile VOs.- JSON descriptor
ConnectSoft.Saas.Tenants.json—valueObjects: [],entities: [],hasMany: []. - ADR stub:
docs/adr/0001-one-aggregate-root-per-repo.md— one root enforced but does not decide flat vs rich shape. - Deep analysis finding T-001 — status Missing.
Strategic decision (ADR-TEN-001):
- Option A — Rich aggregate: Implement missing VOs/entities with NHibernate mappings, migrations, and processor updates.
- Option B — Flat tenant + ADR: Accept wave-1 flat model; document intentional deferral of child entities with mapping notes to future waves.
Target state: Accepted ADR-TEN-001. If Option A, entity model and migrations match blueprint. If Option B, ADR explains which blueprint concepts are collapsed into scalars on ITenant (e.g., ResidencyRegion stands in for TenantRegionResidency.RegionCode).
Why it matters: Downstream Billing and Entitlements assume tenant partition stability and residency metadata. Without a decision, JSON descriptor regeneration and cross-repo contracts remain ambiguous.
Acceptance criteria (testable):
- AC-1: ADR-TEN-001 published with Accepted status and chosen option.
- AC-2: If Option A:
ITenantor associated entities exposeTenantProfile,Contact,TenantConfigurationper blueprint; unit tests cover mapping. - AC-3: If Option B: ADR lists each deferred blueprint type with flat-field mapping table; no orphan blueprint references in Tenants docs without ADR caveat.
- AC-4:
OneAggregateRootPerRepoTests(once real) still passes — child entities must not declare separate aggregate roots.
Implementation notes (full):
- Files:
ITenant.cs,TenantEntity.cs, NHibernate mappings,ConnectSoft.Saas.Tenants.json,docs/adr/ADR-TEN-001-flat-tenant-vs-rich-aggregate.md. - Reference enumeration:
TenantLifecycleStatusEnumerationvs JSONTenantLifecycleStatusvalues. - Do not break
TenantIdstring partition key semantics onITenantScopedEntity.
Out of scope:
- EditionRef / BillingAccountRef —
saas-TEN-F02. - Orleans grain changes —
saas-TEN-F08.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-S01.1 — Decide and implement tenant aggregate shape per ADR-TEN-001¶
Type: User Story
Parent: saas-TEN-F01
Implementation order: 010
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1
Priority: P1
Effort: XL
Dependencies: —
Blocks: saas-TEN-T01.1.1, saas-TEN-T01.1.2
Source gap analysis: Tenants entity model
Description (full):
As a Tenants domain developer, I need a clear decision on flat vs rich aggregate and corresponding code or ADR, so entity model work does not stall Billing provisioning and JSON descriptor alignment.
Acceptance criteria (testable):
- AC-1: ADR-TEN-001 Accepted with explicit Option A or B.
- AC-2: Entity model code and ADR agree — no undocumented missing VOs after story completes.
Implementation notes (full):
- Review blueprint table in deep analysis §4.1 (TenantProfile, Contact, TenantConfiguration rows all Missing).
Out of scope:
- External reference fields.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T01.1.1 — Author and accept ADR-TEN-001 flat vs rich aggregate¶
Type: Task
Parent: saas-TEN-S01.1
Implementation order: 010
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, adr
Priority: P1
Effort: S
Dependencies: —
Blocks: saas-TEN-T01.1.2
Source gap analysis: Tenants entity model
Description (full):
Draft ADR-TEN-001 comparing Option A (implement TenantProfile, TenantRegionResidency, Contact, TenantConfiguration) vs Option B (flat ITenant with ADR). Include evidence from ITenant.cs and empty JSON valueObjects array. Obtain program acceptance and update deep analysis decision log row from Pending to Accepted.
Acceptance criteria (testable):
- AC-1: ADR file at
ConnectSoft.Saas.TenantsTemplate/docs/adr/ADR-TEN-001-flat-tenant-vs-rich-aggregate.mdwith Accepted status. - AC-2: Deep analysis §5 ADR-TEN-001 row updated.
Implementation notes (full):
- Link to
0001-one-aggregate-root-per-repo.md— child entities allowed, only one aggregate root marker.
Out of scope:
- Code changes until decision recorded.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T01.1.2 — Implement chosen aggregate shape in entity model and JSON descriptor¶
Type: Task
Parent: saas-TEN-S01.1
Implementation order: 010
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1
Priority: P1
Effort: L
Dependencies: saas-TEN-T01.1.1
Blocks: saas-TEN-F04
Source gap analysis: Tenants entity model
Description (full):
If Option A: add entity/VO types, NHibernate mappings, migrations, update DefaultTenantsProcessor create/update paths. If Option B: update ConnectSoft.Saas.Tenants.json and inline docs to document flat mapping; add comments on ITenant properties referencing ADR deferred types. Add entity unit tests (replace any placeholder aggregate tests).
Acceptance criteria (testable):
- AC-1: Option A — new types persisted and loaded in repository integration test.
- AC-2: Option B — JSON descriptor
descriptionfields note ADR-TEN-001 deferral; no falsehasManyentries. - AC-3:
ResidencyRegiononITenantdocumented relative to blueprintTenantRegionResidency.
Implementation notes (full):
- Files:
EntityModel/*,PersistenceModel/*,ConnectSoft.Saas.Tenants.json. - Preserve
TenantAggregateIdGuid PK vs stringTenantIdpartition distinction.
Out of scope:
- ServiceModel API shape changes unless Option A requires new request fields.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
[011] saas-TEN-F02 — External references EditionRef and BillingAccountRef¶
Type: Feature
Parent: saas-EPIC-TEN
Implementation order: 011
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, references
Priority: P1
Effort: M
Dependencies: saas-TEN-F01
Blocks: saas-BIL-F01
Source gap analysis: Tenants entity model
Description (full):
Blueprint specifies external references on tenant aggregate: EditionRef (Products Catalog edition identifier) and BillingAccountRef (Billing bounded context account key). Current ITenant has no such properties; JSON descriptor references: [] is empty. Deep analysis finding T-002 — status Missing.
Without these refs, tenant activation cannot link to default edition selection or billing account provisioning triggers expected in E2E onboarding flows.
Target state: ITenant (or approved ADR location for refs) stores EditionRef and BillingAccountRef with validation rules. CreateDraft/Activate requests accept or default refs. Outbound TenantActivatedEvent includes refs for Billing consumer sagas.
Acceptance criteria (testable):
- AC-1: Entity and migration add nullable or required ref columns per ADR.
- AC-2:
TenantActivatedEventexposes edition and billing account ref fields consumed by Billing inbound DTOs. - AC-3: Unit test: Activate tenant with refs persists and publishes refs on event.
- AC-4: JSON descriptor documents reference fields.
Implementation notes (full):
- Files:
ITenant.cs,TenantActivatedEvent.cs,CreateTenantDraftRequest.cs, NHibernate mapping, migration. - Coordinate with Billing
DefaultSubscriptionsProcessortenant-activated handler expectations. - Ref format: string opaque ids matching Catalog/Billing aggregate keys — document in published language.
Out of scope:
- Validating refs exist in Catalog/Billing at write time (optional saga in future wave).
- Subscription creation logic — Billing domain.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-S02.1 — Add EditionRef and BillingAccountRef to tenant aggregate and activation event¶
Type: User Story
Parent: saas-TEN-F02
Implementation order: 011
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1
Priority: P1
Effort: M
Dependencies: saas-TEN-F01
Blocks: saas-TEN-T02.1.1, saas-TEN-T02.1.2
Source gap analysis: Tenants entity model
Description (full):
As a Billing integrator, I need tenant-activated events to carry edition and billing account references, so subscription provisioning can bind to the correct catalog edition and billing account without extra lookup tables.
Acceptance criteria (testable):
- AC-1: Activate flow persists refs on
ITenantrow. - AC-2: Published
TenantActivatedEventJSON includes ref properties matching Billing inbound ACL field names.
Implementation notes (full):
- Align property names with Billing inbound tenant-activated DTO after
saas-INTEG-F01topic fix.
Out of scope:
- Catalog edition existence validation.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T02.1.1 — Extend ITenant entity, migration, and ServiceModel requests with refs¶
Type: Task
Parent: saas-TEN-S02.1
Implementation order: 011
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1
Priority: P1
Effort: M
Dependencies: saas-TEN-F01
Blocks: saas-TEN-T02.1.2
Source gap analysis: Tenants entity model
Description (full):
Add EditionRef and BillingAccountRef properties to ITenant and concrete entity. Create NHibernate migration. Extend CreateTenantDraftRequest / ActivateTenantRequest (or dedicated update operation) to accept refs. Update validators.
Acceptance criteria (testable):
- AC-1: Database migration applies cleanly on empty and existing databases.
- AC-2: REST and gRPC contracts expose ref fields with XML documentation.
Implementation notes (full):
- Files:
ITenant.cs,TenantEntity.cs, mapping files,ServiceModel/*Request.cs,TenantsController.cs,GrpcTenantManagementService.cs.
Out of scope:
- Event publish changes.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T02.1.2 — Publish refs on TenantActivatedEvent and update JSON descriptor¶
Type: Task
Parent: saas-TEN-S02.1
Implementation order: 011
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, messaging
Priority: P1
Effort: S
Dependencies: saas-TEN-T02.1.1
Blocks: saas-BIL-F01
Source gap analysis: Tenants entity model
Description (full):
Add ref properties to TenantActivatedEvent (and optionally TenantCreatedEvent if draft carries refs). Update DefaultTenantsProcessor publish mapping. Document fields in ConnectSoft.Saas.Tenants.json published event schema notes.
Acceptance criteria (testable):
- AC-1: Processor unit test asserts event carries edition and billing refs after Activate.
- AC-2: MassTransit topology unchanged on topic names (
TenantsConstants.EventTopics.TenantActivated).
Implementation notes (full):
- File:
MessagingModel/Events/TenantActivatedEvent.cs, processor publish site.
Out of scope:
- Billing consumer mapping —
saas-BIL-F01.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
[012] saas-TEN-F03 — Full lifecycle saga replacing create-only stub¶
Type: Feature
Parent: saas-EPIC-TEN
Implementation order: 012
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, saga
Priority: P1
Effort: L
Dependencies: saas-INTEG-F05
Blocks: —
Source gap analysis: Tenants messaging
Description (full):
TenantLifecycleSaga is a create-only stub: it correlates on TenantCreatedEvent, logs, sets StartedAt, and finalizes immediately (ConnectSoft.Saas.Tenants.FlowModel.MassTransit/TenantLifecycleSaga.cs). No states exist for activate, suspend, decommission, or residency change despite five operations on ITenantManagementService (CreateDraftAsync, ActivateAsync, SuspendAsync, DecommissionAsync, ChangeResidencyAsync).
Deep analysis finding T-003 — status Partial.
Target state: Saga orchestrates multi-step lifecycle hooks (internal compensation, timed transitions, or publish-side effects) aligned with processor commands. Minimum: saga instance transitions on each outbound domain event (TenantActivated, TenantSuspended, TenantDeleted, ResidencyChanged) with durable state per saas-INTEG-F05.
Acceptance criteria (testable):
- AC-1: Saga defines states beyond Initial/Final for activate, suspend, decommission, residency paths.
- AC-2: Each
ITenantManagementServicecommand that publishes integration event updates saga state in integration test. - AC-3: Saga unit tests cover happy path create → activate and suspend → decommission sequences.
- AC-4: Saga uses durable repository (not in-memory) per INTEG-F05 outcome.
Implementation notes (full):
- Files:
TenantLifecycleSaga.cs,TenantLifecycleSagaState.cs,MassTransitExtensions.cssaga registration. - Correlate events by
TenantAggregateIdconsistently with create handler. - Do not duplicate processor business rules — saga handles orchestration hooks only.
Out of scope:
- Cross-service choreography (Billing subscription creation) — Billing sagas consume Tenants events.
- Compensation transactions across databases.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-S03.1 — Expand TenantLifecycleSaga to cover full tenant lifecycle¶
Type: User Story
Parent: saas-TEN-F03
Implementation order: 012
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, saga
Priority: P1
Effort: L
Dependencies: saas-INTEG-F05
Blocks: saas-TEN-T03.1.1, saas-TEN-T03.1.2
Source gap analysis: Tenants messaging
Description (full):
As a Tenants maintainer, I need the lifecycle saga to react to all tenant domain events, so orchestration state reflects activate/suspend/decommission/residency operations instead of stopping after create.
Acceptance criteria (testable):
- AC-1: Saga state machine includes event handlers for all five published topics in
TenantsConstants.EventTopics. - AC-2: Invalid transition (e.g., suspend before activate) handled per processor rules — saga logs and does not corrupt state.
Implementation notes (full):
- Reference
TenantLifecycleStatusEnumerationvalues: Draft, Active, Suspended, Decommissioned.
Out of scope:
- New outbound events beyond existing five topics.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T03.1.1 — Define saga states and event correlations for lifecycle events¶
Type: Task
Parent: saas-TEN-S03.1
Implementation order: 012
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, saga
Priority: P1
Effort: M
Dependencies: saas-INTEG-F05
Blocks: saas-TEN-T03.1.2
Source gap analysis: Tenants messaging
Description (full):
Extend TenantLifecycleSaga with Event<T> registrations for TenantActivatedEvent, TenantSuspendedEvent, TenantDeletedEvent, ResidencyChangedEvent. Define saga states (e.g., Draft, Active, Suspended, Decommissioned) on TenantLifecycleSagaState. Implement During/When transitions updating state timestamps and lifecycle flags.
Acceptance criteria (testable):
- AC-1: State diagram documented in saga class XML summary matches implemented transitions.
- AC-2:
TenantLifecycleSagaStatepersists new fields via durable saga repository.
Implementation notes (full):
- Files:
TenantLifecycleSaga.cs,TenantLifecycleSagaState.cs. - Import event types from
ConnectSoft.Saas.Tenants.MessagingModel.Events.
Out of scope:
- Saga tests (next task).
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T03.1.2 — Add saga unit and integration tests for lifecycle sequences¶
Type: Task
Parent: saas-TEN-S03.1
Implementation order: 012
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing
Priority: P1
Effort: M
Dependencies: saas-TEN-T03.1.1
Blocks: —
Source gap analysis: Tenants messaging
Description (full):
Add TenantLifecycleSagaTests using MassTransit test harness verifying create → activate → suspend → decommission event sequence updates saga state correctly. Cover residency change on Active tenant. Deep analysis notes "No saga unit tests" — this task closes that gap for Tenants.
Acceptance criteria (testable):
- AC-1: Test harness asserts saga reaches expected state after each published event.
- AC-2: Tests run in CI without external broker (in-memory harness acceptable for unit tier).
Implementation notes (full):
- Place tests in
ConnectSoft.Saas.Tenants.UnitTestsor dedicated FlowModel test project. - Pattern: Billing/Entitlements saga test projects if present.
Out of scope:
- Acceptance tests across five services.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
[013] saas-TEN-F04 — JSON descriptor reconciliation with code¶
Type: Feature
Parent: saas-EPIC-TEN
Implementation order: 013
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, json-descriptor
Priority: P1
Effort: M
Dependencies: saas-TEN-F01
Blocks: —
Source gap analysis: Tenants entity model
Description (full):
Design-time JSON descriptor ConnectSoft.Saas.Tenants.json diverges from runtime entity model in several fields:
| Concept | JSON descriptor | Code (ITenant.cs) |
Gap |
|---|---|---|---|
| Primary key | TenantId (guid) |
TenantAggregateId (Guid) + TenantId (string partition) |
Partial — dual id model not reflected |
| Region | RegionCode |
ResidencyRegion |
Name mismatch |
| Status enum | Decommissioned in JSON |
TenantLifecycleStatusEnumeration includes Decommissioned; event topic uses tenant-deleted |
Vocabulary drift |
| TenantKey | Not in JSON properties | Present on entity + migration | Missing in descriptor |
| AggregateVersion | Not in JSON | Present on ITenant |
Missing in descriptor |
Deep analysis finding T-004 — status Partial.
Target state: JSON descriptor accurately documents code properties, PK strategy, published events, and enumeration values. Factory/codegen tools (if used) regenerate without drift warnings.
Acceptance criteria (testable):
- AC-1:
ConnectSoft.Saas.Tenants.jsonprimaryKey section documentsTenantAggregateIdvs partitionTenantIdstring. - AC-2: Property names align:
ResidencyRegiondocumented (or JSON renamed with migration — prefer code as runtime truth). - AC-3:
TenantKeyandAggregateVersionappear in descriptor properties. - AC-4: Architecture or schema validation test compares JSON to
ITenantpublic surface and fails on drift.
Implementation notes (full):
- Files:
ConnectSoft.Saas.Tenants.json, optional schemaConnectSoft.Saas.Tenants.schema.json. - Coordinate
tenant-deletedtopic vs Decommissioned status in F05 envelope story. - Reference deep analysis entity model table rows for
saas-TEN-F04.
Out of scope:
- Regenerating entire repo from JSON — manual reconciliation only unless tooling owned elsewhere.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-S04.1 — Reconcile ConnectSoft.Saas.Tenants.json with ITenant runtime model¶
Type: User Story
Parent: saas-TEN-F04
Implementation order: 013
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1
Priority: P1
Effort: M
Dependencies: saas-TEN-F01
Blocks: saas-TEN-T04.1.1, saas-TEN-T04.1.2
Source gap analysis: Tenants entity model
Description (full):
As a template tooling maintainer, I need the JSON descriptor to match ITenant.cs, so design-time docs and codegen do not mislead integrators about tenant ids, region fields, and aggregate version.
Acceptance criteria (testable):
- AC-1: Descriptor validation test passes against entity model.
- AC-2: publishedEvents array still matches
TenantsConstants.EventTopicsfive canonical strings.
Implementation notes (full):
publishedEventsin JSON already lists five canonical topics — preserve alignment verified in deep analysis §4.1 Messaging.
Out of scope:
- F01 rich entity JSON for child types until ADR resolves.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T04.1.1 — Update JSON descriptor fields for PK, TenantKey, AggregateVersion, region¶
Type: Task
Parent: saas-TEN-S04.1
Implementation order: 013
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1
Priority: P1
Effort: S
Dependencies: saas-TEN-F01
Blocks: saas-TEN-T04.1.2
Source gap analysis: Tenants entity model
Description (full):
Edit ConnectSoft.Saas.Tenants.json: fix primaryKey to TenantAggregateId (guid) with separate partition property TenantId (string); rename RegionCode property to ResidencyRegion; add TenantKey (string, required) and AggregateVersion (long, required). Update enumeration documentation for lifecycle states.
Acceptance criteria (testable):
- AC-1: JSON validates against
ConnectSoft.Saas.Tenants.schema.jsonif schema enforces property set. - AC-2: Manual review checklist maps each
ITenantproperty to a JSON property entry.
Implementation notes (full):
- File: repo root
ConnectSoft.Saas.Tenants.jsonlines 9–67 (aggregateRoot.properties).
Out of scope:
- NHibernate mapping changes unless JSON-driven codegen requires it.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T04.1.2 — Add descriptor drift architecture test¶
Type: Task
Parent: saas-TEN-S04.1
Implementation order: 013
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing
Priority: P1
Effort: S
Dependencies: saas-TEN-T04.1.1
Blocks: —
Source gap analysis: Tenants entity model
Description (full):
Implement test in ArchitectureTests that loads ConnectSoft.Saas.Tenants.json and asserts property name set matches ITenant public properties (minus navigation props). Fail CI on drift. Pattern similar to Products Catalog descriptor tests if available.
Acceptance criteria (testable):
- AC-1: Test fails if
TenantKeyremoved from JSON but remains onITenant. - AC-2: Test passes after T04.1.1 reconciliation.
Implementation notes (full):
- File: new
JsonDescriptorEntityAlignmentTests.csin ArchitectureTests project.
Out of scope:
- Cross-repo JSON comparisons.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
[014] saas-TEN-F05 — Event envelope adoption and Pending/Deleted vocabulary decision¶
Type: Feature
Parent: saas-EPIC-TEN
Implementation order: 014
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, envelope
Priority: P1
Effort: M
Dependencies: saas-INTEG-F03
Blocks: —
Source gap analysis: Integration event envelope
Description (full):
Tenants outbound events (TenantCreatedEvent, etc.) implement partial envelope: TenantId, aggregate id, AggregateVersion, OccurredOn — but omit schemaVersion, correlationId, and causationId per deep analysis X-004. This feature adopts the common envelope from saas-INTEG-F03 on all Tenants MessagingModel event types and processor publish paths.
Vocabulary decision: JSON descriptor enumeration uses Decommissioned lifecycle state; integration topic uses tenants.domain.v1.tenant-deleted (TenantsConstants.EventTopics.TenantDeleted). Document mapping: Deleted event represents decommission terminal state (not physical row delete) OR rename topic in breaking change — decision recorded in Tenants ADR snippet.
Acceptance criteria (testable):
- AC-1: All five Tenants outbound events include envelope fields from INTEG-F03 helper.
- AC-2: ADR or published-language note documents Decommissioned ↔ tenant-deleted event mapping.
- AC-3: Serialization tests include envelope fields in golden JSON files.
- AC-4:
CrossRepoPublishedLanguageTestsvalidates event types implement envelope interface once placeholder replaced (coordinate with F06).
Implementation notes (full):
- Files:
MessagingModel/Events/*.cs,DefaultTenantsProcessor.cspublish paths,TenantsMassTransitTopology.cs. - Wire correlation from ASP.NET Core trace context in REST/gRPC adapters before processor call.
Out of scope:
- Changing topic names (already canonical).
- Inbound events (Tenants is publish-only for integration).
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-S05.1 — Adopt common event envelope on Tenants integration events¶
Type: User Story
Parent: saas-TEN-F05
Implementation order: 014
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1
Priority: P1
Effort: M
Dependencies: saas-INTEG-F03
Blocks: saas-TEN-T05.1.1, saas-TEN-T05.1.2
Source gap analysis: Integration event envelope
Description (full):
As a platform integrator tracing tenant activation, I need Tenants events to carry schemaVersion and correlationId, so downstream Billing sagas join logs with the originating API request.
Acceptance criteria (testable):
- AC-1:
TenantCreatedEventgolden JSON snapshot includesschemaVersion: 1and non-emptycorrelationId. - AC-2: Decommissioned/deleted vocabulary documented in repo
docs/or ADR.
Implementation notes (full):
- Depends on shared envelope type from INTEG-F03 T03.1.1.
Out of scope:
- Billing inbound envelope fields.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T05.1.1 — Apply envelope properties to all MessagingModel event types¶
Type: Task
Parent: saas-TEN-S05.1
Implementation order: 014
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1
Priority: P1
Effort: M
Dependencies: saas-INTEG-F03
Blocks: saas-TEN-T05.1.2
Source gap analysis: Integration event envelope
Description (full):
Update all event classes under ConnectSoft.Saas.Tenants.MessagingModel/Events/ to implement shared envelope interface. Map TenantAggregateId to canonical JSON aggregateId. Integrate publish helper in processor for all five lifecycle publishes.
Acceptance criteria (testable):
- AC-1: Each event type has
[Required]onSchemaVersion,CorrelationId,AggregateVersion,OccurredOn. - AC-2: Processor unit tests verify helper invoked on publish (mock
IPublishEndpoint).
Implementation notes (full):
- Start from
TenantCreatedEvent.csstructure; replicate across activated/suspended/deleted/residency events.
Out of scope:
- Vocabulary ADR (next task).
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T05.1.2 — Document tenant-deleted vs Decommissioned vocabulary decision¶
Type: Task
Parent: saas-TEN-S05.1
Implementation order: 014
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, docs
Priority: P1
Effort: S
Dependencies: saas-TEN-T05.1.1
Blocks: —
Source gap analysis: Integration event envelope
Description (full):
Author short ADR or published-language appendix entry explaining why integration topic is tenant-deleted while domain enumeration uses Decommissioned and ServiceModel exposes DecommissionAsync. Include consumer guidance for Billing/Entitlements sagas. Optionally add [Obsolete] aliases — prefer documentation-only for wave-1.
Acceptance criteria (testable):
- AC-1: ADR section linked from
TenantDeletedevent XML docs. - AC-2: Deep analysis glossary updated if needed (Flat tenant / Deleted vocabulary).
Implementation notes (full):
- Reference
TenantsConstants.EventTopics.TenantDeletedandDecommissionAsynconITenantManagementService.
Out of scope:
- Renaming public topic string (breaking change).
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
[015] saas-TEN-F06 — Replace placeholder architecture tests¶
Type: Feature
Parent: saas-EPIC-TEN
Implementation order: 015
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, architecture-tests
Priority: P1
Effort: M
Dependencies: saas-TEN-F04, saas-TEN-F05
Blocks: saas-TEN-F07
Source gap analysis: Tenants tests
Description (full):
Tenants ArchitectureTests project contains placeholder tests that always pass:
OneAggregateRootPerRepoTests.cs—Assert.IsTrue(true)with TODO to replace NetArchTest rule (referencesdocs/adr/0001-one-aggregate-root-per-repo.md).CrossRepoPublishedLanguageTests.cs— placeholder enforcing published-language surface rule.
Products Catalog template implements real NetArch tests (OneAggregateRootPerRepo, CrossRepoPublishedLanguage assembly scan) — use as reference implementation.
Deep analysis finding T-005 — status Missing.
Target state: Real NetArchTest rules fail CI on violations: more than one aggregate root in DomainModel, illegal cross-repo type references, envelope interface compliance on MessagingModel events.
Acceptance criteria (testable):
- AC-1:
OneAggregateRootPerRepoTests.Only_one_aggregate_root_is_declareduses NetArchTest and fails if secondIAggregateRoot<>declared in Tenants domain assemblies. - AC-2:
CrossRepoPublishedLanguageTestsfails if DomainModel type referenced from forbidden assembly graph simulation. - AC-3: Optional
TenantAggregateTestsvalidates singleITenantroot marker — no placeholder asserts. - AC-4: All architecture tests pass on current codebase after implementation.
Implementation notes (full):
- Files:
tests/ConnectSoft.Saas.Tenants.ArchitectureTests/*.cs. - Reference:
ConnectSoft.Saas.ProductsCatalogTemplate/tests/ConnectSoft.Saas.ProductsCatalog.ArchitectureTests/. ServiceModelLayeringNetArchTests.csalready Implemented — do not regress.
Out of scope:
- Processor unit tests —
saas-TEN-F07. - Orleans silo tests —
saas-TEN-F08/ future grain tests.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-S06.1 — Enable real NetArch architecture tests in Tenants template¶
Type: User Story
Parent: saas-TEN-F06
Implementation order: 015
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing
Priority: P1
Effort: M
Dependencies: saas-TEN-F04, saas-TEN-F05
Blocks: saas-TEN-T06.1.1, saas-TEN-T06.1.2
Source gap analysis: Tenants tests
Description (full):
As a template quality owner, I need architecture tests that actually enforce aggregate-root and published-language rules, so Tenants template regressions are caught in CI like Products Catalog.
Acceptance criteria (testable):
- AC-1: Removing
Assert.IsTrue(true)placeholders — tests use NetArchTest predicates. - AC-2: CI pipeline runs ArchitectureTests project on every PR.
Implementation notes (full):
- Load base-template NetArch harness if available in Tenants base-template subtree.
Out of scope:
- Billing architecture tests.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T06.1.1 — Implement OneAggregateRootPerRepoTests with NetArchTest¶
Type: Task
Parent: saas-TEN-S06.1
Implementation order: 015
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing
Priority: P1
Effort: S
Dependencies: saas-TEN-F04
Blocks: saas-TEN-T06.1.2
Source gap analysis: Tenants tests
Description (full):
Replace placeholder in OneAggregateRootPerRepoTests.cs with NetArchTest rule: types in assemblies matching ConnectSoft.Saas.Tenants.DomainModel or implementing IAggregateRoot<> in EntityModel — exactly one aggregate root (ITenant). Follow Catalog test structure.
Acceptance criteria (testable):
- AC-1: Test fails when dummy second aggregate root class added to test sandbox.
- AC-2: Test passes on current Tenants codebase.
Implementation notes (full):
- File:
tests/ConnectSoft.Saas.Tenants.ArchitectureTests/OneAggregateRootPerRepoTests.cs. - ADR:
docs/adr/0001-one-aggregate-root-per-repo.md.
Out of scope:
- CrossRepoPublishedLanguage test.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T06.1.2 — Implement CrossRepoPublishedLanguageTests and envelope rule¶
Type: Task
Parent: saas-TEN-S06.1
Implementation order: 015
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing
Priority: P1
Effort: S
Dependencies: saas-TEN-T06.1.1, saas-TEN-F05
Blocks: saas-TEN-F07
Source gap analysis: Tenants tests
Description (full):
Replace placeholder in CrossRepoPublishedLanguageTests.cs with rules: (1) only ServiceModel, MessagingModel, ActorModel assemblies export public API surfaces consumed cross-repo; (2) all types in MessagingModel.Events implement envelope interface from INTEG-F03. Use assembly scanning like Catalog.
Acceptance criteria (testable):
- AC-1: Test fails if domain entity type marked public in wrong assembly.
- AC-2: Test fails if event type missing envelope property after F05.
Implementation notes (full):
- File:
CrossRepoPublishedLanguageTests.cs— comments already link published-language doc URL.
Out of scope:
- NuGet package version pin — INTEG-F07 (Tenants is publisher not consumer).
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
[016] saas-TEN-F07 — Processor, validator, REST, gRPC, and saga test coverage¶
Type: Feature
Parent: saas-EPIC-TEN
Implementation order: 016
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing
Priority: P1
Effort: L
Dependencies: saas-TEN-F03, saas-TEN-F06
Blocks: —
Source gap analysis: Tenants tests
Description (full):
Deep analysis §4.1 Tests: processor/saga coverage Missing; Orleans tests Missing (only base-template BankAccount examples). ITenantManagementService exposes five commands but unit tests do not comprehensively cover DefaultTenantsProcessor validation, conflict rules, REST/gRPC adapters, and saga interactions.
Target state: Unit tests for each processor command (create draft, activate, suspend, decommission, change residency) including validation faults and aggregate version increments. Adapter tests for TenantsController and GrpcTenantManagementService mocking processor. Saga tests linked from F03 included in coverage gate.
Acceptance criteria (testable):
- AC-1: Unit test class
DefaultTenantsProcessorTestswith minimum one happy-path and one fault-path test per public processor method. - AC-2: REST adapter tests verify HTTP status codes for ValidationFault and ConflictFault mapping.
- AC-3: gRPC adapter tests verify fault translation for at least Activate and Suspend.
- AC-4: Code coverage threshold for
DomainModel.ImplandServiceModelmeets program minimum (≥70% line coverage on processor/adapters — adjust in CI config). - AC-5: No
[Ignore]placeholder tests remain in Tenants unit test projects for processor/saga areas.
Implementation notes (full):
- Files:
DefaultTenantsProcessor.cs, validators,TenantsController.cs,GrpcTenantManagementService.cs. - Use in-memory NHibernate or repository fakes from base-template patterns.
- Reference
ITenantManagementService.csfive operations as checklist.
Out of scope:
- Acceptance tests spanning five services — separate demo checklist.
- Orleans grain silo tests —
saas-TEN-F08if ADR-INTEG-001 Option A.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-S07.1 — Achieve comprehensive unit test coverage for Tenants write and adapter paths¶
Type: User Story
Parent: saas-TEN-F07
Implementation order: 016
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing
Priority: P1
Effort: L
Dependencies: saas-TEN-F03, saas-TEN-F06
Blocks: saas-TEN-T07.1.1, saas-TEN-T07.1.2
Source gap analysis: Tenants tests
Description (full):
As a Tenants maintainer, I need automated tests for all five management commands and both adapters, so lifecycle bug fixes do not regress silently.
Acceptance criteria (testable):
- AC-1: Test count ≥ 5 processor happy paths + ≥ 3 fault scenarios (validation, not found, conflict).
- AC-2: CI publishes test results for Tenants.UnitTests on every build.
Implementation notes (full):
- Map tests to
TenantLifecycleStatusEnumerationtransitions.
Out of scope:
- Query service tests (
ITenantQueryService— lower priority P2 unless gaps found).
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T07.1.1 — Add DefaultTenantsProcessor and validator unit tests¶
Type: Task
Parent: saas-TEN-S07.1
Implementation order: 016
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing
Priority: P1
Effort: M
Dependencies: saas-TEN-F03
Blocks: saas-TEN-T07.1.2
Source gap analysis: Tenants tests
Description (full):
Create DefaultTenantsProcessorTests covering CreateDraft, Activate, Suspend, Decommission, ChangeResidency with mocked repository and publish endpoint. Assert aggregate version increments, lifecycle status transitions, and event publish calls with correct topic constants from TenantsConstants.EventTopics.
Acceptance criteria (testable):
- AC-1: Each processor method has ≥1 test; Activate after CreateDraft transitions Draft → Active.
- AC-2: Suspend on Draft tenant throws expected fault type.
Implementation notes (full):
- Project:
ConnectSoft.Saas.Tenants.UnitTests. - Mock
IPublishEndpointor MassTransit publish abstraction used by processor.
Out of scope:
- REST/gRPC tests.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T07.1.2 — Add REST and gRPC adapter tests for ITenantManagementService¶
Type: Task
Parent: saas-TEN-S07.1
Implementation order: 016
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing
Priority: P1
Effort: M
Dependencies: saas-TEN-T07.1.1
Blocks: —
Source gap analysis: Tenants tests
Description (full):
Add adapter tests using WebApplicationFactory (REST) and gRPC test server pattern verifying controllers/services delegate to ITenantsProcessor and map faults to HTTP/gRPC status codes. Cover at least CreateDraft + Activate for REST and Suspend for gRPC.
Acceptance criteria (testable):
- AC-1: REST test returns 400 on validation fault from processor mock.
- AC-2: gRPC test throws RpcException with correct status on ResourceNotFoundFault.
Implementation notes (full):
- Files:
TenantsController.cs,GrpcTenantManagementService.cs. - May extend AcceptanceTests project if already hosts test server (
CONNECTSOFT_ACCEPTANCE_TEST_HOST).
Out of scope:
- Full OpenAPI contract snapshot tests.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
[017] saas-TEN-F08 — Wire writes through TenantLifecycleGrain¶
Type: Feature
Parent: saas-EPIC-TEN
Implementation order: 017
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, orleans
Priority: P1
Effort: M
Dependencies: saas-INTEG-F06
Blocks: —
Source gap analysis: Orleans write-path
Description (full):
Orleans grain TenantLifecycleGrain (TenantEditorGrain.cs) implements ITenantLifecycleActor but ServiceModel write path bypasses grains: TenantsController and GrpcTenantManagementService call ITenantsProcessor directly. Deep analysis §4.1 Actor — Write path via grain: Missing.
This feature executes the outcome of ADR-INTEG-001 (saas-INTEG-F06):
- If Option A (wire grains): REST/gRPC →
IGrainFactory.GetGrain<ITenantLifecycleActor>(tenantKey)→ grain → processor. - If Option B (processor-only ADR): Document bypass in Tenants ADR; optionally remove misleading direct processor calls from docs; architecture test asserts documented pattern; cancel grain wiring AC.
Acceptance criteria (testable):
- AC-1: ADR-INTEG-001 Accepted and Tenants implementation matches chosen option.
- AC-2: Option A: No direct
ITenantsProcessorinjection in ServiceModel adapters — grains mediate all five commands; grain unit or silo test passes for Activate. - AC-3: Option B: ADR in Tenants repo states processor-only write path;
TenantEditorGrainmarked experimental or test-only; architecture test enforces noGetGrainrequirement. - AC-4: Existing
ITenantLifecycleActorinterface methods cover all five ServiceModel operations or ADR explains gap.
Implementation notes (full):
- Files:
TenantEditorGrain.cs,ITenantEditorActor.cs/ITenantLifecycleActor,TenantsController.cs,GrpcTenantManagementService.cs, DI registration in ApplicationModel. - Grain key: align with
TenantIdstring partition orTenantAggregateIdGuid — document choice. - Reference Catalog
ProductEditorGrainSiloTests.csfor silo test pattern if Option A.
Out of scope:
- Other repos' grain wiring — respective
saas-CAT-F01,saas-ENT-F07, etc. - Orleans cluster production hosting tuning.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-S08.1 — Align Tenants write path with ADR-INTEG-001 Orleans decision¶
Type: User Story
Parent: saas-TEN-F08
Implementation order: 017
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, orleans
Priority: P1
Effort: M
Dependencies: saas-INTEG-F06
Blocks: saas-TEN-T08.1.1, saas-TEN-T08.1.2
Source gap analysis: Orleans write-path
Description (full):
As a platform architect enforcing a consistent actor model, I need Tenants API writes to follow the program-wide Orleans decision, so template users are not misled by unused grains.
Acceptance criteria (testable):
- AC-1: Code inspection checklist in PR template matches ADR outcome (grain routed or bypass documented).
- AC-2: At least one automated test validates write path pattern (silo test or architecture rule).
Implementation notes (full):
- Blocked until
saas-INTEG-T06.1.2completes.
Out of scope:
- Read path through grains (query service stays direct).
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T08.1.1 — Refactor ServiceModel adapters per ADR-INTEG-001 outcome¶
Type: Task
Parent: saas-TEN-S08.1
Implementation order: 017
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, orleans
Priority: P1
Effort: M
Dependencies: saas-INTEG-F06
Blocks: saas-TEN-T08.1.2
Source gap analysis: Orleans write-path
Description (full):
If Option A: inject IGrainFactory into TenantsController and GrpcTenantManagementService; route each of five commands to TenantLifecycleGrain methods that delegate to ITenantsProcessor. If Option B: add Tenants ADR mirroring ADR-INTEG-001 Option B; update XML docs on grains stating not used on API path; ensure adapters remain processor-direct intentionally.
Acceptance criteria (testable):
- AC-1: Option A — grep ServiceModel layer shows
GetGrainusage for all write operations. - AC-2: Option B — Tenants ADR file exists; grains documented as non-write-path.
Implementation notes (full):
- Files:
TenantsController.cs,GrpcTenantManagementService.cs,TenantEditorGrain.cs. - Preserve fault contracts on
ITenantManagementService.
Out of scope:
- Processor logic changes.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
saas-TEN-T08.1.2 — Add grain silo test or architecture enforcement for write path¶
Type: Task
Parent: saas-TEN-S08.1
Implementation order: 017
Status: Not Started
Area path: ConnectSoft\SaaS\Tenants
Iteration: TBD
Tags: saas-platform, gap, tenants, p1, testing, orleans
Priority: P1
Effort: M
Dependencies: saas-TEN-T08.1.1
Blocks: —
Source gap analysis: Orleans write-path
Description (full):
If Option A: add TenantLifecycleGrainSiloTests activating silo, calling grain Activate method, asserting processor invoked and state persisted — mirror Catalog ProductEditorGrainSiloTests.cs. If Option B: extend ArchitectureTests to assert ServiceModel does not reference IGrainFactory and document exception list empty.
Acceptance criteria (testable):
- AC-1: Option A — silo test passes in CI (may use collection fixture for Orleans test cluster).
- AC-2: Option B — architecture test passes documenting processor-only pattern.
Implementation notes (full):
- Deep analysis notes "Orleans tests Missing" and "Only base-template BankAccount examples" — replace with Tenants-specific tests if Option A.
Out of scope:
- Multi-silo cluster deployment tests.
Definition of done:
- All AC pass
- Tests added/updated and green
- Docs updated
- Status updated in master + mirrors
Implementation ordering (P0 → P1 → P2)¶
P0 — Cross-epic prerequisites (execute before Tenants E2E slice)¶
Tenants features depend on integration epic outcomes:
[001]–[002]saas-INTEG-F01, F02 — topics and quota payload (Billing consumes Tenants events)[003]saas-INTEG-F03 — envelope contract (blocks[014]saas-TEN-F05)[005]saas-INTEG-F05 — durable saga (blocks[012]saas-TEN-F03)[006]saas-INTEG-F06 — Orleans ADR (blocks[017]saas-TEN-F08)
P1 — Tenants epic (this file, global order)¶
Execute in [NNN] order after relevant INTEG dependencies satisfied:
[010]saas-TEN-F01 — Rich tenant aggregate OR flat-tenant ADR[011]saas-TEN-F02 — External references EditionRef, BillingAccountRef[012]saas-TEN-F03 — Full lifecycle saga (after INTEG-F05)[013]saas-TEN-F04 — JSON descriptor reconciliation[014]saas-TEN-F05 — Event envelope + Deleted/Decommissioned vocabulary (after INTEG-F03)[015]saas-TEN-F06 — Replace placeholder architecture tests[016]saas-TEN-F07 — Processor / adapter / saga test coverage[017]saas-TEN-F08 — Wire writes through TenantLifecycleGrain (after INTEG-F06)
P2 — Follow-on enhancements¶
- Query service expansion and list/filter APIs beyond wave-1
ITenantQueryService - Cross-service ref validation sagas (verify EditionRef exists in Catalog on activate)
- Tenant acceptance tests spanning full five-repo demo harness
- Documentation-only updates in CompanyDocumentation program epics (
saas-DOCS-*)