Skip to content

Plugin API seam: api.reservePath — an API-shim owns fixed routes outside its prefix and can't self-exempt them from WAC #602

Description

@melvincarvalho

One of four plugin-API seams from building 33 out-of-tree plugins on the #206 loader (report). The most-hit finding: 7+ consumers.

The gap

A plugin can register routes outside its one prefix, but the loader WAC-exempts only that single prefix. So:

  • /.well-known/* works by luck — core happens to blanket-exempt it (nip05 nostr.json, webfinger, the DAV discovery docs). The two most-wanted .well-known docs a deployment serves ride an undocumented coincidence.
  • Fixed protocol roots do NOT work/api,/oauth (mastodon), /xrpc (bluesky), /ap (activitypub), /_matrix (matrix) all 401 at the WAC hook until the operator hand-passes appPaths. The plugin cannot self-exempt the paths the protocol fixes.
  • Parameterized paths can't be expressed at alldidweb/ must serve /<user>/did.json inside the pod's own WAC-governed namespace; appPaths matches literal prefixes, and the DID method pins the URL (no fake root to escape to).

Witnessed collision (both directions)

webfinger/ and remotestorage/ both legitimately own parts of /.well-known/webfinger. Load one order → boot fails with a duplicate-route error (and the loader drops err.code — filed as #599). Load the other → the try/catch-guarded claimant silently loses its links. Loud failure or silent loss, both wrong: for a shared discovery document the reservation primitive isn't enough — a link/JRD registry (api.webfinger.addLink) is the real fix for that case.

Counter-witnesses that scope it: micropub/ and jmap/ needed no reservation because their endpoints are client-/session-discovered, not protocol-fixed. The seam is for protocols that pin absolute paths, not API shims per se.

Sketch

api.reservePath('/xrpc') / api.reservePath('/:user/did.json') (or paths: [...] on the loader entry): the loader WAC-exempts and claims each deliberately, and reports collisions at boot. Plus api.webfinger.addLink(...) (or a generic link registry) for the shared-document case.

Cost

Small-medium — generalizes the existing appPaths mechanism from operator config to plugin declaration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpluginCould be implemented as a plugin (#206); core/plugin line defined in #564priority: mediumP2 - Do when time allows

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions