0005: Naming convention
The brand is the noun; PermDock, permdock and createPermDock are used everywhere, import paths name the framework, and a small set of words is reserved.
Status
Accepted, September 2026.
Context
PermDock has one core and more than thirty adapters written by many contributors and, increasingly, by coding agents. Without a convention, adapters drift into NextDock, createHonoPermissions, useAbility, dock.can(...), and every skill and doc page has to special-case them. The landscape has three naming failures worth avoiding by rule: CASL uses can both to define and to check; Kilpi prefixes instance members with $ to dodge collisions with policy names; permix spells the same concept differently across adapters (permix.check, checkMiddleware, usePermix).
next-intl offers a model that Next.js developers already know: useTranslations() in client components and getTranslations() in async server code, same vocabulary, different verb.
Decision
- The brand is the noun. The decision object's type is
PermDock; the instance variable ispermdock. - One factory name. Core and every server or agent adapter export
createPermDock(policy, ...). The import path names the framework:permdock/next,permdock/hono,permdock/mcp. Identifiers never do: noNextDock,HonoDock,createNextPermDock. - React vocabulary.
PermDockProvider,usePermDock,usePermission,Protectedfrompermdock/react, direct exports, no factory. use*/get*duality.usePermDock/usePermissionare synchronous client and RSC hooks;getPermDock/getPermissionare their async server counterparts returned bycreatePermDockfrompermdock/next.- Definition and policy vocabulary.
definePermissions,resource,mergePermissions,listPermissions,findPermission;definePolicy,role,allow,deny,subject. - Instance methods.
can,decide,assert,filter,where,simulate,snapshot,on. - Errors.
PermDockDeniedError,PermDockApprovalRequiredError,PermDockValidationError. - Reserved words that never appear as public identifiers:
dock,ability,canas a definer, and$-prefixed members.
Consequences
- A skill can describe every adapter with one sentence: import
createPermDockfrompermdock/<framework>, call it with the policy and a subject resolver, destructure the framework-shaped result. - Docs, examples and error messages read the same across adapters;
permdock doctorcan lint identifiers against the reserved list. - Helpers are functions, not tree methods, so a resource may be called
listorfindwithout shadowing anything. - The catalog lookup was renamed from
getPermissiontofindPermissionto keepget*exclusively for async server counterparts ofuse*hooks. - Contributors lose some freedom; an adapter proposing a new verb must add it to this page first.
Alternatives considered
- Framework-prefixed identifiers (
NextDock,HonoDock). Rejected: the subpath already carries that information and the identifiers leak into app code. dockas the instance noun. Short, but it is half the brand and reads as jargon in error messages;permdockis unambiguous in logs.ability/canas definers (CASL). Rejected as reserved.$-prefixed members (Kilpi). Rejected; collisions are solved structurally with helper functions.checkinstead ofcan.canreads naturally at call sites and is reserved as a checker only.
Related
0004: Instance actions vs collection actions
Why each resource declares actions that take an instance and collection actions that do not, with the arity encoded in the type.
0006: Explicit factory file, not a Next.js plugin
Why apps wire PermDock through src/permdock/server.ts instead of a Next.js plugin with module augmentation, and why createPermDockPlugin is a build hook only.