npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@proofoftech/breakwater

v0.13.0

Published

Runtime guardrails for Mastra agents: policy, RBAC, audit, enforced connectors, and approval-gated coding CLIs

Readme

breakwater

Runtime guardrails for Mastra agents.

@proofoftech/breakwater adds enforcement at the places where an agent can accept data, emit data, or cause a side effect. It provides Mastra processors for policy and role checks, an enforced connector wrapper for tools, a shared audit stream, and approval-gated adapters for Claude Code and Codex.

Why use breakwater

Model instructions are not an authorization boundary. A production agent also needs code that can:

  • reject an unauthorized caller before the model runs;
  • inspect input, answer text, reasoning, and streaming object snapshots;
  • stop undeclared network access and unapproved writes at the tool boundary;
  • make retries idempotent and enforce execution budgets;
  • produce structured evidence for every allowed, denied, and failed decision.

These controls operate at different boundaries and are designed to be used together.

| Boundary | Public API | What it enforces | | --- | --- | --- | | Guarded agent entry | createGuardedAgent() | Mandatory role and policy order, fixed execution limits, and a narrow call-option allowlist | | Agent input and output | PolicyEngine | Content policies across input, final output, and streaming channels | | Agent input | RBACMiddleware | Actor presence and an explicit role allowlist | | Tool execution | createConnector() | Permission manifests, egress, approvals, dry runs, idempotency, rate limits, isolation, and custom policies | | Every gate | AuditLogger | Structured, attributed audit events with sink failure isolation | | Local coding agents | Agent CLI adapters | The connector controls plus safe argv construction, timeouts, bounded output capture, and redacted diagnostics |

breakwater is safety middleware, not an agent runtime. Use @proofoftech/flowsafe when runs must survive restarts, wait for human approval, stream live state, schedule work, or run durable agent loops on Cloudflare.

Install it

breakwater is ESM-only, requires Node.js 22.13.0 or newer (engine range >=22.13.0), and requires @mastra/core 1.53.0.

npm install @proofoftech/breakwater @mastra/[email protected]

Connector authors who define Zod schemas should also declare Zod directly:

npm install zod

The package supports the root import and six focused subpaths:

import { PolicyEngine } from '@proofoftech/breakwater';
import { createGuardedAgent } from '@proofoftech/breakwater/agent';
import { AuditLogger } from '@proofoftech/breakwater/audit';
import {
  createConnector,
  invokeConnector,
} from '@proofoftech/breakwater/connector-sdk';
import { RBACMiddleware } from '@proofoftech/breakwater/rbac';
import { createCodexConnector } from '@proofoftech/breakwater/agent-cli';
import { denyPatterns } from '@proofoftech/breakwater/policy-engine';

Guard an agent

Use createGuardedAgent() for supported protected agent execution. The factory installs role-based access control (RBAC) before application input processors and policy, then installs policy after application output processors.

import { RequestContext } from '@mastra/core/request-context';
import {
  ACTOR_CONTEXT_KEY,
  AGENT_AUDIT_CONTEXT_KEY,
  AuditLogger,
  createGuardedAgent,
  denyPatterns,
  piiSecrets,
} from '@proofoftech/breakwater';

const audit = new AuditLogger();
const agent = createGuardedAgent({
  id: 'guarded-agent',
  name: 'Guarded agent',
  instructions: 'Answer only from approved business data.',
  model: 'openai/gpt-5',
  allowedRoles: ['operator', 'admin'],
  policies: [
    denyPatterns(['private signing key']),
    piiSecrets({ detectors: ['privateKey', 'awsAccessKey', 'jwt'] }),
  ],
  audit,
  maxSteps: 4,
  toolChoice: 'auto',
});

The host must authenticate the caller and derive trusted request context before invoking the handle:

const requestContext = new RequestContext();
requestContext.set(ACTOR_CONTEXT_KEY, {
  id: 'user-42',
  role: 'operator',
});
requestContext.set(AGENT_AUDIT_CONTEXT_KEY, {
  agentId: agent.id,
  runId: 'server_minted_run_id',
  entryPath: 'http-start',
});

const result = await agent.generate('Summarize the account.', {
  requestContext,
});

The handle exposes only unstructured generate() and stream(). Each call requires requestContext and may accept only runId, memory, and abortSignal. The factory fixes maxSteps and toolChoice, forces streaming policy hold-back, disables background continuations, and rejects processor, model, and structured-output overrides.

