Skip to main content
Glama
vassiliylakhonin

io.github.vassiliylakhonin/vizier-guard

Vizier

Deterministic Authorization & Non-Repudiation Audit Firewall for AI Agents.

CI Deploy Python 3.9+ npm @vizier/sdk npm @vizier/mcp-proxy MCP Registry License: MIT

Vizier is an ultra-fast, edge-native deterministic authorization and audit firewall for action-taking AI agents. Before an agent executes an external side effect (making a payment, executing code, modifying a database, dispatching messages, or deploying infrastructure), it submits the proposed action to Vizier.

⚔ Try the Live Interactive Playground: https://vizier.vassiliy-lakhonin.workers.dev/playground
Test policy presets (ALLOW, BLOCK_AMOUNT, BLOCK_TARGET, SENSITIVE), inspect sub-25ms edge latency, and verify SHA-256 non-repudiation audit receipts in real time directly from your browser.


šŸ›ļø Architecture

flowchart TD
    subgraph Agents["AI Agent Runtimes"]
        A1["Python Agent (LangChain / CrewAI / AutoGen)"]
        A2["MCP Client (Claude / Cursor / Tools)"]
        A3["TypeScript / Node.js Agent"]
    end

    subgraph Guards["Vizier Enforcement Boundary"]
        G1["@vizier_guard / Python SDK"]
        G2["@vizier/mcp-proxy CLI"]
        G3["@vizier/sdk (TypeScript)"]
    end

    subgraph Kernel["Cloudflare Workers Global Edge"]
        K["Vizier Deterministic Kernel (/v1/verify)"]
        P["Policy Engine: Limits, Targets, Roles, Grants"]
        D1["D1 Audit Ledger & Cryptographic Receipts"]
    end

    subgraph Targets["Protected External Side-Effects"]
        T1["Payment / Financial APIs"]
        T2["Database Writes & Deletions"]
        T3["Worker / Infrastructure Deployments"]
        T4["External Message Dispatch"]
    end

    A1 --> G1
    A2 --> G2
    A3 --> G3

    G1 -->|"POST /v1/verify"| K
    G2 -->|"POST /v1/verify"| K
    G3 -->|"POST /v1/verify"| K

    K --> P
    P --> D1

    G1 -.->|"Decision: ALLOW"| T1
    G2 -.->|"Decision: ALLOW"| T2
    G3 -.->|"Decision: ALLOW"| T3

    P -.->|"Decision: BLOCK / REVIEW"| G1
    P -.->|"Decision: BLOCK / REVIEW"| G2
    P -.->|"Decision: BLOCK / REVIEW"| G3

The decision path is strictly deterministic — no non-deterministic LLMs in the critical decision loop. It checks delegated actions, principal identity, amount limits, targets, sensitive operations, and authenticated integration boundaries. Every response includes policy results and a tamper-proof SHA-256 canonical receipt hash.

Status: experimental v0.3.0, deployed on Cloudflare Workers edge. Since v0.3.0, authority can be proved rather than asserted: a principal signs a delegation grant, Vizier verifies it against a registered public key, and the receipt records authority provenance. Read the threat model before placing this service in an execution path.


Related MCP server: evav-gateway

🌐 Public Surfaces


šŸš€ Quickstarts

1. Python SDK (vizier-guard)

Zero external dependencies (Python standard library only):

pip install vizier-guard
from vizier import VizierClient, vizier_guard

client = VizierClient(
    base_url="https://vizier.vassiliy-lakhonin.workers.dev",
    api_key="your-api-key"
)

# Protect any function or tool:
@vizier_guard(
    client=client,
    action_type="purchase",
    max_amount=500.0,
    currency="USD",
    allowed_targets=["supplier.example"]
)
def execute_order(amount: float, target: str):
    # Runs ONLY if Vizier decision is ALLOW
    return {"status": "success", "amount": amount}

execute_order(amount=450.0, target="supplier.example")   # Allowed
execute_order(amount=1200.0, target="supplier.example")  # Raises ActionBlockedError

LangChain / LangGraph & CrewAI:

