[!TIP] This page dissects the output of the
dotnet new bitzorcas-hosttemplate matrix. For greenfield projects prefer the bitz scaffolder; both channels share the same verified consumer baseline.
Template output is a customer-owned solution plus a commercial package-consumption closure. The main example is Acme.ServiceDesk, generated from default-business-multi + sqlsugar, with differences for Mini, Single, and extension Profiles called out.
Ownership boundary
Customers may modify Hosts and Starter Module while preserving generated architecture rules. Framework, Platform, Workflow, Licensing, and Generators arrive as NuGet packages and should not be copied into a local fork.
Multi Business tree
Acme.ServiceDesk/├── Acme.ServiceDesk.slnx├── Directory.Build.props├── Directory.Build.targets├── Directory.Packages.props├── NuGet.Config├── README.md├── composition-manifest.json├── composition-manifest.schema.json├── composition-plan.json├── src/│ ├── Hosts/│ │ ├── Acme.ServiceDesk.Api/│ │ │ ├── Authentication/│ │ │ ├── Composition/│ │ │ ├── Configuration/│ │ │ ├── Schema/│ │ │ ├── Tenancy/│ │ │ ├── Program.cs│ │ │ └── appsettings*.json│ │ ├── Acme.ServiceDesk.AppHost/│ │ └── Acme.ServiceDesk.ServiceDefaults/│ └── Modules/Business/Starter/│ ├── Acme.ServiceDesk.Modules.Business.Starter.Contracts/│ └── Acme.ServiceDesk.Modules.Business.Starter.Application/└── tests/ ├── Acme.ServiceDesk.Unit.Tests/ └── Acme.ServiceDesk.Architecture.Tests/Output has no JobHost, frontend project, deployment YAML, maintenance script, or foundation product source. If a file is absent, first inspect the Profile contract rather than assuming interrupted generation.
Base output differences
| Project/capability | Mini API Single | Default Business Single | Default Business Multi |
|---|---|---|---|
| API | ✓ | ✓ | ✓ |
| ServiceDefaults | ✓ | ✓ | ✓ |
| Unit / Architecture Tests | ✓ | ✓ | ✓ |
| Business Starter Contracts/Application | — | ✓ | ✓ |
| AppHost | — | — | ✓ |
| Tenancy contract | fixed tenant context | fixed tenant context | authenticated tenant_id claim |
| Deployment | none | none | aspire |
| SQL Server development orchestration | — | — | AppHost |
Mini Development Shell runs without SQL Server. Business Profiles require a real database contract. Single relies on a deployment runbook for connection and schema; Multi uses AppHost for development orchestration.
API Host is the composition root
Program.cs owns:
- fail-closed configuration validation;
- ServiceDefaults, Problem Details, Forwarded Headers, and OpenAPI;
- current tenant, current user, and persistence execution context;
- generated Module, Endpoint, and ORM Adapter registration;
- Mediator pipelines, License, JWT, and Authorization;
- health, tenant middleware, and Endpoint mapping;
- process entries for schema or Platform operations.
Business rules do not belong in Host. Inspect composition calls:
rg -n 'AddBitzOrcas|MapBitzOrcas|MapAllGeneratedEndpoints|UseBitzOrcasModules' \ src/Hosts/Acme.ServiceDesk.Api/Program.csSqlSugar and EF Core emit different Program.cs code. Provider selection is physical registration, not a runtime decision from manifest. Real rg hits across both wiring surfaces:
AppHost ordering
Multi AppHost:
- creates SQL Server and
PrimaryDatabase; - creates a one-shot API project resource named
schema-migrator; - passes
--migrate-schema applyand waits for the database; - starts long-running API with database and Persistence identity;
- uses
WaitForCompletion(schemaMigrator)to prevent startup after migration failure.
rg -n 'AddSqlServer|AddDatabase|schema-migrator|WaitForCompletion' \ src/Hosts/Acme.ServiceDesk.AppHost/Program.csAuthorization Multi also adds RabbitMQ and authorization-bootstrap. Other Multi Profiles should not contain those resources.
Business Starter is a complete vertical slice
The Contracts WorkItem is both aggregate and persistence fact:
- derives from
TenantAggregateRoot<string>; [BitzTable]declares tenancy and soft delete;[BitzColumn]declares title constraints;- public parameterless construction exists only for ORM materialization;
- business creation flows through
Create, returning stable errors for invalid tenant/title.
Application CreateWorkItemCommand:
- generates
POST /api/work-itemsthrough[GenerateEndpoint]; - implements
IAuthorizedRequestwith resource and Create action; - resolves tenant from trusted
ICurrentTenant; - saves through
ICommandRepository<WorkItem,string>; - relies on generated transaction, DI, Endpoint, and ORM wiring.
rg -n 'BitzTable|TenantAggregateRoot|GenerateEndpoint|ICommandRepository' \ src/Modules/Business/StarterDo not add a parallel Entity, Mapper, MappingSpec, DataPort, or Infrastructure project for the same fact. That breaks the unified aggregate path and architecture gate.
Commercial packages and central versions
Directory.Packages.props controls versions, while NuGet.Config fixes Feed source mapping. API consumes a Profile package:
| Output | Profile package | ORM package |
|---|---|---|
| Mini | BitzOrcas.Profile.Mini.Api | matching SqlSugar or EF Core Infrastructure |
| Business | BitzOrcas.Profile.Default.Business | matching SqlSugar or EF Core Infrastructure |
Starter Contracts depend on Domain, Persistence Metadata, and Generator packages. Application depends on Application, Modularity, and a conditional Industry package. Project direction remains Host → Application → Contracts.
composition-manifest.json
The manifest is resolved composition fact, currently schemaVersion=2:
| Field | Purpose |
|---|---|
profileChoice/profileId/profilePackageId | public selection and commercial Profile |
runtimeAdapter | physical ORM |
tenancy/deployment | request isolation and topology |
platformModule/industryExtension | conditional closure |
hosts/projects | physical solution members |
modules/capabilities | Modules, Endpoints, Jobs, tenancy contracts |
packages/packageReferences/projectReferences | dependency closure and direction |
generators/endpointAssemblies/jobAssemblies | compile-time discovery |
licenseFeatures | Runtime License requirements |
verification | suggested verification commands |
excluded | explicitly unselected capabilities |
# Confirm schema, Profile, and ORM identity first.# Then review runtime members, License requirements, and explicit exclusions.jq '{ schemaVersion, profileChoice, runtimeAdapter, hosts, modules, capabilities, licenseFeatures, excluded}' composition-manifest.jsonManifest does not read runtime state or prove Feed tokens, License, database, or business configuration.
composition-plan.json
Plan is the physical output list, currently schemaVersion=1:
selectedProjects: projects that belong in the solution;selectedEndpoints/selectedJobs: entries declared by the Profile;writeFiles: files native generation should create;removePaths: paths removed for the selected branch.
# selected fields describe selection; writeFileCount describes physical output.# removePaths should agree with conditional pruning for the current Profile.jq '{ schemaVersion, selectedProjects, selectedEndpoints, selectedJobs, writeFileCount: (.writeFiles | length), removePaths}' composition-plan.jsonPlan is not input to another script. Editing it adds no project, package, or Endpoint. Generate another Profile from the exact template version into an empty directory.
Platform Profile increments
Authorization output adds:
BitzOrcas.Platform.Authorizationand matching Provider/CAP wiring;platform.authorizationlicense feature;- Authorization schema/operations command;
- Platform adoption tests;
- RabbitMQ, post-schema bootstrap, and separate operations identity in Multi AppHost.
MasterData adds its runtime package, Provider, license feature, and adoption tests, but not Authorization RabbitMQ/bootstrap files. Implementation still comes from commercial packages; Consumer owns Host wiring and adoption evidence.
Industry Profile increments
Finance, HR, Auction, and Legal Profiles add the matching industry package and capability to Starter Application and retain IndustryExtensionAdoptionTests. They do not generate a new industry business-module source tree; customers build their owner Module on the package contract.
Inspect manifest closure because Auction or Legal can include Finance through dependencies.
Test projects
Unit Tests cover Result, License composition, Profile/ORM, schema, Starter Aggregate, and conditional extension adoption. Architecture Tests enforce:
- no copied Framework/Platform source;
- no ORM/Host dependency from Application;
- aggregate invariants remain in the aggregate;
- owner-private types do not leak through public contracts;
- Handler and Endpoint stay slice-local;
- Module/Host references and generated wiring obey boundaries.
dotnet test tests/Acme.ServiceDesk.Architecture.Tests \ --configuration ReleaseKeep these as continuous gates after generation.
Extension locations
| Requirement | Modify/add | Do not modify |
|---|---|---|
| New invariant | owner Module Aggregate | API Program.cs |
| New use case | same Module Command/Query + Handler | generic Framework |
| New Endpoint | generation attribute on the use case | global handwritten route registration |
| New persistent field | unified aggregate metadata + schema | parallel Entity/Mapper |
| Platform/Industry adoption | Host wiring, owner contract, tests | manifest text alone |
| Commercial package upgrade | central versions + locks + evidence | copied commercial source |