# Ecosystem index

Source: https://permdock.com/docs/research/ecosystem-index

Every third-party tool, platform and product the PermDock documentation names, grouped by category, with how PermDock composes with each (standard security fields, the Overlay, subjectFromJwt, ApprovalStore, DecisionSink, MCP, AuthZEN, a compiler target or a recipe) and the page that owns the recipe.

This is the single list of third-party tools the docs name. Each row names the tool, what it is, the mechanism PermDock reaches it through, and the page that owns the recipe or verdict. A tool named anywhere in the docs gets a row here in the same change. Prior-art analysis of competing libraries and vendors is on [landscape](/docs/research/landscape).

PermDock composes through wire formats and interfaces, and ships a package entry only for the adapters on the [adapters](/docs/adapters) matrix.

| Mechanism | Meaning |
| --- | --- |
| `security` | The tool reads standard OpenAPI `security` and `securitySchemes` from the applied description; nothing PermDock-specific |
| Overlay | The tool applies or consumes PermDock's [OpenAPI Overlay](/docs/standards/openapi-overlay) |
| `x-permdock-*` | The tool reads a PermDock extension (only the OpenAPI-to-MCP bridges need one) |
| `subjectFromJwt` | The tool issues JWTs verified by [`permdock/jwt`](/docs/adapters/jwt) against its JWKS |
| `authInfo` | The tool issues the access tokens [`permdock/mcp`](/docs/adapters/mcp) receives as `AuthInfo` |
| MCP | The tool consumes or hosts MCP servers, so `protectServer` already guards it |
| AI SDK | The tool builds on the AI SDK, so `permdock/ai-sdk` applies |
| AuthZEN | The tool is an AuthZEN policy enforcement point or decision point ([AuthZEN](/docs/standards/authzen)) |
| `ApprovalStore` | The tool holds or delivers approvals through the [approvals](/docs/adapters/approvals) interface |
| `DecisionSink` | The tool receives decision events through a sink recipe or OpenTelemetry ([audit](/docs/concepts/audit-and-observability)) |
| `where` target | The tool is a compile target for portable conditions, shipped or candidate |
| Hook | The tool has an in-process hook a shipped adapter fills |
| Loader | A framework loader calls `getSnapshot(request)` from `permdock/server` and hands the snapshot to a UI adapter |
| Recipe | Documented composition; no package |
| Tracking | Named and watched; nothing to do yet |

## OpenAPI producers [#openapi-producers]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| next-openapi-gen | Route scanner for Next.js, TanStack Start, React Router, Remix, SvelteKit, Nuxt, Astro, Hono, Express; applies Overlays; scaffolds Scalar; compiles Arazzo | Overlay | [Next.js adapter](/docs/adapters/next), [OpenAPI adapter](/docs/adapters/openapi) |
| hono-openapi, @hono/zod-openapi | Hono spec generators | Hook (`describe`, `security`) | [Hono adapter](/docs/adapters/hono) |
| @orpc/openapi | oRPC spec generator | `openapi()` meta helper | [oRPC adapter](/docs/adapters/orpc) |
| trpc-to-openapi | tRPC spec generator; boolean `protect` only | Hook plus Overlay for per-scope | [tRPC adapter](/docs/adapters/trpc) |
| @elysia/openapi | Elysia spec generator; Scalar by default | Hook | [Elysia adapter](/docs/adapters/elysia) |
| @fastify/swagger, @nestjs/swagger | Fastify and Nest spec generators | Hook | [Fastify](/docs/adapters/fastify), [Nest](/docs/adapters/nest) |
| TypeSpec | Design-first API language (1.0 GA), emits OpenAPI 3.0 to 3.2 | Overlay on emitter output | [OpenAPI adapter](/docs/adapters/openapi) |
| tsoa, ts-rest, Effect HttpApi, feTS | Code-first producers without a per-route hook | Overlay | [OpenAPI adapter](/docs/adapters/openapi) |
| Hand-written YAML or JSON | Design-first descriptions | Overlay | [OpenAPI adapter](/docs/adapters/openapi) |
| `x-gnap` (community GNAP security-scheme extension) | Vendor extension describing a GNAP deployment on a security scheme; no OpenAPI Initiative standing | Tracking (never emitted; preserved untouched by the importer) | [watch list](/docs/standards/watch-list), [OpenAPI 3.2 and 3.3](/docs/standards/openapi) |

## Overlay appliers [#overlay-appliers]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| next-openapi-gen `overlay.apply` | Applies inside `generate`; Overlay 1.0 to 1.2 | Overlay | [Next.js adapter](/docs/adapters/next) |
| Redocly CLI `join --overlay` | Lint, bundle, generate pipelines (experimental flag) | Overlay | [CLI: openapi](/docs/cli/openapi) |
| Bump.sh CLI `bump overlay`, GitHub Action | Applies at docs deploy | Overlay | [CLI: openapi](/docs/cli/openapi) |
| Speakeasy CLI `overlay apply` | SDK generation workflows; chains with Speakeasy's own overlays | Overlay | [CLI: openapi](/docs/cli/openapi) |
| Zuplo CLI | Applies before gateway import | Overlay | [OpenAPI adapter](/docs/adapters/openapi) |
| overlays-js, openapi-format, oas-patch | Vendor-neutral appliers; overlays-js is the reference JavaScript implementation | Overlay | [CLI: openapi](/docs/cli/openapi) |
| Scalar CLI | Docs and registry; no Overlay support yet | Tracking | [OpenAPI adapter](/docs/adapters/openapi) |