from vizier.integrations.langchain import VizierLangChainToolGuard
from vizier.integrations.crewai import VizierCrewAIToolGuard

# LangChain / LangGraph
safe_tool = VizierLangChainToolGuard(
    tool=my_search_tool,
    client=client,
    allowed_actions=["search"],
    max_amount=0.0
)

# CrewAI
safe_crew_tool = VizierCrewAIToolGuard(
    tool=my_payment_tool,
    client=client,
    max_amount=250.0
)

Human-in-the-Loop (Telegram / CLI / Webhooks) & Async:

from vizier import AsyncVizierClient, vizier_guard, TelegramHITLHandler

# Interactive approval buttons via Telegram Bot when decision is REVIEW
telegram_approver = TelegramHITLHandler(
    bot_token=os.environ["TELEGRAM_BOT_TOKEN"],
    chat_id=os.environ["TELEGRAM_CHAT_ID"]
)

@vizier_guard(
    client=AsyncVizierClient(),
    action_type="transfer_funds",
    hitl_handler=telegram_approver
)
async def transfer(amount: float, target: str):
    # Executes ONLY if human operator clicks [Approve] in Telegram
    return await bank_api.send(amount, target)

MCP Server for Claude Desktop & Cursor:

Equip Claude Desktop or Cursor with deterministic guardrails (vizier_screen_action, vizier_verify_receipt, vizier_check_policy):

{
  "mcpServers": {
    "vizier": {
      "command": "uvx",
      "args": ["vizier-guard", "mcp"],
      "env": {
        "VIZIER_BASE_URL": "https://vizier.vassiliy-lakhonin.workers.dev",
        "VIZIER_API_KEY": "your-vizier-api-key"
      }
    }
  }
}

2. MCP Enforcement Proxy CLI

Wrap any local or remote MCP server with deterministic authorization:

npx @vizier/mcp-proxy \
  --upstream http://localhost:3000/mcp \
  --tools "query_db,execute_command,fetch_api" \
  --vizier https://vizier.vassiliy-lakhonin.workers.dev \
  --api-key $VIZIER_API_KEY

3. TypeScript SDK (@vizier/sdk)

npm install @vizier/sdk
import { Vizier } from "@vizier/sdk";

const vizier = new Vizier({
  baseUrl: "https://vizier.vassiliy-lakhonin.workers.dev",
  apiKey: process.env.VIZIER_API_KEY,
});

const decision = await vizier.verify({
  agent: { id: "agent-01", owner: "acme-corp" },
  principal: { id: "acme-corp" },
  action: {
    type: "purchase",
    target: "supplier.example",
    parameters: { amount: 820, currency: "USD" }
  },
  authority: {
    allowed_actions: ["purchase"],
    constraints: { max_amount: 1000, currency: "USD" }
  },
  context: { source: "rest" }
});

if (decision.decision === "ALLOW") {
  // Execute protected operation
}

4. Direct HTTP / cURL

curl -sS https://vizier.vassiliy-lakhonin.workers.dev/v1/verify \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_KEY' \
  -d '{
    "agent": { "id": "agent-01", "owner": "acme" },
    "principal": { "id": "acme" },
    "action": {
      "type": "purchase",
      "target": "supplier.example",
      "parameters": { "amount": 820, "currency": "USD" }
    },
    "authority": {
      "allowed_actions": ["purchase"],
      "constraints": { "max_amount": 1000, "currency": "USD" }
    },
    "context": { "source": "rest" }
  }'

šŸ›‘ Agent Circuit Breaker & Loop Killer

Infinite tool loops and runaway retry storms are among the most catastrophic failure modes of autonomous agents — in minutes, an agent stuck in a loop can exhaust external API rate limits, burn through thousands of dollars in LLM tokens, or flood production databases.

