Skip to content
bitzorcas
中EN

Concept

Extension intake

The productized intake contract for a new module, adapter, background job, or endpoint — capabilities EXT-1 through EXT-8, default semantics, mandatory Operations visibility, and the fixed verification block.

Last updated

The traditional way to add a capability to a platform: create a project, write some code, sprinkle registrations into some god-sized startup class, and pray nobody deletes them. Six months later nobody can say what execution surfaces exist or which default implementation silently swallows production traffic. BitzOrcas intake goes the other way — every addition passes through one repeatable, fail-closed, observable, testable admission contract, guarded by templates, source generators, architecture rules, test gates, and docs, so the same steps produce the same result for every contributor.

failure

New module / adapter / job / endpoint

Declare owner and default semantics

Generators and architecture gates

Tests, operations visibility, docs

Manifests and release evidence

Stop intake

Capabilities

CapabilityScopeGate
EXT-1Intake contract, fixed verification, review checklistExtensionIntakeTests
EXT-2Incomplete module/aggregate input → zero C#, diagnostic list, no template backflowModuleGenerationFailClosedTests
EXT-3New modules register governance via compile-time attributes, fail-closedModuleGovernanceRegistrationTests
EXT-4Adapter matrix / default port ledger / operations probe consistencyAdapterMatrixConsistencyTests
EXT-5Thin endpoint protocol adapters; ProblemDetails/correlation/audit through the unified pipelineEndpoint Source Generator + API smoke
EXT-6Background job intake, JobHost envelope, operations job smokeBackgroundJobIntakeTests + JobHost unit tests
EXT-7dotnet new bitzorcas-host template + full verify-template.sh chainDotnetNewTemplateFlowTests
EXT-8Docs/architecture rules/test gates/final closure of standard intakeThis contract + fixed verification

EXT-2 deserves its own sentence: feed the generator an incomplete module definition and it produces not “half-broken code, fingers crossed” but zero C# output plus a diagnostic list precise about each missing item, with no template backflow files — bad input is rejected at the source.

Global rules

  1. Application does not depend on HttpContext, ORM, CAP, Redis, RabbitMQ, or any concrete infrastructure type.
  2. The Host is only the composition root and runtime wiring — no business rules.
  3. New extensions fail closed by default: without production configuration, the API Shell/JobHost starts with stable off-semantics or gives a fail-fast diagnosis.
  4. Every new extension is visible in at least one of: Operations, health/config diagnostics, trace/log/audit.
  5. A new extension updates implementation + architecture tests + smoke/integration tests + documentation together. The CLI generates no extension code.
  6. Module/aggregate and use-case CLIs write diagnostic lists to staging only; writing directly into the source tree fails closed.
  7. Doc/code conflict means fix the gate first, then fix implementation/docs — never just the words.

Module intake

The simple golden path starts from Contracts (or a standalone Domain owner) + Application. Do not pre-build empty Infrastructure/Endpoints. Request/Handler/short Rules are local; the Handler orchestrates caller/tenant, aggregate behavior, event registration, persistence, and Result.

Module identity is declared through compile-time markers — one XxxModule.cs marker type in the owner project plus owner-local catalogs:

Owner module declaration skeleton
namespace BitzOrcas.Platform.Tracker.Contracts;
using BitzOrcas.Modularity.Governance;
// Identity trio: display name, stable Code (permission prefix {code}.{resource}.{action}), base namespace.
[AppModule("Tracker", Code = "tracker", BaseNamespace = "BitzOrcas.Platform.Tracker")]
[DependsOn("Authorization")] // Every dependency edge is explicit; implicit transitive coupling is banned
[DependsOn("Files")]
internal sealed class TrackerModule;
// Permission ownership registers in the owner-local catalog; the Governance Generator reads both
// at compile time and emits GeneratedModuleContribution_Tracker implementing IModuleContributionProvider,
// with collection fields sorted by Ordinal — catalog output stays byte-deterministic, diffable, auditable.

Nothing scans assemblies at runtime: all governance facts come from generator projection. Full marker semantics, the current 36-marker inventory, and the legacy-ledger ratchet live in Module governance.

Endpoint/DI/ORM Fluent Config are owned by generators; simple aggregates use generated repositories directly.

The deep-module growth path extends physical surfaces only when real complexity appears: an independent public ReadModelStore for list/filter/pagination/projection; a dedicated QueryStore + adapter for joins/group-by/reports/external queries; Infrastructure for external protocols/resource lifecycles/provider asymmetry; thin Endpoint/API adapters only when the transport source generator cannot express the need. Splitting physical surfaces prematurely is over-engineering by another name — let the slice run first, then let structure grow.

Adapter intake

  1. Define ports in Application or Contracts; ports must not expose IQueryable/DbContext/ISqlSugarClient/CAP/Redis/RabbitMQ.
  2. Declare default semantics explicitly:
    • InMemory* — API Shell/local development/tests only, never production.
    • Null* — intentional silent no-op (e.g. a disabled event publisher).
    • Unavailable* — loud failure/fail-closed; callers get a stable error or Result.Failure.
  3. Default/Unavailable adapters register through TryAdd*; production/optional adapters register explicitly and override defaults. So an unconfigured production environment gets deterministic no-op or loud failure, not an unexpected implementation winning the race.
  4. ORM adapters use [RegisterOrmAdapter<TPort>]; the generator emits standard fail-closed default ports verified by provider contract/consistency tests.
  5. Runtime visibility flows into operations adapter probes, config diagnostics, and health readiness — an adapter’s presence ultimately shows up in the /api/operations probe matrix.
  6. Keep the platform adapter matrix and ORM capability matrix in sync; drift in each is guarded respectively by AdapterMatrixConsistencyTests and OrmAdapterParityTests.

Background job intake

Jobs live in src/Hosts/BitzOrcas.JobHost; the API Host carries no scheduled work. A job implements IJob (or equivalent), routing its Execute through QuartzJobExecutionAuditor to emit Activity/CorrelationId/BackgroundJob audit trail plus structured logs, with JobHost composition registering JobKey, trigger, schedule, and options explicitly. A quasi-production environment lacking persistent storage/Redis/OTLP fails fast or closes under config diagnostics. /api/operations/jobs describes job names, sources, enabled state, schedules, and runtime visibility. Jobs must not capture scoped dependencies directly — they create scopes or take safely-lifecycled constructor injection.

Endpoint intake

Endpoints use [GenerateEndpoint] or IEndpoint; route handlers are thin protocol adapters. Authorization defaults on; anonymity requires justification and tests. Business authorization lives in Application’s IAuthorizedRequest/rules, never in endpoints. All failures go through ResultExtensions.ToHttp or the unified exception handler into ProblemDetails, with CorrelationId middleware applied automatically. Required tests cover 401, 403, success/fail-closed, ProblemDetails shape, and API doc smoke.

Fixed verification block

Terminal window
# Run the build, docs, architecture, application, and API shell gates used for intake, in order.
dotnet build BitzOrcas.Modern.slnx --no-restore
scripts/build/check-xml-files.sh --no-build
scripts/build/check-xml-comments.sh --no-build
# Architecture regression and behavior regression leave evidence separately, easing failure triage.
dotnet test BitzOrcas.Architecture.Tests --no-build
dotnet test BitzOrcas.Application.Tests --no-build
dotnet test BitzOrcas.Integration.Tests --no-build --filter ApiShell
git diff --check

Slices touching code generators, JobHost, workflow jobs, templates, or provider adapters must run their additional tests.

See also

100%

Scroll or use controls to zoom · drag when enlarged · double-click for 100% / 200%