Under the pinned Mastra version, parsed structured output bypasses the output-processor chain and reaches messages, persistence, and observability hooks before a wrapper could inspect it. Both guarded methods therefore reject structuredOutput before model execution. The factory also rejects object-only policies because no supported guarded invocation can expose their required channel. Structured-output support requires a future pre-persistence gate, not a post-generation wrapper.

allowedRoles is an exact allowlist with no role hierarchy. Application input processors may implement only processInput. Application output processors must implement both processOutputStream and processOutputResult.

Admit automated callers

Actor carries an optional kindhuman, service, agent, or system. An absent kind means human, so existing hosts are unaffected.

createGuardedAgent() and RBACMiddleware both accept allowedPrincipalKinds, which defaults to ['human']. An agent written before this option denies every automated caller until you widen it:

const agent = createGuardedAgent({
  // ...
  allowedRoles: ['operator', 'admin'],
  allowedPrincipalKinds: ['human', 'system', 'service'],
});

The gate checks kind before role, and it does not consult allowedRoles for a non-human kind. An automated caller carries a role only because Actor.role is required; consulting it would either admit whatever role the host projected, or force you to allow that role and thereby admit real humans holding it. Both the processor gate and the direct-call gate enforce this.

Flowsafe's agent host declares the matching half with allowedAutomation, which names each admitted kind together with the exact entry paths it may arrive on. See Durable agents.

The narrow handle prevents accidental use of raw Mastra execution methods. It is not a sandbox against hostile code in the same JavaScript process. Use the authenticated Flowsafe agent host when callers cross an HTTP or principal boundary.

Choose agent policies

PolicyEngine accepts any PolicyEvaluator. Policies can select the input or output phase and the output channels they inspect. Construction snapshots the policy list, selector arrays, names, hold-back hints, and evaluator callable so later replacement cannot change enforcement. Class-based evaluators retain their original receiver. Evaluator-owned instance or closure state remains application-owned and is not deep-cloned:

  • answer is client-visible text and is also the only input channel.
  • reasoning is the model reasoning trace.
  • object is the latest canonical JSON structured-output snapshot.

Use createContentPolicyGate() when trusted host code must apply the same ordered input-policy contract before content enters a framework-owned path that does not traverse Mastra's input processors. The gate accepts the exact text the downstream model will see plus an optional trusted RequestContext. It returns only allowed, denied, or evaluator-error state; policy names, reasons, content, and thrown values remain confined to the configured audit sink. Every registered policy must be able to run on the input answer channel — one that could never be evaluated here is rejected at construction, not skipped. That includes maxTextLength, which defaults to the output phase: pass maxTextLength(n, { phases: ['input'] }) to use it at this boundary.

The included policies are:

| Policy | Default coverage | Purpose | | --- | --- | --- | | denyPatterns(patterns) | Input and output; answer, reasoning, and object | Deny case-insensitive string matches or caller-supplied regular expressions | | maxTextLength(maxChars) | Output answer | Cap accumulated output length | | piiSecrets(options) | Input and output; answer, reasoning, and object | Detect email, SSN, phone, Luhn-valid cards, AWS keys, PEM headers, JWTs, secret assignments, and high-entropy tokens | | classifierPolicy(options) | Input and output answer | Delegate to a synchronous or asynchronous classifier, with cadence and timeout controls |

piiSecrets() supports detector selection, exact or regular-expression allowlist exemptions, an entropy threshold, phase and channel selection, and a hold-back hint override. Its detectors and denyPatterns() are best-effort text inspection. Unicode tricks, alternate encodings, or deliberately shaped secrets can evade pattern-based controls.

classifierPolicy() fails closed when the classifier throws or exceeds its configured timeout. It has no automatic hold-back window because a classifier has no bounded match length. To buffer a whole channel until classification finishes, set holdBackChars: Number.POSITIVE_INFINITY on the returned evaluator.

Understand streaming hold-back

Without holdBack, each accumulated chunk is evaluated before that chunk is emitted, but text from earlier chunks may already be visible when a later chunk completes a forbidden pattern.

With holdBack: true, the engine retains each policy's declared trailing window and releases only evaluated text. String patterns and the built-in secret detectors provide bounded windows. A regular expression in denyPatterns() defaults to buffering the full segment unless holdBackChars supplies a safe bound. The guarantee is per stream segment; text released at the end of an earlier segment cannot be withdrawn if a match completes in a later segment.

