Supporting modules fill horizontal experience, compliance, reference-data, and connector needs without taking ownership of a business module’s facts. Each module now has a dedicated handbook; this page explains their division of responsibility and composition.
Three capability groups, one dependency rule
Supporting modules expose capability through public contracts while business modules retain business policy. Connectors translate protocols and errors; vendor models and SDK types must not leak into Application.
General experience and shared data
| Module | Provides | Typical composition |
|---|---|---|
| Menu | Menu catalogs, navigation nodes, permission association | Authorization decides visibility; Menu owns structure |
| Guidance | Guides, steps, and user progress | Identity identifies the user; a business module decides when to show guidance |
| Comments | Resource threads, replies, and moderation | A stable resource key attaches to Documents, Tickets, and other modules |
| Numbering | Rule-driven, concurrency-safe business numbers | The business aggregate stores the result; a number is not its primary key |
| Master Data | Countries, languages, rates, holidays, and common codes | Shares reference values without replacing private module enums |
| Document Structure | Folder templates, nodes, favorites, and tree navigation | Documents owns bodies and versions; this module owns organization |
Governance and intelligence
| Module | Provides | Must prove before release |
|---|---|---|
| GDPR | Consent, data-subject requests, and export/deletion orchestration | Each domain still performs its own discovery, retention, and deletion rules |
| AI Manage | Providers, credentials, workspaces, conversations, and messages | Authorization, data minimization, secret handling, model degradation, and audit |
The ability to call a model is not permission to send arbitrary business data. GDPR orchestration likewise cannot bypass aggregate ownership and directly delete another module’s data.
Operations, tools, and industry extensions
| Module | Boundary |
|---|---|
| Ops Extension | Incidents, dead letters, CAP failures, and support records |
| Tool Connectors | Protocol, authentication, rate limiting, and conversion for platform tools |
| Legal Connectors | Anti-corruption adapters for legal external systems |
| Legal Calculators | Pure-rule-first, reproducible legal calculations, and workbench suite |
| Industry Extensions | Isolation point for industry-specific capabilities |
Content publishing and commercial delivery
| Module | Owns | Does not own |
|---|---|---|
| Announcements | Announcement lifecycle, audience policy, and user read facts | Authoritative organization membership or out-of-band notification delivery |
| Release Management | Release notes, client-version catalog, rollout, and force-update decisions | Artifact builds, app stores, or deployment pipelines |
| Commercial Distribution | Private-package download rights and short-lived feed credentials | Runtime authorization, a NuGet server, or a credential provider |
| License Management | License requests, four-eyes review, asynchronous signing, and revocation | Runtime license enforcement, private-key custody, or package download rights |
These modules answer different questions. Commercial Distribution decides whether a customer may download a package. License Management controls whether a runtime license can be signed and revoked. Release Management decides whether a client should upgrade. Announcements decides which users can currently see a message. They can be composed, but their state must not be collapsed into one shared flag.
Composition example: a controlled document with comments
Suppose a user enters a document tree, opens a document, and adds a comment:
- Identity establishes caller and tenant context; Authorization decides access.
- Document Structure returns the visible tree; Documents returns body and version.
- Comments attaches a thread through stable resource type and identifier without owning the Document aggregate.
- Menu and Guidance improve discovery and onboarding without changing document permission.
- For a data-subject request, GDPR orchestrates each module as it exports or deletes its own records.
- The path records the minimum audit fields and fails closed whenever tenant or authorization state is uncertain.
Ask four questions before selection
| Question | Decision rule | Common mistake |
|---|---|---|
| Who owns the business fact? | keep the aggregate and state machine in the business module | use Comments, Menu, or Master Data as a generic business database |
| Is this a synchronous decision or state propagation? | use a narrow query port for immediate decisions and a versioned event for changed state | read another module’s tables or inject its handler |
| What happens when the default fails? | security fails closed; non-critical experience degrades explicitly | a Null adapter returns success and creates false delivery |
| Does it cross a network boundary? | use an anti-corruption layer, stable errors, timeout, idempotency, and observable retry | leak SDK DTOs, exceptions, or secrets into Application |
Failure boundaries
- Menu, Guidance, and Comments consume authorization decisions; they never redefine resource access.
- A Numbering failure must not persist an aggregate with a plausible empty number.
- Callers distinguish “unknown code” from a Master Data service failure.
- GDPR deletion is cross-domain orchestration, not a cross-database cascade; every owner returns auditable evidence.
- AI and connector calls retain business idempotency and replay evidence outside the network client.
- Ops Extension records failure facts but cannot become a second state machine for CAP, jobs, or webhooks.
Source and catalog checks
# Supporting and extension capabilities have directories; shared projects are not domains.find src/Platform -mindepth 1 -maxdepth 1 -type d | sort
# Run architecture tests in the source repo and source mapping in the handbook repo.dotnet test tests/BitzOrcas.Architecture.Tests/BitzOrcas.Architecture.Tests.csproj --filter FullyQualifiedName~Modulenpm run verify:module-sourceRelease gates
- The host registers the module and production adapter; a Null/Unavailable default cannot create a false success.
- Permissions, features, configuration, seeds, and health checks have repeatable evidence.
- Persisted data has explicit tenant, soft-delete, audit, concurrency, and retention semantics.
- Connectors cover timeout, cancellation, idempotency, bounded retry, rate limiting, secrets, and log redaction.
- Business and supporting modules communicate only through Contracts, narrow ports, or versioned events.
- Unit, integration, contract, and end-to-end tests cover success and failure paths.
Change-impact review
- Classify a new shared code as Master Data, a module-private enum, or configuration before creating a global dictionary.
- A new resource attachment defines resource type, stable identifier, tenant source, owner lookup, and deletion callback together.
- A connector replacement keeps Application contracts, stable errors, and idempotency semantics unchanged and proves vendor differences with recorded contracts.
- Menu or guidance visibility is never the only business-feature switch; runtime feature and authorization decisions execute independently.
- Treat model output as untrusted input; validate, authorize, and obtain required human confirmation before changing a business fact.
- A retention change covers business rows, attachments, search indexes, cache, audit, exports, and restored backup copies.
The acceptance record also names each default adapter, production owner, configuration and secret source, health check, capacity budget, retention rule, last failure drill, rollback path, and accountable operator. Missing evidence means “code available,” not “commercial GA.”
Return to the 36-module catalog, then use the add-module guide and module dependency diagram when introducing a capability.