Vizier provides built-in circuit breakers across both Python and MCP environments:

  • Sliding-Window Loop Detection: Computes deterministic SHA-256 canonical JSON hashes of tool arguments. If the same tool is invoked repeatedly within a sliding window (e.g. 3 times in 30 seconds), the circuit trips immediately (CIRCUIT_TRIPPED:LOOP_DETECTED).

  • Session Action Budgets: Caps the total number of actions an agent can execute within a single task or session (CIRCUIT_TRIPPED:BUDGET_EXCEEDED).

  • Python Guard Decorator:

    from vizier import CircuitBreaker, vizier_guard
    
    breaker = CircuitBreaker(max_repeated_calls=3, time_window_seconds=30.0, max_session_actions=25)
    
    @vizier_guard(action_type="query_db", circuit_breaker=breaker)
    def query_database(query: str):
        return db.execute(query)
  • MCP Enforcement Proxy:

    const proxy = createMcpEnforcementProxy({
      // ...
      circuitBreaker: { maxRepeats: 3, windowMs: 30_000 },
    });

    Returns standardized JSON-RPC 2.0 error -32028 on tripped loops without invoking the upstream tool.


Proving the authority instead of asserting it

By default the authority in a request is whatever the calling application says it is. Vizier checks the action against it faithfully and signs the result — but the receipt then attests to a decision, not to a delegation.

A delegation grant closes that gap. The principal signs a compact JWS that binds one authority to one agent for a bounded window, the agent sends it as a grant field, and Vizier verifies it against a public key registered for that principal:

# once, on the principal's machine
node scripts/mint-grant.mjs keygen --kid acme-2026-09 --out principal.jwk.json

# per delegation
node scripts/mint-grant.mjs sign --key principal.jwk.json --grant grant.json --ttl 3600

The public half is registered as VIZIER_PRINCIPAL_KEYS; the private half never leaves the principal, and no endpoint would accept it. A verified grant makes the receipt say so:

{
  "authority_provenance": "principal_signed",
  "grant": {
    "jti": "grant_5f1c…",
    "issuer": "acme-corp",
    "subject": "procurement-agent-01",
    "key_id": "acme-2026-09",
    "expires_at": "2026-09-07T16:00:00.000Z"
  }
}

Two properties are worth stating plainly:

  • A grant that does not verify is BLOCK, never a quiet fall back to the caller-asserted path. Failing it open would make a forged grant strictly better for an attacker than sending none.

  • The request's authority must match the signed one exactly. A genuine grant carried beside an enlarged authority is BLOCK, not an allow at the larger limit.

Keys are registered out of band and never fetched at decision time, so the authorization kernel still makes no outbound request. Full contract, reason codes and limits: docs/DELEGATION_GRANTS.md.

API

POST /v1/verify accepts one proposed action and its delegated authority. Malformed requests return a structured error and never produce ALLOW. JSON bodies are capped at 1 MiB, 64 levels, and 50,000 aggregate values before recursive schema validation. When VIZIER_API_KEY is absent, the service is in evaluation mode: valid requests can return REVIEW or BLOCK, never ALLOW. When the secret is configured, REST and MCP verification calls require Authorization: Bearer <key>. A2A also accepts an anonymous evaluation call for discovery and conformance checks, but that call can return only REVIEW or BLOCK.

{
  "agent": { "id": "procurement-agent-01", "owner": "acme-corp" },
  "principal": { "id": "acme-corp" },
  "action": {
    "type": "purchase",
    "target": "supplier.example",
    "parameters": { "amount": 8200, "currency": "USD" }
  },
  "authority": {
    "allowed_actions": ["purchase"],
    "constraints": { "max_amount": 10000, "currency": "USD" }
  },
  "context": {
    "request_id": "order-1842",
    "timestamp": null,
    "source": "rest"
  }
}

principal must be present. Set it to null when the principal is unknown; Vizier returns REVIEW. Omitting the field is a validation error.

Decision priority is BLOCK, then REVIEW, then ALLOW. The numeric risk score explains accumulated risk but does not override policy results.

Action Covenant lifecycle