## SDK generators [#sdk-generators]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Hey API (`@hey-api/openapi-ts`) | Typed SDKs, TanStack Query, validators | `security` | [OpenAPI adapter](/docs/adapters/openapi) |
| Orval | Clients, TanStack Query, MSW mocks, MCP servers | `security`; `x-permdock-*` for MCP output | [OpenAPI adapter](/docs/adapters/openapi), [MCP adapter](/docs/adapters/mcp) |
| Kubb | Plugin-based generator including MCP and Redoc output | `security`; `x-permdock-*` for MCP output | [OpenAPI adapter](/docs/adapters/openapi) |
| openapi-typescript, openapi-fetch | Types-only generation and a typed fetch wrapper (maintenance mode) | Nothing to do | [OpenAPI adapter](/docs/adapters/openapi) |
| OpenAPI Generator, Kiota | Multi-language generators | `security` | [OpenAPI adapter](/docs/adapters/openapi) |
| Redocly `generate-client` | Clients | `security` | [OpenAPI adapter](/docs/adapters/openapi) |
| Fern, Speakeasy | Commercial SDK, docs and MCP generators | `security`; never their namespaces | [OpenAPI adapter](/docs/adapters/openapi) |
| Stainless | SDK generator; acquired by Anthropic, hosted product wound down | `x-stainless-*` never written | [OpenAPI registries](/docs/standards/openapi-registry) |

## Docs UIs and hosts [#docs-uis-and-hosts]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Scalar | API reference and client; renders `x-badges` | `security`, optional `x-badges` hint | [OpenAPI adapter](/docs/adapters/openapi) |
| Swagger UI, Redoc, Stoplight Elements, RapiDoc, fumadocs-openapi, Zudoku | Open-source docs UIs | `security` | [OpenAPI adapter](/docs/adapters/openapi) |
| Mintlify | Hosted docs; `x-mint`, `x-mcp`; generates an MCP server | `security`; never its namespaces | [OpenAPI adapter](/docs/adapters/openapi) |
| Bump.sh | Hosted docs and changelog; applier | `security`, Overlay | [OpenAPI adapter](/docs/adapters/openapi) |
| Fern docs, Redocly Realm, Docusaurus OpenAPI, GitBook, Postman | Hosted or static docs | `security` | [OpenAPI adapter](/docs/adapters/openapi) |
| ReadMe | Hosted docs; `x-readme` | Never written | [OpenAPI registries](/docs/standards/openapi-registry) |

## OpenAPI-to-MCP bridges and MCP hosts [#openapi-to-mcp-bridges-and-mcp-hosts]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Orval, Kubb, Scalar, Speakeasy, Fern, Mintlify, Postman MCP Generator | Generate an MCP server from a description | `x-permdock-permissions` bound as each tool's `permission` | [MCP adapter](/docs/adapters/mcp), [OpenAPI adapter](/docs/adapters/openapi) |
| Zuplo (`x-zuplo-route.mcp`), Kong `openapi2mcp` and `ai-mcp-proxy` | Gateway-hosted MCP from a description | `x-permdock-permissions`; gateway extensions never written | [OpenAPI adapter](/docs/adapters/openapi) |
| AWS Bedrock AgentCore Gateway | OpenAPI, Lambda and MCP targets as MCP tools; Cedar policy on `context.toolName` (the `operationId`) | MCP when self-hosted; `security` and `operationId` otherwise | [OpenAPI adapter](/docs/adapters/openapi) |
| mcp-handler (Vercel) | Fetch handler for MCP servers on Next.js, Nuxt, SvelteKit, Hono; `withMcpAuth`, `protectedResourceHandler` | MCP (`protectServer` inside `createMcpHandler`) | [MCP adapter](/docs/adapters/mcp), [Next.js adapter](/docs/adapters/next) |
| @modelcontextprotocol/server 2.x | Official TypeScript SDK v2; `scopeChallenge` on `registerTool` | Types-only optional peer of `permdock/mcp` | [MCP adapter](/docs/adapters/mcp), [installation](/docs/getting-started/installation) |
| Official Express middleware, Cloudflare `McpAgent`, FastMCP (TypeScript), xmcp | Other MCP hosts | MCP | [MCP adapter](/docs/adapters/mcp) |
| `@hono/node-server` | Node.js server for Hono with WebSocket upgrade over `ws` | Recipe (`permdock/hono` `connection` and `socket`) | [Hono adapter](/docs/adapters/hono) |
| `ws` | WebSocket server for Node.js | Transport under `@hono/node-server`; the socket is closed with 1008 on denial or revocation | [Hono adapter](/docs/adapters/hono) |
| mcp-remote | stdio bridge for remote servers | Nothing to do | [MCP adapter](/docs/adapters/mcp) |

## Linters, testing and diff [#linters-testing-and-diff]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Spectral, Redocly lint, vacuum | OpenAPI linters | PermDock ruleset file | [CLI: openapi](/docs/cli/openapi) |
| Schemathesis `ignored_auth` | Property-based API tests; verifies protected operations reject anonymous calls | Recipe in CI | [CLI: openapi](/docs/cli/openapi) |
| oasdiff | Breaking-change diff; `security` removals are breaking | Recipe in CI | [CLI: openapi](/docs/cli/openapi) |
| Prism, Microcks | Mock servers honouring `security` | `security` | [OpenAPI adapter](/docs/adapters/openapi) |
| MSW | Request mocking used by `permdock/testing` fixtures | Recipe | [testing](/docs/adapters/testing) |

