Resolve an adapter from config. The type field selects the builder;
the full config object (including type) is forwarded to the builder
alongside the factory-level BuilderContext.
Always returns Promise<T> regardless of whether the builder is sync or async.
Register a builder for type. Throws AdapterFactoryError with
reason: "duplicate" if type is already registered (silent-override
prevention). To intentionally override an existing registration, use
AdapterFactory.replace.
Snapshot of currently registered type names. Used by error messages and tests.
Overwrite a previously-registered builder. Per A6+A7 §2.2.
type is registered: replace the builder. Returns void.type is NOT registered: throws AdapterFactoryError with
reason: "unknown-replace". Replacing a non-existent entry is an
error — the caller's mental model is wrong about what is registered.Security note: replace() has zero production callers at v0.5.0 and is
intended exclusively for test-fixture override of built-in adapters
(e.g., substituting a memory adapter for a Redis adapter in tests). The
runtime security boundary is the resolved adapter instance returned by
AdapterFactory.create, not this factory's builders map.
Freezing this factory would protect an object already off the runtime
path post-boot. See ADR:
.claude/audit/decisions/D-3-resolution.md (D-3, 2026-05-05) for the
full wrong-layer framing analysis and the explicit decision to close
SF-11 by documentation, not by adding freeze().
Name-based adapter registry. Consumers create one factory per "kind" (domain), register a builder per concrete adapter type, and resolve an instance at startup via AdapterFactory.create.
Per A6+A7 §2.3:
AdapterFactoryis a composition-root concern and intentionally has NOfreeze()method. Infrastructure builder composition is not protocol- module registration; there is no temporal boundary at which mutation becomes a contract violation. Throw-on-duplicateregister+ explicitreplaceis sufficient defence.