{"slug":"architecture/GOVERNED_EXECUTION_RUNTIME","title":"Governed Execution Runtime","section":"architecture","sectionLabel":"Architecture","status":"unclassified","type":"document","path":"architecture/GOVERNED_EXECUTION_RUNTIME.mdx","bytes":13314,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\nThe single runtime contract the platform is built around:\n\n```text\nIntent → Capability → Tool Capability → Connection → Governance → Approval\n       → Hermes → Provider → Reconciliation → Promotion → Spine → Projection\n```\n\nThis document records what is enforced in code today, where each rule lives, and\nwhat is not yet proven. It is an engineering record, not a plan.\n\n---\n\n## 1. Where the contract lives\n\n`packages/capability` (`@integratewise/capability`) is the canonical fabric. It\nis dependency-free — no provider SDK, no HTTP client, no storage driver — so\nevery service on the chain can import it without dragging provider logic across\na boundary.\n\n| Concern                                                             | Module                  |\n| ------------------------------------------------------------------- | ----------------------- |\n| Semantic / tool capability, connection, actor contracts             | `src/contracts.ts`      |\n| Registry and deterministic resolution                               | `src/registry.ts`       |\n| Immutable, content-hashed execution plans                           | `src/execution-plan.ts` |\n| The one Governance decision engine                                  | `src/governance.ts`     |\n| Signed, single-use approval tokens                                  | `src/approval.ts`       |\n| The Hermes authority check                                          | `src/authorization.ts`  |\n| Provider reconciliation                                             | `src/reconciliation.ts` |\n| Promotion envelope + projection invalidation keys                   | `src/promotion.ts`      |\n| Governed execution runtime (Hermes body)                            | `src/execution.ts`      |\n| D1-backed authority, replay, idempotency, connection, policy stores | `src/d1-stores.ts`      |\n| Runtime result states                                               | `src/runtime-result.ts` |\n| Seed catalogue (`email.send` → `gmail.email.send@2`, …)             | `src/catalog.ts`        |\n\nServices own the transport, never the rules:\n\n| Service                      | Role                                                                     |\n| ---------------------------- | ------------------------------------------------------------------------ |\n| `services/govern`            | Resolve → plan → decide; issue approval tokens; own the authority record |\n| `services/hermes`            | Verify authority, dispatch, reconcile, emit a promotion envelope         |\n| `services/connector`         | The only component holding provider credentials and protocols            |\n| `services/pipeline`          | The only component that promotes an outcome into canonical Spine truth   |\n| `services/mcp-connector`     | Public semantic facade; decides nothing                                  |\n| `packages/projection-engine` | Projects governance _state_ for display; authorizes nothing              |\n\n---\n\n## 2. The chain, step by step\n\n### Intent → Capability → Tool Capability → Connection\n\nA caller names a **semantic capability** (`email.send`) and never a provider.\n`FabricCapabilityResolver` binds it to a **tool capability**\n(`gmail.email.send@2`) through a **tenant-owned connection**, preferring the\nlowest risk class and then the highest version, so resolution is deterministic.\n\nResolution fails — explicitly, never silently — when the capability is unknown,\nevery tool capability is disabled, the tenant owns no matching connection, the\nconnection is not healthy, or the connection does not grant the scopes the tool\ncapability requires.\n\nA connector definition is not a connection. `tenant_connections` holds the\nnon-secret binding state resolution needs; credentials stay in the connector\nservice's vault.\n\n### Execution plan\n\n`createExecutionPlan` freezes the plan and stamps a SHA-256 hash over every\nfield. Callers supply only a _draft_ of each expected effect (description,\noptional target and assertions); the effect's identity — kind, operation, target\ntype — is stamped from the tool capability's `effectSignature`. That is what\nmakes reconciliation possible: the effects a plan declares and the effects the\nconnector observes come from one source.\n\n### Governance\n\n`evaluate()` returns exactly one of `allowed | approval_required | blocked`,\nwith sorted reason codes, from: actor, tenant, workspace, resolved capability,\ntool capability, connection, plan risk and reversibility, and the policy\nsnapshot. It is deterministic — same inputs, same decision, same decision id.\n\n- **blocked** on any binding mismatch, blocked capability, disabled tool\n  capability, unhealthy connection, missing scopes, missing actor permission,\n  or a risk class the tenant forbids outright.\n- **approval_required** for every mutation, and always when the actor is not\n  human — Twin Law.\n- **allowed** only when every declared effect is a read.\n\nNo other component reinterprets policy. `/v1/check` is retained for callers\nthat ask \"would this be permitted?\", and stamps `authoritative: false` and\n`requires_execution_plan: true` on its answer so it cannot be mistaken for one.\n\n### Approval\n\nAn approval token is a signed, single-use, expiring statement that a **human\nwith an approver role** approved one specific plan under one specific decision.\nIt is bound to the plan hash, so editing a plan after approval invalidates it,\nand it can never outlive the decision it rests on.\n\n### Hermes\n\n`POST /execute` accepts one payload: an `AuthorizedExecutionCommand`. Before any\nprovider is contacted, `verifyAuthorizedCommand` checks tenant, workspace and\nactor match; plan integrity (hash recomputed); decision validity and expiry;\ncapability, tool-capability and connection match; that the command's input and\nidempotency key are identical to the plan's; the approval token when the\ndecision required one; and the replay and idempotency state. Any failure throws\n— there is no warn-and-continue branch.\n\nHermes holds no private copy of the authority record: plans, decisions, replay\nand idempotency all live in Governance and are read over a trusted binding. A\nGovernance outage produces a refusal, never an assumption.\n\n### Provider\n\nHermes contains no provider-specific logic. It calls\n`/internal/capability/dispatch` on the connector with a tool capability id and a\nconnection id; the connector re-verifies the binding on its own side and takes\nthe operation from the registry, so a caller cannot widen what it may do by\nrenaming its request.\n\n### Reconciliation\n\n`/internal/capability/observe` reads provider state back. `reconcile()` compares\nobserved effects with the plan's expected effects and yields `reconciled`,\n`partially_reconciled` or `reconciliation_failed`. An HTTP 200 with nothing\nobserved is a failure, not a success. Only `reconciled` and `promoted` may be\npresented to a user as complete.\n\n### Promotion and projection invalidation\n\nHermes emits a promotion envelope carrying the full continuity chain and hands\nit to `POST /v1/promotion/execution-outcome`. The Pipeline refuses an envelope\nthat did not reconcile or whose chain is incomplete, then queues it for\ncanonical promotion and invalidates the affected projection keys. Hermes writes\nno canonical Spine state itself.\n\n---\n\n## 3. What was removed\n\nThese paths existed and are gone, because each was a way to act without\nauthority:\n\n- Hermes' direct Spine entity write (bypassed Pipeline promotion).\n- Hermes' queued execution path that returned `success: true` without executing.\n- The Durable Object's Spine execution with an approval token it never verified;\n  it now tracks reconciliation lifecycle state and executes nothing.\n- The orchestrator's `http.request` node — arbitrary HTTP with no capability, no\n  connection and no Governance — and its `spine.write` node.\n- The connector's free-form `/execute`, which named a tool and operation\n  directly, is now restricted to trusted service callers and unreachable from\n  the public edge.\n- The Projection Engine's second governance evaluation, which used a different\n  vocabulary (`denied`, `escalated`) and a permissive TODO default policy.\n\nArbitrary HTTP still exists, but only as `internal.http.request` — a registered\ninternal tool capability carrying risk class `critical`, disabled by default,\nand subject to the identical Governance contract as any provider capability.\n\n---\n\n## 4. Storage authority\n\n| Store              | Holds                                                                                            |\n| ------------------ | ------------------------------------------------------------------------------------------------ |\n| Neon PostgreSQL    | Canonical business and operational truth                                                         |\n| R2                 | Files, raw payloads, immutable evidence                                                          |\n| D1                 | Bounded operational state: authority records, idempotency, replay, connections, policy snapshots |\n| KV                 | Ephemeral hot state, caches                                                                      |\n| Vector / AI Search | Retrieval indexes                                                                                |\n\nD1 never answers a canonical read. `GET /executions/:id` returns\n`state: \"stale\"` with `source`, `store`, `cached_at` and\n`canonical_available`, so a cached read always discloses what it is.\n\nSchema: `sql-migrations/d1/013_capability_fabric_authority.sql`.\n\n---\n\n## 5. What CI enforces\n\n`pnpm run check:architecture` (strict, blocking) and\n`pnpm run test:governed-chain` (blocking) run in the `governed-chain` job of\n`.github/workflows/ci.yml`.\n\nBoundary rules R6–R12 cover: no provider SDK in the UI; no bare `fetch` in\nHermes; only the Pipeline writes canonical Spine entities; exactly 19 public MCP\ntools with no internal families leaking; no credential access in client code; no\nfabricated success in a catch handler; one definition of the governance decision\noutcome. Each rule was verified to fail against an injected violation.\n\nTest coverage across the chain (247 tests): tenant isolation, capability\nresolution, connection selection and scope gaps, governance determinism and each\noutcome, approval issuance authority, token mismatch / expiry / replay,\nidempotent execution, every Hermes refusal path, reconciliation success and\nmismatch, promotion gating, projection invalidation keys, and the end-to-end\nCustomer Zero slice.\n\n---\n\n## 6. Not yet proven\n\nHonest gaps. None of these are hidden behind a passing test.\n\n1. **No live provider execution.** The chain is proven end to end against a\n   recording adapter and a connector stub. It has not been run against real\n   Gmail or Salesforce credentials, so the loader operation contract\n   (`/internal/connections/:id/operations/:operation` and `…/records/:ref`) that\n   `services/connector/src/routes/capability.ts` calls is specified but not yet\n   implemented on the loader side. Until it is, dispatch returns\n   `provider_transport_unavailable` and reconciliation refuses to report\n   completion — the failure is explicit, not silent.\n\n2. **Governance has no isolated prod environment.**\n   `services/govern/wrangler.toml` has no `[env.prod]` section and its default\n   environment points at the _test_ D1 database. A `govern-prod` Worker with its\n   own D1, `SERVICE_SECRET` and `APPROVAL_SIGNING_SECRET` must be provisioned\n   before governed actions run in prod. `services/mcp-connector/wrangler.toml`\n   deliberately leaves `env.prod` unbound rather than pointing prod at test's\n   governance database.\n\n3. **Secrets are not set.** `SERVICE_SECRET` and `APPROVAL_SIGNING_SECRET` must\n   be set per environment with `wrangler secret put`. Without them Governance\n   refuses to issue approvals and Hermes refuses to execute — the safe failure,\n   but a non-functional one.\n\n4. **Workspace resolution on the MCP surface.** Governed action tools require a\n   workspace, taken from the Gateway-forwarded `x-workspace-id`. Where One Auth\n   does not yet resolve a workspace the tools refuse rather than inventing one.\n\n5. **Connection registration is not called on connect yet.** The connector\n   exposes `POST /internal/capability/connections` (upsert, trusted callers\n   only, refusing any connection no registered tool capability can bind) and\n   `…/connections/revoke`, and the Nango disconnect path already revokes. The\n   _connect_ path does not call the upsert: the loader's `auth.created` webhook\n   carries neither the granted scopes nor a workspace, and both are required to\n   register a connection honestly. Wiring it means reading the granted scopes\n   from the Nango connection record and resolving the workspace from One Auth;\n   until that is done, resolution reports `no_connection` rather than binding\n   something whose authority is unknown.\n\n6. **Deployment verification could not run here.**\n   `pnpm run verify:continuity` and any non-dry release require\n   `CLOUDFLARE_API_TOKEN`. The dry run\n   (`pnpm release:deploy -- --environment test --service core --dry-run`) passes\n   with the new bindings resolving to `govern-test`, adding no new Wrangler\n   warnings to the six pre-existing ones.\n"}