## Authorization engines, gateways and decision services [#authorization-engines-gateways-and-decision-services]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Kong, Envoy `ext_authz`, Tyk, Zuplo, WSO2 | Gateways with AuthZEN enforcement points | AuthZEN (in-app handler or PermDock Cloud ADS) | [AuthZEN adapter](/docs/adapters/authzen) |
| WorkOS FGA | Resource-scoped RBAC API (check, list resources, list memberships) | Positioning; question-shaped verbs | [landscape](/docs/research/landscape), [comparison](/docs/comparison) |
| OpenFGA, Auth0 FGA (Okta FGA) | Zanzibar relation-graph engine and its hosted service | `openfga({ url, storeId, map })` in `permdock/pdp`: HTTP `check` per row, `list-objects` for `filter` and `where`; tested against the `openfga/openfga` container. Recipe, not an entry: a `RelationSource` whose `related` reads one object's tuples (`POST /stores/{id}/read` with `tuple_key.object`) and whose `ancestors` follows the parent tuples up to `depth`, so PermDock keeps the decision and the model keeps the graph | [pdp](/docs/adapters/pdp), [relationships](/docs/concepts/relationships) |
| SpiceDB (AuthZed) | Zanzibar relation-graph engine with CEL caveats | `spicedb({ url, token, map })` in `permdock/pdp`: HTTP gateway `CheckPermission` per row, `LookupResources` for `filter` and `where`; tested against the `authzed/spicedb` container. Recipe, not an entry: a `RelationSource` over `ReadRelationships` for one object (`related`) and the parent relationships walked up to `depth` (`ancestors`); caveats stay in SpiceDB and are not mirrored as `period` | [pdp](/docs/adapters/pdp), [relationships](/docs/concepts/relationships) |
| Cerbos, Permit.io, AuthZed (SpiceDB), Oso, OpenFGA, Auth0 FGA, Topaz, Keycloak, casbin | Authorization products and engines | AuthZEN through `permdock/pdp`; positioning | [landscape](/docs/research/landscape), [comparison](/docs/comparison) |
| Cedar, Amazon Verified Permissions, AgentCore Policy | Policy language and its hosted engines | Compile target considered, not scheduled | [landscape](/docs/research/landscape), [comparison](/docs/comparison) |
| Open Policy Agent, `@ai-sdk/policy-opa` | Rego engine; AI SDK tool-approval adapter over it that fails open on unrecognised decisions | Positioning; the fail-closed `permdock/ai-sdk` is the alternative | [landscape](/docs/research/landscape), [AI SDK adapter](/docs/adapters/ai-sdk) |
| Gateway import namespaces (`x-amazon-apigateway-*`, `x-google-*`, `x-kong-*`, `x-zuplo-*`, `x-ms-*`) | Vendor extensions in descriptions | Never written | [OpenAPI registries](/docs/standards/openapi-registry) |
| Aserto (Topaz), Styra (OPA) | Standalone authorization companies that shut down or were acqui-hired; Topaz and OPA remain open source | Positioning only | [landscape](/docs/research/landscape) |
| Pomerium, Cloudflare Access | Identity-aware proxies | Positioning only; the verified identity they forward as a header or JWT is read by `subjectFromJwt`, and they never decide for PermDock | [landscape](/docs/research/landscape) |
| Keycard, Natoma, TrueFoundry, Kong AI Gateway, Cloudflare AI Gateway, Solo agentgateway, Aembit, Snowflake MCP gateway, NewCore | MCP and agent-identity gateways | Positioning only; tokens they mint reach `permdock/mcp` as `authInfo`, calls they forward reach `protectServer` | [landscape](/docs/research/landscape), [MCP adapter](/docs/adapters/mcp) |
| Arcade, Composio, Permit MCP Gateway, Oso for Agents | Hosted tool-auth proxies | Positioning only | [landscape](/docs/research/landscape) |

