fedipod-server 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +198 -0
- package/config/server.json +66 -0
- package/dist/adapt.d.ts +18 -0
- package/dist/adapt.js +79 -0
- package/dist/claims.d.ts +12 -0
- package/dist/claims.js +43 -0
- package/dist/components/components.jsonld +12 -0
- package/dist/components/context.jsonld +136 -0
- package/dist/directory.d.ts +38 -0
- package/dist/directory.js +77 -0
- package/dist/handler.d.ts +121 -0
- package/dist/handler.js +432 -0
- package/dist/handler.jsonld +519 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +11 -0
- package/dist/store-css.d.ts +3 -0
- package/dist/store-css.js +41 -0
- package/dist/store-pod.d.ts +20 -0
- package/dist/store-pod.js +148 -0
- package/dist/streaming-handler.d.ts +14 -0
- package/dist/streaming-handler.js +47 -0
- package/dist/streaming-handler.jsonld +72 -0
- package/fedipod-server.svg +134 -0
- package/lib/account.mjs +87 -0
- package/lib/admin.mjs +1606 -0
- package/lib/atproto.mjs +310 -0
- package/lib/bskyfeed.mjs +166 -0
- package/lib/bskygroup.mjs +162 -0
- package/lib/c2s.mjs +305 -0
- package/lib/certs.mjs +265 -0
- package/lib/deliver.mjs +249 -0
- package/lib/directory.mjs +90 -0
- package/lib/embed.mjs +214 -0
- package/lib/export-collections.mjs +161 -0
- package/lib/front-core.mjs +322 -0
- package/lib/gateway-core.mjs +115 -0
- package/lib/guard.mjs +213 -0
- package/lib/home.mjs +161 -0
- package/lib/httpsig.mjs +109 -0
- package/lib/import.mjs +357 -0
- package/lib/intake.mjs +1710 -0
- package/lib/keys.mjs +139 -0
- package/lib/lease.mjs +190 -0
- package/lib/localapi.mjs +87 -0
- package/lib/mastoapi.mjs +1588 -0
- package/lib/migrate.mjs +127 -0
- package/lib/oidc-auth.mjs +53 -0
- package/lib/podrdf.mjs +132 -0
- package/lib/ports.mjs +27 -0
- package/lib/publisher.mjs +1003 -0
- package/lib/remote.mjs +303 -0
- package/lib/safefetch.mjs +235 -0
- package/lib/setup.mjs +262 -0
- package/lib/social.mjs +505 -0
- package/lib/storage.mjs +170 -0
- package/lib/store.mjs +470 -0
- package/lib/streaming.mjs +154 -0
- package/lib/tagfeed.mjs +158 -0
- package/lib/ua.mjs +29 -0
- package/lib/update.mjs +91 -0
- package/lib/webpush.mjs +98 -0
- package/lib/wire.mjs +762 -0
- package/package.json +56 -0
- package/phanpy/dist/404.html +40 -0
- package/phanpy/dist/_headers +2 -0
- package/phanpy/dist/apple-touch-icon.png +0 -0
- package/phanpy/dist/assets/ICONS-DIPJeU0C.js +2 -0
- package/phanpy/dist/assets/ICONS-DIPJeU0C.js.map +1 -0
- package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js +183 -0
- package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js.map +1 -0
- package/phanpy/dist/assets/Temml-CCjoacWt.woff2 +0 -0
- package/phanpy/dist/assets/__vite-browser-external-C7iut881.js +2 -0
- package/phanpy/dist/assets/__vite-browser-external-C7iut881.js.map +1 -0
- package/phanpy/dist/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
- package/phanpy/dist/assets/catch-up-O5q5C75Z.png +0 -0
- package/phanpy/dist/assets/chunk-aKtaBQYM.js +1 -0
- package/phanpy/dist/assets/compose-CFEx7wb4.js +2 -0
- package/phanpy/dist/assets/compose-CFEx7wb4.js.map +1 -0
- package/phanpy/dist/assets/compose-ZJN5xSb4.js +35 -0
- package/phanpy/dist/assets/compose-ZJN5xSb4.js.map +1 -0
- package/phanpy/dist/assets/debug.module-YFQgwnIr.js +52 -0
- package/phanpy/dist/assets/debug.module-YFQgwnIr.js.map +1 -0
- package/phanpy/dist/assets/dom-p1YcJ5Rw.js +2 -0
- package/phanpy/dist/assets/dom-p1YcJ5Rw.js.map +1 -0
- package/phanpy/dist/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
- package/phanpy/dist/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
- package/phanpy/dist/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
- package/phanpy/dist/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
- package/phanpy/dist/assets/icons/add-circle-line-WD0mwORD.js +1 -0
- package/phanpy/dist/assets/icons/alert-line-CpFUMf9s.js +1 -0
- package/phanpy/dist/assets/icons/android-2-line-Bzxnrd3S.js +1 -0
- package/phanpy/dist/assets/icons/announcement-line-5nwaJFJm.js +1 -0
- package/phanpy/dist/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +1 -0
- package/phanpy/dist/assets/icons/arrow-down-line-B8uzXzq6.js +1 -0
- package/phanpy/dist/assets/icons/arrow-left-line-CGrGT9C-.js +1 -0
- package/phanpy/dist/assets/icons/arrow-right-line-CE-HERfX.js +1 -0
- package/phanpy/dist/assets/icons/arrow-to-up-line-CvdQjmcy.js +1 -0
- package/phanpy/dist/assets/icons/arrow-up-circle-line-DEparSNF.js +1 -0
- package/phanpy/dist/assets/icons/arrow-up-line-C7yBeugc.js +1 -0
- package/phanpy/dist/assets/icons/arrows-right-line-BtbXmJGP.js +1 -0
- package/phanpy/dist/assets/icons/at-line-CF66Bznk.js +1 -0
- package/phanpy/dist/assets/icons/attachment-line-BY8It-l9.js +1 -0
- package/phanpy/dist/assets/icons/blockquote-line-BS6pU_hm.js +1 -0
- package/phanpy/dist/assets/icons/board-line-C0UWXyA6.js +1 -0
- package/phanpy/dist/assets/icons/bookmark-line-1CtX5JLF.js +1 -0
- package/phanpy/dist/assets/icons/building-5-line-Dd59MzbO.js +1 -0
- package/phanpy/dist/assets/icons/bus-2-line-6_dvA0GG.js +1 -0
- package/phanpy/dist/assets/icons/calendar-day-line-Crpl_fmu.js +1 -0
- package/phanpy/dist/assets/icons/calendar-month-line-vommts2C.js +1 -0
- package/phanpy/dist/assets/icons/calendar-time-add-line-BU_DTlQk.js +1 -0
- package/phanpy/dist/assets/icons/camera-line-Cv69MEei.js +1 -0
- package/phanpy/dist/assets/icons/celebrate-line-B8DvIoi0.js +1 -0
- package/phanpy/dist/assets/icons/chart-bar-line-FK-QOmtF.js +1 -0
- package/phanpy/dist/assets/icons/chart-line-line-BGcJAFWw.js +1 -0
- package/phanpy/dist/assets/icons/chat-3-line-YFK2-hwz.js +1 -0
- package/phanpy/dist/assets/icons/check-circle-line-DsAxFr5-.js +1 -0
- package/phanpy/dist/assets/icons/clipboard-line-BBp364gJ.js +1 -0
- package/phanpy/dist/assets/icons/close-circle-line-CICdiuGz.js +1 -0
- package/phanpy/dist/assets/icons/close-line-DYrFWcjv.js +1 -0
- package/phanpy/dist/assets/icons/cloud-line-tiQAbah8.js +1 -0
- package/phanpy/dist/assets/icons/code-line-fAl8iiV3.js +1 -0
- package/phanpy/dist/assets/icons/comment-2-line-CR3g7WeB.js +1 -0
- package/phanpy/dist/assets/icons/copy-2-line-CLW69yF5.js +1 -0
- package/phanpy/dist/assets/icons/delete-2-line-B8xmbr4n.js +1 -0
- package/phanpy/dist/assets/icons/document-3-line-DBGNhAg2.js +1 -0
- package/phanpy/dist/assets/icons/document-line-C7mb9sb7.js +1 -0
- package/phanpy/dist/assets/icons/down-line-BGqSSThd.js +1 -0
- package/phanpy/dist/assets/icons/edit-4-line-DcgGaEhx.js +1 -0
- package/phanpy/dist/assets/icons/emoji-2-line-D8YgnM-y.js +1 -0
- package/phanpy/dist/assets/icons/exit-line-Dc07BS-x.js +1 -0
- package/phanpy/dist/assets/icons/external-link-line-BvpSkmjO.js +1 -0
- package/phanpy/dist/assets/icons/eye-2-line-CiWXx-f_.js +1 -0
- package/phanpy/dist/assets/icons/eye-close-line-BgTaSJ4P.js +1 -0
- package/phanpy/dist/assets/icons/filter-2-line-B_mR2usy.js +1 -0
- package/phanpy/dist/assets/icons/filter-line-C_nm-3cU.js +1 -0
- package/phanpy/dist/assets/icons/flag-1-line-C2HB05I0.js +1 -0
- package/phanpy/dist/assets/icons/forbid-circle-line-D3LTT9yd.js +1 -0
- package/phanpy/dist/assets/icons/formula-line-DLrt2d6j.js +1 -0
- package/phanpy/dist/assets/icons/grid-line-CgUmEikf.js +1 -0
- package/phanpy/dist/assets/icons/group-line-C5fnX0wU.js +1 -0
- package/phanpy/dist/assets/icons/hand-finger-2-line-BGgxbuL9.js +1 -0
- package/phanpy/dist/assets/icons/hashtag-line-CyTEEXBb.js +1 -0
- package/phanpy/dist/assets/icons/heart-crack-line-BZddbO2C.js +1 -0
- package/phanpy/dist/assets/icons/heart-line-CJ7K47J4.js +1 -0
- package/phanpy/dist/assets/icons/history-2-line-kWWvFzqv.js +1 -0
- package/phanpy/dist/assets/icons/history-line-bGQiwbTH.js +1 -0
- package/phanpy/dist/assets/icons/home-3-line-fRU1zeLG.js +1 -0
- package/phanpy/dist/assets/icons/information-line-iNk6-sOY.js +1 -0
- package/phanpy/dist/assets/icons/keyboard-line-DsCyuQNz.js +1 -0
- package/phanpy/dist/assets/icons/layout-4-line-CZkOX52Z.js +1 -0
- package/phanpy/dist/assets/icons/layout-5-line-B_znt5wO.js +1 -0
- package/phanpy/dist/assets/icons/left-line-eUw0tya4.js +1 -0
- package/phanpy/dist/assets/icons/lightning-line-DaKoDdix.js +1 -0
- package/phanpy/dist/assets/icons/link-2-line-DCqLmMA7.js +1 -0
- package/phanpy/dist/assets/icons/list-check-line-BAxosBh9.js +1 -0
- package/phanpy/dist/assets/icons/lock-line-CPoaXeUW.js +1 -0
- package/phanpy/dist/assets/icons/mail-line-B0P8aa1L.js +1 -0
- package/phanpy/dist/assets/icons/moon-line-CEqNAToP.js +1 -0
- package/phanpy/dist/assets/icons/more-1-fill-Dw2e5xab.js +1 -0
- package/phanpy/dist/assets/icons/more-3-line-BIiVjYTz.js +1 -0
- package/phanpy/dist/assets/icons/notification-line-BZZq2Gtu.js +1 -0
- package/phanpy/dist/assets/icons/pencil-line-CKh8-A1v.js +1 -0
- package/phanpy/dist/assets/icons/photo-album-line-Bnfg2u40.js +1 -0
- package/phanpy/dist/assets/icons/pin-line-DpTolyhs.js +1 -0
- package/phanpy/dist/assets/icons/play-fill-B0-G_8lX.js +1 -0
- package/phanpy/dist/assets/icons/qrcode-2-line-B6SPCaHn.js +1 -0
- package/phanpy/dist/assets/icons/quill-pen-line-B6LUrnCP.js +1 -0
- package/phanpy/dist/assets/icons/quote-left-fill-hQZ1cj_6.js +1 -0
- package/phanpy/dist/assets/icons/radar-line-CKyroTth.js +1 -0
- package/phanpy/dist/assets/icons/react-line-CoIKhhtK.js +1 -0
- package/phanpy/dist/assets/icons/refresh-2-line-D0mTF97S.js +1 -0
- package/phanpy/dist/assets/icons/right-line-B3KWJaqc.js +1 -0
- package/phanpy/dist/assets/icons/rocket-line-4KZl537D.js +1 -0
- package/phanpy/dist/assets/icons/round-fill-C69NTrZ0.js +1 -0
- package/phanpy/dist/assets/icons/round-line-B9k_1uo-.js +1 -0
- package/phanpy/dist/assets/icons/route-line-B28ReHcE.js +1 -0
- package/phanpy/dist/assets/icons/rows-4-line-CrBniagM.js +1 -0
- package/phanpy/dist/assets/icons/scan-line-DSf74YdP.js +1 -0
- package/phanpy/dist/assets/icons/search-2-line-B6geIU1z.js +1 -0
- package/phanpy/dist/assets/icons/settings-3-line-azJwK47w.js +1 -0
- package/phanpy/dist/assets/icons/settings-6-line-C_5zc5YR.js +1 -0
- package/phanpy/dist/assets/icons/share-2-line-D5MxWjrm.js +1 -0
- package/phanpy/dist/assets/icons/share-forward-line-Cp61fZzZ.js +1 -0
- package/phanpy/dist/assets/icons/sparkles-2-line-DYYyXTaW.js +1 -0
- package/phanpy/dist/assets/icons/sparkles-line-C2hY1s6I.js +1 -0
- package/phanpy/dist/assets/icons/time-line-BF3eet1v.js +1 -0
- package/phanpy/dist/assets/icons/transfer-4-line-oisfvTBw.js +1 -0
- package/phanpy/dist/assets/icons/translate-line-BFWol2Ce.js +1 -0
- package/phanpy/dist/assets/icons/unlock-line-X_x5vwv3.js +1 -0
- package/phanpy/dist/assets/icons/upload-3-line-DgzwUJeW.js +1 -0
- package/phanpy/dist/assets/icons/user-4-line-BVSynZCp.js +1 -0
- package/phanpy/dist/assets/icons/user-add-2-line-BlGS5Q8q.js +1 -0
- package/phanpy/dist/assets/icons/user-add-line-BbXdHG4z.js +1 -0
- package/phanpy/dist/assets/icons/user-edit-line-BFAHOV0X.js +1 -0
- package/phanpy/dist/assets/icons/user-follow-line-BXux0wSd.js +1 -0
- package/phanpy/dist/assets/icons/user-star-line-DdYlpHLU.js +1 -0
- package/phanpy/dist/assets/icons/user-warning-line-Cj43j0_E.js +1 -0
- package/phanpy/dist/assets/icons/user-x-line-DIDgNlPH.js +1 -0
- package/phanpy/dist/assets/icons/volume-line-Bs390KQt.js +1 -0
- package/phanpy/dist/assets/icons/volume-mute-line-DzlzIqFZ.js +1 -0
- package/phanpy/dist/assets/icons/walk-line-yNXfB-md.js +1 -0
- package/phanpy/dist/assets/icons/world-2-line-CenkGIwj.js +1 -0
- package/phanpy/dist/assets/icons/zoom-in-line-CaENUphf.js +1 -0
- package/phanpy/dist/assets/icons/zoom-out-line-BDNk0EWo.js +1 -0
- package/phanpy/dist/assets/instances-BNPptnn-.json +333 -0
- package/phanpy/dist/assets/locales/ar-SA-CfheRbCu.js +1 -0
- package/phanpy/dist/assets/locales/ca-ES-DHRW86Tz.js +1 -0
- package/phanpy/dist/assets/locales/cs-CZ-CKoqEuA1.js +1 -0
- package/phanpy/dist/assets/locales/de-DE-ByRPMRFy.js +1 -0
- package/phanpy/dist/assets/locales/eo-UY-CPC7wLCS.js +1 -0
- package/phanpy/dist/assets/locales/es-ES-dJa0Fd9t.js +1 -0
- package/phanpy/dist/assets/locales/eu-ES-C3djlPR2.js +1 -0
- package/phanpy/dist/assets/locales/fa-IR-DTT490Ck.js +1 -0
- package/phanpy/dist/assets/locales/fi-FI-B23MCPuz.js +1 -0
- package/phanpy/dist/assets/locales/fr-FR-BcaQsO5C.js +1 -0
- package/phanpy/dist/assets/locales/gl-ES-BR-CVKBN.js +1 -0
- package/phanpy/dist/assets/locales/he-IL-CfheRbCu.js +1 -0
- package/phanpy/dist/assets/locales/hu-HU-CfheRbCu.js +1 -0
- package/phanpy/dist/assets/locales/it-IT-C1136UFV.js +1 -0
- package/phanpy/dist/assets/locales/ja-JP-CRZmRAhD.js +1 -0
- package/phanpy/dist/assets/locales/kab-Cz8xH_TT.js +1 -0
- package/phanpy/dist/assets/locales/ko-KR-CG9UiY4o.js +1 -0
- package/phanpy/dist/assets/locales/lt-LT-CJcI6sHZ.js +1 -0
- package/phanpy/dist/assets/locales/nb-NO-CfheRbCu.js +1 -0
- package/phanpy/dist/assets/locales/nl-NL-DxN4Yc1t.js +1 -0
- package/phanpy/dist/assets/locales/oc-FR-CfheRbCu.js +1 -0
- package/phanpy/dist/assets/locales/pl-PL-DkwGXf6P.js +1 -0
- package/phanpy/dist/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +1 -0
- package/phanpy/dist/assets/locales/pt-BR-nGL0HdFS.js +1 -0
- package/phanpy/dist/assets/locales/pt-PT-Cp17aj2z.js +1 -0
- package/phanpy/dist/assets/locales/ru-RU-0Y8cIoaK.js +1 -0
- package/phanpy/dist/assets/locales/th-TH-CfheRbCu.js +1 -0
- package/phanpy/dist/assets/locales/tok-CfheRbCu.js +1 -0
- package/phanpy/dist/assets/locales/tr-TR-CfheRbCu.js +1 -0
- package/phanpy/dist/assets/locales/uk-UA-C5E3dFBf.js +1 -0
- package/phanpy/dist/assets/locales/zh-CN-BHJi7_et.js +1 -0
- package/phanpy/dist/assets/locales/zh-TW-CfheRbCu.js +1 -0
- package/phanpy/dist/assets/main-BdqNbG-a.js +26 -0
- package/phanpy/dist/assets/main-BdqNbG-a.js.map +1 -0
- package/phanpy/dist/assets/mock-home-DGhR__He.js +2 -0
- package/phanpy/dist/assets/mock-home-DGhR__He.js.map +1 -0
- package/phanpy/dist/assets/multi-column-ROck0NVt.jpg +0 -0
- package/phanpy/dist/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
- package/phanpy/dist/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
- package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js +2 -0
- package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js.map +1 -0
- package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js +20 -0
- package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js.map +1 -0
- package/phanpy/dist/assets/style-B1iLPTPR.css +2 -0
- package/phanpy/dist/assets/temml-DuyIQMei.js +97 -0
- package/phanpy/dist/assets/temml-DuyIQMei.js.map +1 -0
- package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js +2 -0
- package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js.map +1 -0
- package/phanpy/dist/assets/year-in-posts-B2lywqdx.png +0 -0
- package/phanpy/dist/assets/year-in-posts-DJv_star.js +3 -0
- package/phanpy/dist/assets/year-in-posts-DJv_star.js.map +1 -0
- package/phanpy/dist/compose/index.html +20 -0
- package/phanpy/dist/favicon.ico +0 -0
- package/phanpy/dist/index.html +73 -0
- package/phanpy/dist/logo-192.png +0 -0
- package/phanpy/dist/logo-512.png +0 -0
- package/phanpy/dist/logo-badge-72.png +0 -0
- package/phanpy/dist/logo-maskable-512.png +0 -0
- package/phanpy/dist/logo-monochrome-512.png +0 -0
- package/phanpy/dist/logo-monochrome-maskable-512.png +0 -0
- package/phanpy/dist/manifest.webmanifest +1 -0
- package/phanpy/dist/og-image-2.jpg +0 -0
- package/phanpy/dist/og-image.png +0 -0
- package/phanpy/dist/robots.txt +2 -0
- package/phanpy/dist/sw.js +25 -0
- package/phanpy/dist/version.json +1 -0
- package/run-agent.mjs +805 -0
- package/vendor/gate.cjs +132 -0
- package/vendor/idp-grant.cjs +394 -0
- package/vendor/jfetch.cjs +16 -0
- package/web/admin/admin.js +958 -0
- package/web/admin/bar.css +64 -0
- package/web/admin/bar.js +61 -0
- package/web/admin/client/client.js +66 -0
- package/web/admin/client/index.html +42 -0
- package/web/admin/index.html +493 -0
- package/web/admin/setup/index.html +172 -0
- package/web/admin/setup/setup.js +268 -0
- package/web/admin/window.css +55 -0
- package/web/admin/window.js +136 -0
- package/web/front/install.sh +69 -0
- package/web/front/new-account.html +424 -0
- package/web/front/run.html +138 -0
- package/web/front/solid-client-authn.bundle.js +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# FediPod Server
|
|
2
|
+
|
|
3
|
+
-- a full ActivityPub server deployed as a Community Solid Server component
|
|
4
|
+
|
|
5
|
+
This is a CSS component. Install it in a fresh server instance or an instance
|
|
6
|
+
you already run for pods, and turn sign-up on. A pod owner signs in at the
|
|
7
|
+
server's `/run` page and opts in; from then on their pod is a full fediverse
|
|
8
|
+
account: it accepts follows, delivers their posts, and serves their Mastodon
|
|
9
|
+
client at the pod's own address. Signing up is the only way an account is
|
|
10
|
+
made, and opting out is the only way one ends.
|
|
11
|
+
|
|
12
|
+
With nothing configured beyond the defaults, installing the component changes
|
|
13
|
+
nothing about how the server serves pods.
|
|
14
|
+
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
npm install fedipod-server
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Add the package context to your CSS config and import the shipped snippet:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"@context": [
|
|
28
|
+
"...your CSS context...",
|
|
29
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/fedipod-server/^0.0.0/components/context.jsonld"
|
|
30
|
+
],
|
|
31
|
+
"import": [
|
|
32
|
+
"css:config/default.json",
|
|
33
|
+
"fps:config/server.json"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then set what you need on the `urn:fedipod:server:Handler` node and restart
|
|
39
|
+
the server.
|
|
40
|
+
Use a subdomain-pods CSS config: identities need an origin of their own, and
|
|
41
|
+
a path-pod config cannot opt anyone in.
|
|
42
|
+
The snippet places the component in the routing waterfall ahead of
|
|
43
|
+
the LDP catch-all, on the initializer and finalizer lists so identities start
|
|
44
|
+
and stop with the server, and on the websocket handler list for the live feed.
|
|
45
|
+
|
|
46
|
+
## Turning sign-up on
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"@id": "urn:fedipod:server:Handler",
|
|
51
|
+
"@type": "FediPodServerHandler",
|
|
52
|
+
"args_agentRuntimeOptIn": true,
|
|
53
|
+
"args_agentDataDir": "/var/lib/css/fedipod-agent/"
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
An identity is provisioned when its owner opts in: its name is the pod's
|
|
58
|
+
subdomain label, and it publishes an actor, a signing key and WebFinger on the
|
|
59
|
+
pod itself. Its state lives on the pod. Its signing key lives in
|
|
60
|
+
`agentDataDir`, one directory per identity — and beside it,
|
|
61
|
+
`door-secret.json`: the secret guarding that identity's own pages. Each
|
|
62
|
+
identity has its own; one owner's secret opens nobody else's door.
|
|
63
|
+
|
|
64
|
+
| Setting | What it is |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `agentRuntimeOptIn` | Whether pod owners can sign up. With it off, nothing runs. |
|
|
67
|
+
| `agentDataDir` | Where each identity keeps its signing key, credential and door secret; its log lines go to the server's own log. Required whenever sign-up is on. |
|
|
68
|
+
| `agentUiPath` | Where the owner's pages live on the pod's origin. `/fedipod/` by default; empty serves no pages. |
|
|
69
|
+
| `agentRegistryContainer` | The internal container holding the sign-up rows. |
|
|
70
|
+
| `runPage` | The HTML served at `/run`: the page where a pod owner opts in or out. The package's own `web/front/run.html` is served unless you set this. |
|
|
71
|
+
| `agentWebIdSuffix` | Path from a pod's base to its owner's WebID. Defaults to `profile/card#me`. |
|
|
72
|
+
| `agentPollSeconds` | How often the inbox is swept. Deliveries also wake the sweep as they land, so this is the fallback. |
|
|
73
|
+
| `agentAutoAcceptFollows` | Whether a newly provisioned identity accepts follows without review. On by default. |
|
|
74
|
+
|
|
75
|
+
| Setting | What it is |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `frontHost` | The apex host the shared front answers on. Defaults to this server's own base URL, so a plain install answers on its own address; set it only to front a different apex. |
|
|
78
|
+
| `frontOrigin` | Its origin. |
|
|
79
|
+
| `directoryContainer` | The internal container holding the handle directory. |
|
|
80
|
+
| `agentAutoFront` | Whether every identity that starts also gets a `@handle@frontHost` address — an inbox-only directory row, written once. Off by default. |
|
|
81
|
+
| `offersPods` | Whether the signup page offers to create pods here. |
|
|
82
|
+
| `signupPage` | The signup page served at `/`, `/signup` and `/new-account`. The package's own is served unless you set this. |
|
|
83
|
+
| `gatewayWebId` | The WebID stamped on verification receipts. |
|
|
84
|
+
|
|
85
|
+
`signupPage` and `runPage` are the page's HTML itself, not a path to a file.
|
|
86
|
+
|
|
87
|
+
### The pod is the instance
|
|
88
|
+
|
|
89
|
+
Each identity answers on its pod's origin, so the pod is what a client
|
|
90
|
+
connects to. Point a Mastodon app at `https://mei.example.org/` and it finds
|
|
91
|
+
what it expects: nodeinfo, the client API under `/api/`, sign-in under
|
|
92
|
+
`/oauth/`, the live feed at `/api/v1/streaming`, and the ActivityPub write API
|
|
93
|
+
at `/ap/outbox`. The owner's own pages — the record and, in a repository
|
|
94
|
+
checkout, the bundled web client — are behind `agentUiPath`, which the door
|
|
95
|
+
secret guards. The published package does not carry the web client; point a
|
|
96
|
+
Mastodon app at the pod instead.
|
|
97
|
+
|
|
98
|
+
The client API answers any origin, the way any Mastodon server does, so a
|
|
99
|
+
browser client works too: it registers an app, and the authorize screen names
|
|
100
|
+
what is asking and where the code will be sent before the owner approves it
|
|
101
|
+
with the password. The authorization code is bound to the client's registered
|
|
102
|
+
redirect, and only that client, holding its secret, can exchange it for a
|
|
103
|
+
token.
|
|
104
|
+
|
|
105
|
+
A client API is rooted at an origin, so each identity needs an origin of its
|
|
106
|
+
own: subdomain pods, one per identity. A second identity on a host is
|
|
107
|
+
refused at opt-in rather than half-working.
|
|
108
|
+
|
|
109
|
+
### Before you turn it on
|
|
110
|
+
|
|
111
|
+
**The server holds the keys.** Whoever runs the server can act as the
|
|
112
|
+
identities it runs. For a self-hoster that is their own machine either way;
|
|
113
|
+
for anyone hosting other people, it is a promise being made to them.
|
|
114
|
+
|
|
115
|
+
**Sign-in needs a password.** These routes face the whole internet, so
|
|
116
|
+
`/oauth/authorize` refuses until the identity has one. Set it once through the
|
|
117
|
+
owner's door, with that identity's own door secret:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
curl -X POST https://mei.example.org/fedipod/config \
|
|
121
|
+
-H 'x-dk-token: THE_DOOR_SECRET_FROM_door-secret.json' -H 'content-type: application/json' \
|
|
122
|
+
-d '{"password":"the one you will type into your phone"}'
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Some pod paths stop being served.** On an identity's origin the paths above
|
|
126
|
+
belong to the identity, so pod resources at those names — a container called
|
|
127
|
+
`api`, `oauth` or `fedipod`, or documents at `ap/actor`, `ap/outbox`,
|
|
128
|
+
`.well-known/nodeinfo` and `nodeinfo/2.0` — are not served over HTTP there.
|
|
129
|
+
They stay in the pod and in its listings. Every other path is the pod, exactly
|
|
130
|
+
as before.
|
|
131
|
+
|
|
132
|
+
**Run one worker.** A delivery is picked up the moment it lands only in a
|
|
133
|
+
single-worker server. With `--workers` above one the inbox is swept on the
|
|
134
|
+
timer instead, and the server says so at startup. Sign-up requires a
|
|
135
|
+
single worker outright, and says so when refused.
|
|
136
|
+
|
|
137
|
+
## How sign-up works
|
|
138
|
+
|
|
139
|
+
A pod owner opens the `/run` page, signs in with their pod,
|
|
140
|
+
and opts in or out. Underneath it is one endpoint:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
POST /api/agent
|
|
144
|
+
{"action": "opt-in", "podBase": "https://mei.example.org/"}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The request carries a Solid-OIDC token; the WebID it proves must live under
|
|
148
|
+
the pod being claimed. The reply carries the identity's door secret, shown
|
|
149
|
+
that once and never again — losing it is not fatal, because opting in again
|
|
150
|
+
mints a fresh one and retires the old, with no restart and no dropped
|
|
151
|
+
connections. `{"action": "opt-out", "podBase": "https://mei.example.org/"}`,
|
|
152
|
+
with the same token as opt-in, stops the identity and returns the pod
|
|
153
|
+
to plain pod serving; deliveries keep landing in its inbox and simply wait.
|
|
154
|
+
Opted-in pods are recorded in the registry container and come back after a
|
|
155
|
+
server restart — which is also why sign-up wants a persistent storage
|
|
156
|
+
backend: rows kept in a memory backend vanish when the server stops.
|
|
157
|
+
|
|
158
|
+
## What is in the package
|
|
159
|
+
|
|
160
|
+
| File | What it does |
|
|
161
|
+
|---|---|
|
|
162
|
+
| `src/handler.ts` | The HTTP handler, and the identities' lifecycle. Claims each identity's routes; everything else falls through to the server. |
|
|
163
|
+
| `src/streaming-handler.ts` | The live feed. Websocket upgrades never enter the request waterfall, so they arrive here. |
|
|
164
|
+
| `src/claims.ts` | Which paths belong to an identity. |
|
|
165
|
+
| `src/store-pod.ts` | An identity's whole conversation with its pod, carried by the server's store instead of the network. |
|
|
166
|
+
| `src/store-css.ts` | The component's own reads and writes, likewise. |
|
|
167
|
+
| `src/directory.ts` | The handle-to-pod directory, one document per handle. |
|
|
168
|
+
| `src/adapt.ts` | Node request and response to the WHATWG pair the shared core speaks. |
|
|
169
|
+
|
|
170
|
+
Writing through the store bypasses access control by design: the component is
|
|
171
|
+
the thing that decided the write is legitimate — a verified delivery, or an
|
|
172
|
+
identity acting on its own pod.
|
|
173
|
+
|
|
174
|
+
The agent is FediPod's own, unchanged: this package is the part that knows
|
|
175
|
+
about CSS.
|
|
176
|
+
|
|
177
|
+
## Build and test
|
|
178
|
+
|
|
179
|
+
TypeScript, built the way CSS builds its own components.
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
npm install
|
|
183
|
+
npm run build # tsc → dist, then componentsjs-generator → dist/components
|
|
184
|
+
npm test # unit tests, plus the transport against a real CSS store
|
|
185
|
+
npm run test:e2e # boots a real server and uses it as a client would
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`npm test` drives a genuine CSS store stack — ETags, conditional writes,
|
|
189
|
+
container listings — through the transport an identity uses, and checks the
|
|
190
|
+
lease protocol and the deletion deny-list still hold across it.
|
|
191
|
+
|
|
192
|
+
`npm run test:e2e` starts a real Community Solid Server with three pods (two
|
|
193
|
+
become identities up front; the third opts in and out at runtime), then signs in as a phone app does, posts,
|
|
194
|
+
receives a follow from another server, and watches the live feed. It takes
|
|
195
|
+
about a minute. `FEDIPOD_E2E_LOG=info` shows the server's log while it runs.
|
|
196
|
+
|
|
197
|
+
`dist/` and `node_modules/` are gitignored; `src/`, `config/` and this file are
|
|
198
|
+
the sources.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": [
|
|
3
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
|
|
4
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/fedipod-server/^0.0.0/components/context.jsonld"
|
|
5
|
+
],
|
|
6
|
+
"@graph": [
|
|
7
|
+
{
|
|
8
|
+
"comment": "The FediPod server handler. The front answers on this server's own base URL unless args_frontHost names another apex; pod subdomains fall through to CSS untouched. Field names carry the args_ prefix the generator produced from the constructor's options object.",
|
|
9
|
+
"@id": "urn:fedipod:server:Handler",
|
|
10
|
+
"@type": "FediPodServerHandler",
|
|
11
|
+
"args_resourceStore": { "@id": "urn:solid-server:default:ResourceStore" },
|
|
12
|
+
"args_frontOrigin": { "@id": "urn:solid-server:default:variable:baseUrl" },
|
|
13
|
+
"args_directoryContainer": "/.internal/fedipod/directory/",
|
|
14
|
+
"args_offersPods": false,
|
|
15
|
+
"args_clusterManager": { "@id": "urn:solid-server:default:ClusterManager" },
|
|
16
|
+
"args_agentRegistryContainer": "/.internal/fedipod/agents/"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"comment": "The live feed for a pod-hosted identity. A websocket upgrade never enters the request waterfall — CSS routes it through a handler list of its own — so this is a second class holding the same handler instance. Appending to the list here unions with whichever notification configuration the deployment loads.",
|
|
20
|
+
"@id": "urn:fedipod:server:StreamingHandler",
|
|
21
|
+
"@type": "FediPodStreamingHandler",
|
|
22
|
+
"args_server": { "@id": "urn:fedipod:server:Handler" }
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"@id": "urn:solid-server:default:WebSocketHandler",
|
|
26
|
+
"@type": "WaterfallHandler",
|
|
27
|
+
"handlers": [
|
|
28
|
+
{ "@id": "urn:fedipod:server:StreamingHandler" }
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"comment": "Starting each opted-in identity when the server starts, and stopping it cleanly when the server stops. The same handler instance does both, which is what InitializableHandler and FinalizableHandler are for. With sign-up off both are no-ops.",
|
|
33
|
+
"@id": "urn:solid-server:default:PrimaryParallelInitializer",
|
|
34
|
+
"@type": "ParallelHandler",
|
|
35
|
+
"handlers": [
|
|
36
|
+
{
|
|
37
|
+
"@type": "InitializableHandler",
|
|
38
|
+
"initializable": { "@id": "urn:fedipod:server:Handler" }
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"@id": "urn:solid-server:default:Finalizer",
|
|
44
|
+
"@type": "ParallelHandler",
|
|
45
|
+
"handlers": [
|
|
46
|
+
{
|
|
47
|
+
"@type": "FinalizableHandler",
|
|
48
|
+
"finalizable": { "@id": "urn:fedipod:server:Handler" }
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"comment": "Insert the handler into the routing waterfall just before the LDP catch-all, so it claims only the front routes and everything else stays normal CSS. OverrideListInsertBefore is available in componentsjs 5.x (which CSS 7 uses).",
|
|
54
|
+
"@type": "Override",
|
|
55
|
+
"overrideInstance": { "@id": "urn:solid-server:default:BaseHttpHandler" },
|
|
56
|
+
"overrideSteps": [
|
|
57
|
+
{
|
|
58
|
+
"@type": "OverrideListInsertBefore",
|
|
59
|
+
"overrideParameter": { "@id": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/dist/util/handlers/WaterfallHandler.jsonld#WaterfallHandler_handlers" },
|
|
60
|
+
"overrideTarget": { "@id": "urn:solid-server:default:LdpHandler" },
|
|
61
|
+
"overrideValue": { "@id": "urn:fedipod:server:Handler" }
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
package/dist/adapt.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type NodeReq = {
|
|
2
|
+
method?: string;
|
|
3
|
+
url?: string;
|
|
4
|
+
headers: Record<string, unknown>;
|
|
5
|
+
on(event: string, cb: (arg?: unknown) => void): void;
|
|
6
|
+
};
|
|
7
|
+
type NodeRes = {
|
|
8
|
+
writeHead(status: number, headers?: Record<string, string>): void;
|
|
9
|
+
end(body?: string | null): void;
|
|
10
|
+
};
|
|
11
|
+
type CoreResult = Response | {
|
|
12
|
+
status: number;
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
body?: string | null;
|
|
15
|
+
};
|
|
16
|
+
export declare function nodeToWhatwg(req: NodeReq, origin: string): Promise<Request>;
|
|
17
|
+
export declare function applyToNode(res: NodeRes, out: CoreResult): Promise<void>;
|
|
18
|
+
export {};
|
package/dist/adapt.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// adapt.ts — the one glue layer between CSS and the gateway core.
|
|
3
|
+
//
|
|
4
|
+
// CSS hands a handler Node's own request/response. The FediPod core
|
|
5
|
+
// (routeFront/handleDelivery) speaks WHATWG Request/Response. These convert
|
|
6
|
+
// both ways; they are the only CSS-shaped code that needs unit coverage.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.nodeToWhatwg = nodeToWhatwg;
|
|
9
|
+
exports.applyToNode = applyToNode;
|
|
10
|
+
// The same ceiling the agent surface's own readBody has. Everything the front
|
|
11
|
+
// accepts is far smaller; without this a stranger's POST buffers unbounded.
|
|
12
|
+
const MAX_BODY_BYTES = 1024 * 1024;
|
|
13
|
+
function readBody(req) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
if (req.method === 'GET' || req.method === 'HEAD') {
|
|
16
|
+
resolve(null);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const chunks = [];
|
|
20
|
+
let total = 0;
|
|
21
|
+
let done = false;
|
|
22
|
+
const fail = (err) => {
|
|
23
|
+
if (done)
|
|
24
|
+
return;
|
|
25
|
+
done = true;
|
|
26
|
+
reject(err);
|
|
27
|
+
};
|
|
28
|
+
req.on('data', (c) => {
|
|
29
|
+
if (done)
|
|
30
|
+
return;
|
|
31
|
+
total += c.length;
|
|
32
|
+
if (total > MAX_BODY_BYTES) {
|
|
33
|
+
const err = new Error('request body too large');
|
|
34
|
+
err.statusCode = 413;
|
|
35
|
+
fail(err);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
chunks.push(c);
|
|
39
|
+
});
|
|
40
|
+
req.on('end', () => { if (!done)
|
|
41
|
+
resolve(chunks.length ? Buffer.concat(chunks) : null); });
|
|
42
|
+
req.on('error', (e) => fail(e));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
// A Node request → a WHATWG Request. `origin` is the public origin CSS serves
|
|
46
|
+
// on, so the core sees the same absolute URL a remote used.
|
|
47
|
+
async function nodeToWhatwg(req, origin) {
|
|
48
|
+
const url = new URL(req.url ?? '/', origin).href;
|
|
49
|
+
const headers = new Headers();
|
|
50
|
+
for (const [k, v] of Object.entries(req.headers)) {
|
|
51
|
+
if (Array.isArray(v))
|
|
52
|
+
for (const one of v)
|
|
53
|
+
headers.append(k, String(one));
|
|
54
|
+
else if (v !== undefined && v !== null)
|
|
55
|
+
headers.set(k, String(v));
|
|
56
|
+
}
|
|
57
|
+
const body = await readBody(req);
|
|
58
|
+
return new Request(url, {
|
|
59
|
+
method: req.method,
|
|
60
|
+
headers,
|
|
61
|
+
...(body ? { body: body, duplex: 'half' } : {}),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// Apply a core result onto the Node response. The core returns either a WHATWG
|
|
65
|
+
// Response or a plain { status, headers, body } (front-core uses the latter).
|
|
66
|
+
async function applyToNode(res, out) {
|
|
67
|
+
if (out && typeof out.status === 'number' && !(out instanceof Response)) {
|
|
68
|
+
const o = out;
|
|
69
|
+
res.writeHead(o.status, o.headers || {});
|
|
70
|
+
res.end(o.body ?? null);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const r = out;
|
|
74
|
+
const headers = {};
|
|
75
|
+
r.headers.forEach((v, k) => { headers[k] = v; });
|
|
76
|
+
res.writeHead(r.status, headers);
|
|
77
|
+
const text = await r.text();
|
|
78
|
+
res.end(text || null);
|
|
79
|
+
}
|
package/dist/claims.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function claims(input: {
|
|
2
|
+
host?: string;
|
|
3
|
+
pathname: string;
|
|
4
|
+
}, frontHost: string): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* True when this request belongs to an identity's client surface.
|
|
7
|
+
* `agentHosts` is keyed by host including port, as the Host header carries it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function agentClaims(input: {
|
|
10
|
+
host?: string;
|
|
11
|
+
pathname: string;
|
|
12
|
+
}, agentHosts: Set<string>, uiPath?: string): boolean;
|
package/dist/claims.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// claims.ts — which requests the gateway owns, so canHandle can reject the rest
|
|
3
|
+
// and let normal pod/LDP traffic fall through to CSS. Scoped by HOST: on the
|
|
4
|
+
// front's apex the gateway answers the fediverse routes; a pod subdomain is a
|
|
5
|
+
// real Solid pod and is never claimed.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.claims = claims;
|
|
8
|
+
exports.agentClaims = agentClaims;
|
|
9
|
+
const FRONT_PATHS = new Set(['/', '/signup', '/new-account', '/run',
|
|
10
|
+
'/.well-known/webfinger', '/api/handle', '/api/attach', '/api/agent',
|
|
11
|
+
// What the two pages load: the sign-in library both use, and the installer
|
|
12
|
+
// the signup page hands every new user.
|
|
13
|
+
'/solid-client-authn.bundle.js', '/install']);
|
|
14
|
+
function claims(input, frontHost) {
|
|
15
|
+
if (!input.host || !frontHost)
|
|
16
|
+
return false;
|
|
17
|
+
const bare = String(input.host).split(':')[0].toLowerCase();
|
|
18
|
+
if (bare !== String(frontHost).toLowerCase())
|
|
19
|
+
return false; // a pod subdomain → not ours
|
|
20
|
+
return FRONT_PATHS.has(input.pathname) || input.pathname.startsWith('/u/');
|
|
21
|
+
}
|
|
22
|
+
// What an identity answers on its own pod's origin: the protocol routes other
|
|
23
|
+
// software addresses it by, and the one path its owner's pages live under.
|
|
24
|
+
// Everything else on that origin is the pod, and falls through to CSS.
|
|
25
|
+
const AGENT_PATHS = new Set(['/ap/actor', '/ap/outbox', '/.well-known/nodeinfo', '/nodeinfo/2.0']);
|
|
26
|
+
const AGENT_PREFIXES = ['/api/', '/oauth/'];
|
|
27
|
+
/**
|
|
28
|
+
* True when this request belongs to an identity's client surface.
|
|
29
|
+
* `agentHosts` is keyed by host including port, as the Host header carries it.
|
|
30
|
+
*/
|
|
31
|
+
function agentClaims(input, agentHosts, uiPath = '/fedipod/') {
|
|
32
|
+
if (!input.host || agentHosts.size === 0)
|
|
33
|
+
return false;
|
|
34
|
+
if (!agentHosts.has(String(input.host).toLowerCase()))
|
|
35
|
+
return false;
|
|
36
|
+
const { pathname } = input;
|
|
37
|
+
if (AGENT_PATHS.has(pathname))
|
|
38
|
+
return true;
|
|
39
|
+
if (AGENT_PREFIXES.some((prefix) => pathname.startsWith(prefix)))
|
|
40
|
+
return true;
|
|
41
|
+
// The owner's door, when there is one: '' turns the pages off entirely.
|
|
42
|
+
return uiPath !== '' && (pathname === uiPath.slice(0, -1) || pathname.startsWith(uiPath));
|
|
43
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": [
|
|
3
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/fedipod-server/^0.0.0/components/context.jsonld"
|
|
4
|
+
],
|
|
5
|
+
"@id": "npmd:fedipod-server",
|
|
6
|
+
"@type": "Module",
|
|
7
|
+
"requireName": "fedipod-server",
|
|
8
|
+
"import": [
|
|
9
|
+
"fps:dist/handler.jsonld",
|
|
10
|
+
"fps:dist/streaming-handler.jsonld"
|
|
11
|
+
]
|
|
12
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": [
|
|
3
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/componentsjs/^5.0.0/components/context.jsonld",
|
|
4
|
+
{
|
|
5
|
+
"npmd": "https://linkedsoftwaredependencies.org/bundles/npm/",
|
|
6
|
+
"fps": "npmd:fedipod-server/^0.0.0/",
|
|
7
|
+
"FediPodServerHandler": {
|
|
8
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler",
|
|
9
|
+
"@prefix": true,
|
|
10
|
+
"@context": {
|
|
11
|
+
"args_resourceStore": {
|
|
12
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_resourceStore"
|
|
13
|
+
},
|
|
14
|
+
"args_frontHost": {
|
|
15
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_frontHost"
|
|
16
|
+
},
|
|
17
|
+
"args_frontOrigin": {
|
|
18
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_frontOrigin"
|
|
19
|
+
},
|
|
20
|
+
"args_directoryContainer": {
|
|
21
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_directoryContainer"
|
|
22
|
+
},
|
|
23
|
+
"args_gatewayWebId": {
|
|
24
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_gatewayWebId"
|
|
25
|
+
},
|
|
26
|
+
"args_offersPods": {
|
|
27
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_offersPods"
|
|
28
|
+
},
|
|
29
|
+
"args_signupPage": {
|
|
30
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_signupPage"
|
|
31
|
+
},
|
|
32
|
+
"args_runPage": {
|
|
33
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_runPage"
|
|
34
|
+
},
|
|
35
|
+
"args_agentDataDir": {
|
|
36
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentDataDir"
|
|
37
|
+
},
|
|
38
|
+
"args_agentWebIdSuffix": {
|
|
39
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentWebIdSuffix"
|
|
40
|
+
},
|
|
41
|
+
"args_agentPollSeconds": {
|
|
42
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentPollSeconds"
|
|
43
|
+
},
|
|
44
|
+
"args_agentAutoAcceptFollows": {
|
|
45
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentAutoAcceptFollows"
|
|
46
|
+
},
|
|
47
|
+
"args_clusterManager": {
|
|
48
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_clusterManager"
|
|
49
|
+
},
|
|
50
|
+
"args_agentUiPath": {
|
|
51
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentUiPath"
|
|
52
|
+
},
|
|
53
|
+
"args_agentRuntimeOptIn": {
|
|
54
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentRuntimeOptIn"
|
|
55
|
+
},
|
|
56
|
+
"args_agentAutoFront": {
|
|
57
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentAutoFront"
|
|
58
|
+
},
|
|
59
|
+
"args_agentRegistryContainer": {
|
|
60
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentRegistryContainer"
|
|
61
|
+
},
|
|
62
|
+
"resourceStore": {
|
|
63
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_resourceStore"
|
|
64
|
+
},
|
|
65
|
+
"frontHost": {
|
|
66
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_frontHost"
|
|
67
|
+
},
|
|
68
|
+
"frontOrigin": {
|
|
69
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_frontOrigin"
|
|
70
|
+
},
|
|
71
|
+
"directoryContainer": {
|
|
72
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_directoryContainer"
|
|
73
|
+
},
|
|
74
|
+
"gatewayWebId": {
|
|
75
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_gatewayWebId"
|
|
76
|
+
},
|
|
77
|
+
"offersPods": {
|
|
78
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_offersPods"
|
|
79
|
+
},
|
|
80
|
+
"signupPage": {
|
|
81
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_signupPage"
|
|
82
|
+
},
|
|
83
|
+
"runPage": {
|
|
84
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_runPage"
|
|
85
|
+
},
|
|
86
|
+
"agentDataDir": {
|
|
87
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentDataDir"
|
|
88
|
+
},
|
|
89
|
+
"agentWebIdSuffix": {
|
|
90
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentWebIdSuffix"
|
|
91
|
+
},
|
|
92
|
+
"agentPollSeconds": {
|
|
93
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentPollSeconds"
|
|
94
|
+
},
|
|
95
|
+
"agentAutoAcceptFollows": {
|
|
96
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentAutoAcceptFollows"
|
|
97
|
+
},
|
|
98
|
+
"clusterManager": {
|
|
99
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_clusterManager"
|
|
100
|
+
},
|
|
101
|
+
"agentUiPath": {
|
|
102
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentUiPath"
|
|
103
|
+
},
|
|
104
|
+
"agentRuntimeOptIn": {
|
|
105
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentRuntimeOptIn"
|
|
106
|
+
},
|
|
107
|
+
"agentAutoFront": {
|
|
108
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentAutoFront"
|
|
109
|
+
},
|
|
110
|
+
"agentRegistryContainer": {
|
|
111
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler_args_agentRegistryContainer"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"FediPodServerArgs": {
|
|
116
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerArgs",
|
|
117
|
+
"@prefix": true,
|
|
118
|
+
"@context": {}
|
|
119
|
+
},
|
|
120
|
+
"FediPodStreamingHandler": {
|
|
121
|
+
"@id": "fps:dist/streaming-handler.jsonld#FediPodStreamingHandler",
|
|
122
|
+
"@prefix": true,
|
|
123
|
+
"@context": {
|
|
124
|
+
"args_server": {
|
|
125
|
+
"@id": "fps:dist/streaming-handler.jsonld#FediPodStreamingHandler_args_server"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"FediPodStreamingArgs": {
|
|
130
|
+
"@id": "fps:dist/streaming-handler.jsonld#FediPodStreamingArgs",
|
|
131
|
+
"@prefix": true,
|
|
132
|
+
"@context": {}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface IO {
|
|
2
|
+
read(url: string): Promise<string | null>;
|
|
3
|
+
write(url: string, body: string, contentType: string): Promise<void>;
|
|
4
|
+
/** Absence is not an error: removing what is already gone succeeds. */
|
|
5
|
+
remove?(url: string): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export interface DirectoryRecord {
|
|
8
|
+
handle: string;
|
|
9
|
+
podHome: string;
|
|
10
|
+
actorUrl: string;
|
|
11
|
+
kind: string;
|
|
12
|
+
webId?: string;
|
|
13
|
+
hmacSecret?: string;
|
|
14
|
+
gatewayWebId?: string | null;
|
|
15
|
+
/** Inbox-only fronting: the row exists to resolve @handle@front and take verified delivery; the actor keeps its own ids on the pod. */
|
|
16
|
+
inboxOnly?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface Directory {
|
|
19
|
+
lookup(handle: string): Promise<DirectoryRecord | null>;
|
|
20
|
+
putDirectory(handle: string, record: DirectoryRecord): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export declare function makeDirectory(io: IO, containerUrl: string): Directory;
|
|
23
|
+
/** A pod whose owner opted in at runtime. The door secret is never in the row. */
|
|
24
|
+
export interface AgentRegistryRecord {
|
|
25
|
+
podBase: string;
|
|
26
|
+
handle: string;
|
|
27
|
+
host: string;
|
|
28
|
+
webId: string;
|
|
29
|
+
optedInAt: string;
|
|
30
|
+
}
|
|
31
|
+
export interface AgentRegistry {
|
|
32
|
+
listHosts(): Promise<string[]>;
|
|
33
|
+
get(host: string): Promise<AgentRegistryRecord | null>;
|
|
34
|
+
add(record: AgentRegistryRecord): Promise<void>;
|
|
35
|
+
remove(host: string): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export declare function makeAgentRegistry(io: IO, containerUrl: string): AgentRegistry;
|
|
38
|
+
export declare function makeStorePodPut(io: IO): (url: string, body: string, contentType: string) => Promise<boolean>;
|