Under the supported @mastra/core peer, only object chunks that traverse the processor chain reach a standalone engine. The engine validates those chunks as JSON, evaluates the canonical snapshot, and forwards the same canonical clone. Parsed generate() results and core's structured-output processor chunks bypass that chain. If an object-only policy sees no processor-visible object chunk, the engine requires an audit sink and aborts at the result boundary. JSON carried as answer text is still inspected by answer-inclusive policies.

Enforce tool permissions

Create tools through createConnector() when policy must hold on agent, workflow, nested, and direct calls.

import {
  createConnector,
  invokeConnector,
} from '@proofoftech/breakwater/connector-sdk';
import { z } from 'zod';

const accountLookup = createConnector({
  id: 'crm.get-account',
  description: 'Read one CRM account',
  inputSchema: z.object({ accountId: z.string().min(1) }),
  outputSchema: z.object({ name: z.string() }),
  permissions: {
    sideEffect: 'read',
    egress: ['api.example-crm.com'],
  },
  policies: {
    networkEgress: { allowedDomains: ['api.example-crm.com'] },
  },
  execute: async ({ accountId }, _context, runtime) => {
    const response = await runtime.fetch(
      `https://api.example-crm.com/accounts/${accountId}`,
    );
    const account = (await response.json()) as { name: string };
    return { name: account.name };
  },
});

Call the connector outside an agent loop through the supported direct boundary:

const account = await invokeConnector(accountLookup, {
  accountId: 'account_123',
});

Pass a trusted RequestContext when the connector uses grants, identity, dry-run, idempotency, or isolation keys. invokeConnector() preserves Mastra schema validation and every Breakwater gate. It rejects plain tools and connectors whose ID, execution function, or schema surface changed after construction. Validation failures throw a redacted ConnectorValidationError with the connector ID and input or output phase.

The permission manifest is enforced:

  • sideEffect classifies the connector as read, write, destructive, or idempotent.
  • egress lists exact hosts or leading *. wildcards. The organization allowlist gates the declaration, and runtime.fetch gates each actual request and redirect hop.
  • requiresApproval makes the server-minted approval grant mandatory.
  • requiredPermissions makes the trusted principal-permissions projection mandatory: the executing principal must hold every listed identifier, checked before dry-run and before the approval grant.
  • dryRun requires dryRunExecute and allows callers to request a side-effect-free simulation.
  • idempotencyKey requires a per-call key and a configured store.
  • rateLimit declares a fixed-window budget and requires a configured store.
  • background permits background overrides only for read-only connectors. Mastra still owns actual background-task eligibility.

Custom ToolPolicyEvaluator instances run before execution. Included evaluators cover declared network egress, cross-workflow scope, required tenant scope, and the direct-call background override defense. The connector authoring guide contains the complete manifest, storage, invocation, egress, and testing contract.

Apply the physical-deployment preset

Use singleTenantConnectorPolicies() when one physically isolated deployment serves one organization. It requires D1-backed stores for declared idempotency and rate limits, production audit export or an explicit development opt-out, an organization egress allowlist, principal-permission wiring, and the background-execution policy. Set its idempotencyKeyMigration acknowledgement only after legacy connector writers sharing the D1 store are stopped and drained. The preset rejects tenantIsolation(), weakened destructive approval, incomplete manifest policy, and replacement of validated policy members.

Build the preset once and pass the returned frozen policy set to each connector. Read Connector interface for the configuration contract.

Set request context at trusted boundaries

The connector wrapper reads these keys:

| Constant | Runtime key | Value | Who should set it | | --- | --- | --- | --- | | ACTOR_CONTEXT_KEY | breakwater.actor | { id, role, kind? } | Authenticated host or getActor | | CONNECTOR_GRANTS_CONTEXT_KEY | breakwater.connectorGrants | ConnectorApprovalGrant[] | Trusted approval service only | | CONNECTOR_EXECUTION_CONTEXT_KEY | breakwater.connectorExecution | ConnectorExecutionIdentity | Trusted runtime only | | PRINCIPAL_PERMISSIONS_CONTEXT_KEY | breakwater.principalPermissions | PrincipalPermissions or null | Trusted host resolver only | | DRY_RUN_CONTEXT_KEY | breakwater.dryRun | true | Caller requesting simulation | | IDEMPOTENCY_KEY_CONTEXT_KEY | breakwater.idempotencyKey | Non-empty string | Host-derived operation identity | | ISOLATION_SCOPE_CONTEXT_KEY | breakwater.isolationScope | Opaque non-empty string | Multi-tenant runtime only | | WORKFLOW_SCOPE_CONTEXT_KEY | breakwater.workflowScope | Current workflow ID | Workflow runtime only |