## Identity providers and agent identity [#identity-providers-and-agent-identity]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Supabase Auth, Clerk, Better Auth, Convex | Providers with an in-process verification hook | Adapter (`subjectFrom*`) | [authentication](/docs/concepts/authentication), provider pages |
| `@supabase/middleware` | Supabase's Web-Fetch middleware engine, 1.0.0 (`defineMiddleware`, `pipeline`, typed `ctx` contributions, `seedContext` and `bufferRequest` for framework bridges) | Adapter: `permdock/supabase/middleware` (`withPermDock`), optional peer | [Supabase provider](/docs/adapters/supabase) |
| `@supabase/server` (`withSupabase`, `withClaims`, `withRequiredClaims`, `withPostgresClient`, `withPostgresAdminClient`, `withOAuthProtectedResource`, `withFeatureFlag`) | Stateless header-based Supabase auth, 1.9.1; JWKS-verified `jwtClaims`, RLS-scoped clients, RFC 9728 metadata. The framework adapters (`adapters/hono`, `h3`, `elysia`, `nestjs`) are deprecated and removed on 1 December 2026 | Recipe: `subjectFromSupabase(ctx.jwtClaims)`; a `toHono`-style bridge for Hono, H3, Elysia and NestJS; `withOAuthProtectedResource` before the auth gate; `withPostgresClient` as the runtime twin of `permdock rls verify` | [Supabase provider](/docs/adapters/supabase), [MCP adapter](/docs/adapters/mcp), [RLS adapter](/docs/adapters/rls) |
| `@supabase/ssr` | Cookie-session Supabase client for Next.js, SvelteKit, Remix, React Router and Astro, 0.12.7 | Recipe: `getClaims()` feeding `subjectFromSupabase` inside the framework adapter's `subject` | [Supabase provider](/docs/adapters/supabase) |
| better-supabase | Supabase toolkit: token verification through `@supabase/server`, the `kind`-tagged `AuthSession`, typed clients, Storage and Realtime definitions (`defineBucket`, `defineTopic`), jobs, `createMcp` with `authorize` and `visible` hooks, `checkSession` and database hygiene lints | Entry: `permdock/better-supabase` fills its slots with `authorizationProvider` (the `authorization` config its SQL modules, entitlements, access policies and doctor read), `bucketPolicy`, `topicPolicy`, `apiKeyVerifier`, `apiKeyClaimOptions` and `subjectFromBetterSupabase`, with `act.kind` support and impersonation sessions as actors and `anonymousSignIns: 'deny'`; Hono, oRPC and `createMcp` recipes; PermDock owns the claims, the one token hook and the SQL helpers the provider's templates call; better-supabase imports nothing from PermDock; the `bs.cached()` snapshot recipe with `snapshotTag(sub)` and `bs.invalidateSession`; an optional peer of `permdock/better-supabase` | [better-supabase](/docs/adapters/better-supabase), [Supabase token hook](/docs/adapters/supabase-hook), [RLS adapter](/docs/adapters/rls#sql-helper-contract), [Next.js Cache Components guide](/docs/guides/next-cache-components#supabase-claims) |
| Clerk Billing | Plans and features as `pla` and `fea` claims | `pla` maps to `principal.plans`; `fea` maps to roles | [Clerk provider](/docs/adapters/clerk) |
| Auth.js (NextAuth) | Framework session | Session resolver | [authentication](/docs/concepts/authentication) |
| WorkOS AuthKit and Connect, Auth0, Logto, Kinde, Neon Auth, Stack Auth, Firebase Auth, Amazon Cognito, Keycloak, Ory | JWKS-publishing providers | `subjectFromJwt` | [authentication](/docs/concepts/authentication) |
| Stytch Connected Apps, Descope, Scalekit, Auth0 Token Vault, Supabase OAuth 2.1 server | OAuth 2.1 authorization servers for MCP servers | `subjectFromJwt`, `authInfo` | [authentication](/docs/concepts/authentication), [MCP authorization](/docs/standards/mcp-authorization) |
| Okta (Cross App Access), Microsoft Entra ID (Agent ID) | Enterprise IdPs with agent identity; `sub` is the human, the client is the agent | `subjectFromJwt`; EMA / ID-JAG transparent | [authentication](/docs/concepts/authentication), [delegation](/docs/security/delegation) |
| Google Identity (Sign in with Google, Google Workspace) | Consumer and workforce OIDC IdP; `hd` tenant, no groups in the token | `subjectFromJwt` or the auth layer's session; groups from a directory lookup | [authentication](/docs/concepts/authentication) |
| Enterprise SSO layers (WorkOS AuthKit and Directory Sync, Clerk Enterprise SSO, Better Auth SSO plugin, Auth0 Organizations, Supabase SAML) | SAML / OIDC termination and group-to-role mapping in front of the app | Session or JWT consumed by `subjectFrom*`; Directory Sync rows read by `context` or a `MembershipSource`; or the IdP provisions straight into [`permdock/scim`](/docs/adapters/scim) | [authentication](/docs/concepts/authentication) |
| Frontegg, PropelAuth, SuperTokens, Hanko | Application-auth vendors | `subjectFromJwt` | [authentication](/docs/concepts/authentication) |
| Zitadel | Open-source IdP with project roles nested per organisation in `urn:zitadel:iam:org:project:roles` | `subjectFromJwt` with `claims.memberships` flattening role to `{ tenant, roles }` | [JWT authorization claims](/docs/standards/jwt-authorization-claims), [tenancy](/docs/concepts/tenancy) |
| Organisation, team and custom-role models (Clerk, Auth0 Organizations, WorkOS, Better Auth `organization` plugin, Kinde, Descope, Frontegg, PropelAuth, Logto) | Where memberships and tenant-defined roles are stored | `principal.memberships` from `subjectFrom*`; `RoleSource` and `MembershipSource` per provider; never a PermDock table | [tenancy](/docs/concepts/tenancy) |
| SCIM 2.0 directories (Okta, Entra ID, Google Workspace; or via WorkOS Directory Sync) | Group provisioning; group `id` as team identifier | Adapter (`permdock/scim`: `scimHandler` writes a `DirectoryStore` you own, `directoryMembershipSource` yields memberships keyed on the SCIM id); the Cloud relay replays into the same handler | [SCIM adapter](/docs/adapters/scim), [JWT authorization claims](/docs/standards/jwt-authorization-claims) |
| Vercel Agent Auth (Better Auth) | Delegated agent identities via RFC 8693; capability grants | `actor` and `delegation` mapper when published; capability grants are permission references | [landscape](/docs/research/landscape), [Cloud adapter](/docs/adapters/cloud) |
| Web Bot Auth, SPIFFE | Workload and bot identity | `actor` from signature or SVID | [Web Bot Auth](/docs/standards/web-bot-auth), [threat model](/docs/security/threat-model) |
| `jose` (panva) | JOSE library: JWS / JWE / JWK / JWT, remote JWK Sets, `typ` and `requiredClaims` checks | Optional peer of `permdock/jwt` and `permdock/ssf`; `joseTokenVerifier` and `joseTokenSigner` wrap it; other libraries plug in through `TokenVerifier` / `TokenSigner` | [JWT adapter](/docs/adapters/jwt), [JOSE](/docs/standards/jose) |
| OpenID Connect providers publishing Discovery | Source of `issuer` and `jwks_uri` for verification | `subjectFromJwt({ discovery })`; RFC 8414 fallback | [OpenID Connect](/docs/standards/openid-connect), [JWT adapter](/docs/adapters/jwt) |

## Agent runtimes and frameworks [#agent-runtimes-and-frameworks]

