170 lines
11 KiB
Markdown
170 lines
11 KiB
Markdown
# Tool↔Gateway Mapping Contract (D8)
|
||
|
||
Status: DRAFT — awaiting ratification (webui-audit S2, contract 5 of 9).
|
||
Authority: PRD D8/D12 (Part I §8) — the webUI sits OVER official tooling:
|
||
every webUI operation goes through the Gateway API backed by the same
|
||
official framework tooling the CLI uses, and a webUI operation with no
|
||
backing tool is scored **blocked on tooling** and the tool is built
|
||
first. Measured input: the webui-audit A5 tooling baseline
|
||
(operation-by-operation inventory of the current Gateway surface and the
|
||
P1 gaps, cross-reviewed; `fleet/lanes/webui-audit/findings/
|
||
A5-tooling-baseline.md` in the estate brain). The T10 ruling adopted the
|
||
targeted-update plan including building the D8 tools in A5's rank order.
|
||
|
||
This contract binds three things: the operation→tool mapping itself
|
||
(§2–§3), the command envelope every mapped operation satisfies
|
||
(§4), and the process rule that keeps the mapping closed (§5). Domain
|
||
semantics stay with their owning contracts — hierarchy (contract 1,
|
||
`hierarchy-schema.md`), grants (contract 2, `rbac-grant-model.md`),
|
||
wizard (contract 3, `onboarding-wizard.md`), identity
|
||
(`identity-lifecycle.md`), kanban lifecycle (`native-kanban-sot.md`
|
||
§§5–6), roll-up (contract 8), API artifact format (contract 9).
|
||
|
||
## 1. Definitions
|
||
|
||
1. **Official tool**: a command implemented in the framework packages and
|
||
exposed through the Gateway API; the CLI remains the primary execution
|
||
method for the same command (D8). The webUI is a Gateway client only.
|
||
2. **Mapped operation**: a webUI operation with a named official path in
|
||
§2 or §3. Anything else the webUI wants to do is unmapped and follows
|
||
§5.
|
||
3. **Legacy non-substitute**: an existing endpoint that resembles a P1
|
||
need but is contractually barred from backing it (§3.2).
|
||
|
||
## 2. P0 mapping (current operations, ratified as-is)
|
||
|
||
The measured P0 surface is conformant today and stays bound to these
|
||
paths:
|
||
|
||
| WebUI operation | Official path |
|
||
| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||
| Register / log in / log out / OIDC callback | better-auth mount `/api/auth/*`; `GET /api/sso/providers` |
|
||
| List/show projects (legacy read) | `GET /api/projects`, `GET /api/projects/:id` |
|
||
| List tasks / task detail (legacy read) | `GET /api/tasks`, `GET /api/tasks/:id` |
|
||
| Conversation CRUD/search/messages | `/api/conversations*` |
|
||
| Chat turn / stop / thinking / command execute+approve / streaming | `/chat` socket events `message`, `abort`, `set:thinking`, `command:execute`, `command:approve` |
|
||
| Harness/model selection | `GET /api/harnesses*`, `GET/PUT /api/chat/preferences/selection` |
|
||
| Preferences; provider inspect/test | `/api/memory/preferences`, `GET /api/providers`, `POST /api/providers/test` |
|
||
| Admin users / roles / ban / health | `/api/admin/users*`, `/api/admin/health` |
|
||
|
||
P0 rows inherit §4 obligations as their backing controllers are next
|
||
touched; they are not required to be retrofitted in one sweep.
|
||
|
||
## 3. P1 mapping (bound to the build-first tools)
|
||
|
||
1. Every P1 operation maps to exactly one build-first command family, in
|
||
the T10-ruled rank order:
|
||
|
||
| Rank | Command family (owning contract) | P1 webUI operations it backs |
|
||
| ---- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| 1 | Hierarchy command family (contract 1 §5; grants attach per contract 2) | Company/estate/platform-project/workspace CRUD, parentage and reparenting, hierarchy reads; the wizard's initial-hierarchy step (contract 3 §3.4) |
|
||
| 2 | Hierarchy RBAC command/evaluator (contract 2) | Grant create/change/revoke at company/estate/platform-project; inherited evaluation down to workspace; authorization-safe hierarchy queries |
|
||
| 3 | Typed kanban command/query surface (SOT §§5–6, A1) | Workspace task lifecycle (create/edit/cancel/archive/move), board rank, typed queries |
|
||
| 4 | Agent enrollment command | Enroll one agent: harness, credential reference/API-key intake (values never echoed), name/persona, assignment scope (contract 3 §3.5) |
|
||
| 5 | Authorized roll-up query (contract 8) | Read-only aggregated task counts/statuses at every hierarchy level over readable workspaces only |
|
||
| 6 | Onboarding orchestration (contract 3) | The re-runnable wizard flow, composing ranks 1, 2, and 4 |
|
||
|
||
2. **Legacy non-substitutes.** The following MUST NOT back any P1
|
||
operation, matching the audit findings: legacy `/api/projects` and
|
||
`/api/tasks` CRUD (planning-data records, not hierarchy nodes and not
|
||
the typed kanban boundary); `POST /api/workspaces` (filesystem
|
||
bootstrap, not audited hierarchy parentage); `/api/teams` reads (no
|
||
grants, no inheritance); `POST /api/bootstrap/setup` (one-shot
|
||
epoch transition, identity §3 — not the re-runnable wizard); the MCP
|
||
`brain_*` task mutations (legacy Brain writes, not the typed kanban
|
||
commands). These stay serving their existing P0/host consumers until
|
||
each is retired by the migration its owning contract schedules.
|
||
3. New P1 mapping rows (operations this table does not list) are added by
|
||
amending this contract, not ad hoc (§5).
|
||
|
||
## 4. Command envelope (request / result / error / audit)
|
||
|
||
Binding on every mapped operation the build-first families expose:
|
||
|
||
1. **Typed request and result.** Each command and query has an explicit
|
||
request DTO and result DTO in the shared types package, validated at
|
||
the Gateway boundary; unvalidated pass-through and `any`-typed
|
||
payloads are non-conformant. Mutations on records with an
|
||
expected-version rule in their owning contract carry the expected
|
||
version in the request and fail on mismatch with the conflict error
|
||
class (SOT §6 optimistic concurrency; hierarchy per contract 1).
|
||
2. **Error taxonomy.** Every error result carries a stable
|
||
machine-readable code from a closed per-family enum plus an HTTP
|
||
status mapping, distinguishing at minimum: validation failure,
|
||
authentication failure, authorization refusal, not-found, conflict
|
||
(version/uniqueness), precondition/state refusal (e.g. bootstrap
|
||
epoch, suspended team subjects), and internal fault. Where contract
|
||
2's no-existence-oracle rule applies, authorization refusal and
|
||
not-found are indistinguishable on the wire for unauthorized readers
|
||
— same code, same status, same shape.
|
||
3. **Audit linkage.** A mutating mapped operation emits exactly the
|
||
audit events its owning contract defines (contract 1 §5.2, contract 2
|
||
§4.4, identity §§2–4, SOT audit rules); the envelope contributes the
|
||
correlation: every request accepts/generates a correlation id,
|
||
carried into the audit events and returned in the result, so a UI
|
||
action is traceable end to end. The mapping layer itself adds no
|
||
second audit stream.
|
||
4. **Fail-closed.** A mapped operation that cannot evaluate its
|
||
authorization or reach its owning tool refuses (contract 2 §3.5); the
|
||
envelope never degrades to an unauthorized fallback read or a direct
|
||
data access.
|
||
5. **CLI parity.** Each build-first family is invocable through the
|
||
official CLI against the same Gateway commands with the same
|
||
request/result/error contracts. No webUI-only command exists; a
|
||
Gateway command without CLI exposure is a conformance gap tracked at
|
||
the family's implementing issue.
|
||
|
||
## 5. Closure rule (blocked on tooling)
|
||
|
||
1. A webUI change that needs an operation with no mapping row is
|
||
**blocked on tooling**: the backing tool is built and mapped first
|
||
(D8). Scoring a gap "blocked on tooling" is mandatory, not
|
||
discretionary; working around it in the UI (direct DB or filesystem
|
||
access, calling a legacy non-substitute, embedding domain logic in
|
||
the web app) is non-conformant.
|
||
2. The mapping is enforced closed by §6.1's inventory witness: the web
|
||
app's network surface must be a subset of the mapped paths.
|
||
|
||
## 6. Verification requirements
|
||
|
||
Binding on the implementing PRs:
|
||
|
||
1. **Network-surface inventory witness:** a CI assertion extracting the
|
||
web app's Gateway calls (route literals and socket event names in
|
||
`apps/web` sources) and failing on any call outside the §2/§3 mapped
|
||
paths. The inventory is closed like contract 1 §6.3's allowlist: a
|
||
new call fails until a mapping row exists in the same PR. Dynamic
|
||
route construction that evades extraction is resolved toward the
|
||
witness (routes are declared extractably), not by exempting the
|
||
caller.
|
||
2. **Non-substitute witness:** the P1 surfaces (hierarchy, RBAC, kanban,
|
||
enrollment, roll-up, wizard UI) make zero calls to the §3.2 legacy
|
||
endpoints — asserted by the same inventory, scoped per surface.
|
||
3. **Envelope witnesses per family:** for each build-first family — a
|
||
request with an invalid DTO is refused with the validation code; a
|
||
version-mismatch mutation returns the conflict code; an unauthorized
|
||
read of an existing node and a read of a nonexistent node return
|
||
indistinguishable results where the no-existence-oracle rule applies;
|
||
a correlation id submitted on a mutation appears in its audit
|
||
event(s) and result.
|
||
4. **CLI-parity witness:** for each family, a CLI smoke invocation of at
|
||
least one command and one query against the Gateway succeeds with the
|
||
same typed result the web client receives.
|
||
5. **Fail-closed witness:** with the owning tool or grant state
|
||
unreachable (fault injection), the mapped operation returns the
|
||
internal-fault or authorization-refusal class and performs no
|
||
fallback read/write (extends contract 2 §7.6 to the mapping layer).
|
||
|
||
## Ruling request
|
||
|
||
Ratify sections 1–6 as written, with one decision embedded:
|
||
|
||
- Decision (§3.2): the legacy endpoints named there are **frozen for new
|
||
consumers** as of ratification — existing P0/host consumers keep
|
||
working, new UI or tool code may not call them, and each is retired by
|
||
the migration its owning contract schedules. Alternative if rejected:
|
||
allow P1 surfaces to reuse legacy endpoints as interim backends —
|
||
rejected by the audit's finding that they cannot satisfy the
|
||
hierarchy/kanban/RBAC contracts, so the interim would ship
|
||
non-conformant semantics.
|