157 lines
5.7 KiB
Markdown
157 lines
5.7 KiB
Markdown
# Capability consumer experience baseline
|
|
|
|
Correctness inside a reusable capability is not sufficient. The platform is
|
|
also evaluated by how much of that correctness a normal feature developer must
|
|
understand.
|
|
|
|
These measurements are baselines, not score targets. A lower line count is not
|
|
automatically better if it hides business semantics or creates a universal
|
|
repository abstraction.
|
|
|
|
## Scenario A — reference REST feature
|
|
|
|
The existing reference feature is the executable REST consumer.
|
|
|
|
It covers list/detail/create behavior, mapping, typed operation inputs,
|
|
application ports and an optimistic mutation path.
|
|
|
|
Current source size:
|
|
|
|
| Feature-owned area | LOC |
|
|
| --- | ---: |
|
|
| `application/reference-feature-api.ts` | 91 |
|
|
| `contracts/reference-mapper.ts` | 109 |
|
|
| `adapters/reference-http-gateway.ts` | 65 |
|
|
| `adapters/create-reference-feature-input.ts` | 41 |
|
|
| Total measured boundary/application source | 306 |
|
|
|
|
The important boundary metric is not the raw total. It is what those files need
|
|
to know about the platform.
|
|
|
|
Current result:
|
|
|
|
- HTTP platform imports in the feature adapter layer: 2 files,
|
|
- canonical import path used by both:
|
|
`src/adapters/http/index.ts`,
|
|
- direct imports of `http-execution-v3.ts`, retry scheduler, response reader,
|
|
auth admission or effect-certainty internals: 0,
|
|
- feature gateway owns transport failure projection: 0,
|
|
- feature gateway chooses operation ID, route ID, exact input/value type and
|
|
mapper: yes,
|
|
- central installed files own feature-specific adapter/runtime wiring: no;
|
|
feature-owned contributions are aggregated centrally.
|
|
|
|
The reusable HTTP capability now owns execution-outcome normalization through
|
|
`createFeatureHttpBinding`. A feature may still implement a custom outbound
|
|
adapter behind its application port when the reusable contract does not match
|
|
its business requirement.
|
|
|
|
## Scenario B — IndexedDB local draft
|
|
|
|
The original executable consumer probe remains at:
|
|
|
|
`tests/contract/consumer-experience/indexeddb-local-draft.test.ts`
|
|
|
|
with its isolated fixture:
|
|
|
|
`tests/contract/consumer-experience/fixtures/local-draft-feature.ts`
|
|
|
|
The architecture is now also exercised by a real vertical slice under:
|
|
|
|
`src/features/local-draft-feature`
|
|
|
|
It owns the Local Draft domain/application API and binds an
|
|
`IndexedDbRepositoryPort<LocalDraft, never>` in its feature adapter. The
|
|
cross-capability composition contract lives at:
|
|
|
|
`tests/contract/reusable-capability/feature-adapter-composition.test.ts`
|
|
|
|
That test composes one HTTP-only contribution and the IndexedDB-only Local Draft
|
|
contribution through the same generic catalog path.
|
|
|
|
The browser-level composition proof lives at:
|
|
|
|
`tests/browser-capabilities/local-draft-composition.spec.ts`
|
|
|
|
It runs against native browser IndexedDB. The test creates the platform
|
|
`createIndexedDbRuntime`, exposes that runtime through the typed
|
|
`createIndexedDbRepositoryProvider`, composes
|
|
`LOCAL_DRAFT_FEATURE_ADAPTER_CONTRIBUTION`, then executes Local Draft
|
|
save/find/remove through the feature API. The Local Draft feature still does
|
|
not import the IndexedDB runtime or native browser API.
|
|
|
|
Measured probe result:
|
|
|
|
| Metric | Result |
|
|
| --- | ---: |
|
|
| feature-owned fixture LOC | 97 |
|
|
| platform import statements | 1 |
|
|
| native IndexedDB API references | 0 |
|
|
| `src/adapters/storage/indexeddb/**` imports | 0 |
|
|
| runtime-internal IndexedDB types imported by feature | 0 |
|
|
|
|
The feature depends only on the public application boundary:
|
|
|
|
`src/application/ports/browser-file-storage/index.ts`
|
|
|
|
and specifically `IndexedDbRepositoryPort<LocalDraft, never>`.
|
|
|
|
The contract test rejects feature source that reaches for
|
|
`globalThis.indexedDB`, `IDBFactory`, `IDBDatabase`, `IDBTransaction`,
|
|
`IDBObjectStore` or the concrete IndexedDB adapter directory.
|
|
|
|
## What this does and does not prove
|
|
|
|
The contract probe confirms that **feature business code does not need native
|
|
IndexedDB knowledge** once an `IndexedDbRepositoryPort` has been composed.
|
|
The browser-capability proof additionally confirms that the same feature
|
|
contribution works when that port is backed by the repository's real
|
|
`createIndexedDbRuntime` and native IndexedDB implementation.
|
|
|
|
It does not prove that composition of `createIndexedDbRuntime` is cheap.
|
|
That constructor still owns substantial infrastructure policy:
|
|
|
|
- dataset scope and storage policy,
|
|
- physical store governance,
|
|
- retention/idempotency stores,
|
|
- schema migrations,
|
|
- codec and query policy,
|
|
- lifecycle authority,
|
|
- durability, scheduling and observation.
|
|
|
|
That complexity belongs at the composition/platform boundary, not in the
|
|
feature. The Local Draft vertical slice is now the second concrete consumer, and
|
|
it confirms that the stable seam is the typed repository provider plus a
|
|
feature-owned repository identity. It does **not** show that dataset scope,
|
|
retention, migration, codec or lifecycle-authority configuration can be safely
|
|
collapsed into one universal `create...Repository<T>` factory.
|
|
|
|
A convenience profile should therefore be introduced only after another
|
|
IndexedDB-backed product feature repeats the same infrastructure policy, not
|
|
merely because two features consume the same repository port.
|
|
|
|
## Consumer-quality review checklist
|
|
|
|
For each new product feature, record:
|
|
|
|
- feature-owned adapter LOC,
|
|
- platform glue LOC,
|
|
- files changed,
|
|
- central catalog edits,
|
|
- direct imports from capability-internal modules,
|
|
- native browser/network API references,
|
|
- duplicated failure/retry/lifecycle policy.
|
|
|
|
A healthy feature path should look like:
|
|
|
|
1. domain type and invariant,
|
|
2. use case,
|
|
3. business port,
|
|
4. feature-owned mapper/codec and policy,
|
|
5. capability-specific binding,
|
|
6. presentation controller/page.
|
|
|
|
The feature should not need the retry scheduler, abort ownership,
|
|
effect-certainty machinery, IndexedDB transaction lifecycle, OPFS journal,
|
|
reconnect coordinator or provider process model.
|