Approval, permission, and isolation values are capabilities. Never accept them from a request body, model output, tool result, or client-controlled header. Flowsafe derives structured approval grants from approved records, projects the server-resolved principal permissions, and mints the current execution identity, workflow scope, and run ID on each run leg. Its physical data plane reserves and drops the isolation scope.

Mastra's native requireApproval pauses an agent run, but it does not replace the Breakwater grant. Every execution path checks the structured grant against the runtime-owned identity. Legacy connector ID arrays fail closed.

Durable-agent approvals use tool-call scope: connector ID, workflow, run, exact (stepPath, suspendedAt, resumeCount) suspension, and Mastra toolCallId must match. Workflow approvals use suspension scope because Mastra exposes no reproducible tool-call identity for an arbitrary workflow gate. Trusted standing grants use an explicit run scope.

The same durable tool-call attempt may retry with the same toolCallId. A new model tool call has a new ID and requires approval. Use connector idempotency for side-effect replay protection; the grant is not a one-shot token.

Choose replay and rate-limit stores

Development stores keep state in one JavaScript isolate:

  • InMemoryIdempotencyStore provides atomic same-isolate reservations and bounded replay storage.
  • InMemoryRateLimitStore provides fixed windows per isolate.

Production Cloudflare deployments can use:

  • D1IdempotencyStore, which uses an atomic insert claim, lease tokens, and stale-pending takeover across isolates.
  • D1RateLimitStore, which atomically increments shared fixed-window rows.

The store's reach is the control's reach. In a Durable Object per run, in-memory rate limits become per-run budgets and in-memory replay protection does not cross isolates. Use shared stores when the declared behavior must hold across runs.

Set D1IdempotencyStore.pendingTtlMs above the longest possible execution. The default is 900,000 ms. Agent CLI connectors reject a configured pending TTL that is not greater than their execution timeout. The store accepts only a positive safe integer up to 8,640,000,000,000,000 ms.

New idempotency records use an opaque collision-proof v2 key. Before allowing new v2 records, set idempotencyKeyMigration: 'legacy-writers-drained' only after every old writer sharing the store has stopped and drained. Safe unscoped legacy records remain replayable. Scoped legacy records and unscoped business keys containing : are ambiguous and fail closed until an operator maps them to one proven identity. Atomic custom stores must implement non-mutating inspect() so pending legacy work cannot look absent.

D1IdempotencyStore persists JSON-native connector results (plus a top-level undefined). It rejects values such as Date, Map, non-finite numbers, sparse arrays, or nested undefined that JSON would silently change; the wrapper then uses its existing degraded-final-write behavior rather than creating a type-changing replay record.

Breakwater stores only the connector result. It does not hash arbitrary input or reject a changed body under the same key. Applications that promise request mismatch detection must canonicalize the request and store a fingerprint with the result at their gateway boundary.

A fixed window can admit traffic on both sides of a boundary, approaching twice the nominal count in a short interval. Use another RateLimitStore implementation if you require token-bucket or GCRA semantics. Counts must be safe integers from 1 through Number.MAX_SAFE_INTEGER. D1RateLimitStore commits its increment and rollover cleanup in one D1 batch, so cleanup failure cannot consume quota for a rejected call.

Record audit and metrics

Every gate writes AuditEvent records with a timestamp, actor, action, resource, decision, optional reason, and optional detail.

import {
  AuditLogger,
  combineAuditSinks,
  metricsAuditSink,
} from '@proofoftech/breakwater/audit';

const audit = new AuditLogger({
  maxBuffered: 2_000,
  sink: combineAuditSinks(
    metricsAuditSink(metricsRecorder),
    async (event) => auditQueue.send(event),
  ),
  onSinkError: (error, event) => {
    reportAuditExportFailure(error, event.action);
  },
});

AuditLogger keeps an in-memory ring buffer, defaulting to 1,000 events. Synchronous and asynchronous sink failures do not abort the guarded operation; they are reported through onSinkError. combineAuditSinks() runs every sink and aggregates failures. metricsAuditSink() emits the breakwater.audit.decision counter and observes breakwater.audit.duration_seconds when an event contains a finite, non-negative detail.durationSeconds.

