Context
0042 chose DI-first. The owner’s container answers CT1 to CT4 (mem L841–845, 2026-10-20) fix scopes, registration, lifecycle and testing. Its spike passed (gap C49). The answers replace the older lifecycle names of P12 (contradiction C-13), and the audit’s forRoot table is folded in here (audit 3.3).Decision
- Scopes (CT1).
singletonis the default.requestis per request, job or workflow step, held inAsyncLocalStorage, and carries tenant, actor, locale and trace.transientis created on each injection. A singleton may not inject a request-scoped provider; it injects the context accessor instead. This is checked at boot. - Registration (CT2).
forRoot,forRootAsync({ useFactory, inject }),forFeatureandregister, with named instances (forRoot({ default, instances })). Lazy modules are allowed. AConfigurableModuleBuilderis the base for all of them. - Lifecycle (CT3). Hooks follow the Nest names:
onModuleInit,onApplicationBootstrap,beforeApplicationShutdown,onModuleDestroyandonApplicationShutdown, with the shutdown hooks in reverse order and draining timeouts. Explorers run at bootstrap. Readiness is reported only after bootstrap. - Cycles and tests (CT4). A circular dependency is a boot error.
forwardRefis not used.createTestingModuleprovidesoverride*, auto-mocks and a request-context helper. A devtools graph is included.
Consequences
- Scope mistakes fail at boot, not at the first request.
- Modules expose one registration vocabulary, so readers do not learn a new one per package.
Enforcement
planned — the container checks the singleton-to-request injection and circular dependencies at boot, and the test module is covered by the container’s own tests under__tests__/.
Alternatives
forwardReffor cycles: rejected by CT4.- The P12 hook names: superseded (C-13).
Supersedes and sources
Supersedes: none. Amends: 0042 (now Accepted), 0005. Sources: owner container answers CT1 to CT4 (stackra-decisions-2026-10-19.md L841–845, 2026-10-20); spike result (gap C49); audit 3.3.