@@ -45,40 +45,46 @@ ports reached for it without coordinating.
4545 has the emitter internally (` src/notifications/events.js ` ). The seam
4646 every "react to pod writes" app (webhooks, indexing, sync, full-text)
4747 will want.
48- 3 . ** ` api.serverInfo ` (` { baseUrl, port } ` at listen)** — ** consumers:
49- notifications/, webdav/, sparql/, nip05/** (subdomain per-host
50- filtering). Every plugin that mints absolute URLs or reaches the host
51- over loopback repeats the origin in config today; a wrong value fails
52- quietly (nip05 serves an empty identity map). Cheap to provide.
48+ 3 . ** ` api.serverInfo ` (` { baseUrl, port } ` at listen)** — ** eight+
49+ consumers: notifications/, webdav/, carddav/, caldav/, sparql/, rss/,
50+ nip05/, webfinger/, mastodon/, bluesky/, activitypub/** — essentially
51+ every plugin that mints absolute URLs or reaches the host over loopback.
52+ All repeat the origin in config today; a wrong value fails quietly (nip05
53+ serves an empty identity map). The single most * broadly* needed seam
54+ (vs. api.authorize being the most * blocking* ); trivially cheap to provide.
53554 . ** The unconsumed-body-** stream** primitive (#583 )** — consumer:
5456 gitscratch/ sharpened it. tunnel/ needed the raw * buffer* ; git needs the
5557 raw * stream* piped to a subprocess gzip-and-all. Whatever ` api.mountApp `
5658 / raw-body mode ships must hand back the un-drained stream, not just a
5759 buffered body. (This is exactly what the merged loader's scoped
5860 pass-through parser does — the finding is to keep it that way.)
59- 5 . ** Routes/WAC-exemption outside the single prefix** — ** four consumers:
60- nip05/, webdav/ & carddav/ (` /.well-known/* ` ), mastodon/ (` /api ` ,
61- ` /oauth ` ).** A plugin can * register* absolute/exact routes outside its
62- prefix (the loader doesn't confine ` api.fastify ` ), but the loader
63- WAC-exempts only its ** one** ` prefix ` (` plugins.js ` pushes ` prefix ` to
64- ` appPaths ` ). Consequences, in increasing severity:
65- - nip05/webdav/carddav land on ` /.well-known/* ` , which core * happens* to
66- blanket-exempt — so they work ** by luck** , not by contract.
67- - ** mastodon** needs ` /api ` ** and** ` /oauth ` , and ** bluesky** needs
68- ` /xrpc ` — none of which core exempts, so ** the plugin cannot serve its
69- own surface** : every call 401s at the WAC hook until the operator
70- hand-passes ` appPaths: ['/api','/oauth','/xrpc'] ` . A plugin has no way
71- to exempt a path it owns. ** Two independent confirmations** (two
72- protocol shims, built separately), and bluesky sharpens it: it needs
73- only * one* extra root and still can't reach it, so the seam is not
74- "more prefixes" but ** "a plugin declares the paths it owns,
75- independent of its mount prefix."**
61+ 5 . ** Routes/WAC-exemption outside the single prefix** — ** the most-hit
62+ finding: seven+ consumers.** A plugin can * register* absolute/exact
63+ routes outside its prefix (the loader doesn't confine ` api.fastify ` ), but
64+ the loader WAC-exempts only its ** one** ` prefix ` . Consequences, in
65+ increasing severity:
66+ - ** ` /.well-known/* ` served by luck** — nip05/ (` nostr.json ` ),
67+ webfinger/ (` webfinger ` ), webdav/carddav/caldav (` caldav ` /` carddav ` ).
68+ Core * happens* to blanket-exempt ` /.well-known/* ` , so they work but by
69+ coincidence, not contract. Notably nip05 and webfinger are the ** two
70+ most-wanted ` .well-known ` docs a deployment serves** , both riding the
71+ same undocumented luck.
72+ - ** fixed roots core does NOT exempt** — mastodon/ (` /api ` ,` /oauth ` ),
73+ bluesky/ (` /xrpc ` ), activitypub/ (` /ap ` ). Here the plugin ** cannot
74+ serve its own surface** : every call 401s at the WAC hook until the
75+ operator hand-passes ` appPaths ` . ** Three independent protocol-shim
76+ confirmations** , each built separately. bluesky sharpened it (one root,
77+ still unreachable → the ask is "declare owned paths," not "more
78+ prefixes"); activitypub sharpened it further — its natural layout wants
79+ paths ** interleaved with** the pod's own ` /<user>/ ` namespace, which no
80+ single mount prefix can carve out at all.
7681 - none of it has conflict detection: a future core route at a
77- plugin-claimed path throws ` FST_ERR_DUPLICATED_ROUTE ` at boot.
82+ plugin-claimed path throws ` FST_ERR_DUPLICATED_ROUTE ` at boot (and a
83+ link registry — ` api.webfinger.addLink ` — is missing, so two plugins
84+ contributing ` .well-known/webfinger ` links would collide silently).
7885 The seam: ` api.reservePath('/xrpc') ` (or ` paths: [...] ` in the entry) —
7986 the loader exempts * and* claims each deliberately and reports collisions.
80- This is the seam ** every API-shim plugin** (mastodon, bluesky, and any
81- future ActivityPub/Matrix/gateway) structurally requires; it's the third
87+ The seam ** every API-shim plugin** structurally requires; third
8288 most-demanded after ` api.authorize ` and ` api.events ` .
83896 . ** Can't set fastify server options** — consumer: capability/ hit
8490 ` maxParamLength ` (100) silently 404ing long tokens in named params;
0 commit comments