Generic connector exceptions are rethrown to the caller, but their arbitrary messages are not copied into connector audit events. Audit reasons remain static unless breakwater created a private, safe error summary.

Connector audit events also use trusted breakwater.auditContext correlation. Host-derived agent, deployment (tenantId), run, thread, resource, entry-path, and principal fields override same-named decision detail. Unknown and non-scalar context fields remain excluded.

For durable Cloudflare Queues to SIEM export, use the flowsafe audit-export subpath.

Run coding agents through the same gate

The agent CLI subpath wraps Claude Code and Codex as write-class, approval-required connectors.

import { RequestContext } from '@mastra/core/request-context';
import {
  createCodexConnector,
  DRY_RUN_CONTEXT_KEY,
  invokeConnector,
} from '@proofoftech/breakwater';

const codex = createCodexConnector();
const requestContext = new RequestContext();
requestContext.set(DRY_RUN_CONTEXT_KEY, true);

const preview = await invokeConnector(
  codex,
  {
    prompt: 'Add unit tests.',
    cwd: '/srv/workspace',
    model: 'your-model-id',
  },
  { requestContext },
);

The default runner is Node-only and:

  • spawns an argv array without a shell;
  • appends -- and the real prompt as the final positional argument;
  • selects workspace editing with Claude Code acceptEdits or Codex workspace-write;
  • terminates the child process tree after the configured timeout (a POSIX process group or absolute taskkill.exe /T /F from a drive-absolute local %SystemRoot% or %WINDIR%), and reports a distinct safe failure if tree termination itself fails;
  • retains only the tail of stdout and stderr, capped by UTF-8 bytes;
  • returns the CLI stdout as text and a prompt-redacted display command;
  • exposes static AgentCliError messages plus structured, non-secret metadata.

The default timeout is 600,000 ms and the default retained output is 1 MiB per stream. An injected exec implementation is responsible for its own sandbox, process-tree termination, timeout, and output limits.

The returned text is functional agent output and may contain sensitive data. The command redacts the prompt and --flag=value option values. Validation failures, error messages, error metadata, and breakwater-generated audit reasons do not contain the prompt or captured stdout and stderr.

The adapter does not sandbox the child. It inherits the parent environment and credentials, and cwd is the workspace the CLI may modify. Its manifest declares provider hosts, but a child process does not use ConnectorRuntime.fetch; actual socket enforcement belongs in the container, VM, or host firewall. See the CLI section of the connector guide before enabling real execution.

Know the egress boundary

runtime.fetch accepts an absolute HTTP(S) URL string or URL object, not a Request. It checks the initial host and every followed redirect. It strips authorization, cookie, and proxy-authorization on a cross-origin redirect, rewrites methods according to fetch redirect rules, refuses to replay one-shot bodies across 307 or 308 redirects, and defaults to 20 hops.

This enforcement cannot see:

  • global fetch calls made around runtime.fetch;
  • vendor SDKs that do not accept the injected fetch;
  • raw sockets or child-process network traffic.

Route every connector request through runtime.fetch. Use host-level network controls when code outside that seam must also be constrained.

Public API

The root entry point re-exports the supported APIs from every subpath.

Policy engine exports

| Runtime exports | Purpose | | --- | --- | | PolicyEngine | Mastra input, stream-output, and final-output processor | | createContentPolicyGate | Opaque, reusable input-policy gate for trusted host boundaries | | denyPatterns, maxTextLength, piiSecrets, classifierPolicy | Included agent-boundary evaluators | | PII_SECRETS_DETECTOR_IDS | Stable detector ID list | | extractMessageText | Extract policy text from Mastra messages | | networkEgress, crossWorkflowIsolation, tenantIsolation, backgroundExecution | Included tool-boundary evaluators | | approvalRequired | Resolve approval from a manifest and organization policy | | egressDomainAllowed | One-shot normalized exact or wildcard host match | | ISOLATION_SCOPE_CONTEXT_KEY, WORKFLOW_SCOPE_CONTEXT_KEY, LLM_BACKGROUND_OVERRIDE_KEY | Stable scope and override keys |

Type exports: PolicyEngineOptions, PolicyEvaluator, PolicyContext, PolicyDecision, ContentPolicyGate, ContentPolicyGateInput, ContentPolicyGateOptions, ContentPolicyGateResult, PolicyPhase, OutputChannel, PiiSecretsOptions, PiiSecretsDetectorId, ClassifierPolicyOptions, ToolPolicyEvaluator, ToolCallContext, SideEffect, NetworkEgressOptions, CrossWorkflowIsolationOptions, BackgroundExecutionOptions, and WritePermissionsPolicy.

RBAC and audit exports

| Runtime exports | Purpose | | --- | --- | | RBACMiddleware, ROLES, ACTOR_CONTEXT_KEY, actorFromRequestContext | Actor authorization and lookup | | isPermissionIdentifier, isPrincipalPermissions, PRINCIPAL_PERMISSIONS_CONTEXT_KEY | Canonical permission identifiers and the trusted principal-permissions projection | | AuditLogger, combineAuditSinks, metricsAuditSink | Buffered audit, sink fan-out, and metrics adaptation |

Type exports: Actor, Role, Permission, PrincipalKind, PrincipalPermissions, RBACMiddlewareOptions, AuditEvent, AuditSink, AuditLoggerOptions, and MetricsRecorder. The rbac subpath also re-exports AuditLogger and its original audit types for compatibility.

Connector SDK exports

| Runtime exports | Purpose | | --- | --- | | createConnector, connectorManifest | Build an enforced Mastra connector and inspect its immutable manifest | | invokeConnector | Invoke an unmodified connector from trusted host or workflow code without fabricating a Mastra tool context | | singleTenantConnectorPolicies | Build the validated connector-policy baseline for one physically isolated deployment | | ConnectorPolicyError, ConnectorValidationError | Structured policy denial and redacted direct-invocation validation failure | | CONNECTOR_GRANTS_CONTEXT_KEY, CONNECTOR_EXECUTION_CONTEXT_KEY, DRY_RUN_CONTEXT_KEY, IDEMPOTENCY_KEY_CONTEXT_KEY | Stable connector request-context keys | | InMemoryIdempotencyStore, D1IdempotencyStore | Development and durable replay stores | | inspectLegacyConnectorIdempotency, migrateLegacyConnectorIdempotency | Inventory and atomically migrate one externally proven ambiguous legacy D1 row without exposing storage keys | | InMemoryRateLimitStore, D1RateLimitStore | Development and durable fixed-window stores | | egressFetch, EgressDeniedError | Standalone fetch guard and its default denial |

Type exports: Connector, ConnectorInvocationOptions, PermissionManifest, ConnectorConfig, ConnectorPolicies, SingleTenantConnectorPolicies, SingleTenantConnectorPoliciesOptions, SingleTenantAuditPosture, SingleTenantDurableStores, SingleTenantPermissionPosture, ConnectorApprovalGrant, ConnectorApprovalGrantBase, ConnectorApprovalSuspension, ConnectorExecutionIdentity, ConnectorRuntime, IdempotencyStore, AtomicIdempotencyStore, InspectableIdempotencyStore, IdempotencyInspection, IdempotencyRecord, IdempotencyReservation, RateLimitStore, LegacyConnectorIdempotencyIdentity, LegacyConnectorIdempotencyMigrationRequest, LegacyConnectorIdempotencyMigrationResult, D1IdempotencyStoreOptions, IdempotencyDatabase, IdempotencyBatchDatabase, IdempotencyStatement, IdempotencyBatchResult, D1RateLimitStoreOptions, RateLimitDatabase, RateLimitStatement, RateLimitBatchResult, EgressDenial, EgressFetchOptions, EgressFetchBase, EgressGuardedFetch, EgressRequestInit, EgressResponse, and EgressResponseHeaders.

Agent CLI exports

| Runtime exports | Purpose | | --- | --- | | createAgentCliConnector | Wrap another positional-prompt CLI | | createClaudeCodeConnector, createCodexConnector | Built-in adapters | | CLAUDE_CODE_CLI, CODEX_CLI | Reusable adapter definitions | | AgentCliError | Safe structured execution failure |

Type exports: AgentCliInput, AgentCliOutput, AgentCliExec, AgentCliExecResult, AgentCliDefinition, AgentCliConnectorOptions, AgentCliErrorCode, and AgentCliErrorMetadata.

Read the design and operational docs

Verify a checkout

pnpm --filter @proofoftech/breakwater lint
pnpm --filter @proofoftech/breakwater typecheck
pnpm --filter @proofoftech/breakwater test
pnpm --filter @proofoftech/breakwater build
pnpm --filter @proofoftech/breakwater test:packed-consumer

Apache-2.0. See LICENSE.