111 lines
4.2 KiB
Markdown
111 lines
4.2 KiB
Markdown
# Contract ownership
|
|
|
|
`src/contracts` is not a default destination for every shared-looking type.
|
|
A contract belongs there only when the change authority is genuinely shared
|
|
across layers, capabilities, build tooling, or runtime composition.
|
|
|
|
## Decision rule
|
|
|
|
For every proposed contract, ask:
|
|
|
|
1. Which requirement can cause this type or policy to change?
|
|
2. Is there one clear capability or feature owner?
|
|
3. Does another runtime/tooling boundary consume the same semantic contract?
|
|
4. Is the contract a wire/artifact authority shared by browser runtime and
|
|
build/release tooling?
|
|
|
|
The placement rule is:
|
|
|
|
- one feature owner -> keep it under that feature,
|
|
- one reusable capability owner -> keep it under that adapter/capability and
|
|
export it through the capability public entry point,
|
|
- multiple independent capability/layer owners -> `src/contracts`,
|
|
- browser/build/release wire or artifact authority -> `src/contracts` even
|
|
when the browser source graph alone looks small.
|
|
|
|
Consumer count alone is not sufficient. Scripts, generated artifacts and
|
|
release gates are semantic consumers too.
|
|
|
|
## Audit result
|
|
|
|
The September 2026 architecture review triggered an import-graph audit of all
|
|
39 contract files.
|
|
|
|
### Capability-owned contract moved
|
|
|
|
`cursor-pagination.ts` had one production owner:
|
|
`src/adapters/query-cache/cursor-pagination-runtime.ts`.
|
|
|
|
It moved to:
|
|
|
|
`src/adapters/query-cache/cursor-pagination-contract.ts`
|
|
|
|
and is exported through:
|
|
|
|
`src/adapters/query-cache/index.ts`
|
|
|
|
Tests use that public capability entry point. Pagination vocabulary no longer
|
|
occupies the global contract bucket merely because it is reusable inside one
|
|
adapter.
|
|
|
|
### Contracts intentionally kept global
|
|
|
|
The following examples have multiple semantic owners and remain global:
|
|
|
|
- `errors.ts` — application, presentation and several adapters,
|
|
- `result.ts` — common success/failure carrier below application,
|
|
- `boundary-mapper.ts` — HTTP, browser RPC, realtime and feature registries,
|
|
- `mutation-intent.ts` — application, presentation, HTTP, platform and
|
|
bootstrap,
|
|
- `exact-snapshot.ts` — HTTP, query-cache and browser-transfer,
|
|
- `rest-profiles.ts` — auth, HTTP, bootstrap and feature contract validation,
|
|
- `query-invalidation.ts` / `query-keys.ts` — query-cache, presentation,
|
|
bootstrap and features,
|
|
- `cache-invalidation.ts` — cross-context wire protocol plus query
|
|
invalidation policy,
|
|
- `storage-keys.ts` — browser storage and cross-context invalidation,
|
|
- `telemetry.ts` / `diagnostics.ts` — runtime adapters, application and
|
|
bootstrap.
|
|
|
|
Some contracts appear to have few browser-source consumers but are still shared
|
|
authorities:
|
|
|
|
- `env.ts` is consumed by bootstrap, runtime-schema/security tests and
|
|
registry governance,
|
|
- `deployment-admission.ts` is shared by runtime-config generation and release
|
|
admission,
|
|
- `release-tokens.ts` is shared by runtime coherence tooling and tests,
|
|
- `service-worker-static-manifest.ts` is a runtime-neutral canonical format
|
|
shared by build generation, validation and service-worker evidence.
|
|
|
|
Moving those based only on `src/**` import counts would split one semantic
|
|
authority across processes.
|
|
|
|
## Feature contracts
|
|
|
|
Feature-specific contracts stay inside the vertical slice:
|
|
|
|
`features/<feature>/contracts`
|
|
|
|
The reference feature owns routes, schemas, mapper definitions, message
|
|
catalogs and contribution identities. Central installed files aggregate those
|
|
contributions; they do not own their semantics.
|
|
|
|
The message catalog is a deliberate special case: the compiled catalog remains
|
|
total even when a feature is build-time disabled so the typed message lookup
|
|
does not become partial. The central message file therefore aggregates compiled
|
|
message keys rather than treating runtime installation as message ownership.
|
|
|
|
## Review rule for future additions
|
|
|
|
A new file under `src/contracts` should be rejected during review when all of
|
|
the following are true:
|
|
|
|
- one feature or one capability is the only semantic owner,
|
|
- no build/release/runtime wire authority needs the same definition,
|
|
- moving the definition to that owner does not create an inward dependency
|
|
violation.
|
|
|
|
Do not move a contract merely to reduce the number 39. The goal is explicit
|
|
ownership, not a smaller directory.
|