PACT is the release-integrity control plane for production AI agents: CAPTURE what
is running, COMPARE what changed, PROVE it behaves acceptably, CONTROL what
reaches production. Its transaction engine (preview → approval → one-shot commit
→ canonical verification → receipt) is the CONTROL subsystem that also recovers
external effects when a bad release escapes. See docs/release-integrity.md
for the implemented surface and the explicit not-built list.
PACT is an experimental trust and transaction layer for consequential agent actions. It binds a human-approved semantic plan to canonical state, commits under short-lived authority, verifies the resulting state, and emits a tamper-evident receipt. The same authority can sit behind ordinary HTTPS clients, MCP hosts, or browser WebMCP tools.
src/webmcp.js— imperative WebMCP bridge targetingdocument.modelContext, with state-dependent tools, current security annotations, registration-lifetime cleanup and structured JavaScript results.src/agent-bridge.js— shared canonical agent-tool catalog for HTTP, WebMCP and MCP surfaces.src/http.js— reusable HTTPS connector for the canonical PACT/api/pactauthority endpoint. Commit fails closed without an idempotency key; caller cancellation and connector deadlines are distinct errors.src/adapter.js— executable adapter contract and defensive declarative-plan validator.src/api-authority.js— canonical durable server authority implementingpreview, authenticatedapprove, one-shotcommit,verify,receipt, andinspect.src/durable-state.js— journaled durable transaction state with persistent replay records, CAS transitions and crash-recovery validation.src/canonical-store.js— durable internal canonical application-state repository with atomic version CAS and exact replay snapshots.src/rest-resource.js— real REST-provider canonical bridge. It binds PACT state to providerETagrevisions, commits withIf-MatchplusIdempotency-Key, detects out-of-band provider drift, and supports exact lost-response recovery when the real provider state can be proven.src/authority.js— short-lived single-use commit capability bound to transaction, plan, canonical version and verified identity claims.src/server-approval.js— HMAC-SHA256 approval verifier binding claims to transaction ID, plan hash, base version, adapter, principal, agent session, nonce and expiry.src/redis-store.js— Redis-compatible HTTPS REST atomic store using create-if-absent and Lua compare-and-swap.src/server-runtime.js— production composition layer. It supports the built-in generic canonical document and an officialrest-jsonmode for real JSON REST resources.api/pact.js— Vercel Function entrypoint. It fails closed when durable storage, approval secret or exact release provenance are unavailable.src/playground.js+/workspace/— canonical HTTP playground showing request, plan, approval, commit, verification, receipt, errors and durable recovery by transaction ID.pact-manifest.json+schema/pact-manifest.schema.json— machine-readable product, WebMCP and agent-bridge contract checked against its schema by CI.src/provenance.js+scripts/build.mjs— deterministic release provenance and integrity hashing.src/release-lock.js+schema/pact-lock.schema.json— immutable content-hashpact.lockrelease identity (CAPTURE).src/release-discover.js— real discovery: git, package inventory, MCP handshakes, model metadata.src/trace-corpus.js— normalized execution corpus with OTel mapping and redaction.src/replay.js— side-effect-safe replay, decision compatibility, empirical PROVE reports.src/release-bisect.js+src/release-canary.js— regression isolation and canary evaluation.src/release-diff.js— structural release diff with deterministic severities (COMPARE).src/release-registry.js— CAS-backed immutable lock registry with pin/get/history.src/release-drift.js— pinned-vs-observed drift evaluation for undeployed change.src/release-gate.js— deterministic ALLOW/WARN/BLOCK release gate under explicit policy.src/release-attribution.js— exact changed-dependency attribution without probabilities.scripts/pact-release.mjs(npm run release) —capture/discover/diff/drift/gateCLI for CI.
PACT therefore contains a real server-side transaction plane rather than only a browser simulation. The default generic runtime remains useful for the playground and integration testing. For real systems, use a domain adapter and canonical bridge; the shipped rest-json mode is the first production-oriented bridge for JSON REST resources.
PREVIEWED
-> APPROVED
-> COMMIT_AUTHORIZED
-> COMMITTED
-> VERIFIED
preview creates the exact semantic plan against a canonical base version. approve accepts only an authenticated approval claim and issues transaction-bound single-use commit authority. commit requires an idempotency key and writes canonical state. verify checks the resulting real state against the approved plan. receipt returns the verified durable receipt. inspect supports recovery after client or server interruption.
A crash after canonical write but before transaction-journal completion is explicitly recoverable when PACT can prove the observed state matches the authorized transaction. Concurrent retries with the same commit key converge on one durable authorization path; competing base-version writers permit one winner.
The official /api/pact runtime can bind a transaction directly to a real JSON REST resource:
PACT_RUNTIME_MODE=rest-json
PACT_REST_BASE_URL=https://api.example.com
PACT_REST_RESOURCE_PATH=/v1/accounts/42
PACT_REST_RESOURCE_KEY=provider:account-42
PACT_REST_ADAPTER_ID=provider.account
PACT_REST_ADAPTER_VERSION=1.0.0 # optional
PACT_REST_METHOD=PUT # PUT or PATCH; optional
PACT_REST_BEARER_TOKEN=... # optional, server-only
The provider must return a representation-specific ETag on successful reads and writes. PACT records that revision and sends the consequential write with If-Match; a provider change outside PACT makes an already-approved plan stale before mutation. The internal consumed authorization ID is sent as Idempotency-Key.
A network failure after a provider may have applied the write is treated as PACT_REST_COMMIT_UNCERTAIN, not silently retried. A later read/retry can recover only when the provider's new ETag and JSON object exactly match the intended result. PACT does not claim universal exactly-once behavior if a third-party provider ignores conditional writes or idempotency.
Provider credentials stay server-side. The REST bridge rejects insecure remote HTTP origins, cross-origin resource configuration, missing ETags, ETag reuse for a different representation, stale conditional writes, and mismatched provider postconditions.
See docs/rest-provider.md for the integration contract.
/— product thesis and product boundary/demo/— guided reference transaction/workspace/— canonical/api/pactplayground with recovery/how-it-works/— protocol lifecycle/security/— threat model and enforced invariants/developers/— SDK, real-provider, HTTP, WebMCP and agent integration guidance/pact-manifest.json— machine-readable compatibility manifest/schema/pact-manifest.schema.json— product manifest schema/schema/pact-adapter.schema.json— adapter plan schema/sdk/runtime.js— adapter-driven runtime/sdk/api-authority.js— canonical server authority/sdk/http-handler.js— canonical HTTP handler/sdk/server-runtime.js— server runtime composition/sdk/rest-resource.js— real REST provider canonical bridge and JSON-resource adapter/sdk/server-approval.js— authenticated approval verifier/sdk/durable-state.js— durable transaction/journal state/sdk/canonical-store.js— internal canonical state repository/sdk/authority.js— one-shot authority primitive/sdk/redis-store.js— Redis-compatible atomic store/sdk/agent-bridge.js— canonical HTTP/WebMCP/MCP shared tool bridge/sdk/provenance.js— release provenance resolver/docs/rest-provider.md— real provider integration guide/release-provenance.json— generated source provenance for the built artifact
src/agent-bridge.js exposes the same six canonical operations through HTTP-backed WebMCP and MCP integrations:
inspect
preview
approve
commit
verify
receipt
The agent bridge intentionally does not invent rollback or cancel operations that the canonical server does not implement. commit is the only consequential operation in this surface and requires an idempotency key. WebMCP provider/API output is marked untrusted by default. MCP transport/framing remains owned by the MCP host/SDK rather than reimplemented by PACT.
PACT targets the experimental imperative WebMCP API at document.modelContext.registerTool(). Tool definitions use explicit names, titles, descriptions, closed JSON input schemas and the annotation fields readOnlyHint and untrustedContentHint.
The current ToolExecuteCallback receives a single input object. Registration lifetime is controlled by the AbortSignal in ModelContextRegisterToolOptions; aborting that registration signal unregisters the tool. The current draft does not define a second per-execution abort-signal argument. HTTP and MCP surfaces retain their own cancellation mechanisms.
PACT does not emit a consequentialHint field. Consequential-action protection is enforced by PACT's transaction and authority layer rather than represented as a WebMCP guarantee. Imperative callbacks return normal JavaScript values for the user agent to serialize.
WebMCP remains experimental and subject to change. Recheck the live Community Group draft before production adoption.
import { definePactAdapter } from './src/adapter.js';
const adapter = definePactAdapter({
id: 'projects.v1',
version: '1.0.0',
describe() {
return { name: 'Project ownership', operations: ['transfer_owner'] };
},
async plan({ intent, state }) {
return {
effects: [{
path: `projects.${intent.projectId}.owner`,
before: state.projects[intent.projectId].owner,
after: intent.newOwner
}],
invariants: [{ path: 'billing.plan', equals: state.billing.plan }]
};
},
async verify({ state, plan }) {
return plan.effects.every(effect =>
effect.path.split('.').reduce((node, key) => node?.[key], state) === effect.after
);
}
});The validator rejects prototype-related paths, duplicate effect paths, non-JSON values and unbounded effect/invariant sets before a plan can be accepted.
For generic JSON REST resources, createPactJsonResourceAdapter() provides a safe path-replacement adapter over resource.*. Domain-specific systems should use their own adapter when invariants, commands, partial updates, side effects or verification need richer semantics.
import { createPactHttpConnector } from './src/http.js';
const pact = createPactHttpConnector({ baseUrl: 'https://your-app.example' });
const request = new AbortController();
const preview = await pact.preview({
adapter: { id: 'provider.account', version: '1.0.0' },
intent: { path: ['account', 'owner'], value: 'maya' }
}, { signal: request.signal });
const transactionId = preview.transaction.id;
const approved = await pact.approve({
transactionId,
approval: signedApprovalClaim
}, { signal: request.signal });
await pact.commit(
{ transactionId, capabilityToken: approved.capability.token },
`commit:${transactionId}`,
{ signal: request.signal }
);
const verified = await pact.verify({ transactionId }, { signal: request.signal });
const receipt = await pact.receipt({ transactionId }, { signal: request.signal });The canonical HTTP surface is exactly inspect, preview, approve, commit, verify, and receipt. The connector refuses insecure remote HTTP origins; plain HTTP is accepted only for localhost development. commit requires an explicit idempotency key. Caller cancellation raises PACT_HTTP_ABORTED; the connector deadline raises PACT_HTTP_TIMEOUT.
Real-provider errors are intentionally classifiable by agents and clients: stale provider state maps to conflict semantics, uncertain provider commit is surfaced separately, and upstream/provider failures are not collapsed into an opaque successful response. Provider response bodies and unexpected internal exception messages are not copied into protocol errors.
Every production mode requires:
UPSTASH_REDIS_REST_URL HTTPS Redis REST endpoint
UPSTASH_REDIS_REST_TOKEN Redis REST bearer token
PACT_APPROVAL_SECRET strong server-only approval HMAC secret
VERCEL_GIT_COMMIT_SHA exact 40-hex source SHA from a Git-linked deployment
PACT_SOURCE_COMMIT and GITHUB_SHA are also recognized provenance sources. If multiple provenance sources are present, all must resolve to the same SHA or the build/runtime fails closed.
PACT_RUNTIME_MODE=generic is the default. PACT_RUNTIME_MODE=rest-json activates the real provider configuration shown above. Unknown modes or incomplete provider configuration fail closed.
vercel.json runs npm run build, publishes dist, and retains api/pact.js as the serverless Function. Do not accept a locally copied artifact without an exact source SHA. A production release should be accepted only when live /release-provenance.json and the x-pact-release API header match the intended Git commit and the real transaction smoke gate succeeds.
The verification suite covers, among other cases:
- exact plan/canonical-version binding
- authenticated approval claims
- transaction/plan/version/identity-bound one-shot capabilities
- persistent idempotency and exact replay
- same-key/different-payload replay rejection
- canonical CAS and single-winner concurrency
- crash recovery after canonical write before journal completion
- real provider ETag revision binding and
If-Matchconditional writes - out-of-band provider drift invalidation
- provider
Idempotency-Keypropagation - lost provider response recovery without a second write when state can be proven
- prototype-pollution path rejection in the JSON-resource adapter
- approval expiry and malformed/forged approval rejection
- corrupt/non-monotonic durable-record rejection
- receipt and audit integrity
- HTTP method/media-type/error/header behavior
- HTTPS-only connector/provider behavior
- HTTP/MCP cancellation vs timeout distinction
- current imperative WebMCP registration and single-input execution contract
- canonical HTTP/WebMCP/MCP operation-surface parity
- generic playground durable recovery by transaction ID
- manifest/schema self-consistency
- deterministic provenance hashing and provenance-conflict rejection
- Vercel
dist+/api/pactrelease contract
These tests establish checked-in behavior; they are not a substitute for live verification of the configured Redis provider, third-party provider semantics, secret management, deployment identity, network behavior or operational limits.
npm run verifyThe release gate runs the Node test suite, JavaScript syntax checks, deterministic production build, release contract assertions and generated bundle syntax validation.