The v0.3.0 resources are additive; /v1/verify remains compatible.

  1. POST /v1/covenants accepts a strict ActionCovenantDraft plus a principal acceptance bound to the draft hash. A model may produce the draft, but it cannot activate it by naming itself as the principal.

  2. POST /v1/authorizations checks covenant integrity and expiry, exact action equality, evidence presence and freshness, shallow exact-match invalidation signals, and the existing delegated-authority policies. It returns a compact ES256 authorization JWS for every decision.

  3. The executor acts only on ALLOW before the receipt expires.

  4. POST /v1/outcomes verifies the authorization receipt, binds the reported execution outcome, checks exact forbidden-effect rules, and returns a compact ES256 outcome JWS.

All three resources require authenticated enforcement and RECEIPT_SIGNING_KEY; there is no evaluation-only activation path. Covenants remain caller-held immutable envelopes in this milestone. Vizier stores bounded operational metadata and hashes asynchronously, but not full action parameters, evidence, signals, outcome effects, JWS tokens, or signing material. It does not retrieve evidence independently.

Integration rule

Call Vizier immediately before the external action. Treat timeout, invalid JSON, REVIEW, and BLOCK as stop conditions.

const decision = await vizier.verify(proposedAction);

if (decision.decision === "ALLOW") {
  await executeAction();
}

The thin TypeScript client lives in packages/sdk:

import { Vizier } from "@vizier/sdk";

const vizier = new Vizier({
  baseUrl: "https://vizier.vassiliy-lakhonin.workers.dev",
  apiKey: process.env.VIZIER_API_KEY,
});
const decision = await vizier.verify(request);

Python SDK (vizier-guard)

The Python SDK lives in packages/python-sdk with zero external dependencies:

from vizier import VizierClient, vizier_guard

client = VizierClient(
    base_url="https://vizier.vassiliy-lakhonin.workers.dev",
    api_key=os.environ["VIZIER_API_KEY"],
)

# Protect any function / agent tool:
@vizier_guard(client=client, action_type="purchase", max_amount=1000.0, currency="USD")
def execute_order(amount: float, target: str):
    return {"status": "success", "amount": amount}

Or protect LangChain / LangGraph tools:

from vizier.integrations.langchain import VizierLangChainToolGuard

guarded_tool = VizierLangChainToolGuard(
    tool=my_search_or_db_tool,
    client=client,
    allowed_actions=["query_db"],
)

MCP Enforcement Proxy

Protect any existing local or remote MCP server with deterministic policy checks:

npx @vizier/mcp-proxy \
  --upstream http://localhost:3000/mcp \
  --tools "query_db,transfer_funds,send_message" \
  --vizier https://vizier.vassiliy-lakhonin.workers.dev \
  --api-key $VIZIER_API_KEY

The API key belongs only in a controlled backend or orchestrator. Do not expose it to the action-taking agent. This key authenticates the integration; it does not prove that each supplied delegation was issued by the principal.

Policy rules

Rule

Result

No authenticated integration credential is configured

REVIEW / AUTHORITY_SOURCE_UNTRUSTED

Action is absent from allowed_actions

BLOCK / ACTION_NOT_DELEGATED

Principal is null

REVIEW / PRINCIPAL_UNVERIFIED

Amount exceeds max_amount

BLOCK / AUTHORITY_LIMIT_EXCEEDED

Amount or currency cannot be checked

REVIEW

Target is blocked or absent from an allowlist

BLOCK

Sensitive action lacks explicit sensitive authority

REVIEW / SENSITIVE_ACTION_REVIEW

Authority requires reversibility and the action is not declared reversible

REVIEW / IRREVERSIBLE_ACTION_REVIEW

The default sensitive actions are transfer_funds, delete_data, deploy_worker, execute_code, send_external_message, modify_permissions, and sign_contract.

action.is_reversible is an integration-supplied assertion, not an independently verified property. require_review_for_irreversible fails to REVIEW when that assertion is absent or false; it cannot prove a true assertion is accurate.

