/** * Plugin API capabilities (ADR 0008, plugin-architecture.md §"Plugin API"). * * A capability is a named group of host methods a plugin may call. The plugin * declares the capabilities it needs in its manifest `permissions`; the host * router rejects any call to a method whose capability was not declared. Every * call is executed by the host against the REST API with the **viewing user's** * session, so a plugin can never read more than the person looking at it could. */ /** The capability names a manifest may declare in `permissions`. */ export const CAPABILITIES = [ 'readCurrentPage', 'readPond', 'readBlock', 'blockData', 'ui', ] as const; export type Capability = (typeof CAPABILITIES)[number]; /** * Which host methods each capability unlocks. This is the single source of * truth mapping an RPC method name to the capability that must be declared for * it; both the host router (permission filtering) and the plugin-side `host` * proxy derive from it. */ export const CAPABILITY_METHODS = { readCurrentPage: ['getOutline', 'getContent', 'getMeta'], readPond: ['listPages', 'getPageOutline', 'getPageContent'], readBlock: ['getBlock'], blockData: ['getData', 'setData'], ui: ['resize', 'openPage', 'toast', 'scrollToHeading', 'enterFullscreen', 'exitFullscreen'], } as const satisfies Record; /** Every host method name across all capabilities. */ export type HostMethod = (typeof CAPABILITY_METHODS)[Capability][number]; /** Reverse index: method name → the capability that must be declared for it. */ export const METHOD_CAPABILITY: Readonly> = Object.fromEntries( CAPABILITIES.flatMap((capability) => CAPABILITY_METHODS[capability].map((method) => [method, capability] as const), ), ); /** Returns the capability a host method belongs to, or `undefined` if the * method is not part of the v1 API surface. */ export function capabilityForMethod(method: string): Capability | undefined { return METHOD_CAPABILITY[method]; } /** * Lifecycle methods the **host** calls on the **plugin** (the reverse * direction of the capability methods above). A code plugin implements the * subset it needs; unimplemented methods are answered with an * `unknown_method` error by the plugin endpoint. */ export const PLUGIN_LIFECYCLE_METHODS = ['render', 'edit', 'destroy'] as const; export type PluginLifecycleMethod = (typeof PLUGIN_LIFECYCLE_METHODS)[number];