OpenAPI registries
The OpenAPI Initiative registries, the x-permdock- namespace PermDock emits, which registered x-oai-* extensions it reuses, why it does not use x-agent-trust, the JWS typ values and media types PermDock signs with, and the rule for never inventing names in someone else's namespace.
Status: planned
What it is
The OpenAPI Initiative maintains a set of registries that give shared names to things the specification itself leaves open:
| Registry | What it lists |
|---|---|
| Extension Field | Individual x-* fields with a defined meaning and the objects they may appear on |
| Namespace | Prefixes of the form x-{namespace}- reserved for one organisation or project |
| Format | Values for the JSON Schema format keyword |
| Tag Kind | Values for the tag kind field |
| Media Type | Media types with defined handling in OpenAPI descriptions |
| Draft Feature | Features being trialled before they enter the specification |
| Alternative Schema | Schema languages other than JSON Schema that a description may reference |
Registering is a pull request against OAI/spec.openapis.org that adds a Markdown file under registries/_{registryName}. The Namespace Registry requires the prefix format x-{namespace}- with lowercase identifiers; registered namespaces are fdx, jsonschema, ms, oai (reserved for the OpenAPI Initiative), oas-draft, oas, sap and scalar.
The Extension Registry entries that matter to PermDock:
x-oai-deprecated: marks a Security Scheme deprecated in documents older than 3.2.x-oai-deviceAuthorization: the OAuth 2.0 device authorization flow insideflows, pre-3.2.x-oai-deviceAuthorizationUrl: the RFC 8628 device authorization endpoint, pre-3.2.x-agent-trust: a trust-level block (algorithm,trustLevels,issuerKeysUrl) forapiKeyschemes whose header isAgent-Signature, from thedraft-sharif-agent-identity-frameworkfamily. It is listed here because it looks close to Web Bot Auth and is not: PermDock does not emit it (see below).
There is no registered x-oai-oauth2MetadataUrl, and permdock is not a registered namespace today.
Why it matters for PermDock
PermDock puts permission keys, portable conditions, approval metadata and security-profile declarations into OpenAPI documents so gateways, SDK generators, portals and agents can read them. Every one of those fields is an extension. Two things go wrong when extensions are named casually:
- Collisions. An
x-permissionsfield means something different to every tool that emits one. A registered namespace makesx-permdock-permissionsmean exactly one thing. - Impersonation. Writing an unregistered
x-oai-*name looks official and is not; a viewer that implements the registeredx-oai-*set will ignore it or, worse, misread it.oaiis reserved for the OpenAPI Initiative.
Conversely, when a registered extension already says what PermDock needs to say, reusing it means other tools understand the output without knowing PermDock exists. That is why the 3.1 fallbacks for device authorization and deprecation use the x-oai-* names. The converse also holds: a registered name whose definition is for a different protocol is not reused because it looks close, which is why the Web Bot Auth scheme carries no x-agent-trust.
How PermDock uses it
The permdock namespace
Registering permdock in the Namespace Registry is planned; the permdock/openapi entry and permdock openapi already emit the prefix. The registration is:
- Open a pull request against OAI/spec.openapis.org adding a Markdown file for the
permdocknamespace under the namespace registry directory. - Prefix:
x-permdock-; identifiers are lowercase, camelCase after the prefix as inx-permdock-securityProfile(the registry constrains the namespace token, not the suffix). - Point the entry at this page as the description of every field in the namespace.
Until the registration lands, the extensions are still valid OpenAPI (any x- field is), but the prefix is not reserved. Nothing in PermDock's output changes when it is.
PermDock extensions
| Extension | Appears on | JSON shape | Purpose |
|---|---|---|---|
x-permdock-permissions | Operation | Array of permission keys: ["post.delete"]; the matching scope of each key appears in the operation's security | The permissions protect enforces on the route, in catalog terms |
x-permdock-conditions | Operation | Object keyed by permission key whose values are portable condition JSON (wire formats) | What a scope allows beyond "the scope is present", e.g. authorId = principal.id |
x-permdock-securityProfile | Security Scheme, Operation | String, currently "fapi2" | Declares that the resource server implements a named security profile (FAPI 2.0); an operation-level value overrides the scheme's. On --target 3.3 output it is the stable twin of the native type: profile scheme and securityProfileRequirements emitted from the pinned OpenAPI 3.3 draft, so consumers that ignore the draft still see the declaration |
x-permdock-approval | Operation | Object keyed by permission key: { "post.delete": { "reason": "human" } } | The operation may answer approval-required; clients can plan for an approval step (approvals) |
x-permdock-arity | Operation (permdock openapi emit --arity only) | { "kind": "collection" } or { "kind": "instance", "parameter": "id" } | Whether the operation acts on one resource and which path parameter carries its id, for generated MCP servers and SDKs (permdock openapi) |
x-permdock-oauth2MetadataUrl | Security Scheme (3.1 targets only) | URL string | Fallback for the 3.2 oauth2MetadataUrl field, for which no x-oai-* extension is registered |
x-permdock-catalog | Root | { "v": 1, "generator": "permdock/openapi", "drafts": { "oas": "3.3-dev@<commit>", "securityProfiles": "oai-discussion-5304@2026-09-01", "overlay": "1.2-dev@<commit>" } } | Identifies the generator and the shape version (v); it carries no catalog hash, because permdock openapi --check detects drift by regenerating the output and comparing it. drafts is present only when the output depends on an unfinished specification (today: --target 3.3 for oas and securityProfiles, --overlay 1.2 for overlay) and names each pinned revision; --check fails and permdock doctor warns when the pins differ from the installed CLI's |
Every value is plain JSON that survives the same round trips as a permission leaf; nothing in an extension is a reference to a runtime object.
x-permdock-permissions needs only the permission references, so permissionsExtension(permissions) and securityFor(permission) in permdock/openapi build it without a policy, for contract packages that cannot import server code (contract packages). The other operation extensions read the grants and come from the policy-backed emitter.
{
"paths": {
"/posts/{id}": {
"delete": {
"operationId": "deletePost",
"security": [{ "permdockOAuth": ["post:delete"] }],
"x-permdock-permissions": ["post.delete"],
"x-permdock-conditions": {
"post.delete": {
"op": "eq",
"field": "authorId",
"value": { "ref": "principal.id" }
}
},
"x-permdock-approval": { "post.delete": { "reason": "human" } },
"x-permdock-securityProfile": "fapi2",
"responses": {
"204": { "description": "Deleted" },
"403": { "$ref": "#/components/responses/PermDockDenied" }
}
}
}
}
}Registered names PermDock reuses
| Situation | Registered extension | Where PermDock writes it |
|---|---|---|
Deprecated scheme, --target 3.1 | x-oai-deprecated | Security Scheme |
Device authorization flow, --target 3.1 | x-oai-deviceAuthorization | Inside flows of an oauth2 scheme |
Device authorization endpoint, --target 3.1 | x-oai-deviceAuthorizationUrl | Inside that flow |
JWS typ values PermDock emits
These are not OpenAPI extensions but they are the other namespace PermDock writes into a registered-vocabulary position: the typ header parameter of every JWS PermDock signs (RFC 7515 section 4.1.9; the value is a media type name without the application/ prefix per RFC 7519 section 5.1). They are listed here so that one page holds every name PermDock places in a shared registry-shaped slot, and so that emitting a typ not in this table is a documentation failure before it is a code one (JOSE, wire formats).
typ | Private claim | Emitted by |
|---|---|---|
permdock-snapshot+jwt | snapshot (snapshot v: 1) | permdock.snapshot({ signer }), permdock/cloud snapshots |
permdock-approval+jwt | approval | approvalsHandler({ signer }) |
permdock-decisions+jwt | events | A DecisionSink with signer, permdock/cloud export |
permdock-policy+jwt | policy (policy document v: 1); iss = aud = the Cloud environment URL, exp = iat + 24 hours | PermDock Cloud hosted grants, read by cloud().policies |
permdock-capability+jwt | capability (capability v: 1); sub = the link id, exp = capability.expiresAt | signCapability, read by subjectFromCapability |
The +jwt structured syntax suffix is registered (RFC 8417 section 7.2), so any JOSE library treats these as JWTs. Each typ is the short form of a media type, and the full names are the media types PermDock documents:
| Media type | typ | Carried as |
|---|---|---|
application/permdock-snapshot+jwt | permdock-snapshot+jwt | A signed snapshot in a response body or SnapshotSource payload |
application/permdock-approval+jwt | permdock-approval+jwt | A signed approval request handed to a delivery surface |
application/permdock-decisions+jwt | permdock-decisions+jwt | A signed event batch: a sink export or a Cloud webhook delivery |
application/permdock-policy+jwt | permdock-policy+jwt | The hosted-grants policy document from GET /policy |
application/permdock-capability+jwt | permdock-capability+jwt | A link capability, usually in a URL query parameter |
On the wire PermDock sends and accepts application/jwt as the Content-Type of every one of them, because a receiver checks typ after verifying and application/jwt is registered (RFC 7519 section 10.3.1); the specific names identify the envelope in documentation, in OpenAPI content keys a team writes for its own endpoints, and in the typ check. They are not registered with IANA, unlike at+jwt (RFC 9068), secevent+jwt (RFC 8417) and logout+jwt (Back-Channel Logout); until they are, the names are safe because a verifier only accepts the typ it was configured for. A breaking change to an envelope is a new typ value and a new row, never a changed row. Fixtures in permdock/testing assert the set of typ values the package can emit equals this table.
For Web Bot Auth, a team that wants signed agent traffic in its description declares an apiKey scheme with in: header and name: Signature-Agent, the header through which the verifier discovers the signer's keys, and lists it as an alternative requirement next to the OAuth scheme. It uses standard fields only:
{
"components": {
"securitySchemes": {
"webBotAuth": {
"type": "apiKey",
"in": "header",
"name": "Signature-Agent",
"description": "RFC 9421 HTTP Message Signature (Web Bot Auth); keys are discovered through the Signature-Agent directory."
}
}
}
}PermDock does not emit this scheme, because whether a route accepts signed agents is the application's deployment decision, and it does not attach x-agent-trust to it: that extension is defined for the Agent-Signature header of a different draft family, with its own trust-level vocabulary, and a consumer that implements it would misread a Web Bot Auth scheme.
Rules
- Never invent an
x-oai-*name. Theoainamespace belongs to the OpenAPI Initiative; if a 3.2 or 3.3 feature has no registered pre-3.2 extension, the fallback isx-permdock-*(as foroauth2MetadataUrl). - Use a registered extension whenever one exists for the purpose, including extensions outside the
oainamespace, and only for the purpose its entry defines. - Otherwise use
x-permdock-*, document it in the table above, and version its shape throughx-permdock-catalog.v. - Never write into another registered namespace (
x-ms-,x-sap-,x-scalar-,x-jsonschema-), nor into an unregistered vendor namespace a consumer reads as its own: gateway import fields (x-amazon-apigateway-*,x-google-*,x-kong-*,x-zuplo-*), docs-host and generator fields (x-mint,x-mcp,x-topics,x-fern-*,x-speakeasy-*,x-stainless-*,x-readme), nor another party's extension for a protocol PermDock has not adopted (the communityx-gnap; see GNAP). A team that wants one of those derived from PermDock's fields writes its own consumer-side overlay (OpenAPI ecosystem), even when a field there looks close. - The importer reads the native fields, the registered fallbacks and the
x-permdock-*set; unknown extensions are preserved untouched, never dropped. - Draft-only native fields (today the
type: profilescheme andsecurityProfileRequirementson--target 3.3, and the Overlay 1.2components.actionsshape on--overlay 1.2) are emitted only behind an experimental flag, always with a stable twin (thex-permdock-*extension, or the 1.1 Overlay form), and with the pinned revision written intox-permdock-catalog.drafts.
tests/standards/openapi-registry.test.ts enforces rules 1, 3 and 4 mechanically: every x- name in the emitter's output, on every target and in both Overlay versions, must be a row of the extension table above or one of the three registered x-oai-* names, and the JWS typ literals in the source must equal the typ table.
Registration checklist
These steps happen outside this repository. Remove the Status: planned line at the top of this page in the pull request that records the first one as merged.
- Namespace: open the pull request against OAI/spec.openapis.org that adds
registries/_namespace/permdock.mdwith prefixx-permdock-, a link to this page and the maintainers' contact; record the PR link here. - Extensions: after the namespace merges, nothing further is needed per field; the table above is the description the registry entry links to.
- Media types: decide whether to request IANA registration of the five
application/permdock-*+jwttypes (a specification-required registration under RFC 6838 section 3.1 needs a published document; this page and wire formats are the candidate). Until then the table above is the only definition.
Why
- No
x-agent-trust. The entry's definition, header name and trust-level vocabulary belong to another draft family. Rule 2 exists so other tools understand PermDock's output; reusing a name for a different protocol produces the opposite. application/jwton the wire. Receivers already routeapplication/jwt, and thetypcheck after verification is what selects the envelope; a specificContent-Typewould add a second place for the two to disagree.
Mapping table
| Registry concept | PermDock concept |
|---|---|
Namespace permdock, prefix x-permdock- | Every PermDock-specific field in a document |
Extension x-oai-deprecated | scheme.deprecated adapter option, 3.1 output |
Extension x-oai-deviceAuthorization, x-oai-deviceAuthorizationUrl | scheme.flows.deviceAuthorization adapter option (--device-flow), 3.1 output |
Extension x-agent-trust | Not used: it is defined for Agent-Signature, not Web Bot Auth's Signature-Agent |
Extension Registry, no entry for oauth2MetadataUrl | x-permdock-oauth2MetadataUrl |
| Format, Tag Kind, Draft Feature, Alternative Schema registries | Not used; PermDock emits standard JSON Schema formats and no draft features |
| Media Type registry, IANA media types | application/permdock-*+jwt, documented above; not registered |
(JOSE, not OAI) JWS typ header values | permdock-snapshot+jwt, permdock-approval+jwt, permdock-decisions+jwt, permdock-policy+jwt, permdock-capability+jwt, the closed list above |
Sources
- OpenAPI Initiative registries.
- Namespace Registry.
- Extension Registry.
- OAI/spec.openapis.org, where registrations are submitted.
Related
- OpenAPI: the 3.1 fallback table, and why
x-permdock-securityProfileexists and what it twins on 3.3 output. - OpenAPI Overlay: how the extensions are delivered without mutating the source document.
- watch list: the draft pin in
x-permdock-catalog.drafts. - Web Bot Auth: the
Signature-Agentscheme recipe. - OpenAPI adapter and CLI: openapi.
Last updated on
Arazzo workflows
How an Arazzo 1.1.0 workflow is an agent plan, and how permdock simulate pre-flights every step by resolving its operationId to the operation's x-permdock-permissions and returning one Decision per step before anything executes.
RFC 9457 Problem Details
The application/problem+json body PermDock's HTTP adapters return for denied and approval-required decisions, and why it is written for humans and models alike.