Protocol endpoints

  • GET /openapi.json and GET /.well-known/openapi.json return the same OpenAPI 3.1 contract for /v1/verify, /v1/covenants, /v1/authorizations, /v1/outcomes, and the authenticated /v1/insights. Request schemas are emitted from the same Zod definitions used at the runtime boundary.

  • GET /.well-known/ai-catalog.json routes machines to the A2A Agent Card, the OpenAPI contract, and the MCP server manifest.

  • GET /.well-known/agent-card.json returns an A2A v1.0 Agent Card with a canonical ES256 JWS in signatures[] when AGENT_CARD_SIGNING_KEY is configured.

  • GET /.well-known/jwks.json returns the matching public key. The JWS protected header points to this endpoint through a same-origin jku.

  • POST /a2a implements the A2A v1.0 JSON-RPC SendMessage method. Anonymous requests run only in evaluation mode; a wrong supplied credential is rejected.

  • POST /mcp implements MCP 2026-07-28 with server/discover, tools/list, and tools/call for vizier_verify_action. The same endpoint also answers the session handshake used by shipping clients: initialize, notifications/initialized, ping, tools/list, and tools/call over 2025-06-18, 2025-03-26, or 2024-11-05. The request body selects the profile: only 2026-07-28 carries its protocol version in params._meta.

  • GET /.well-known/mcp.json returns the MCP server manifest, the same document published to the MCP Registry from server.json at the repository root.

The session profile exists because no off-the-shelf client speaks the stateless profile yet. Measured 2026-09-02 against the deployed Worker: a standard initialize was rejected with -32600, so the endpoint could not be connected from any MCP client. The stateless contract is unchanged; the session profile is additive and shares one verification path.

MCP Enforcement Proxy (@vizier/mcp-proxy)

packages/mcp-proxy is a standalone reverse proxy adapter that places any existing MCP server behind Vizier. The proxy:

  • exposes only the configured upstream tool names;

  • authenticates every MCP request with a proxy-specific Bearer token;

  • maps the exact tool name and arguments to one mcp_tool_call verification;

  • forwards the unchanged MCP request only after a verified ALLOW;

  • stops on REVIEW, BLOCK, timeout, invalid Vizier output, or upstream error;

  • replaces the incoming credential with a separate upstream credential; and

  • logs integration ID, request ID, tool name, decision, receipt ID, outcome, and latency without logging arguments or secrets.

Run directly via npx:

npx @vizier/mcp-proxy \
  --upstream http://127.0.0.1:8791/mcp \
  --tools "write_file,query_db" \
  --vizier https://vizier.vassiliy-lakhonin.workers.dev \
  --api-key $VIZIER_API_KEY

Or configure via environment variables:

export VIZIER_BASE_URL="http://127.0.0.1:8787"
export VIZIER_API_KEY="local-development-key"
export VIZIER_PROXY_INTEGRATION_ID="pilot-acme"
export VIZIER_PROXY_CLIENT_TOKEN="replace-with-a-random-client-token"
export VIZIER_PROXY_AGENT_ID="coding-agent-01"
export VIZIER_PROXY_AGENT_OWNER="acme"
export VIZIER_PROXY_PRINCIPAL_ID="platform-team"
export VIZIER_PROXY_UPSTREAM_ID="filesystem"
export VIZIER_PROXY_UPSTREAM_URL="http://127.0.0.1:8791/mcp"
export VIZIER_PROXY_UPSTREAM_BEARER_TOKEN="replace-with-upstream-token"
export VIZIER_PROXY_ALLOWED_TOOLS="write_file"
npm exec --workspace @vizier/mcp-proxy -- vizier-mcp-proxy

Point the pilot MCP client at http://127.0.0.1:8790/mcp, use VIZIER_PROXY_CLIENT_TOKEN as its Bearer credential, and remove its direct access to the upstream URL and credential. The proxy is not an enforcement boundary if the agent can still reach the upstream server, read either backend credential, or use a shell with equivalent authority.

Connect an MCP client

The credential is optional at connect time. An anonymous tools/call runs in evaluation mode: the decision is real but the supplied authority is untrusted, so it can never return ALLOW. The credential unlocks enforcement results, and a credential that is supplied and wrong is rejected with -32001.