PermDock's agent adapters are thin translators from a `Decision` into a runtime's vocabulary. A framework earns an adapter only when it has a per-tool-call hook that can proceed, refuse or ask a human; a resume path on which the adapter can recompute `Decision.token`; and no existing route through MCP, the AI SDK, AuthZEN or a shipped adapter. Most frameworks fail the last test: MCP guards every tool a framework consumes from an MCP server, and the AI SDK adapter applies to everything built on it. A hook that cannot express "ask a human" must never map `approval-required` to `denied`, and the subject always comes from the host's verified material, never from agent state.

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Vercel AI SDK 7 | Model and tool layer; `toolApproval` returns `approved`, `denied` or `user-approval` | Adapter (`permdock/ai-sdk`) | [AI SDK adapter](/docs/adapters/ai-sdk) |
| Claude Agent SDK | Anthropic agent runtime; `canUseTool`, `PermissionRequest` hook | Adapter (`permdock/claude-agent`) | [Claude Agent adapter](/docs/adapters/claude-agent) |
| Eve | Vercel agent framework; `approval` and `approval.response` on `defineTool` | Adapter (`permdock/eve`) | [Eve adapter](/docs/adapters/eve) |
| OpenAI Agents SDK | `needsApproval`, `interruptions`, serialisable `RunState`; tool guardrails as a second hook that cannot pause | Adapter (`permdock/openai`) | [OpenAI adapter](/docs/adapters/openai) |
| Model Context Protocol servers | Tool protocol runs the official SDK behind OAuth 2.1 | Adapter (`permdock/mcp`) | [MCP adapter](/docs/adapters/mcp) |
| WebMCP | Browser tool registration | Adapter (`permdock/webmcp`) | [WebMCP adapter](/docs/adapters/webmcp) |
| A2A | Agent-to-agent protocol | Adapter (`permdock/a2a`) | [A2A adapter](/docs/adapters/a2a) |
| `@ai-sdk/react` | AI SDK UI hooks (`useChat`, tool approval parts) | Recipe (`permdock/ai-sdk` on the route, approval parts rendered by the app) | [AI SDK adapter](/docs/adapters/ai-sdk) |
| LangGraph.js | Graph runtime; `interrupt()` in a node, `Command({ resume })` with a checkpointer | Recipe (wrap each tool with `decide`, `interrupt` on `approval-required`, recompute `token` on resume); the one adapter candidate if the recipe proves too fiddly | [approvals](/docs/security/approvals) |
| Mastra | Tool `execute`; workflow `suspend()` and `resume()` | AI SDK; recipe mapping `approval-required` to `suspend` | [approvals](/docs/security/approvals) |
| Cloudflare Agents SDK | AI SDK tools on Durable Objects | AI SDK; Durable Objects as the `ApprovalStore` | [approvals adapter](/docs/adapters/approvals) |
| Vercel Workflow `WorkflowAgent` | Durable `needsApproval` suspend | AI SDK (`needsApproval(permission)`) | [AI SDK adapter](/docs/adapters/ai-sdk) |
| Inngest AgentKit | Tool handlers, `beforeTool`-style middleware, `step.waitForEvent` | Recipe: middleware calls `decide`; approval as a wait step keyed by `token` | [approvals](/docs/security/approvals) |
| Google ADK for TypeScript | `beforeToolCallback`, `afterToolCallback` | Recipe: refuse from `decide`; approvals need the app's own pause | [approvals](/docs/security/approvals) |
| OpenAI Apps SDK (ChatGPT apps) | Apps are MCP servers | MCP | [MCP adapter](/docs/adapters/mcp) |
| n8n | AI Agent "Require approval" option and "Send and Wait for Response" node | MCP on the tool side; no-code approval delivery | [approvals adapter](/docs/adapters/approvals) |
| AWS Bedrock AgentCore Runtime and Policy | Hosted runtime; Cedar at the gateway over tool name and parsed arguments, with no row and no pause | MCP; recipe | [OpenAPI adapter](/docs/adapters/openapi) |
| Custom loops on raw provider SDKs | Whatever the loop author writes | `decide` and `assert` directly | [for AI agents](/docs/for-ai-agents) |
| AG-UI | Event stream between agent backend and UI, including human-in-the-loop events | Tracking; carries PermDock's approval request payload unchanged as a tool-call or custom event | [wire formats](/docs/concepts/wire-formats) |
| Agent Client Protocol | Editor-to-coding-agent protocol with permission requests | Tracking; same shape as the coding-agent hooks | [terminal adapter](/docs/adapters/terminal) |

## Coding-agent hooks [#coding-agent-hooks]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Claude Code hooks | `PreToolUse` allow, deny, ask | Adapter (`permissionRequestHook`) | [Claude Agent adapter](/docs/adapters/claude-agent) |
| Cursor hooks, Gemini CLI hooks, Codex CLI, OpenCode | Pre-tool hooks (`beforeShellExecution`, `beforeMCPExecution`, `BeforeTool`, `tool.execute.before`); tool name and arguments in, allow, deny or ask out | Recipe: one hook script over a `permdock/terminal` guard, subject from the developer's verified login | [terminal adapter](/docs/adapters/terminal) |

