fedipod-server 0.28.1 → 0.30.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 +38 -34
- package/config/server.json +22 -0
- package/dist/claims.js +3 -2
- package/dist/directory.d.ts +2 -0
- package/dist/door.d.ts +4 -0
- package/dist/door.js +31 -0
- package/dist/fedipod.d.ts +16 -0
- package/dist/fedipod.js +13 -0
- package/dist/front.d.ts +3 -0
- package/dist/front.js +94 -0
- package/dist/handler.d.ts +39 -101
- package/dist/handler.js +86 -617
- package/dist/handler.jsonld +6 -30
- package/dist/identities.d.ts +62 -0
- package/dist/identities.js +236 -0
- package/dist/mounts.d.ts +43 -0
- package/dist/mounts.js +123 -0
- package/dist/opt-in.d.ts +46 -0
- package/dist/opt-in.js +176 -0
- package/dist/store-pod.js +37 -0
- package/package.json +10 -18
- package/lib/client/c2s.mjs +0 -582
- package/lib/client/localapi.mjs +0 -87
- package/lib/client/masto/accounts.mjs +0 -309
- package/lib/client/masto/body.mjs +0 -156
- package/lib/client/masto/index.mjs +0 -206
- package/lib/client/masto/instance.mjs +0 -112
- package/lib/client/masto/media.mjs +0 -79
- package/lib/client/masto/oauth.mjs +0 -656
- package/lib/client/masto/render.mjs +0 -518
- package/lib/client/masto/statuses.mjs +0 -372
- package/lib/client/masto/timelines.mjs +0 -438
- package/lib/client/oidc-auth.mjs +0 -62
- package/lib/client/streaming.mjs +0 -154
- package/lib/client/webpush.mjs +0 -98
- package/lib/connections/acctfeed.mjs +0 -257
- package/lib/connections/atproto.mjs +0 -309
- package/lib/connections/bskyfeed.mjs +0 -243
- package/lib/connections/bskygroup.mjs +0 -162
- package/lib/connections/fediacct.mjs +0 -253
- package/lib/connections/import.mjs +0 -357
- package/lib/connections/tagfeed.mjs +0 -212
- package/lib/connections/vault.mjs +0 -114
- package/lib/core/as2.mjs +0 -206
- package/lib/core/contexts/activitystreams.json +0 -379
- package/lib/core/contexts/anno.json +0 -126
- package/lib/core/contexts/did-v1.json +0 -57
- package/lib/core/contexts/fep-5711.json +0 -36
- package/lib/core/contexts/gotosocial.json +0 -86
- package/lib/core/contexts/identity-v1.json +0 -152
- package/lib/core/contexts/index.mjs +0 -63
- package/lib/core/contexts/join-lemmy.json +0 -33
- package/lib/core/contexts/joinmastodon.json +0 -28
- package/lib/core/contexts/litepub-0.1.json +0 -60
- package/lib/core/contexts/map.json +0 -19
- package/lib/core/contexts/miscellany.json +0 -19
- package/lib/core/contexts/quotes.json +0 -18
- package/lib/core/contexts/schemaorg.json +0 -8845
- package/lib/core/contexts/security-data-integrity-v1.json +0 -78
- package/lib/core/contexts/security-data-integrity-v2.json +0 -81
- package/lib/core/contexts/security-multikey-v1.json +0 -35
- package/lib/core/contexts/security-v1.json +0 -74
- package/lib/core/contexts/webfinger.json +0 -10
- package/lib/core/deliver.mjs +0 -371
- package/lib/core/graphview.mjs +0 -327
- package/lib/core/intake/activities.mjs +0 -633
- package/lib/core/intake/activity.mjs +0 -318
- package/lib/core/intake/channel.mjs +0 -144
- package/lib/core/intake/group.mjs +0 -256
- package/lib/core/intake/index.mjs +0 -701
- package/lib/core/intake/notes.mjs +0 -360
- package/lib/core/intake/verify.mjs +0 -142
- package/lib/core/keys.mjs +0 -153
- package/lib/core/lease.mjs +0 -206
- package/lib/core/polls.mjs +0 -105
- package/lib/core/profile-page.mjs +0 -104
- package/lib/core/proof.mjs +0 -79
- package/lib/core/publisher/collections.mjs +0 -237
- package/lib/core/publisher/index.mjs +0 -500
- package/lib/core/publisher/notes.mjs +0 -453
- package/lib/core/publisher/questions.mjs +0 -239
- package/lib/core/publisher/restore.mjs +0 -224
- package/lib/core/shapes/activitystreams.ttl +0 -157
- package/lib/core/shapes/index.mjs +0 -132
- package/lib/core/shapes/shapes-text.mjs +0 -13
- package/lib/core/social.mjs +0 -531
- package/lib/core/storage.mjs +0 -176
- package/lib/core/store.mjs +0 -568
- package/lib/core/wire-quotes.mjs +0 -71
- package/lib/core/wire.mjs +0 -889
- package/lib/device/account.mjs +0 -87
- package/lib/device/admin/index.mjs +0 -13
- package/lib/device/admin/origins.mjs +0 -35
- package/lib/device/admin/routes/connections.mjs +0 -144
- package/lib/device/admin/routes/gateway.mjs +0 -199
- package/lib/device/admin/routes/lifecycle.mjs +0 -200
- package/lib/device/admin/routes/owner.mjs +0 -322
- package/lib/device/admin/routes/setup.mjs +0 -412
- package/lib/device/admin/routes/social.mjs +0 -188
- package/lib/device/admin/server.mjs +0 -95
- package/lib/device/admin/static.mjs +0 -247
- package/lib/device/admin/surface.mjs +0 -315
- package/lib/device/certs.mjs +0 -281
- package/lib/device/cli/commands/account.mjs +0 -586
- package/lib/device/cli/commands/run.mjs +0 -278
- package/lib/device/cli/commands/service.mjs +0 -221
- package/lib/device/cli/commands/setup.mjs +0 -447
- package/lib/device/cli/commands/state.mjs +0 -561
- package/lib/device/cli/context.mjs +0 -288
- package/lib/device/export-collections.mjs +0 -161
- package/lib/device/gateway-move.mjs +0 -58
- package/lib/device/home.mjs +0 -161
- package/lib/device/migrate.mjs +0 -115
- package/lib/device/ports.mjs +0 -27
- package/lib/device/remote.mjs +0 -54
- package/lib/device/setup.mjs +0 -459
- package/lib/device/update.mjs +0 -96
- package/lib/gateway/caches.mjs +0 -36
- package/lib/gateway/directory.mjs +0 -90
- package/lib/gateway/front-core.mjs +0 -970
- package/lib/gateway/gateway-core.mjs +0 -165
- package/lib/gateway/headers.mjs +0 -49
- package/lib/gateway/httpsig.mjs +0 -159
- package/lib/gateway/notices.mjs +0 -84
- package/lib/gateway/quiet.mjs +0 -189
- package/lib/pod/README.md +0 -61
- package/lib/pod/actor.mjs +0 -96
- package/lib/pod/collection.mjs +0 -77
- package/lib/pod/containers.mjs +0 -140
- package/lib/pod/discovery.mjs +0 -46
- package/lib/pod/featured.mjs +0 -18
- package/lib/pod/followers.mjs +0 -24
- package/lib/pod/following.mjs +0 -10
- package/lib/pod/http.mjs +0 -74
- package/lib/pod/inbox.mjs +0 -166
- package/lib/pod/links.mjs +0 -35
- package/lib/pod/media.mjs +0 -27
- package/lib/pod/notes.mjs +0 -80
- package/lib/pod/notifications.mjs +0 -89
- package/lib/pod/outbox.mjs +0 -18
- package/lib/pod/package.json +0 -19
- package/lib/pod/policy.mjs +0 -58
- package/lib/pod/private.mjs +0 -19
- package/lib/pod/root.mjs +0 -104
- package/lib/pod/state.mjs +0 -40
- package/lib/pod/transport.mjs +0 -525
- package/lib/pod/urls.mjs +0 -85
- package/lib/server/embed.mjs +0 -423
- package/lib/session/README.md +0 -137
- package/lib/session/demo.html +0 -94
- package/lib/session/fedi-account.mjs +0 -408
- package/lib/session/fedi-login.mjs +0 -123
- package/lib/session/oidc-session.mjs +0 -233
- package/lib/session/package.json +0 -49
- package/lib/shared/guard.mjs +0 -213
- package/lib/shared/links.mjs +0 -9
- package/lib/shared/safefetch.mjs +0 -235
- package/lib/shared/ua.mjs +0 -29
- package/phanpy/dist/404.html +0 -40
- package/phanpy/dist/_headers +0 -2
- package/phanpy/dist/apple-touch-icon.png +0 -0
- package/phanpy/dist/assets/ICONS-DIPJeU0C.js +0 -2
- package/phanpy/dist/assets/ICONS-DIPJeU0C.js.map +0 -1
- package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js +0 -183
- package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
- package/phanpy/dist/assets/Temml-CCjoacWt.woff2 +0 -0
- package/phanpy/dist/assets/__vite-browser-external-C7iut881.js +0 -2
- package/phanpy/dist/assets/__vite-browser-external-C7iut881.js.map +0 -1
- 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 +0 -1
- package/phanpy/dist/assets/compose-CFEx7wb4.js +0 -2
- package/phanpy/dist/assets/compose-CFEx7wb4.js.map +0 -1
- package/phanpy/dist/assets/compose-ZJN5xSb4.js +0 -35
- package/phanpy/dist/assets/compose-ZJN5xSb4.js.map +0 -1
- package/phanpy/dist/assets/debug.module-YFQgwnIr.js +0 -52
- package/phanpy/dist/assets/debug.module-YFQgwnIr.js.map +0 -1
- package/phanpy/dist/assets/dom-p1YcJ5Rw.js +0 -2
- package/phanpy/dist/assets/dom-p1YcJ5Rw.js.map +0 -1
- 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 +0 -1
- package/phanpy/dist/assets/icons/alert-line-CpFUMf9s.js +0 -1
- package/phanpy/dist/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
- package/phanpy/dist/assets/icons/announcement-line-5nwaJFJm.js +0 -1
- package/phanpy/dist/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
- package/phanpy/dist/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
- package/phanpy/dist/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
- package/phanpy/dist/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
- package/phanpy/dist/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
- package/phanpy/dist/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
- package/phanpy/dist/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
- package/phanpy/dist/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
- package/phanpy/dist/assets/icons/at-line-CF66Bznk.js +0 -1
- package/phanpy/dist/assets/icons/attachment-line-BY8It-l9.js +0 -1
- package/phanpy/dist/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
- package/phanpy/dist/assets/icons/board-line-C0UWXyA6.js +0 -1
- package/phanpy/dist/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
- package/phanpy/dist/assets/icons/building-5-line-Dd59MzbO.js +0 -1
- package/phanpy/dist/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
- package/phanpy/dist/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
- package/phanpy/dist/assets/icons/calendar-month-line-vommts2C.js +0 -1
- package/phanpy/dist/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
- package/phanpy/dist/assets/icons/camera-line-Cv69MEei.js +0 -1
- package/phanpy/dist/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
- package/phanpy/dist/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
- package/phanpy/dist/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
- package/phanpy/dist/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
- package/phanpy/dist/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
- package/phanpy/dist/assets/icons/clipboard-line-BBp364gJ.js +0 -1
- package/phanpy/dist/assets/icons/close-circle-line-CICdiuGz.js +0 -1
- package/phanpy/dist/assets/icons/close-line-DYrFWcjv.js +0 -1
- package/phanpy/dist/assets/icons/cloud-line-tiQAbah8.js +0 -1
- package/phanpy/dist/assets/icons/code-line-fAl8iiV3.js +0 -1
- package/phanpy/dist/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
- package/phanpy/dist/assets/icons/copy-2-line-CLW69yF5.js +0 -1
- package/phanpy/dist/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
- package/phanpy/dist/assets/icons/document-3-line-DBGNhAg2.js +0 -1
- package/phanpy/dist/assets/icons/document-line-C7mb9sb7.js +0 -1
- package/phanpy/dist/assets/icons/down-line-BGqSSThd.js +0 -1
- package/phanpy/dist/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
- package/phanpy/dist/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
- package/phanpy/dist/assets/icons/exit-line-Dc07BS-x.js +0 -1
- package/phanpy/dist/assets/icons/external-link-line-BvpSkmjO.js +0 -1
- package/phanpy/dist/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
- package/phanpy/dist/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
- package/phanpy/dist/assets/icons/filter-2-line-B_mR2usy.js +0 -1
- package/phanpy/dist/assets/icons/filter-line-C_nm-3cU.js +0 -1
- package/phanpy/dist/assets/icons/flag-1-line-C2HB05I0.js +0 -1
- package/phanpy/dist/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
- package/phanpy/dist/assets/icons/formula-line-DLrt2d6j.js +0 -1
- package/phanpy/dist/assets/icons/grid-line-CgUmEikf.js +0 -1
- package/phanpy/dist/assets/icons/group-line-C5fnX0wU.js +0 -1
- package/phanpy/dist/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
- package/phanpy/dist/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
- package/phanpy/dist/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
- package/phanpy/dist/assets/icons/heart-line-CJ7K47J4.js +0 -1
- package/phanpy/dist/assets/icons/history-2-line-kWWvFzqv.js +0 -1
- package/phanpy/dist/assets/icons/history-line-bGQiwbTH.js +0 -1
- package/phanpy/dist/assets/icons/home-3-line-fRU1zeLG.js +0 -1
- package/phanpy/dist/assets/icons/information-line-iNk6-sOY.js +0 -1
- package/phanpy/dist/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
- package/phanpy/dist/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
- package/phanpy/dist/assets/icons/layout-5-line-B_znt5wO.js +0 -1
- package/phanpy/dist/assets/icons/left-line-eUw0tya4.js +0 -1
- package/phanpy/dist/assets/icons/lightning-line-DaKoDdix.js +0 -1
- package/phanpy/dist/assets/icons/link-2-line-DCqLmMA7.js +0 -1
- package/phanpy/dist/assets/icons/list-check-line-BAxosBh9.js +0 -1
- package/phanpy/dist/assets/icons/lock-line-CPoaXeUW.js +0 -1
- package/phanpy/dist/assets/icons/mail-line-B0P8aa1L.js +0 -1
- package/phanpy/dist/assets/icons/moon-line-CEqNAToP.js +0 -1
- package/phanpy/dist/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
- package/phanpy/dist/assets/icons/more-3-line-BIiVjYTz.js +0 -1
- package/phanpy/dist/assets/icons/notification-line-BZZq2Gtu.js +0 -1
- package/phanpy/dist/assets/icons/pencil-line-CKh8-A1v.js +0 -1
- package/phanpy/dist/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
- package/phanpy/dist/assets/icons/pin-line-DpTolyhs.js +0 -1
- package/phanpy/dist/assets/icons/play-fill-B0-G_8lX.js +0 -1
- package/phanpy/dist/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
- package/phanpy/dist/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
- package/phanpy/dist/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
- package/phanpy/dist/assets/icons/radar-line-CKyroTth.js +0 -1
- package/phanpy/dist/assets/icons/react-line-CoIKhhtK.js +0 -1
- package/phanpy/dist/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
- package/phanpy/dist/assets/icons/right-line-B3KWJaqc.js +0 -1
- package/phanpy/dist/assets/icons/rocket-line-4KZl537D.js +0 -1
- package/phanpy/dist/assets/icons/round-fill-C69NTrZ0.js +0 -1
- package/phanpy/dist/assets/icons/round-line-B9k_1uo-.js +0 -1
- package/phanpy/dist/assets/icons/route-line-B28ReHcE.js +0 -1
- package/phanpy/dist/assets/icons/rows-4-line-CrBniagM.js +0 -1
- package/phanpy/dist/assets/icons/scan-line-DSf74YdP.js +0 -1
- package/phanpy/dist/assets/icons/search-2-line-B6geIU1z.js +0 -1
- package/phanpy/dist/assets/icons/settings-3-line-azJwK47w.js +0 -1
- package/phanpy/dist/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
- package/phanpy/dist/assets/icons/share-2-line-D5MxWjrm.js +0 -1
- package/phanpy/dist/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
- package/phanpy/dist/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
- package/phanpy/dist/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
- package/phanpy/dist/assets/icons/time-line-BF3eet1v.js +0 -1
- package/phanpy/dist/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
- package/phanpy/dist/assets/icons/translate-line-BFWol2Ce.js +0 -1
- package/phanpy/dist/assets/icons/unlock-line-X_x5vwv3.js +0 -1
- package/phanpy/dist/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
- package/phanpy/dist/assets/icons/user-4-line-BVSynZCp.js +0 -1
- package/phanpy/dist/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
- package/phanpy/dist/assets/icons/user-add-line-BbXdHG4z.js +0 -1
- package/phanpy/dist/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
- package/phanpy/dist/assets/icons/user-follow-line-BXux0wSd.js +0 -1
- package/phanpy/dist/assets/icons/user-star-line-DdYlpHLU.js +0 -1
- package/phanpy/dist/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
- package/phanpy/dist/assets/icons/user-x-line-DIDgNlPH.js +0 -1
- package/phanpy/dist/assets/icons/volume-line-Bs390KQt.js +0 -1
- package/phanpy/dist/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
- package/phanpy/dist/assets/icons/walk-line-yNXfB-md.js +0 -1
- package/phanpy/dist/assets/icons/world-2-line-CenkGIwj.js +0 -1
- package/phanpy/dist/assets/icons/zoom-in-line-CaENUphf.js +0 -1
- package/phanpy/dist/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
- package/phanpy/dist/assets/instances-BNPptnn-.json +0 -333
- package/phanpy/dist/assets/locales/ar-SA-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/ca-ES-DHRW86Tz.js +0 -1
- package/phanpy/dist/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
- package/phanpy/dist/assets/locales/de-DE-ByRPMRFy.js +0 -1
- package/phanpy/dist/assets/locales/eo-UY-CPC7wLCS.js +0 -1
- package/phanpy/dist/assets/locales/es-ES-dJa0Fd9t.js +0 -1
- package/phanpy/dist/assets/locales/eu-ES-C3djlPR2.js +0 -1
- package/phanpy/dist/assets/locales/fa-IR-DTT490Ck.js +0 -1
- package/phanpy/dist/assets/locales/fi-FI-B23MCPuz.js +0 -1
- package/phanpy/dist/assets/locales/fr-FR-BcaQsO5C.js +0 -1
- package/phanpy/dist/assets/locales/gl-ES-BR-CVKBN.js +0 -1
- package/phanpy/dist/assets/locales/he-IL-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/hu-HU-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/it-IT-C1136UFV.js +0 -1
- package/phanpy/dist/assets/locales/ja-JP-CRZmRAhD.js +0 -1
- package/phanpy/dist/assets/locales/kab-Cz8xH_TT.js +0 -1
- package/phanpy/dist/assets/locales/ko-KR-CG9UiY4o.js +0 -1
- package/phanpy/dist/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
- package/phanpy/dist/assets/locales/nb-NO-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
- package/phanpy/dist/assets/locales/oc-FR-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/pl-PL-DkwGXf6P.js +0 -1
- package/phanpy/dist/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
- package/phanpy/dist/assets/locales/pt-BR-nGL0HdFS.js +0 -1
- package/phanpy/dist/assets/locales/pt-PT-Cp17aj2z.js +0 -1
- package/phanpy/dist/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
- package/phanpy/dist/assets/locales/th-TH-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/tok-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/tr-TR-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/uk-UA-C5E3dFBf.js +0 -1
- package/phanpy/dist/assets/locales/zh-CN-BHJi7_et.js +0 -1
- package/phanpy/dist/assets/locales/zh-TW-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/main-BdqNbG-a.js +0 -26
- package/phanpy/dist/assets/main-BdqNbG-a.js.map +0 -1
- package/phanpy/dist/assets/mock-home-DGhR__He.js +0 -2
- package/phanpy/dist/assets/mock-home-DGhR__He.js.map +0 -1
- 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 +0 -2
- package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js.map +0 -1
- package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js +0 -20
- package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js.map +0 -1
- package/phanpy/dist/assets/style-B1iLPTPR.css +0 -2
- package/phanpy/dist/assets/temml-DuyIQMei.js +0 -97
- package/phanpy/dist/assets/temml-DuyIQMei.js.map +0 -1
- package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js +0 -2
- package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
- package/phanpy/dist/assets/year-in-posts-B2lywqdx.png +0 -0
- package/phanpy/dist/assets/year-in-posts-DJv_star.js +0 -3
- package/phanpy/dist/assets/year-in-posts-DJv_star.js.map +0 -1
- package/phanpy/dist/compose/index.html +0 -20
- package/phanpy/dist/favicon.ico +0 -0
- package/phanpy/dist/index.html +0 -73
- 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 +0 -1
- package/phanpy/dist/og-image-2.jpg +0 -0
- package/phanpy/dist/og-image.png +0 -0
- package/phanpy/dist/robots.txt +0 -2
- package/phanpy/dist/sw.js +0 -2
- package/phanpy/dist/sw.js.map +0 -1
- package/phanpy/dist/version.json +0 -1
- package/run-agent.mjs +0 -897
- package/vendor/gate.cjs +0 -138
- package/vendor/idp-grant.cjs +0 -394
- package/vendor/jfetch.cjs +0 -16
- package/web/admin/actors.js +0 -145
- package/web/admin/bar.css +0 -126
- package/web/admin/bar.js +0 -99
- package/web/admin/client/client.js +0 -66
- package/web/admin/client/index.html +0 -69
- package/web/admin/client-pick.js +0 -79
- package/web/admin/common.js +0 -23
- package/web/admin/connections.js +0 -112
- package/web/admin/gateway.js +0 -133
- package/web/admin/group.js +0 -258
- package/web/admin/index.html +0 -603
- package/web/admin/notices-bar.js +0 -90
- package/web/admin/oauth-signin.mjs +0 -37
- package/web/admin/record.js +0 -390
- package/web/admin/setup/index.html +0 -241
- package/web/admin/setup/setup.js +0 -326
- package/web/admin/tokens.css +0 -68
- package/web/admin/upkeep.js +0 -177
- package/web/admin/window.css +0 -55
- package/web/admin/window.js +0 -136
- package/web/app/README.md +0 -81
- package/web/app/admin-facade.mjs +0 -588
- package/web/app/agent.mjs +0 -663
- package/web/app/atproto-browser.mjs +0 -86
- package/web/app/authorize_interaction.html +0 -56
- package/web/app/authorize_interaction.js +0 -69
- package/web/app/boot.mjs +0 -576
- package/web/app/deliver-relay.mjs +0 -129
- package/web/app/dist/boot.js +0 -34218
- package/web/app/dist/boot.js.map +0 -7
- package/web/app/dist/sw.js +0 -72810
- package/web/app/dist/sw.js.map +0 -7
- package/web/app/fediacct-browser.mjs +0 -146
- package/web/app/gateway-move.mjs +0 -60
- package/web/app/idb-kv.mjs +0 -35
- package/web/app/index.html +0 -242
- package/web/app/keys-browser.mjs +0 -71
- package/web/app/keystore.mjs +0 -82
- package/web/app/oidc-session.mjs +0 -6
- package/web/app/pod-auth.mjs +0 -248
- package/web/app/pod-remote.mjs +0 -84
- package/web/app/shims/_globals.mjs +0 -2
- package/web/app/shims/fedify-sig.mjs +0 -77
- package/web/app/shims/node-crypto.mjs +0 -113
- package/web/app/shims/node-fs.mjs +0 -17
- package/web/app/shims/node-path.mjs +0 -19
- package/web/app/shims/node-url.mjs +0 -7
- package/web/app/shims/prelude.js +0 -58
- package/web/app/shims/safefetch.mjs +0 -58
- package/web/app/shims/shapes-text.mjs +0 -8
- package/web/app/shims/web-push.mjs +0 -14
- package/web/app/signup.mjs +0 -318
- package/web/app/sw-src.mjs +0 -220
- package/web/app/update.js +0 -70
- package/web/front/admin.html +0 -55
- package/web/front/admin.js +0 -89
- package/web/front/install.sh +0 -69
- package/web/front/new-account.html +0 -35
- package/web/front/new-account.js +0 -13
- package/web/front/notices.html +0 -69
- package/web/front/notices.js +0 -107
- package/web/front/run.html +0 -58
- package/web/front/run.js +0 -195
- package/web/front/solid-oidc-client.js +0 -6
- package/web/icons/forum.svg +0 -11
- package/web/icons/gateway.svg +0 -14
- package/web/icons/local.svg +0 -11
package/dist/handler.jsonld
CHANGED
|
@@ -273,6 +273,10 @@
|
|
|
273
273
|
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_agentHandles",
|
|
274
274
|
"memberFieldName": "agentHandles"
|
|
275
275
|
},
|
|
276
|
+
{
|
|
277
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_roots",
|
|
278
|
+
"memberFieldName": "roots"
|
|
279
|
+
},
|
|
276
280
|
{
|
|
277
281
|
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_frontHost",
|
|
278
282
|
"memberFieldName": "frontHost"
|
|
@@ -318,16 +322,8 @@
|
|
|
318
322
|
"memberFieldName": "constructor"
|
|
319
323
|
},
|
|
320
324
|
{
|
|
321
|
-
"@id": "fps:dist/handler.jsonld#
|
|
322
|
-
"memberFieldName": "
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_resolveClaim",
|
|
326
|
-
"memberFieldName": "resolveClaim"
|
|
327
|
-
},
|
|
328
|
-
{
|
|
329
|
-
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_stripMount",
|
|
330
|
-
"memberFieldName": "stripMount"
|
|
325
|
+
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_internals",
|
|
326
|
+
"memberFieldName": "internals"
|
|
331
327
|
},
|
|
332
328
|
{
|
|
333
329
|
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_initialize",
|
|
@@ -337,26 +333,10 @@
|
|
|
337
333
|
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_finalize",
|
|
338
334
|
"memberFieldName": "finalize"
|
|
339
335
|
},
|
|
340
|
-
{
|
|
341
|
-
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_doorSecretFor",
|
|
342
|
-
"memberFieldName": "doorSecretFor"
|
|
343
|
-
},
|
|
344
|
-
{
|
|
345
|
-
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_startIdentity",
|
|
346
|
-
"memberFieldName": "startIdentity"
|
|
347
|
-
},
|
|
348
|
-
{
|
|
349
|
-
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_frontIdentity",
|
|
350
|
-
"memberFieldName": "frontIdentity"
|
|
351
|
-
},
|
|
352
336
|
{
|
|
353
337
|
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_canHandle",
|
|
354
338
|
"memberFieldName": "canHandle"
|
|
355
339
|
},
|
|
356
|
-
{
|
|
357
|
-
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_runsIdentities",
|
|
358
|
-
"memberFieldName": "runsIdentities"
|
|
359
|
-
},
|
|
360
340
|
{
|
|
361
341
|
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_matchIdentity",
|
|
362
342
|
"memberFieldName": "matchIdentity"
|
|
@@ -377,10 +357,6 @@
|
|
|
377
357
|
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_optOutPod",
|
|
378
358
|
"memberFieldName": "optOutPod"
|
|
379
359
|
},
|
|
380
|
-
{
|
|
381
|
-
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_deliverAtDoor",
|
|
382
|
-
"memberFieldName": "deliverAtDoor"
|
|
383
|
-
},
|
|
384
360
|
{
|
|
385
361
|
"@id": "fps:dist/handler.jsonld#FediPodServerHandler__member_handle",
|
|
386
362
|
"memberFieldName": "handle"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { FediPodServerHandler } from './handler';
|
|
2
|
+
/** One running identity, and the call that stops it. */
|
|
3
|
+
export interface EmbeddedIdentity {
|
|
4
|
+
handle: string;
|
|
5
|
+
host: string;
|
|
6
|
+
/** Where the identity's own tree begins on its pod, and the actor inside it. */
|
|
7
|
+
podHome: string;
|
|
8
|
+
actorUrl: string;
|
|
9
|
+
surface: {
|
|
10
|
+
handler: (req: unknown, res: unknown) => Promise<void>;
|
|
11
|
+
streaming?: unknown;
|
|
12
|
+
};
|
|
13
|
+
stop: () => Promise<void>;
|
|
14
|
+
agent?: {
|
|
15
|
+
store?: {
|
|
16
|
+
getConfig?: () => {
|
|
17
|
+
kind?: string;
|
|
18
|
+
} | null | undefined;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Whether identities run in this process. They run in one: the lease admits
|
|
24
|
+
* a single drainer, and the state each one holds is in memory. With workers,
|
|
25
|
+
* that process is the primary — which serves no requests, so every process
|
|
26
|
+
* still has to know which hosts belong to an identity even though only one
|
|
27
|
+
* of them can answer for it.
|
|
28
|
+
*/
|
|
29
|
+
export declare function runsIdentities(h: FediPodServerHandler): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Start an agent for each opted-in pod. Runs before the server listens, so
|
|
32
|
+
* the identities come up in the background and boot is never held on a pod.
|
|
33
|
+
*/
|
|
34
|
+
export declare function initialize(h: FediPodServerHandler): Promise<void>;
|
|
35
|
+
/** Stop every identity: timers cleared, state written, lease let go. */
|
|
36
|
+
export declare function finalize(h: FediPodServerHandler): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* One identity's door secret, in its own pod's state. `agentDataDir` is
|
|
39
|
+
* handed in as the place an identity set up before this kept it, so its
|
|
40
|
+
* owner's existing door link survives the move.
|
|
41
|
+
*/
|
|
42
|
+
export declare function doorSecretFor(h: FediPodServerHandler, podBase: string, session?: {
|
|
43
|
+
fetch: unknown;
|
|
44
|
+
}, opts?: {
|
|
45
|
+
rotate?: boolean;
|
|
46
|
+
}): Promise<{
|
|
47
|
+
secret: string;
|
|
48
|
+
url: string;
|
|
49
|
+
rotated: boolean;
|
|
50
|
+
}>;
|
|
51
|
+
export declare function startIdentity(h: FediPodServerHandler, podBase: string): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* When this server is also the door, give a running identity a
|
|
54
|
+
* @handle@<frontHost> address: one inbox-only directory row so the
|
|
55
|
+
* shared-domain handle resolves and the door can take verified delivery for
|
|
56
|
+
* it. The row names the identity's own tree, which is where its inbox and
|
|
57
|
+
* its actor are — the door writes deliveries there and the agent watches
|
|
58
|
+
* that container. A row written by an attach belongs to its owner and is
|
|
59
|
+
* left alone; one this server wrote itself is corrected. The identity keeps
|
|
60
|
+
* its own ids on the pod; nothing is moved.
|
|
61
|
+
*/
|
|
62
|
+
export declare function frontIdentity(h: FediPodServerHandler, podBase: string, identity: EmbeddedIdentity): Promise<void>;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// identities.ts — the identities this server runs: started when the server
|
|
3
|
+
// boots or an owner opts in, retried while a pod is still being created,
|
|
4
|
+
// stopped together at shutdown, and each given its address at the apex and
|
|
5
|
+
// its door secret in its pod.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.runsIdentities = runsIdentities;
|
|
8
|
+
exports.initialize = initialize;
|
|
9
|
+
exports.finalize = finalize;
|
|
10
|
+
exports.doorSecretFor = doorSecretFor;
|
|
11
|
+
exports.startIdentity = startIdentity;
|
|
12
|
+
exports.frontIdentity = frontIdentity;
|
|
13
|
+
const node_crypto_1 = require("node:crypto");
|
|
14
|
+
const store_pod_1 = require("./store-pod");
|
|
15
|
+
const directory_1 = require("./directory");
|
|
16
|
+
const fedipod_1 = require("./fedipod");
|
|
17
|
+
const mounts_1 = require("./mounts");
|
|
18
|
+
// A pod that will not come up yet is usually a pod still being created by the
|
|
19
|
+
// server that is booting. Keep asking, slower each time, up to a few minutes.
|
|
20
|
+
const START_RETRY_MS = [2_000, 5_000, 15_000, 60_000, 300_000];
|
|
21
|
+
/**
|
|
22
|
+
* Whether identities run in this process. They run in one: the lease admits
|
|
23
|
+
* a single drainer, and the state each one holds is in memory. With workers,
|
|
24
|
+
* that process is the primary — which serves no requests, so every process
|
|
25
|
+
* still has to know which hosts belong to an identity even though only one
|
|
26
|
+
* of them can answer for it.
|
|
27
|
+
*/
|
|
28
|
+
function runsIdentities(h) {
|
|
29
|
+
const s = h.internals();
|
|
30
|
+
const cluster = s.args.clusterManager;
|
|
31
|
+
return !cluster || cluster.isSingleThreaded() || cluster.isPrimary();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Start an agent for each opted-in pod. Runs before the server listens, so
|
|
35
|
+
* the identities come up in the background and boot is never held on a pod.
|
|
36
|
+
*/
|
|
37
|
+
async function initialize(h) {
|
|
38
|
+
const s = h.internals();
|
|
39
|
+
if (!s.registry)
|
|
40
|
+
return;
|
|
41
|
+
const runs = runsIdentities(h);
|
|
42
|
+
// The stock CSS CLI installs no signal handlers, so a SIGTERM (systemd
|
|
43
|
+
// stop, docker stop, Ctrl+C) killed the process with agent state
|
|
44
|
+
// unflushed and the lease held for its whole TTL. Flush first, bounded,
|
|
45
|
+
// then re-raise so the process still dies the way it was asked to.
|
|
46
|
+
if (runs && !s.onSignal) {
|
|
47
|
+
s.onSignal = (signal) => {
|
|
48
|
+
const timeout = new Promise((resolve) => { setTimeout(resolve, 5_000).unref?.(); });
|
|
49
|
+
void Promise.race([finalize(h), timeout]).then(() => {
|
|
50
|
+
process.kill(process.pid, signal);
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
process.once('SIGTERM', s.onSignal);
|
|
54
|
+
process.once('SIGINT', s.onSignal);
|
|
55
|
+
}
|
|
56
|
+
// Identities run in the primary, and requests are answered by the workers,
|
|
57
|
+
// so with more than one worker an identity federates but cannot be reached:
|
|
58
|
+
// its client API, its owner pages and its live feed are in a process no
|
|
59
|
+
// request arrives at. Said once, by the process that has them.
|
|
60
|
+
if (runs && s.args.clusterManager && !s.args.clusterManager.isSingleThreaded()) {
|
|
61
|
+
s.logger.warn('FediPod is running in a multi-worker server. Deliveries are picked up by the inbox '
|
|
62
|
+
+ 'sweep rather than as they land, and no identity can answer its client API, its live feed or its '
|
|
63
|
+
+ "owner's pages while requests are served by other processes. Run with --workers 1.");
|
|
64
|
+
}
|
|
65
|
+
// Awaited, and BEFORE the server listens: a pod whose owner opted in must
|
|
66
|
+
// have its routes claimed from the first request after a restart, never
|
|
67
|
+
// served briefly by LDP. A failed load must not fail the boot — the rows
|
|
68
|
+
// persist, and the next start recovers them.
|
|
69
|
+
const pods = [];
|
|
70
|
+
try {
|
|
71
|
+
const keys = await s.registry.listKeys();
|
|
72
|
+
for (const key of keys) {
|
|
73
|
+
const row = await s.registry.get(key);
|
|
74
|
+
if (!row)
|
|
75
|
+
continue;
|
|
76
|
+
if (s.claimed.has(row.podBase) || s.identities.has(row.podBase))
|
|
77
|
+
continue; // already claimed
|
|
78
|
+
let claim;
|
|
79
|
+
try {
|
|
80
|
+
claim = (0, mounts_1.validateAgentPod)(h, row.podBase);
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
s.logger.error(`opted-in pod ${row.podBase} no longer valid: ${e.message}`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
s.claimed.set(row.podBase, claim);
|
|
87
|
+
s.agentHandles.set(row.handle, row.podBase);
|
|
88
|
+
s.roots.set(row.podBase, row.root || 'fedipod/');
|
|
89
|
+
pods.push(row.podBase);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
s.logger.error(`could not read the opt-in registry — opted-in identities are absent this boot: ${e.message}`);
|
|
94
|
+
}
|
|
95
|
+
if (pods.length > 0) {
|
|
96
|
+
s.logger.info(runs
|
|
97
|
+
? `FediPod agent enabled for ${pods.length} opted-in pod(s)`
|
|
98
|
+
: `FediPod claimed the routes of ${pods.length} opted-in pod(s); they are run elsewhere`);
|
|
99
|
+
}
|
|
100
|
+
// Claimed everywhere, run in one place. A process that does not run them
|
|
101
|
+
// must still not let a pod answer for a path that belongs to an identity.
|
|
102
|
+
if (runs)
|
|
103
|
+
for (const pod of pods)
|
|
104
|
+
void startIdentity(h, pod);
|
|
105
|
+
}
|
|
106
|
+
/** Stop every identity: timers cleared, state written, lease let go. */
|
|
107
|
+
async function finalize(h) {
|
|
108
|
+
const s = h.internals();
|
|
109
|
+
s.stopping = true;
|
|
110
|
+
if (s.onSignal) {
|
|
111
|
+
process.removeListener('SIGTERM', s.onSignal);
|
|
112
|
+
process.removeListener('SIGINT', s.onSignal);
|
|
113
|
+
s.onSignal = null;
|
|
114
|
+
}
|
|
115
|
+
const running = [...s.identities.values()];
|
|
116
|
+
s.identities.clear();
|
|
117
|
+
s.surfaces.clear();
|
|
118
|
+
s.doorSecrets.clear();
|
|
119
|
+
s.starting.clear();
|
|
120
|
+
await Promise.allSettled(running.map(async (identity) => {
|
|
121
|
+
await identity.stop();
|
|
122
|
+
s.logger.info(`FediPod agent @${identity.handle} stopped`);
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* One identity's door secret, in its own pod's state. `agentDataDir` is
|
|
127
|
+
* handed in as the place an identity set up before this kept it, so its
|
|
128
|
+
* owner's existing door link survives the move.
|
|
129
|
+
*/
|
|
130
|
+
async function doorSecretFor(h, podBase, session, opts = {}) {
|
|
131
|
+
const s = h.internals();
|
|
132
|
+
const { ensureDoorSecret } = await (0, fedipod_1.esmImport)(fedipod_1.EMBED);
|
|
133
|
+
return ensureDoorSecret(session ?? (0, store_pod_1.makeStoreSession)(s.args.resourceStore, podBase), podBase, {
|
|
134
|
+
...opts,
|
|
135
|
+
root: s.roots.get(podBase) ?? 'fedipod/',
|
|
136
|
+
dataDir: s.args.agentDataDir,
|
|
137
|
+
handle: (0, mounts_1.deriveHandle)(podBase),
|
|
138
|
+
log: (message) => { s.logger.info(`@${(0, mounts_1.deriveHandle)(podBase)}: ${message}`); },
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
async function startIdentity(h, podBase) {
|
|
142
|
+
const s = h.internals();
|
|
143
|
+
if (s.starting.has(podBase) || s.identities.has(podBase))
|
|
144
|
+
return;
|
|
145
|
+
s.starting.add(podBase);
|
|
146
|
+
s.startCancelled.delete(podBase);
|
|
147
|
+
const session = (0, store_pod_1.makeStoreSession)(s.args.resourceStore, podBase);
|
|
148
|
+
try {
|
|
149
|
+
for (let attempt = 0; !s.stopping && !s.startCancelled.has(podBase); attempt++) {
|
|
150
|
+
try {
|
|
151
|
+
const { startEmbeddedAgent } = await (0, fedipod_1.esmImport)(fedipod_1.EMBED);
|
|
152
|
+
// The secret is in the map BEFORE the surface can exist, so the
|
|
153
|
+
// gate's resolver never comes up empty — empty would mean gate-off.
|
|
154
|
+
if (!s.doorSecrets.has(podBase)) {
|
|
155
|
+
const door = await doorSecretFor(h, podBase, session);
|
|
156
|
+
s.doorSecrets.set(podBase, door.secret);
|
|
157
|
+
s.logger.info(`door secret for @${(0, mounts_1.deriveHandle)(podBase)} is in its pod at ${door.url}`);
|
|
158
|
+
}
|
|
159
|
+
const identity = await startEmbeddedAgent({
|
|
160
|
+
podBase,
|
|
161
|
+
root: s.roots.get(podBase) ?? 'fedipod/',
|
|
162
|
+
dataDir: s.args.agentDataDir,
|
|
163
|
+
session,
|
|
164
|
+
resourceStore: s.args.resourceStore,
|
|
165
|
+
webIdSuffix: s.args.agentWebIdSuffix ?? 'profile/card#me',
|
|
166
|
+
pollSeconds: s.args.agentPollSeconds ?? null,
|
|
167
|
+
autoAcceptFollows: s.args.agentAutoAcceptFollows !== false,
|
|
168
|
+
gateToken: () => s.doorSecrets.get(podBase),
|
|
169
|
+
uiPath: s.uiPath,
|
|
170
|
+
log: (message) => {
|
|
171
|
+
s.logger.info(message);
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
// Stopped, or opted out, while this one was still coming up.
|
|
175
|
+
if (s.stopping || s.startCancelled.has(podBase)) {
|
|
176
|
+
await identity.stop();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
s.identities.set(podBase, identity);
|
|
180
|
+
s.surfaces.set(podBase, identity);
|
|
181
|
+
s.logger.info(`FediPod agent @${identity.handle} running on ${podBase}`);
|
|
182
|
+
// A suffix pod cannot answer WebFinger for itself — its host root is
|
|
183
|
+
// the front's — so it is followable ONLY through the door's apex
|
|
184
|
+
// dispatch. Front it whether or not auto-front is on: the row is the
|
|
185
|
+
// whole of what makes @handle@host resolve to it.
|
|
186
|
+
if (s.args.agentAutoFront || s.claimed.get(podBase)?.mount) {
|
|
187
|
+
await frontIdentity(h, podBase, identity);
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
const wait = START_RETRY_MS[Math.min(attempt, START_RETRY_MS.length - 1)];
|
|
193
|
+
s.logger.warn(`FediPod agent for ${podBase} did not start: ${e.message} — retrying in ${Math.round(wait / 1000)}s`);
|
|
194
|
+
await new Promise((resolve) => {
|
|
195
|
+
setTimeout(resolve, wait).unref?.();
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
s.starting.delete(podBase);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* When this server is also the door, give a running identity a
|
|
206
|
+
* @handle@<frontHost> address: one inbox-only directory row so the
|
|
207
|
+
* shared-domain handle resolves and the door can take verified delivery for
|
|
208
|
+
* it. The row names the identity's own tree, which is where its inbox and
|
|
209
|
+
* its actor are — the door writes deliveries there and the agent watches
|
|
210
|
+
* that container. A row written by an attach belongs to its owner and is
|
|
211
|
+
* left alone; one this server wrote itself is corrected. The identity keeps
|
|
212
|
+
* its own ids on the pod; nothing is moved.
|
|
213
|
+
*/
|
|
214
|
+
async function frontIdentity(h, podBase, identity) {
|
|
215
|
+
const s = h.internals();
|
|
216
|
+
const { handle, podHome, actorUrl } = identity;
|
|
217
|
+
try {
|
|
218
|
+
const existing = await h.dir.lookup(handle);
|
|
219
|
+
const row = (0, directory_1.frontRow)(existing, {
|
|
220
|
+
handle, podHome, actorUrl,
|
|
221
|
+
kind: identity.agent?.store?.getConfig?.()?.kind === 'group' ? 'group' : 'person',
|
|
222
|
+
gatewayWebId: s.args.gatewayWebId ?? null,
|
|
223
|
+
hmacSecret: (0, node_crypto_1.randomBytes)(32).toString('base64'),
|
|
224
|
+
inboxOnly: true,
|
|
225
|
+
}, podBase);
|
|
226
|
+
if (!row)
|
|
227
|
+
return;
|
|
228
|
+
await h.dir.putDirectory(handle, row);
|
|
229
|
+
s.logger.info(existing
|
|
230
|
+
? `FediPod: the door's record of @${handle} now names ${podHome}`
|
|
231
|
+
: `FediPod: @${handle}@${s.frontHost} now resolves to ${podBase}`);
|
|
232
|
+
}
|
|
233
|
+
catch (e) {
|
|
234
|
+
s.logger.warn(`FediPod: could not front @${handle}: ${e.message}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
package/dist/mounts.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { FediPodServerHandler } from './handler';
|
|
2
|
+
/**
|
|
3
|
+
* A pod this server claims the routes of, whether or not its identity has
|
|
4
|
+
* finished starting. A request belongs to this claim when its host matches
|
|
5
|
+
* and its path is at or under the mount.
|
|
6
|
+
*/
|
|
7
|
+
export interface AgentClaim {
|
|
8
|
+
host: string;
|
|
9
|
+
mount: string;
|
|
10
|
+
podBase: string;
|
|
11
|
+
handle: string;
|
|
12
|
+
}
|
|
13
|
+
/** The pod's path as a mount prefix: `''` for a host root, else `/aisha`. */
|
|
14
|
+
export declare function mountOf(podBase: string): string;
|
|
15
|
+
/** Whether `a` is `b` or an ancestor path of `b` (both mount-shaped, no trailing slash). */
|
|
16
|
+
export declare function pathContains(a: string, b: string): boolean;
|
|
17
|
+
/** The identity's name, from its pod URL. Mirrors handleFor in fedipod/embed. */
|
|
18
|
+
export declare function deriveHandle(podBase: string): string;
|
|
19
|
+
/** The opt-in page's path: leading slash, no trailing one, the default when unset. */
|
|
20
|
+
export declare function normalizeRunPath(raw?: string): string;
|
|
21
|
+
/** A door path always has both slashes, so claiming and stripping agree. */
|
|
22
|
+
export declare function normalizeUiPath(raw?: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Whether this pod may become an identity here, and the claim it earns: a
|
|
25
|
+
* real URL, a place no other identity already sits, and a handle no other
|
|
26
|
+
* identity uses — two pods must never share <agentDataDir>/<handle>/.
|
|
27
|
+
*
|
|
28
|
+
* A HOST-ROOT or subdomain pod needs an origin of its own, and it may not be
|
|
29
|
+
* the front's host: the whole surface answers at the origin root, so two of
|
|
30
|
+
* them, or one sharing the front, would collide. A SUFFIX pod lives on a path
|
|
31
|
+
* (`server/aisha/`), so it may share its host — with the front and with other
|
|
32
|
+
* suffix pods — provided no claim already contains or nests under its path.
|
|
33
|
+
*/
|
|
34
|
+
export declare function validateAgentPod(h: FediPodServerHandler, podBase: string): AgentClaim;
|
|
35
|
+
/**
|
|
36
|
+
* The claim a request belongs to, or null. A request matches when its host is
|
|
37
|
+
* the claim's host and its path is at or under the claim's mount; the deepest
|
|
38
|
+
* mount wins, so a suffix pod's own routes are never swallowed by a shallower
|
|
39
|
+
* claim on the same host.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveClaim(h: FediPodServerHandler, host: string, pathname: string): AgentClaim | null;
|
|
42
|
+
/** A request path relative to a mount: `/aisha/ap/actor` under `/aisha` → `/ap/actor`. */
|
|
43
|
+
export declare function stripMount(pathname: string, mount: string): string;
|
package/dist/mounts.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// mounts.ts — which pod a request belongs to. A claim is a pod whose routes
|
|
3
|
+
// this server answers for, matched by host and by mount: the pod's own path,
|
|
4
|
+
// `''` for a host-root or subdomain pod, `/aisha` for a suffix pod on
|
|
5
|
+
// `https://host/aisha/`. claims.ts says which PATHS are an identity's; this
|
|
6
|
+
// says which POD.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.mountOf = mountOf;
|
|
9
|
+
exports.pathContains = pathContains;
|
|
10
|
+
exports.deriveHandle = deriveHandle;
|
|
11
|
+
exports.normalizeRunPath = normalizeRunPath;
|
|
12
|
+
exports.normalizeUiPath = normalizeUiPath;
|
|
13
|
+
exports.validateAgentPod = validateAgentPod;
|
|
14
|
+
exports.resolveClaim = resolveClaim;
|
|
15
|
+
exports.stripMount = stripMount;
|
|
16
|
+
const claims_1 = require("./claims");
|
|
17
|
+
/** The pod's path as a mount prefix: `''` for a host root, else `/aisha`. */
|
|
18
|
+
function mountOf(podBase) {
|
|
19
|
+
return new URL(podBase).pathname.replace(/\/+$/u, '');
|
|
20
|
+
}
|
|
21
|
+
/** Whether `a` is `b` or an ancestor path of `b` (both mount-shaped, no trailing slash). */
|
|
22
|
+
function pathContains(a, b) {
|
|
23
|
+
return a === b || b.startsWith(a + '/') || a === '';
|
|
24
|
+
}
|
|
25
|
+
/** The identity's name, from its pod URL. Mirrors handleFor in fedipod/embed. */
|
|
26
|
+
function deriveHandle(podBase) {
|
|
27
|
+
const u = new URL(podBase);
|
|
28
|
+
const segments = u.pathname.split('/').filter((seg) => seg.length > 0);
|
|
29
|
+
return segments.length > 0 ? segments[segments.length - 1] : u.hostname.split('.')[0];
|
|
30
|
+
}
|
|
31
|
+
/** The opt-in page's path: leading slash, no trailing one, the default when unset. */
|
|
32
|
+
function normalizeRunPath(raw) {
|
|
33
|
+
const said = String(raw ?? '').trim().replace(/\/+$/u, '');
|
|
34
|
+
if (!said)
|
|
35
|
+
return claims_1.DEFAULT_RUN_PATH;
|
|
36
|
+
return said.startsWith('/') ? said : `/${said}`;
|
|
37
|
+
}
|
|
38
|
+
/** A door path always has both slashes, so claiming and stripping agree. */
|
|
39
|
+
function normalizeUiPath(raw) {
|
|
40
|
+
if (raw === '')
|
|
41
|
+
return '';
|
|
42
|
+
const path = raw ?? '/fp/';
|
|
43
|
+
return `/${path.replace(/^\/+|\/+$/gu, '')}/`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Whether this pod may become an identity here, and the claim it earns: a
|
|
47
|
+
* real URL, a place no other identity already sits, and a handle no other
|
|
48
|
+
* identity uses — two pods must never share <agentDataDir>/<handle>/.
|
|
49
|
+
*
|
|
50
|
+
* A HOST-ROOT or subdomain pod needs an origin of its own, and it may not be
|
|
51
|
+
* the front's host: the whole surface answers at the origin root, so two of
|
|
52
|
+
* them, or one sharing the front, would collide. A SUFFIX pod lives on a path
|
|
53
|
+
* (`server/aisha/`), so it may share its host — with the front and with other
|
|
54
|
+
* suffix pods — provided no claim already contains or nests under its path.
|
|
55
|
+
*/
|
|
56
|
+
function validateAgentPod(h, podBase) {
|
|
57
|
+
const s = h.internals();
|
|
58
|
+
let host;
|
|
59
|
+
let mount;
|
|
60
|
+
try {
|
|
61
|
+
const u = new URL(podBase);
|
|
62
|
+
host = u.host.toLowerCase();
|
|
63
|
+
mount = mountOf(podBase);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
throw new Error(`not a pod URL: ${podBase}`);
|
|
67
|
+
}
|
|
68
|
+
if (mount === '') {
|
|
69
|
+
// A pod at the root of its host: it owns the whole origin, so it cannot
|
|
70
|
+
// share it with the front or with any other claim.
|
|
71
|
+
if (host.split(':')[0] === String(s.frontHost).toLowerCase()) {
|
|
72
|
+
throw new Error(`${podBase} is on the front's own host — give the identity its own origin, or host it on a path`);
|
|
73
|
+
}
|
|
74
|
+
for (const c of s.claimed.values()) {
|
|
75
|
+
if (c.host === host) {
|
|
76
|
+
throw new Error(`the host ${host} already carries an identity — a host-root identity needs an origin of its own`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// A pod on a path: it owns only its subtree. Refuse anything that already
|
|
82
|
+
// contains it or that it would contain, so no identity can answer under
|
|
83
|
+
// another's path (and none straddles the front's own routes underneath).
|
|
84
|
+
for (const c of s.claimed.values()) {
|
|
85
|
+
if (c.host !== host)
|
|
86
|
+
continue;
|
|
87
|
+
if (pathContains(c.mount, mount) || pathContains(mount, c.mount)) {
|
|
88
|
+
throw new Error(`${podBase} nests with the identity already at ${c.podBase} — a suffixed pod owns only its own subtree`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const handle = deriveHandle(podBase);
|
|
93
|
+
const holder = s.agentHandles.get(handle);
|
|
94
|
+
if (holder && holder !== podBase) {
|
|
95
|
+
throw new Error(`the name ${handle} already belongs to ${holder} — two identities cannot share it`);
|
|
96
|
+
}
|
|
97
|
+
return { host, mount, podBase, handle };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The claim a request belongs to, or null. A request matches when its host is
|
|
101
|
+
* the claim's host and its path is at or under the claim's mount; the deepest
|
|
102
|
+
* mount wins, so a suffix pod's own routes are never swallowed by a shallower
|
|
103
|
+
* claim on the same host.
|
|
104
|
+
*/
|
|
105
|
+
function resolveClaim(h, host, pathname) {
|
|
106
|
+
const s = h.internals();
|
|
107
|
+
let best = null;
|
|
108
|
+
for (const c of s.claimed.values()) {
|
|
109
|
+
if (c.host !== host)
|
|
110
|
+
continue;
|
|
111
|
+
if (c.mount === '' || pathname === c.mount || pathname.startsWith(c.mount + '/')) {
|
|
112
|
+
if (!best || c.mount.length > best.mount.length)
|
|
113
|
+
best = c;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return best;
|
|
117
|
+
}
|
|
118
|
+
/** A request path relative to a mount: `/aisha/ap/actor` under `/aisha` → `/ap/actor`. */
|
|
119
|
+
function stripMount(pathname, mount) {
|
|
120
|
+
if (!mount)
|
|
121
|
+
return pathname;
|
|
122
|
+
return pathname.slice(mount.length) || '/';
|
|
123
|
+
}
|
package/dist/opt-in.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { FediPodServerHandler } from './handler';
|
|
2
|
+
/**
|
|
3
|
+
* The WebIDs behind the account session in the request, or none. The server
|
|
4
|
+
* keeps that session in a `css-account` cookie; its own account API is what
|
|
5
|
+
* says which WebIDs the session owns, and it takes the same cookie. Nothing
|
|
6
|
+
* here trusts the cookie's presence — the account API does the deciding, and
|
|
7
|
+
* the caller picks the WebID that owns the pod being claimed.
|
|
8
|
+
*/
|
|
9
|
+
export declare function webIdsFromSession(h: FediPodServerHandler, request: {
|
|
10
|
+
headers: {
|
|
11
|
+
get(name: string): string | null;
|
|
12
|
+
};
|
|
13
|
+
}): Promise<string[]>;
|
|
14
|
+
/**
|
|
15
|
+
* A pod owner, already proven to control podBase, asks this server to run
|
|
16
|
+
* their identity. Returns { httpStatus, ...body }; the secret appears in the
|
|
17
|
+
* reply and nowhere else. Re-opting-in rotates the secret — that is how a
|
|
18
|
+
* lost one is recovered.
|
|
19
|
+
*/
|
|
20
|
+
export declare function optInPod(h: FediPodServerHandler, { podBase, webId, container, createIndex }: {
|
|
21
|
+
podBase: string;
|
|
22
|
+
webId: string;
|
|
23
|
+
container?: string;
|
|
24
|
+
createIndex?: boolean;
|
|
25
|
+
}): Promise<Record<string, unknown> & {
|
|
26
|
+
httpStatus: number;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* What a pod would be as an identity here, without changing anything: its
|
|
30
|
+
* handle, the host its address carries, and whether it runs here already.
|
|
31
|
+
*/
|
|
32
|
+
export declare function describePod(h: FediPodServerHandler, { podBase }: {
|
|
33
|
+
podBase: string;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
handle: string;
|
|
36
|
+
host: string;
|
|
37
|
+
address: string;
|
|
38
|
+
running: boolean;
|
|
39
|
+
manage: string;
|
|
40
|
+
}>;
|
|
41
|
+
/** The reverse: stop the identity and let the pod be plain LDP again. */
|
|
42
|
+
export declare function optOutPod(h: FediPodServerHandler, { podBase }: {
|
|
43
|
+
podBase: string;
|
|
44
|
+
}): Promise<Record<string, unknown> & {
|
|
45
|
+
httpStatus: number;
|
|
46
|
+
}>;
|