Anonymous calls share a budget of 60 requests per minute per client IP. Past it the endpoint answers 429 with JSON-RPC error -32029 and a Retry-After header. Attaching a wrong credential does not leave that budget; a valid one does.

An anonymous call leaves no receipt, so the only record of it is a counter: one row per UTC day per surface per outcome, bumped in place. It holds no client IP, no arguments, and nothing else about the caller, and it is swept by the same 30-day retention as the rest of the audit store. GET /v1/insights reads it back. Counts are best-effort instrumentation, not proof of adoption, and each deploy adds exactly four to mcp / served: the live check below probes the credential-free path on purpose.

claude mcp add --transport http vizier \
  https://vizier.vassiliy-lakhonin.workers.dev/mcp

Add the header once you hold a credential:

claude mcp add --transport http vizier \
  https://vizier.vassiliy-lakhonin.workers.dev/mcp \
  --header "Authorization: Bearer <integration-credential>"

Any client that accepts a Streamable HTTP URL works the same way. Verify the handshake without a client:

curl -sS https://vizier.vassiliy-lakhonin.workers.dev/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'

Registry listing

server.json at the repository root is the MCP Registry entry for io.github.vassiliylakhonin/vizier, published on 2026-09-02 and validated against the 2025-12-11 server schema. It carries no repository block: the source repository is private, and an entry pointing at a URL that answers 404 is worse than no link at all. The namespace is claimed through the GitHub account, not the repository.

The deploy workflow republishes it. scripts/publish-registry.mjs compares server.json against the live entry and publishes only when the registry lacks that version, authenticating through GitHub Actions OIDC so no registry token is stored anywhere. The registry keys an entry on its version, so a manifest edit rides along with a version bump; an edit without one is reported and skipped rather than rejected by the registry.

Check the decision without making it, using an existing mcp-publisher login github session:

node scripts/publish-registry.mjs --dry-run

Publishing by hand still works and takes the same path:

mcp-publisher login github
node scripts/publish-registry.mjs

Read the live entry back:

curl -sS "https://registry.modelcontextprotocol.io/v0/servers?search=vizier"

An unrelated io.github.pipeworx-io/vizier is listed in the same registry. The namespace is what separates them, so a search by bare name returns both.

tests/discovery-contracts.test.ts holds server.json and the served /.well-known/mcp.json to the same content, so a registry listing cannot drift away from the endpoint the Worker serves.

Receipts

Each successful verification returns a receipt ID, creation time, request hash, decision, risk score, rule IDs, and reason codes. Object keys are sorted before SHA-256 hashing. This canonicalization is documented and tested, but it is not an RFC 8785 claim.

Legacy /v1/verify receipts remain unsigned and caller-held for compatibility. The SDK validates the complete response, checks decision-to-receipt consistency, and recomputes the request hash before returning a decision.

Action Covenant authorization and outcome receipts are compact ES256 JWS values. They use a dedicated receipt key and protected typ values for domain separation. The SDK obtains the matching public key from /.well-known/jwks.json, verifies the signature, and recomputes the covenant, request, action, evidence, signal, authorization-token, and outcome bindings before returning. Signed does not mean independently timestamped or principal-issued. Vizier persists only selected receipt metadata and hashes; the complete signed receipt and token remain caller-held.

GET /v1/insights exposes authenticated decision counts, lifecycle totals, average legacy risk score, and reported failure/violation count. These are best-effort operational aggregates: asynchronous audit writes can fail, and the numbers are not proof of production adoption or complete execution history. Metadata is retained for 30 days and pruned daily by a scheduled Worker handler.

Development

npm run typecheck
npm test
npm run build
npm run check

npm run build compiles @vizier/sdk, compiles the private gated-deploy tool, and runs a Cloudflare deployment dry run. It does not deploy the Worker.

Two checks describe production rather than a commit, so they are separate from npm run check and need the network:

npm run check:deployed
npm run check:live

