Split out of #206 (see the plugin-zero results comment there): the first seam a third-party app plugin needs, discovered by mounting Tideholm inside JSS.
Problem
The global WAC preHandler authorizes every URL against pod ACLs and rejects with handleUnauthorized before routes run. The only escapes are the hook's hardcoded prefix list (/storage/, /db, /mcp, webrtc, terminal, tunnel, mashlib, …). A third-party plugin registering routes on the returned fastify instance cannot extend that list — its GETs are at the mercy of the root ACL and its POSTs die in WAC before the handler is reached.
Put differently: every bundled pseudo-plugin needed this exemption and got it by editing server.js. External plugins can't.
Proposal
createServer({ appPaths: ['/tideholm'] }) — URL prefixes owned by registered applications; requests at or below an app path skip the WAC hook. The app owns authentication and authorization under its prefix, exactly the deal /storage/ and /db/ already have.
Working diff (the Tideholm demo runs on this):
@@ createServer options @@
+ const appPaths = Array.isArray(options.appPaths)
+ ? options.appPaths.filter((p) => typeof p === 'string' && p.startsWith('/') && p.length > 1)
+ : [];
@@ the WAC preHandler exempt condition @@
+ appPaths.some(p => request.url === p || request.url.startsWith(p + '/') || request.url.startsWith(p + '?')) ||
Relationship to the plugin loader (#206, #564)
- Today: a standalone option serving bitmark-explorer-style manual compositions.
- Loader lands: a plugin's manifest-declared prefix feeds
appPaths automatically — api.fastify carries the exemption implicitly, and this option becomes the loader's implementation detail.
Acceptance
Split out of #206 (see the plugin-zero results comment there): the first seam a third-party app plugin needs, discovered by mounting Tideholm inside JSS.
Problem
The global WAC
preHandlerauthorizes every URL against pod ACLs and rejects withhandleUnauthorizedbefore routes run. The only escapes are the hook's hardcoded prefix list (/storage/,/db,/mcp, webrtc, terminal, tunnel, mashlib, …). A third-party plugin registering routes on the returned fastify instance cannot extend that list — its GETs are at the mercy of the root ACL and its POSTs die in WAC before the handler is reached.Put differently: every bundled pseudo-plugin needed this exemption and got it by editing server.js. External plugins can't.
Proposal
createServer({ appPaths: ['/tideholm'] })— URL prefixes owned by registered applications; requests at or below an app path skip the WAC hook. The app owns authentication and authorization under its prefix, exactly the deal/storage/and/db/already have.Working diff (the Tideholm demo runs on this):
Relationship to the plugin loader (#206, #564)
appPathsautomatically —api.fastifycarries the exemption implicitly, and this option becomes the loader's implementation detail.Acceptance
/, length > 1); invalid entries droppedrequest.webId(apps resolve identity themselves — see theapi.auth.getAgentissue)