## Approval delivery and durable execution [#approval-delivery-and-durable-execution]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Vercel Chat SDK `requestApproval` | Approval cards on Slack, Teams, Discord with signature-verified responders | `ApprovalStore` delivery recipe (reference) | [approvals adapter](/docs/adapters/approvals) |
| Vercel Workflow SDK | Durable steps | Holds the wait | [approvals adapter](/docs/adapters/approvals) |
| Trigger.dev waitpoints, Temporal, Restate, Inngest, Cloudflare Workflows | Durable execution runtimes | `ApprovalStore` recipe | [approvals adapter](/docs/adapters/approvals) |
| Cloudflare Durable Objects, D1, Turso, SQLite, Redis, Upstash, Vercel KV, Postgres, Neon, Supabase | Backing stores | `ApprovalStore` recipe | [approvals adapter](/docs/adapters/approvals) |
| Knock, Novu, Courier, Resend, Twilio | Notification channels | Recipe; link to `approvalsHandler` | [approvals adapter](/docs/adapters/approvals) |
| Pushary, Rills, intrupt, Sesame, AxonFlow | Approval-as-a-service APIs and SDKs | Positioning; a self-hoster may back an `ApprovalStore` with any of them | [landscape](/docs/research/landscape), [approvals adapter](/docs/adapters/approvals) |
| PermDock Cloud | Hosted store, inbox, delivery at [app.permdock.com](https://app.permdock.com); machine API at [api.permdock.com](https://api.permdock.com) | `cloud().approvals` | [Cloud adapter](/docs/adapters/cloud) |
| PermDock Cloud SCIM relay | Hosted SCIM endpoint per tenant replaying into your `scimHandler` | RFC 7523 JWT bearer verified by `scimHandler({ verifier })`; never a `MembershipSource` | [SCIM adapter](/docs/adapters/scim), [Cloud adapter](/docs/adapters/cloud) |

## Sinks, observability and compliance [#sinks-observability-and-compliance]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| OpenTelemetry (`@opentelemetry/api`), GenAI semantic conventions | Tracing API and the `execute_tool` span | Adapter (`permdock/otel`) | [OpenTelemetry adapter](/docs/adapters/otel) |
| Langfuse, LangSmith, Braintrust, Datadog LLM Observability, Sentry, PostHog | LLM observability | OpenTelemetry; no sink needed | [audit](/docs/concepts/audit-and-observability) |
| Splunk, Microsoft Sentinel, Datadog Cloud SIEM, AWS Security Lake, Google SecOps, Elastic Security | SIEMs and security lakes | `DecisionSink` with the OCSF projection; the Cloud posts the same projection to their ingest endpoints | [audit](/docs/concepts/audit-and-observability), [Cloud integrations](/docs/adapters/cloud-integrations) |
| Axiom, Better Stack, a Postgres table, a queue | Log and event destinations | `DecisionSink` recipe; CloudEvents envelope | [audit](/docs/concepts/audit-and-observability) |
| Vanta, Drata, Secureframe | Compliance automation collecting access-review evidence | Pull the signed batch (`permdock-decisions+jwt`) or CSV from the Cloud export endpoint, or query your own sink | [audit](/docs/concepts/audit-and-observability), [Cloud integrations](/docs/adapters/cloud-integrations) |
| Grafana Cloud, Honeycomb, New Relic, Datadog (OTLP intake), OpenTelemetry Collector | OTLP-native backends and receiver | The Cloud exports the evidence log as OTLP log records with `permdock.*` attributes; `permdock/otel` sends the app's spans to the same collector; a convenience copy, never the evidence | [Cloud integrations](/docs/adapters/cloud-integrations), [OpenTelemetry adapter](/docs/adapters/otel) |
| Supabase Edge Functions, Supabase Postgres, Neon, your own Postgres (as evidence destinations) | Tables and functions you own | Scheduled signed-batch pull or a CloudEvents webhook; the Cloud never reads your tables or RLS | [Cloud integrations](/docs/adapters/cloud-integrations) |
| Slack, Microsoft Teams, Discord, email, PagerDuty, Opsgenie | Approval delivery and paging surfaces | Chat SDK `requestApproval` run by the Cloud (Slack, Teams, Discord); email links land on the authenticated inbox; PagerDuty and Opsgenie receive a CloudEvents webhook and never resolve | [Cloud integrations](/docs/adapters/cloud-integrations), [approvals adapter](/docs/adapters/approvals) |
| PermDock Cloud MCP server ([mcp.permdock.com](https://mcp.permdock.com)) | The Cloud's read-only MCP server (evidence queries, pending approvals, catalog and drift) | MCP over streamable HTTP with OAuth 2.1; approvals are never resolvable through it | [Cloud integrations](/docs/adapters/cloud-integrations), [MCP authorization](/docs/standards/mcp-authorization) |
| OCSF, CloudEvents | Schemas for the events on the wire | Projection and envelope | [wire formats](/docs/concepts/wire-formats) |
| PermDock Cloud decision log | Hosted sink | `cloud().sink` | [Cloud adapter](/docs/adapters/cloud) |

## Feature flags and entitlements [#feature-flags-and-entitlements]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| OpenFeature | CNCF vendor-neutral flag API | `subject` or `context` input | [policies](/docs/concepts/policies) |
| `@supabase-labs/middleware-openfeature` | OpenFeature as a `@supabase/middleware` entry (`withOpenFeature`), 0.2.0 | Recipe: the evaluation context's `targetingKey` and tenant come from `ctx.permdock`; a flag never grants a permission | [Supabase provider](/docs/adapters/supabase) |
| Vercel Flags SDK, PostHog, LaunchDarkly, Statsig, Unleash, Flagsmith, GrowthBook | Flag vendors | Through OpenFeature or directly as `context`; never grants | [policies](/docs/concepts/policies) |
| Stripe Entitlements, Clerk Billing, Frontegg entitlements, Kinde `feature_flags` | Billing and plan entitlements | `principal.plans` and `to: plan(...)`, fed by an `EntitlementSource` (`fromStripeEntitlements` reads `stripe.entitlements.activeEntitlements.list` through a structural client, no SDK import); Clerk `fea` stays on roles | [policies](/docs/concepts/policies), [Supabase token hook](/docs/adapters/supabase-hook), [Clerk provider](/docs/adapters/clerk) |
| Stigg, Schematic | Entitlement platforms (features per plan, overrides, usage limits) | Plan features become roles through `context` or a `RoleSource.assignable(tenant)` subset; usage limits map to `limit` grants with a `LimitStore`; never grants on their own | [tenancy](/docs/concepts/tenancy), [policies](/docs/concepts/policies) |
| Nile | Postgres with a tenants table, per-tenant isolation and a tenant-aware connection | `scopes.tenant.key` on rows; `memberOf` compiles to the tenant column; a `MembershipSource` over `users.tenant_users` | [tenancy](/docs/concepts/tenancy), [RLS adapter](/docs/adapters/rls) |

## Databases and sync engines [#databases-and-sync-engines]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Drizzle, Prisma, Kysely | TypeScript query builders and ORMs | Adapter (`toWhere`) | [Drizzle](/docs/adapters/drizzle), [Prisma](/docs/adapters/prisma), [Kysely](/docs/adapters/kysely) |
| splinter | Supabase's Postgres linter (CalVer 2026.09.1), run by `supabase db advisors` and the Supabase MCP server's `get_advisors` | Recipe (`tests/integration` asserts generated RLS raises no WARN or ERROR lint; `permdock rls verify --advisors` maps lints to doctor codes) | [Postgres RLS](/docs/standards/postgres-rls#splinter-supautils-and-pg_jsonschema) |
| supautils | Supabase's Postgres extension guarding reserved roles and superuser-only statements, 3.4.4 | Recipe (`rls generate` and doctor PD063 keep generated SQL and app migrations from altering, dropping or renaming a reserved role or granting a reserved membership) | [Postgres RLS](/docs/standards/postgres-rls#splinter-supautils-and-pg_jsonschema) |
| pg\_jsonschema | JSON Schema validation for `json` and `jsonb` columns, 0.3.3 on Supabase | Recipe (`rls.jsonSchema` emits named `check` constraints on generated `jsonb` columns) | [Postgres RLS](/docs/standards/postgres-rls#splinter-supautils-and-pg_jsonschema) |
| Postgres, Supabase, Neon (RLS) | Row-level security targets | `permdock rls generate` | [RLS adapter](/docs/adapters/rls), [Postgres RLS](/docs/standards/postgres-rls) |
| `@supabase/postgrest-typegen` | Generates TypeScript types from a PostgREST schema | None: the resource schema stays the Standard Schema a resource declares; better-supabase runs it for its typed clients | [better-supabase](/docs/adapters/better-supabase) |
| `@supabase/postgres-meta` | Supabase's catalog API over `pg_catalog` (tables, policies, grants, functions) | Not a dependency: `permdock rls verify --introspect` uses catalog queries modelled on its own | [RLS CLI](/docs/cli/rls#verify) |
| `@supabase-cache-helpers/*` | Query-cache bindings (SWR, TanStack Query) for PostgREST and Storage | None: they cache what RLS already filtered; invalidate on role change as for any cached read | [Supabase provider](/docs/adapters/supabase) |
| `@supabase/lite` | Lightweight Supabase runtime | Not a parity target: no RLS parity with hosted Postgres is claimed; `permdock rls verify` runs against Postgres | [Testing](/docs/adapters/testing) |
| PGlite, `@electric-sql/pglite-socket` | Postgres compiled to WASM and its wire-protocol socket server | Test and example database for `toWhere` (Drizzle through `drizzle-orm/pglite`, Prisma 7 through `@prisma/adapter-pg`); never a runtime dependency | [Drizzle](/docs/adapters/drizzle), [Prisma](/docs/adapters/prisma), [Testing](/docs/adapters/testing) |
| Convex | Backend platform | Adapter (`permdock/convex`) | [Convex adapter](/docs/adapters/convex) |
| Zero (Rocicorp) | Sync engine; ZQL permission expressions per table and operation with `authData` from a JWT | `where` target candidate: a `toZeroPermissions(policy)` generator, the closest fit | This page, [roadmap](/docs/roadmap) |
| ElectricSQL | Sync engine; shapes are a table plus a SQL-subset `where` chosen by your proxy | `where` target candidate for reads; writes stay on routes behind `protect` | This page, [roadmap](/docs/roadmap) |
| PowerSync | Sync engine; edition 3 Sync Streams with SQL subqueries over `auth.user_id()` and token parameters | `permdock powersync generate` compiles read grants to Sync Streams and streams the user's own membership and role rows; `verify` checks no stream syncs a denied row; `powersyncSource` builds the device snapshot from them | [powersync](/docs/cli/powersync) |
| InstantDB | Sync engine; `allow` rule expressions per namespace and operation | Generator candidate after the SQL-like targets | This page, [roadmap](/docs/roadmap) |
| TinyBase | Local-first store with no permission language | Nothing to compile to; `filter`, the snapshot and `protect` | This page, [roadmap](/docs/roadmap) |
| MongoDB, Mongoose | Document database; Mongoose implements Standard Schema; no row-level policy | `where` target candidate: Prisma's MongoDB connector first, then a Mongoose or driver `toFilter` | This page, [roadmap](/docs/roadmap), [RLS adapter](/docs/adapters/rls) |
| Payload CMS | CMS with access-control functions returning `Where` | Tracking | [landscape](/docs/research/landscape) |
| Cloudflare D1, Turso, SQLite | SQLite-family stores without RLS | Drizzle `sqlite` dialect; `ApprovalStore` recipe | [approvals adapter](/docs/adapters/approvals), [RLS adapter](/docs/adapters/rls) |

Every sync-engine and MongoDB candidate is a compiler or generator in the `permdock` CLI, never a runtime dependency, and joins the parity suite in `permdock/testing` before it ships. The RLS portable subset is the contract: an operator that does not compile to RLS will not compile to a sync engine either. Engine filters take subject material only from verified token claims, and they cover reads only; every write still passes through a route or mutator guarded by `protect`, so `approval-required` and closures keep working.

## Testing and CI [#testing-and-ci]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Supabase capability matrix (`supabase/sdk`) | Three-segment capability ids (`auth.session.get_claims`) shared by the Supabase client SDKs, `capability-matrix-v1.12.0`; a `{ feature, cases }` conformance-vector schema is in review (PR #30) | Tracking: the Supabase manifest names the capability ids the adapter needs; claim vectors follow the conformance shape | [Watch list](/docs/standards/watch-list) |
| Playwright | Browser and API e2e runner | Recipe (runs `@next/playwright`; no PermDock entry) | [Next.js Cache Components guide](/docs/guides/next-cache-components) |
| `@next/playwright` | Next.js Playwright helper; `instant()` asserts a navigation completed from prefetched UI | Recipe (the instant-navigation test, no wrapper in `permdock/testing`) | [Next.js Cache Components guide](/docs/guides/next-cache-components) |
| testcontainers | Docker-backed Postgres for RLS parity and the `next-better-supabase` example | Recipe (`pnpm test:integration`, the example's `serve`) | [Testing adapter](/docs/adapters/testing), [RLS adapter](/docs/adapters/rls) |
| Bun, Deno | JavaScript runtimes with a Web `fetch` server | WinterTC entries run unchanged; `tests/runtimes` smoke (kernel, Hono, AuthZEN, JWT; Elysia on Bun) | [Testing adapter](/docs/adapters/testing), [server kernel](/docs/adapters/server-kernel) |
| workerd, Miniflare | Cloudflare Workers runtime and its local simulator | WinterTC entries without `nodejs_compat`; `tests/runtimes` smoke through Miniflare | [Testing adapter](/docs/adapters/testing), [server kernel](/docs/adapters/server-kernel) |
| esbuild | Bundler | Builds the `platform: 'neutral'` Worker bundle in `tests/runtimes`; never a dependency of `permdock` | [Testing adapter](/docs/adapters/testing) |
| `@pgkit/migra` | The schema diff engine `supabase db diff` runs | Recipe (`tests/integration` diffs the generated schema files against the migrations with the CLI's options; never a dependency of `permdock`) | [rls](/docs/cli/rls#supabase-db-diff) |

## Distribution channels [#distribution-channels]

| Channel | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| npm (`permdock`) | The package | Install path | [installation](/docs/getting-started/installation) |
| Vercel Marketplace | Native integration listing for PermDock Cloud; `eve-agent` template | Cloud provisioning | [Cloud adapter](/docs/adapters/cloud), [landscape](/docs/research/landscape) |
| Supabase partner marketplace, Convex components directory | Provider ecosystems | Distribution | [landscape](/docs/research/landscape) |
| Cursor and Claude Code plugin marketplaces, skills.sh | Skills and a docs MCP | Distribution | [agent docs standards](/docs/standards/agent-docs-standards) |
| Slack App Directory | Listing for an approval bot | Distribution | [Cloud integrations](/docs/adapters/cloud-integrations) |
| GitHub (App for `permdock-audit`; Actions recipe for `--check`) | CI and review | Recipe; Cloud PR bot | [CLI: openapi](/docs/cli/openapi) |
| MCP Registry | Discovery of MCP servers | Recipe (`server.json`, `POST /mcp`) | [agent docs standards](/docs/standards/agent-docs-standards) |
| AWS Marketplace | Channel for the hosted ADS for teams enforcing from Go or Java on AWS | Not yet | [landscape](/docs/research/landscape) |

## App frameworks (collect-only) [#app-frameworks-collect-only]

| Tool | What it is | Mechanism | Owning page |
| --- | --- | --- | --- |
| Nuxt | Vue meta-framework on Nitro and Vite | Loader (`getSnapshot` in a server route, `permdock/vue`) | [server kernel](/docs/adapters/server-kernel#snapshot-loaders), [Vue](/docs/adapters/vue) |
| Astro | Content-first framework with Vite and islands | Recipe (`createPermDockUnplugin.vite`, island UI adapter, `permdock/server`) | [unplugin](/docs/cli/unplugin) |
| React Router 7 | Vite-based router / framework | Loader (`getSnapshot` and `snapshotHeaders` in `loader`, `permdock/react`) | [unplugin](/docs/cli/unplugin), [UI](/docs/concepts/ui) |
| TanStack Start | Full-stack Vite framework | Loader (`getSnapshot` in `createServerFn`, `permdock/react`) | [unplugin](/docs/cli/unplugin), [UI](/docs/concepts/ui) |
| Effect | Typed-effects runtime; Effect Schema and HttpApi | Recipe (Standard Schema adapter; Overlay on HttpApi output; unplugin when the bundler is Vite) | [unplugin](/docs/cli/unplugin), [Standard Schema](/docs/standards/standard-schema), [OpenAPI](/docs/adapters/openapi) |
| SvelteKit | Svelte meta-framework on Vite | Loader (`getSnapshot` in `+layout.server.ts`, `permdock/svelte` stores) | [Svelte](/docs/adapters/svelte), [unplugin](/docs/cli/unplugin) |
| SolidStart | Solid meta-framework on Vinxi and Nitro | Recipe (`permdock/solid` accessors, `permdock/server` in server functions) | [Solid](/docs/adapters/solid), [unplugin](/docs/cli/unplugin) |
| Nitro | Server engine under Nuxt, SolidStart and TanStack Start | Recipe (`permdock/server` over the Web `Request`) | [server kernel](/docs/adapters/server-kernel) |
| Expo Router and `expo-server` | File-based routing and API routes for React Native apps | Recipe (`permdock/react-native` in screens, `permdock/server` in API routes) | [React Native](/docs/adapters/react-native) |
| Turborepo | Monorepo task runner | Recipe (shared definitions package, `permdock collect` with globbed `srcPath`) | [collect](/docs/cli/collect), [Next.js plugin](/docs/cli/next-plugin) |
| tsdown | Library bundler used for PermDock's packages and a shared definitions package | Build tool; a bundled copy of the definitions resolves to the same grants by `key` | [collect](/docs/cli/collect) |
| unplugin | Unified bundler plugin helper | Hook (`createPermDockUnplugin`) | [unplugin](/docs/cli/unplugin) |

## Adopt / adapt / avoid [#adopt--adapt--avoid]

Adopt: standard fields, the Overlay, `subjectFromJwt`, the hosted-capability interfaces (`ApprovalStore`, `DecisionSink`, `SnapshotSource`), MCP and AuthZEN as the mechanisms through which every row is reached; MCP and the AI SDK as the two integration points that cover most agent frameworks.

Adapt: a recipe on the owning page whenever a tool needs more than a standard field; a consumer-side overlay when a tool wants a derived value in its own namespace; compilers and generators, not runtime adapters, for new data targets.

Avoid: a package entry for any row that is not already on the [adapters](/docs/adapters) matrix; one adapter per agent framework; naming a tool anywhere in the docs without a row here.