check:deployed compares the current bundle digest against the newest deployment: is production running this code? check:live calls the deployed Worker and asserts what it answers — health, the released version on the service index and the MCP manifest, a signed agent card, both JWKS keys, the MCP session handshake, tools/list, an anonymous tools/call that returns a receipt and cannot grant ALLOW, and the stateless server/discover. A digest can match while the endpoint is broken, which is why both exist. Point it elsewhere with VIZIER_ORIGIN. The deploy workflow runs it after the deploy and before the registry publish, so a Worker that stopped answering is never advertised as a new version.

To prepare an enforcement deployment after reviewing the threat model:

npx wrangler whoami
npx wrangler secret put VIZIER_API_KEY
npx wrangler secret put AGENT_CARD_SIGNING_KEY
npx wrangler secret put RECEIPT_SIGNING_KEY
npx wrangler deploy

AGENT_CARD_SIGNING_KEY and RECEIPT_SIGNING_KEY are separate private P-256 JWKs with distinct kid values, alg: "ES256", use: "sig", and stable key identifiers. Wrangler stores them as secrets; they must not be committed. A malformed configured key fails the affected signed surface instead of silently downgrading it.

The public Worker completed its one-time v0.1-to-v0.2 bootstrap on 2026-08-24. After the integration credential has been stored in macOS Keychain under service com.vizier.gated-deploy and account VIZIER_API_KEY, normal deployments use:

npm run deploy:gated

The private tool accepts no command arguments. It drafts and accepts a five-minute covenant for the current commit, the fixed deploy_worker action, and the fixed worker:vizier target. A worktree snapshot is freshness evidence and a dirty worktree is an invalidation signal. It runs wrangler deploy --strict only after the SDK verifies a signed ALLOW receipt, then records a signed success or failure outcome. If outcome recording fails after execution, the command returns outcome_unrecorded and a non-zero exit code instead of reporting a complete lifecycle.

A new Worker name or fresh environment that does not expose the covenant endpoints needs one explicit bootstrap deployment through its existing v0.1 gate:

VIZIER_V0_2_BOOTSTRAP=1 npm run deploy:gated

This bypass is only for the deployment that introduces the covenant endpoints and receipt key. Do not set VIZIER_V0_2_BOOTSTRAP for normal deployments of the public Vizier Worker; they use the covenant lifecycle.

This wrapper is an integration test, not an operating-system security boundary. An agent with unrestricted shell access and Cloudflare credentials can bypass it by invoking Wrangler directly. A production integration must expose only the wrapper capability and keep both Cloudflare and Vizier credentials outside the action-taking agent.

The deployment command is intentionally not part of npm run build. Without the secret, a deployment remains evaluation-only and cannot return ALLOW.

The Worker uses D1 only for an asynchronous, metadata-only operational audit trail. The authorization decision path does not depend on D1 availability. It uses no KV, Durable Object, queue, AI model, or outbound fetch. npm run check applies every D1 migration in order to an in-memory SQLite database and verifies that legacy payload-bearing columns are removed. The repository structure and protocol sources are documented in docs/ARCHITECTURE.md, docs/ADR-0001-ACTION-COVENANTS.md, docs/PILOT.md, docs/CLAIMS.md, and docs/SECURITY_REVIEW.md.

What is deferred

Independent principal authentication, durable policy/evidence/full-receipt storage, principal-signed delegation and acceptance, billing, dashboards, reputation models, payment settlement, and LLM policy evaluation inside the privileged kernel remain outside v0.3.0. See FUTURE.md.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    A governance proxy for AI tools — every MCP/agent tool call is policy-gated, secret-redacted, and written to a hash-chained, offline-verifiable audit trail.
    13
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Governed MCP gateway that lets AI agents call tools with policy enforcement, prompt-injection screening, a kill-switch, and tamper-evident signed audit logs.
    Apache 2.0
  • F
    license
    Not graded
    quality
    B
    maintenance
    Provides a secure MCP boundary for AI agents, intercepting and validating tool calls, redacting secrets, and requiring human approval for sensitive actions with a tamper-evident audit trail.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    An MCP server that acts as an authorization gateway between an AI agent and external systems, deterministically refusing actions that exceed granted authority and sealing every decision into an auditable chain of custody.
    -