In-Memory Adapters as Reference Implementations
Context and Problem Statement
Each output port Protocol needs at least one concrete implementation. Test stubs (used in service-level tests) satisfy the Protocol structurally but lack real behaviour — e.g., a stub PolicyRepository returns a fixed list regardless of the resource URI. Should we ship production-quality in-memory adapters alongside the package, or keep them as test-only fixtures?
Decision Drivers
- In-memory adapters enable running the proxy without any external infrastructure (useful for development, demos, and CI)
- They serve as executable documentation of what each port Protocol expects
- Service-layer tests use minimal stubs; integration tests need adapters with real behaviour (e.g., glob matching, hashing)
- New contributors can understand the port contract by reading the in-memory implementation
Considered Options
- Test stubs only — in-memory logic lives in
tests/conftest fixtures - In-memory adapters as first-class code in
src/hdc_auth_proxy/adapters/memory/ - Abstract base classes with in-memory subclasses
Decision Outcome
Chosen option: "In-memory adapters as first-class code in adapters/memory/", because they provide a zero-dependency reference implementation for every output port while doubling as integration-test infrastructure.
Implementation
Each in-memory adapter lives in src/hdc_auth_proxy/adapters/memory/ and implements the corresponding port Protocol via structural subtyping (no explicit inheritance):
| Adapter | Protocol | Key behaviour |
|---|---|---|
InMemoryTokenValidator |
TokenValidator |
dict[str, TokenClaims] lookup by raw token string |
InMemoryPrincipalResolver |
PrincipalResolver |
dict[str, Principal] lookup by subject_id |
InMemoryApiKeyValidator |
ApiKeyValidator |
SHA-256 hash before lookup (see ADR-0008) |
InMemoryPolicyRepository |
PolicyRepository |
fnmatch glob matching on resource_pattern |
InMemoryResourceRepository |
ResourceRepository |
dict[str, ProtectedResource] lookup by URI |
All adapters expose add_* methods for populating data in tests and development.
Consequences
- Good, because the proxy can run end-to-end with zero external dependencies
- Good, because integration tests use the same code that ships in the package
- Good, because new port implementations can be validated against in-memory adapter behaviour
- Neutral, because in-memory adapters are not suitable for production (no persistence, no distributed state)
- Bad, because maintaining two sets of adapters (in-memory + production) increases surface area
Confirmation
tests/test_integration_inmemory.pywires all in-memory adapters through services and verifies end-to-end authentication + authorization- Architecture test
test_all_adapters_modules_importableconfirms all adapter modules import cleanly from hdc_auth_proxy.adapters.memory import *exports all five adapters
More Information
- Related: ADR-0002 Adopt DDD, ADR-0008 API Key Hashing
- Affected files:
src/hdc_auth_proxy/adapters/memory/