A pass over JSS’s plugin-labelled backlog, asking of each: can the public
plugin api do this today, and if not, what’s missing? This repo is the
evidence. Legend:
src/ (this is a finding, not a gap)| Issue | Plugin | Note |
|---|---|---|
| #445 | nip05/ |
NIP-05 discovery from pods’ public keys |
| #382 / #379 | corsproxy/ |
CORS forward proxy, fail-closed SSRF defense |
| #506 | capability/ |
scoped, time-bound, revocable capability URLs |
| #507 | webdav/ |
mount a pod in Finder/Nautilus/Windows |
| #509 | sparql/ |
SPARQL SELECT + UPDATE over pod JSON-LD (write-index → 🔩 api.events) |
| #322 | gitscratch/ |
ephemeral Solid-authed git remotes (git-http-backend CGI) |
| #515 / #516 | mastodon/ |
Mastodon-API shim — a client can log into its own pod (needs appPaths widened → 🔩) |
| #505 | otp/ |
one-time-password session flow (account recovery → 🔩 core auth) |
| #157 | carddav/ |
CardDAV contact sync (iOS/macOS/Thunderbird/DAVx5) |
| #211 | bluesky/ |
AT-Protocol XRPC shim — a client logs into its own pod (needs appPaths widened → 🔩) |
| #157-sib | caldav/ |
CalDAV calendar sync — completes the DAV family |
| #164 | webfinger/ |
/.well-known/webfinger — the WebFinger half of #164 |
| #51/#164 | activitypub/ |
federate a pod as an AS2 actor (needs appPaths widened → 🔩) |
| — | rss/ |
any pod container as an Atom/RSS feed |
| — | matrix/ |
Matrix Client-Server API shim (chat) |
| — | search/ |
full-text search over pod resources |
| — | didweb/ |
did:web DID-document resolver |
| — | s3/ |
S3-compatible object-storage gateway |
| — | micropub/ |
IndieWeb Micropub endpoint (media upload → 🔩 raw-body stream #583) |
| — | backup/ |
pod → .tar.gz export (incremental backup → 🔩 api.events) |
| — | metrics/ |
/healthz + Prometheus exporter (core-pipeline metrics → 🔩 gated hooks) |
| — | dashboard/ |
plugin status page (sibling discovery → 🔩 app-registry #463/#464) |
| — | oembed/ |
oEmbed provider (discovery injection → 🔩 header/content hooks) |
| — | jmap/ |
JMAP mail over the pod (push/delta → 🔩 api.events; blobs → 🔩 #583) |
| #163 | remotestorage/ |
remoteStorage server — 7th port; witnessed the webfinger collision |
| — | shortlink/ |
link shortener for pod URLs (pluginDir persistence, 11th witness) |
| #463/#464-adj | admin/ |
operator home — the wp-admin gap analysis; every missing pillar names a seam |
Plus seven ports of bundled features proving the migration path for
#564 / #164: relay/ webrtc/ terminal/ tunnel/ notifications/
remotestorage/, and pay/
(the wall-report — it can’t be a plugin, which is the point).
| Issue | Where |
|---|---|
| #206 | the loader — createServer({ plugins }), merged, v0.0.215 |
| #582 | appPaths WAC exemption, v0.0.213 |
| #584 | api.auth.getAgent, v0.0.214 |
| #588 | api.ws.route WebSocket routing, v0.0.215 |
| #564 | the core/plugin line — answered empirically in NOTES.md |
| Issue | Shape |
|---|---|
| #527 | Tunnel client mode — extends tunnel/ to dial out to a relay |
| #277 | MongoDB-backed relay — relay/ with a Mongo store (needs the infra) |
Each names the seam and the consumer that proves it. Ranked in NOTES.md.
| Issue(s) | Missing seam |
|---|---|
| #509 (write-index), #501 | api.events.onResourceChange — react to pod writes |
| #382 (per-pod ACL), #506 (pod grants) | api.authorize(request, path, mode) — ask the host’s WAC |
#515/#516, #211 (both built, but need operator appPaths) |
api.reservePath() — an API-shim owns fixed roots outside its prefix and can’t self-exempt them from WAC; two independent confirmations |
| #505 (recovery) | api.auth.mintSession / api.identity.addAuthKey — turn a proven channel into pod authority |
| #495 #496 #500 #501 | api.mcp.registerTool — MCP has no plugin-tool seam; all four MCP issues want new tools a plugin can’t add today |
| #463 #464 | app-registry primitive — surfacing installed plugins as Solid resources; dashboard/ is the live proof-of-need (it must be handed a hand-copied duplicate of the createServer list) |
Pipeline-modifying or infrastructural — they are the pod, or they change every request:
| Issue | Why core |
|---|---|
| #185 | token-based storage quota — gates the LDP write path |
| #476, #271 | git auto-init header, git-mark post-receive — inside the core git handler |
| #236 | SFTP/SSH — a separate server protocol, not a Fastify route |
| #154 | SQLite db backend — a storage driver |
| #133 | OIDC-provider replacement — the auth core itself |
Large features or open questions beyond one plugin: #200 (marketplace),
#199 #198 (agent containers), #194 #184 (pane store), #183 (skill
provenance), #163 (remoteStorage follow-ups), #134 (WebID/AP URI unification),
#164 (WebFinger/OAuth extraction — partially met by mastodon/’s OAuth
bridge). Several become tractable on top of the plugin system now that it
exists.
Of ~40 plugin-tagged issues: 14 built as plugins here (plus rss/,
matrix/, search/, didweb/, s3/, micropub/, backup/, metrics/,
dashboard/, oembed/, jmap/, shortlink/, admin/ — capability
demonstrations with no single issue), 7 ported, 5 shipped upstream,
2 more plugin-able with no blocker, 6 clusters blocked on a named
seam (each with a proof-of-need consumer), the rest core-by-nature or
product-scale. 33 plugins total, 386 tests. The plugin api reaches most
of the backlog today; ranked by demand, the seams that would unlock the
most next are api.authorize (4 consumers, 3 hard-blocked), api.events (7
consumers — matrix /sync needs live push, jmap can’t do push or delta
sync, backup can only pull-on-demand),
api.reservePath (API-shims + didweb’s parameterized case + the
witnessed webfinger collision), and
api.serverInfo (broadest: ~23 plugins hand-roll their own origin).