fedipod-server 0.29.0 → 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.
Files changed (440) hide show
  1. package/README.md +11 -6
  2. package/dist/door.d.ts +4 -0
  3. package/dist/door.js +31 -0
  4. package/dist/fedipod.d.ts +16 -0
  5. package/dist/fedipod.js +13 -0
  6. package/dist/front.d.ts +3 -0
  7. package/dist/front.js +94 -0
  8. package/dist/handler.d.ts +36 -101
  9. package/dist/handler.js +85 -645
  10. package/dist/handler.jsonld +2 -30
  11. package/dist/identities.d.ts +62 -0
  12. package/dist/identities.js +236 -0
  13. package/dist/mounts.d.ts +43 -0
  14. package/dist/mounts.js +123 -0
  15. package/dist/opt-in.d.ts +46 -0
  16. package/dist/opt-in.js +176 -0
  17. package/package.json +10 -18
  18. package/lib/client/c2s.mjs +0 -636
  19. package/lib/client/localapi.mjs +0 -87
  20. package/lib/client/masto/accounts.mjs +0 -310
  21. package/lib/client/masto/body.mjs +0 -156
  22. package/lib/client/masto/index.mjs +0 -206
  23. package/lib/client/masto/instance.mjs +0 -112
  24. package/lib/client/masto/media.mjs +0 -79
  25. package/lib/client/masto/oauth.mjs +0 -656
  26. package/lib/client/masto/render.mjs +0 -518
  27. package/lib/client/masto/statuses.mjs +0 -372
  28. package/lib/client/masto/timelines.mjs +0 -438
  29. package/lib/client/oidc-auth.mjs +0 -62
  30. package/lib/client/streaming.mjs +0 -154
  31. package/lib/client/webpush.mjs +0 -98
  32. package/lib/connections/acctfeed.mjs +0 -257
  33. package/lib/connections/atproto.mjs +0 -309
  34. package/lib/connections/bskyfeed.mjs +0 -243
  35. package/lib/connections/bskygroup.mjs +0 -162
  36. package/lib/connections/fediacct.mjs +0 -253
  37. package/lib/connections/import.mjs +0 -357
  38. package/lib/connections/tagfeed.mjs +0 -212
  39. package/lib/connections/vault.mjs +0 -114
  40. package/lib/core/as2.mjs +0 -206
  41. package/lib/core/contexts/activitystreams.json +0 -379
  42. package/lib/core/contexts/anno.json +0 -126
  43. package/lib/core/contexts/did-v1.json +0 -57
  44. package/lib/core/contexts/fep-5711.json +0 -36
  45. package/lib/core/contexts/gotosocial.json +0 -86
  46. package/lib/core/contexts/identity-v1.json +0 -152
  47. package/lib/core/contexts/index.mjs +0 -63
  48. package/lib/core/contexts/join-lemmy.json +0 -33
  49. package/lib/core/contexts/joinmastodon.json +0 -28
  50. package/lib/core/contexts/litepub-0.1.json +0 -60
  51. package/lib/core/contexts/map.json +0 -19
  52. package/lib/core/contexts/miscellany.json +0 -19
  53. package/lib/core/contexts/quotes.json +0 -18
  54. package/lib/core/contexts/schemaorg.json +0 -8845
  55. package/lib/core/contexts/security-data-integrity-v1.json +0 -78
  56. package/lib/core/contexts/security-data-integrity-v2.json +0 -81
  57. package/lib/core/contexts/security-multikey-v1.json +0 -35
  58. package/lib/core/contexts/security-v1.json +0 -74
  59. package/lib/core/contexts/webfinger.json +0 -10
  60. package/lib/core/deliver.mjs +0 -387
  61. package/lib/core/graphview.mjs +0 -327
  62. package/lib/core/intake/activities.mjs +0 -649
  63. package/lib/core/intake/activity.mjs +0 -318
  64. package/lib/core/intake/channel.mjs +0 -144
  65. package/lib/core/intake/group.mjs +0 -258
  66. package/lib/core/intake/index.mjs +0 -732
  67. package/lib/core/intake/notes.mjs +0 -367
  68. package/lib/core/intake/verify.mjs +0 -142
  69. package/lib/core/keys.mjs +0 -153
  70. package/lib/core/lease.mjs +0 -206
  71. package/lib/core/place.mjs +0 -82
  72. package/lib/core/polls.mjs +0 -105
  73. package/lib/core/profile-page.mjs +0 -104
  74. package/lib/core/proof.mjs +0 -79
  75. package/lib/core/publisher/collections.mjs +0 -272
  76. package/lib/core/publisher/index.mjs +0 -522
  77. package/lib/core/publisher/notes.mjs +0 -519
  78. package/lib/core/publisher/own.mjs +0 -143
  79. package/lib/core/publisher/questions.mjs +0 -241
  80. package/lib/core/publisher/restore.mjs +0 -224
  81. package/lib/core/shapes/activitystreams.ttl +0 -157
  82. package/lib/core/shapes/index.mjs +0 -132
  83. package/lib/core/shapes/shapes-text.mjs +0 -13
  84. package/lib/core/social.mjs +0 -561
  85. package/lib/core/storage.mjs +0 -176
  86. package/lib/core/store.mjs +0 -578
  87. package/lib/core/wire-quotes.mjs +0 -71
  88. package/lib/core/wire.mjs +0 -925
  89. package/lib/device/account.mjs +0 -87
  90. package/lib/device/admin/index.mjs +0 -13
  91. package/lib/device/admin/origins.mjs +0 -35
  92. package/lib/device/admin/routes/connections.mjs +0 -144
  93. package/lib/device/admin/routes/gateway.mjs +0 -199
  94. package/lib/device/admin/routes/lifecycle.mjs +0 -200
  95. package/lib/device/admin/routes/owner.mjs +0 -322
  96. package/lib/device/admin/routes/setup.mjs +0 -428
  97. package/lib/device/admin/routes/social.mjs +0 -188
  98. package/lib/device/admin/server.mjs +0 -95
  99. package/lib/device/admin/static.mjs +0 -247
  100. package/lib/device/admin/surface.mjs +0 -315
  101. package/lib/device/certs.mjs +0 -281
  102. package/lib/device/cli/commands/account.mjs +0 -586
  103. package/lib/device/cli/commands/run.mjs +0 -278
  104. package/lib/device/cli/commands/service.mjs +0 -221
  105. package/lib/device/cli/commands/setup.mjs +0 -489
  106. package/lib/device/cli/commands/state.mjs +0 -561
  107. package/lib/device/cli/context.mjs +0 -288
  108. package/lib/device/export-collections.mjs +0 -161
  109. package/lib/device/gateway-move.mjs +0 -58
  110. package/lib/device/home.mjs +0 -161
  111. package/lib/device/migrate.mjs +0 -115
  112. package/lib/device/ports.mjs +0 -27
  113. package/lib/device/remote.mjs +0 -54
  114. package/lib/device/setup.mjs +0 -496
  115. package/lib/device/update.mjs +0 -96
  116. package/lib/gateway/caches.mjs +0 -36
  117. package/lib/gateway/directory.mjs +0 -90
  118. package/lib/gateway/front-core.mjs +0 -966
  119. package/lib/gateway/gateway-core.mjs +0 -244
  120. package/lib/gateway/headers.mjs +0 -49
  121. package/lib/gateway/httpsig.mjs +0 -159
  122. package/lib/gateway/notices.mjs +0 -84
  123. package/lib/gateway/quiet.mjs +0 -189
  124. package/lib/gateway/relay-extras.mjs +0 -89
  125. package/lib/gateway/token-claims.mjs +0 -16
  126. package/lib/pod/README.md +0 -61
  127. package/lib/pod/actor.mjs +0 -96
  128. package/lib/pod/collection.mjs +0 -77
  129. package/lib/pod/containers.mjs +0 -140
  130. package/lib/pod/discovery.mjs +0 -46
  131. package/lib/pod/featured.mjs +0 -18
  132. package/lib/pod/followers.mjs +0 -24
  133. package/lib/pod/following.mjs +0 -10
  134. package/lib/pod/http.mjs +0 -74
  135. package/lib/pod/inbox.mjs +0 -166
  136. package/lib/pod/links.mjs +0 -35
  137. package/lib/pod/location.mjs +0 -52
  138. package/lib/pod/media.mjs +0 -27
  139. package/lib/pod/notes.mjs +0 -78
  140. package/lib/pod/notifications.mjs +0 -89
  141. package/lib/pod/outbox.mjs +0 -18
  142. package/lib/pod/package.json +0 -19
  143. package/lib/pod/policy.mjs +0 -58
  144. package/lib/pod/private.mjs +0 -19
  145. package/lib/pod/root.mjs +0 -104
  146. package/lib/pod/state.mjs +0 -40
  147. package/lib/pod/transport.mjs +0 -674
  148. package/lib/pod/type-index.mjs +0 -101
  149. package/lib/pod/urls.mjs +0 -91
  150. package/lib/server/embed.mjs +0 -424
  151. package/lib/session/README.md +0 -137
  152. package/lib/session/demo.html +0 -94
  153. package/lib/session/fedi-account.mjs +0 -417
  154. package/lib/session/fedi-login.mjs +0 -123
  155. package/lib/session/oidc-session.mjs +0 -233
  156. package/lib/session/package.json +0 -49
  157. package/lib/shared/guard.mjs +0 -213
  158. package/lib/shared/links.mjs +0 -9
  159. package/lib/shared/safefetch.mjs +0 -235
  160. package/lib/shared/ua.mjs +0 -29
  161. package/phanpy/dist/404.html +0 -40
  162. package/phanpy/dist/_headers +0 -2
  163. package/phanpy/dist/apple-touch-icon.png +0 -0
  164. package/phanpy/dist/assets/ICONS-DIPJeU0C.js +0 -2
  165. package/phanpy/dist/assets/ICONS-DIPJeU0C.js.map +0 -1
  166. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js +0 -183
  167. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
  168. package/phanpy/dist/assets/Temml-CCjoacWt.woff2 +0 -0
  169. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js +0 -2
  170. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js.map +0 -1
  171. package/phanpy/dist/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
  172. package/phanpy/dist/assets/catch-up-O5q5C75Z.png +0 -0
  173. package/phanpy/dist/assets/chunk-aKtaBQYM.js +0 -1
  174. package/phanpy/dist/assets/compose-CFEx7wb4.js +0 -2
  175. package/phanpy/dist/assets/compose-CFEx7wb4.js.map +0 -1
  176. package/phanpy/dist/assets/compose-ZJN5xSb4.js +0 -35
  177. package/phanpy/dist/assets/compose-ZJN5xSb4.js.map +0 -1
  178. package/phanpy/dist/assets/debug.module-YFQgwnIr.js +0 -52
  179. package/phanpy/dist/assets/debug.module-YFQgwnIr.js.map +0 -1
  180. package/phanpy/dist/assets/dom-p1YcJ5Rw.js +0 -2
  181. package/phanpy/dist/assets/dom-p1YcJ5Rw.js.map +0 -1
  182. package/phanpy/dist/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
  183. package/phanpy/dist/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
  184. package/phanpy/dist/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
  185. package/phanpy/dist/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
  186. package/phanpy/dist/assets/icons/add-circle-line-WD0mwORD.js +0 -1
  187. package/phanpy/dist/assets/icons/alert-line-CpFUMf9s.js +0 -1
  188. package/phanpy/dist/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
  189. package/phanpy/dist/assets/icons/announcement-line-5nwaJFJm.js +0 -1
  190. package/phanpy/dist/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
  191. package/phanpy/dist/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
  192. package/phanpy/dist/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
  193. package/phanpy/dist/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
  194. package/phanpy/dist/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
  195. package/phanpy/dist/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
  196. package/phanpy/dist/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
  197. package/phanpy/dist/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
  198. package/phanpy/dist/assets/icons/at-line-CF66Bznk.js +0 -1
  199. package/phanpy/dist/assets/icons/attachment-line-BY8It-l9.js +0 -1
  200. package/phanpy/dist/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
  201. package/phanpy/dist/assets/icons/board-line-C0UWXyA6.js +0 -1
  202. package/phanpy/dist/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
  203. package/phanpy/dist/assets/icons/building-5-line-Dd59MzbO.js +0 -1
  204. package/phanpy/dist/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
  205. package/phanpy/dist/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
  206. package/phanpy/dist/assets/icons/calendar-month-line-vommts2C.js +0 -1
  207. package/phanpy/dist/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
  208. package/phanpy/dist/assets/icons/camera-line-Cv69MEei.js +0 -1
  209. package/phanpy/dist/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
  210. package/phanpy/dist/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
  211. package/phanpy/dist/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
  212. package/phanpy/dist/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
  213. package/phanpy/dist/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
  214. package/phanpy/dist/assets/icons/clipboard-line-BBp364gJ.js +0 -1
  215. package/phanpy/dist/assets/icons/close-circle-line-CICdiuGz.js +0 -1
  216. package/phanpy/dist/assets/icons/close-line-DYrFWcjv.js +0 -1
  217. package/phanpy/dist/assets/icons/cloud-line-tiQAbah8.js +0 -1
  218. package/phanpy/dist/assets/icons/code-line-fAl8iiV3.js +0 -1
  219. package/phanpy/dist/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
  220. package/phanpy/dist/assets/icons/copy-2-line-CLW69yF5.js +0 -1
  221. package/phanpy/dist/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
  222. package/phanpy/dist/assets/icons/document-3-line-DBGNhAg2.js +0 -1
  223. package/phanpy/dist/assets/icons/document-line-C7mb9sb7.js +0 -1
  224. package/phanpy/dist/assets/icons/down-line-BGqSSThd.js +0 -1
  225. package/phanpy/dist/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
  226. package/phanpy/dist/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
  227. package/phanpy/dist/assets/icons/exit-line-Dc07BS-x.js +0 -1
  228. package/phanpy/dist/assets/icons/external-link-line-BvpSkmjO.js +0 -1
  229. package/phanpy/dist/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
  230. package/phanpy/dist/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
  231. package/phanpy/dist/assets/icons/filter-2-line-B_mR2usy.js +0 -1
  232. package/phanpy/dist/assets/icons/filter-line-C_nm-3cU.js +0 -1
  233. package/phanpy/dist/assets/icons/flag-1-line-C2HB05I0.js +0 -1
  234. package/phanpy/dist/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
  235. package/phanpy/dist/assets/icons/formula-line-DLrt2d6j.js +0 -1
  236. package/phanpy/dist/assets/icons/grid-line-CgUmEikf.js +0 -1
  237. package/phanpy/dist/assets/icons/group-line-C5fnX0wU.js +0 -1
  238. package/phanpy/dist/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
  239. package/phanpy/dist/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
  240. package/phanpy/dist/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
  241. package/phanpy/dist/assets/icons/heart-line-CJ7K47J4.js +0 -1
  242. package/phanpy/dist/assets/icons/history-2-line-kWWvFzqv.js +0 -1
  243. package/phanpy/dist/assets/icons/history-line-bGQiwbTH.js +0 -1
  244. package/phanpy/dist/assets/icons/home-3-line-fRU1zeLG.js +0 -1
  245. package/phanpy/dist/assets/icons/information-line-iNk6-sOY.js +0 -1
  246. package/phanpy/dist/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
  247. package/phanpy/dist/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
  248. package/phanpy/dist/assets/icons/layout-5-line-B_znt5wO.js +0 -1
  249. package/phanpy/dist/assets/icons/left-line-eUw0tya4.js +0 -1
  250. package/phanpy/dist/assets/icons/lightning-line-DaKoDdix.js +0 -1
  251. package/phanpy/dist/assets/icons/link-2-line-DCqLmMA7.js +0 -1
  252. package/phanpy/dist/assets/icons/list-check-line-BAxosBh9.js +0 -1
  253. package/phanpy/dist/assets/icons/lock-line-CPoaXeUW.js +0 -1
  254. package/phanpy/dist/assets/icons/mail-line-B0P8aa1L.js +0 -1
  255. package/phanpy/dist/assets/icons/moon-line-CEqNAToP.js +0 -1
  256. package/phanpy/dist/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
  257. package/phanpy/dist/assets/icons/more-3-line-BIiVjYTz.js +0 -1
  258. package/phanpy/dist/assets/icons/notification-line-BZZq2Gtu.js +0 -1
  259. package/phanpy/dist/assets/icons/pencil-line-CKh8-A1v.js +0 -1
  260. package/phanpy/dist/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
  261. package/phanpy/dist/assets/icons/pin-line-DpTolyhs.js +0 -1
  262. package/phanpy/dist/assets/icons/play-fill-B0-G_8lX.js +0 -1
  263. package/phanpy/dist/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
  264. package/phanpy/dist/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
  265. package/phanpy/dist/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
  266. package/phanpy/dist/assets/icons/radar-line-CKyroTth.js +0 -1
  267. package/phanpy/dist/assets/icons/react-line-CoIKhhtK.js +0 -1
  268. package/phanpy/dist/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
  269. package/phanpy/dist/assets/icons/right-line-B3KWJaqc.js +0 -1
  270. package/phanpy/dist/assets/icons/rocket-line-4KZl537D.js +0 -1
  271. package/phanpy/dist/assets/icons/round-fill-C69NTrZ0.js +0 -1
  272. package/phanpy/dist/assets/icons/round-line-B9k_1uo-.js +0 -1
  273. package/phanpy/dist/assets/icons/route-line-B28ReHcE.js +0 -1
  274. package/phanpy/dist/assets/icons/rows-4-line-CrBniagM.js +0 -1
  275. package/phanpy/dist/assets/icons/scan-line-DSf74YdP.js +0 -1
  276. package/phanpy/dist/assets/icons/search-2-line-B6geIU1z.js +0 -1
  277. package/phanpy/dist/assets/icons/settings-3-line-azJwK47w.js +0 -1
  278. package/phanpy/dist/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
  279. package/phanpy/dist/assets/icons/share-2-line-D5MxWjrm.js +0 -1
  280. package/phanpy/dist/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
  281. package/phanpy/dist/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
  282. package/phanpy/dist/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
  283. package/phanpy/dist/assets/icons/time-line-BF3eet1v.js +0 -1
  284. package/phanpy/dist/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
  285. package/phanpy/dist/assets/icons/translate-line-BFWol2Ce.js +0 -1
  286. package/phanpy/dist/assets/icons/unlock-line-X_x5vwv3.js +0 -1
  287. package/phanpy/dist/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
  288. package/phanpy/dist/assets/icons/user-4-line-BVSynZCp.js +0 -1
  289. package/phanpy/dist/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
  290. package/phanpy/dist/assets/icons/user-add-line-BbXdHG4z.js +0 -1
  291. package/phanpy/dist/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
  292. package/phanpy/dist/assets/icons/user-follow-line-BXux0wSd.js +0 -1
  293. package/phanpy/dist/assets/icons/user-star-line-DdYlpHLU.js +0 -1
  294. package/phanpy/dist/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
  295. package/phanpy/dist/assets/icons/user-x-line-DIDgNlPH.js +0 -1
  296. package/phanpy/dist/assets/icons/volume-line-Bs390KQt.js +0 -1
  297. package/phanpy/dist/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
  298. package/phanpy/dist/assets/icons/walk-line-yNXfB-md.js +0 -1
  299. package/phanpy/dist/assets/icons/world-2-line-CenkGIwj.js +0 -1
  300. package/phanpy/dist/assets/icons/zoom-in-line-CaENUphf.js +0 -1
  301. package/phanpy/dist/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
  302. package/phanpy/dist/assets/instances-BNPptnn-.json +0 -333
  303. package/phanpy/dist/assets/locales/ar-SA-CfheRbCu.js +0 -1
  304. package/phanpy/dist/assets/locales/ca-ES-DHRW86Tz.js +0 -1
  305. package/phanpy/dist/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
  306. package/phanpy/dist/assets/locales/de-DE-ByRPMRFy.js +0 -1
  307. package/phanpy/dist/assets/locales/eo-UY-CPC7wLCS.js +0 -1
  308. package/phanpy/dist/assets/locales/es-ES-dJa0Fd9t.js +0 -1
  309. package/phanpy/dist/assets/locales/eu-ES-C3djlPR2.js +0 -1
  310. package/phanpy/dist/assets/locales/fa-IR-DTT490Ck.js +0 -1
  311. package/phanpy/dist/assets/locales/fi-FI-B23MCPuz.js +0 -1
  312. package/phanpy/dist/assets/locales/fr-FR-BcaQsO5C.js +0 -1
  313. package/phanpy/dist/assets/locales/gl-ES-BR-CVKBN.js +0 -1
  314. package/phanpy/dist/assets/locales/he-IL-CfheRbCu.js +0 -1
  315. package/phanpy/dist/assets/locales/hu-HU-CfheRbCu.js +0 -1
  316. package/phanpy/dist/assets/locales/it-IT-C1136UFV.js +0 -1
  317. package/phanpy/dist/assets/locales/ja-JP-CRZmRAhD.js +0 -1
  318. package/phanpy/dist/assets/locales/kab-Cz8xH_TT.js +0 -1
  319. package/phanpy/dist/assets/locales/ko-KR-CG9UiY4o.js +0 -1
  320. package/phanpy/dist/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
  321. package/phanpy/dist/assets/locales/nb-NO-CfheRbCu.js +0 -1
  322. package/phanpy/dist/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
  323. package/phanpy/dist/assets/locales/oc-FR-CfheRbCu.js +0 -1
  324. package/phanpy/dist/assets/locales/pl-PL-DkwGXf6P.js +0 -1
  325. package/phanpy/dist/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
  326. package/phanpy/dist/assets/locales/pt-BR-nGL0HdFS.js +0 -1
  327. package/phanpy/dist/assets/locales/pt-PT-Cp17aj2z.js +0 -1
  328. package/phanpy/dist/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
  329. package/phanpy/dist/assets/locales/th-TH-CfheRbCu.js +0 -1
  330. package/phanpy/dist/assets/locales/tok-CfheRbCu.js +0 -1
  331. package/phanpy/dist/assets/locales/tr-TR-CfheRbCu.js +0 -1
  332. package/phanpy/dist/assets/locales/uk-UA-C5E3dFBf.js +0 -1
  333. package/phanpy/dist/assets/locales/zh-CN-BHJi7_et.js +0 -1
  334. package/phanpy/dist/assets/locales/zh-TW-CfheRbCu.js +0 -1
  335. package/phanpy/dist/assets/main-BdqNbG-a.js +0 -26
  336. package/phanpy/dist/assets/main-BdqNbG-a.js.map +0 -1
  337. package/phanpy/dist/assets/mock-home-DGhR__He.js +0 -2
  338. package/phanpy/dist/assets/mock-home-DGhR__He.js.map +0 -1
  339. package/phanpy/dist/assets/multi-column-ROck0NVt.jpg +0 -0
  340. package/phanpy/dist/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
  341. package/phanpy/dist/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
  342. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js +0 -2
  343. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js.map +0 -1
  344. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js +0 -20
  345. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js.map +0 -1
  346. package/phanpy/dist/assets/style-B1iLPTPR.css +0 -2
  347. package/phanpy/dist/assets/temml-DuyIQMei.js +0 -97
  348. package/phanpy/dist/assets/temml-DuyIQMei.js.map +0 -1
  349. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js +0 -2
  350. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
  351. package/phanpy/dist/assets/year-in-posts-B2lywqdx.png +0 -0
  352. package/phanpy/dist/assets/year-in-posts-DJv_star.js +0 -3
  353. package/phanpy/dist/assets/year-in-posts-DJv_star.js.map +0 -1
  354. package/phanpy/dist/compose/index.html +0 -20
  355. package/phanpy/dist/favicon.ico +0 -0
  356. package/phanpy/dist/index.html +0 -73
  357. package/phanpy/dist/logo-192.png +0 -0
  358. package/phanpy/dist/logo-512.png +0 -0
  359. package/phanpy/dist/logo-badge-72.png +0 -0
  360. package/phanpy/dist/logo-maskable-512.png +0 -0
  361. package/phanpy/dist/logo-monochrome-512.png +0 -0
  362. package/phanpy/dist/logo-monochrome-maskable-512.png +0 -0
  363. package/phanpy/dist/manifest.webmanifest +0 -1
  364. package/phanpy/dist/og-image-2.jpg +0 -0
  365. package/phanpy/dist/og-image.png +0 -0
  366. package/phanpy/dist/robots.txt +0 -2
  367. package/phanpy/dist/sw.js +0 -2
  368. package/phanpy/dist/sw.js.map +0 -1
  369. package/phanpy/dist/version.json +0 -1
  370. package/run-agent.mjs +0 -899
  371. package/vendor/gate.cjs +0 -138
  372. package/vendor/idp-grant.cjs +0 -394
  373. package/vendor/jfetch.cjs +0 -16
  374. package/web/admin/actors.js +0 -147
  375. package/web/admin/bar.css +0 -126
  376. package/web/admin/bar.js +0 -99
  377. package/web/admin/client/client.js +0 -66
  378. package/web/admin/client/index.html +0 -69
  379. package/web/admin/client-pick.js +0 -79
  380. package/web/admin/common.js +0 -23
  381. package/web/admin/connections.js +0 -112
  382. package/web/admin/gateway.js +0 -133
  383. package/web/admin/group.js +0 -258
  384. package/web/admin/index.html +0 -612
  385. package/web/admin/notices-bar.js +0 -90
  386. package/web/admin/oauth-signin.mjs +0 -37
  387. package/web/admin/record.js +0 -393
  388. package/web/admin/setup/index.html +0 -257
  389. package/web/admin/setup/setup.js +0 -339
  390. package/web/admin/tokens.css +0 -68
  391. package/web/admin/upkeep.js +0 -177
  392. package/web/admin/window.css +0 -55
  393. package/web/admin/window.js +0 -136
  394. package/web/app/README.md +0 -81
  395. package/web/app/admin-facade.mjs +0 -588
  396. package/web/app/agent.mjs +0 -672
  397. package/web/app/atproto-browser.mjs +0 -86
  398. package/web/app/authorize_interaction.html +0 -56
  399. package/web/app/authorize_interaction.js +0 -69
  400. package/web/app/boot.mjs +0 -616
  401. package/web/app/deliver-relay.mjs +0 -129
  402. package/web/app/dist/boot.js +0 -34562
  403. package/web/app/dist/boot.js.map +0 -7
  404. package/web/app/dist/sw.js +0 -73456
  405. package/web/app/dist/sw.js.map +0 -7
  406. package/web/app/fediacct-browser.mjs +0 -146
  407. package/web/app/gateway-move.mjs +0 -60
  408. package/web/app/idb-kv.mjs +0 -35
  409. package/web/app/index.html +0 -258
  410. package/web/app/keys-browser.mjs +0 -71
  411. package/web/app/keystore.mjs +0 -82
  412. package/web/app/oidc-session.mjs +0 -6
  413. package/web/app/pod-auth.mjs +0 -248
  414. package/web/app/pod-remote.mjs +0 -84
  415. package/web/app/shims/_globals.mjs +0 -2
  416. package/web/app/shims/fedify-sig.mjs +0 -77
  417. package/web/app/shims/node-crypto.mjs +0 -113
  418. package/web/app/shims/node-fs.mjs +0 -17
  419. package/web/app/shims/node-path.mjs +0 -19
  420. package/web/app/shims/node-url.mjs +0 -7
  421. package/web/app/shims/prelude.js +0 -58
  422. package/web/app/shims/safefetch.mjs +0 -58
  423. package/web/app/shims/shapes-text.mjs +0 -8
  424. package/web/app/shims/web-push.mjs +0 -14
  425. package/web/app/signup.mjs +0 -357
  426. package/web/app/sw-src.mjs +0 -220
  427. package/web/app/update.js +0 -70
  428. package/web/front/admin.html +0 -55
  429. package/web/front/admin.js +0 -89
  430. package/web/front/install.sh +0 -69
  431. package/web/front/new-account.html +0 -35
  432. package/web/front/new-account.js +0 -13
  433. package/web/front/notices.html +0 -69
  434. package/web/front/notices.js +0 -107
  435. package/web/front/run.html +0 -64
  436. package/web/front/run.js +0 -221
  437. package/web/front/solid-oidc-client.js +0 -6
  438. package/web/icons/forum.svg +0 -11
  439. package/web/icons/gateway.svg +0 -14
  440. package/web/icons/local.svg +0 -11
@@ -1,489 +0,0 @@
1
- // setup.mjs — making an identity and its secrets: setup, rotate-key,
2
- // revoke-credential, tokens, passwd, keys.
3
-
4
- import fs from 'node:fs';
5
- import path from 'node:path';
6
- import { pathToFileURL } from 'node:url';
7
- import { tildify, rootOf, recordLastUsed, writeJsonAtomic } from '../../home.mjs';
8
- import { insecureUrlReason } from '../../../shared/safefetch.mjs';
9
- import { localFetch } from '../../../client/localapi.mjs';
10
- import { args, flag, has, PROFILE, AP_ROOT, HOME, PORT, recordAgent, useProfile, requireHandle, requireIdentity, askHidden, ask, endAsking, openBrowser, finish, IDENTITY_FLAGS, refuseExistingIdentity, runBrowserSetup } from '../context.mjs';
11
-
12
- export async function setup() {
13
- // --profile names the home before anything is asked, so a collision is
14
- // knowable now; refuseExistingIdentity exits when it finds one.
15
- if (PROFILE) { useProfile(PROFILE); refuseExistingIdentity(); }
16
- // At a terminal with no identity flag, setup asks two things and hands the
17
- // rest to the page.
18
- if (process.stdin.isTTY && !has('cli') && !IDENTITY_FLAGS.some(f => args.includes('--' + f))) {
19
- return runBrowserSetup();
20
- }
21
- // Where on the pod: --root names it outright (scripts); otherwise the person
22
- // names the container that holds `fedipod/`, asked below once the pod is known.
23
- let root = flag('root') || null;
24
- const place = await import(new URL('../../../../lib/core/place.mjs', import.meta.url));
25
- const kind = has('group') ? 'group' : 'person';
26
- const approveJoins = has('group') && has('approve-joins');
27
- const summary = flag('summary');
28
- const icon = flag('icon');
29
- let pod = flag('pod');
30
- const interactive = process.stdin.isTTY;
31
-
32
- // Everything that shapes your identity is asked for here, with defaults,
33
- // because these are decisions — the pod name becomes half of your
34
- // permanent address, and nobody should discover that after the fact.
35
- // Flags skip the matching question, so scripted setup is unchanged.
36
- let newAccount = has('new-account');
37
- if (!newAccount && !pod) {
38
- if (!interactive) {
39
- console.error('need --email and --handle, plus either --pod <url> or --new-account');
40
- process.exit(2);
41
- }
42
- const have = await ask('do you already have a Solid pod? (y/n)', 'n');
43
- if (/^y/i.test(have)) {
44
- // Either tuck the fediverse account into the pod they already have,
45
- // or make a fresh pod on the same Solid account for it.
46
- const where = await ask('store your Fediverse account in that pod, or in a new pod? (existing/new)', 'existing');
47
- if (/^n/i.test(where)) newAccount = true;
48
- else pod = await ask('your pod address (e.g. https://you.solidcommunity.net/)');
49
- } else {
50
- newAccount = true;
51
- }
52
- }
53
- if (!newAccount && !pod) { console.error('no pod given'); process.exit(2); }
54
- const CONTAINER_Q = 'Store your data in a container named fedipod, inside this container';
55
- let container = flag('in');
56
- if (!newAccount) {
57
- const podBase = pod.endsWith('/') ? pod : pod + '/';
58
- if (!root) {
59
- if (container == null) container = interactive ? await ask(`${CONTAINER_Q} (empty: ${new URL(podBase).pathname})`, '') : '';
60
- const chosen = place.chosenRoot(podBase, container);
61
- if (chosen.problem) { console.error(`Where to store it: ${chosen.problem}.`); process.exit(2); }
62
- root = chosen.root;
63
- }
64
- const { resourceExists } = await import(new URL('../../../../lib/pod/root.mjs', import.meta.url));
65
- const { apUrls, DEFAULT_ROOT: DR } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
66
- // An account at the chosen place, or an older one where accounts used to go.
67
- if (await resourceExists(fetch, apUrls(pod, root).actor) || await resourceExists(fetch, apUrls(pod, DR).actor)) {
68
- if (String(flag('address') || 'pod').toLowerCase() !== 'front') {
69
- console.error('The pod already hosts a FediPod account. If you want a second account, put it on a different pod.');
70
- console.error('To move an account whose address is at another gateway to this one, add --address front.');
71
- process.exit(2);
72
- }
73
- console.log('The pod already holds an account; if its address is at another gateway, setup moves it here.');
74
- }
75
- }
76
-
77
- const issuer = flag('issuer') || await ask('Solid identity provider', 'https://solidcommunity.net');
78
- // Before the password is asked for, let alone sent. The issuer is where it
79
- // goes and the pod is where the credential it buys is used, so an http:
80
- // address off this machine puts both in clear. Loopback is exempt: it never
81
- // reaches a network interface, and a pod on this machine is an ordinary way
82
- // to run this.
83
- for (const [url, what] of [[issuer, 'identity provider address'], [pod, 'pod address']]) {
84
- const bad = insecureUrlReason(url, what);
85
- if (bad) { console.error(bad); process.exit(2); }
86
- }
87
- const email = flag('email') || await ask(`account email at ${new URL(issuer).host}`);
88
- const handle = flag('handle') || await ask('handle (the name in your address; permanent)');
89
- if (!email || !handle) {
90
- console.error('an email and a handle are required');
91
- process.exit(2);
92
- }
93
- // Before anything irreversible: the account creation and the mint are both
94
- // one-way, and a credential is shown once. A home that cannot be decided has
95
- // to be refused here, not after there is something to lose.
96
- requireHandle(handle);
97
- useProfile(PROFILE || handle);
98
- refuseExistingIdentity();
99
- const podName = newAccount
100
- ? (flag('pod-name') || await ask('pod name (this becomes the domain of your address)', handle))
101
- : null;
102
- const name = flag('name') || await ask('display name (shown above your address)', handle);
103
-
104
- // A handle resolves through <host>/.well-known/webfinger, so it only works
105
- // when the pod owns the root of its host. Whether a NEW pod gets its own
106
- // subdomain is the server's call, so promise nothing here we cannot keep.
107
- const { webfingerHost, apUrls, DEFAULT_ROOT } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
108
- const issuerHost = new URL(issuer).host;
109
- const wfHost = newAccount ? null : webfingerHost(pod);
110
-
111
- // Where the address lives: on the pod (default), or at a gateway. A pod on a
112
- // suffix-based host cannot answer WebFinger for a handle, so its address
113
- // is at the gateway whatever was asked. `--address front` takes a gateway
114
- // address for a host-root pod too; `--gateway <origin>` names the gateway.
115
- const addressShape = String(flag('address') || 'pod').toLowerCase();
116
- if (addressShape !== 'pod' && addressShape !== 'front') { console.error('--address must be pod or front'); process.exit(2); }
117
- const gatewayOrigin = flag('gateway') || 'https://fedipod.net';
118
- { const badGw = insecureUrlReason(gatewayOrigin, 'gateway address'); if (badGw) { console.error(badGw); process.exit(2); } }
119
- const gatewayHost = new URL(gatewayOrigin).host;
120
- // For an EXISTING pod the shape is known now; for a NEW pod the path case is
121
- // decided after the pod is made, below.
122
- let fronted = (!newAccount && !wfHost) || addressShape === 'front';
123
- if (fronted && kind === 'group') {
124
- console.error('a group needs a pod at its own host — a gateway address for a group is not supported yet.');
125
- process.exit(2);
126
- }
127
- // A person warned about an unresolvable handle is the one who suffers, so a
128
- // warning is their call to accept. Nobody could ever find this group, and the
129
- // people it would fail are not the operator reading the warning.
130
- if (kind === 'group' && !newAccount && !wfHost) {
131
- console.error(`${pod} is a suffixed pod, not a subdomained one.`);
132
- console.error('WebFinger is answered only for a subdomained pod, so nobody could find this group.');
133
- console.error('Give the group a pod of its own: fedipod setup --group --new-account');
134
- process.exit(2);
135
- }
136
- console.log(kind === 'group' ? '\nThe group will be:\n' : '\nYou will be:\n');
137
- console.log(` ${name}`);
138
- if (fronted) {
139
- console.log(` @${handle}@${gatewayHost}\n`);
140
- console.log(`— your address lives at ${gatewayHost}; your posts, key and data stay on your pod.\n`);
141
- } else if (wfHost) {
142
- console.log(` @${handle}@${wfHost}\n`);
143
- } else if (newAccount) {
144
- console.log(` @${handle}@${podName}.${issuerHost}\n`);
145
- console.log(`— provided ${issuerHost} gives each pod its own subdomain. A server that puts`);
146
- console.log(`pods at ${issuerHost}/${podName}/ instead cannot answer WebFinger for an address,`);
147
- console.log(`so setup takes an address at ${gatewayHost} for you and says so.\n`);
148
- }
149
- // Where the account lives is recorded in the pod's public type index. A new
150
- // pod has none; a pod you bring is asked. With none, only a yes goes on.
151
- let createIndex = has('create-type-index');
152
- if (!createIndex) {
153
- const known = newAccount ? false : await place.publicIndexKnown(fetch, pod.endsWith('/') ? pod : pod + '/');
154
- if (known !== true) {
155
- const why = newAccount ? 'A new pod has no public type index' : 'Your pod has no public type index';
156
- if (!interactive) {
157
- console.error(`${why}. FediPod records where your account lives in one; add --create-type-index to make it.`);
158
- process.exit(2);
159
- }
160
- const yes = await ask(`${why}, the list Solid apps use to find your things. FediPod needs one to record `
161
- + 'where your account lives. Create it? It will be readable by anyone, like your profile. (y/n)', 'n');
162
- if (!/^y/i.test(yes)) { console.log('Setup stopped. Nothing was written to your pod.'); process.exit(0); }
163
- createIndex = true;
164
- }
165
- }
166
- if (newAccount && !root && container == null) {
167
- container = await ask(`${CONTAINER_Q} (empty: the new pod's root)`, '');
168
- }
169
- console.log('The display name can be changed later; the handle and pod cannot.');
170
- const go = await ask(newAccount
171
- ? (kind === 'group' ? 'create pod and group? (y/n)' : 'create pod and Fediverse account? (y/n)')
172
- : (kind === 'group' ? 'create group on this pod? (y/n)' : 'create Fediverse account on this pod? (y/n)'), 'y');
173
- if (!/^y/i.test(go)) { console.log('nothing was created'); process.exit(0); }
174
- endAsking(); // hand the tty to the password prompt
175
-
176
- const password = process.env.AP_PASSWORD || await askHidden(`password for ${email} at ${issuer}: `);
177
-
178
- if (newAccount) {
179
- const { createAccountWithPod } = await import(new URL('../../../../lib/device/account.mjs', import.meta.url));
180
- const made = await createAccountWithPod({ issuer, email, password, podName });
181
- pod = made.pod;
182
- console.log(`account + pod created: ${pod}`);
183
- if (!root) {
184
- const chosen = place.chosenRootInNewPod(pod.endsWith('/') ? pod : pod + '/', container);
185
- if (chosen.problem) { console.error(`Where to store it: ${chosen.problem}. The pod was made; nothing else was.`); process.exit(2); }
186
- root = chosen.root;
187
- }
188
- if (!webfingerHost(pod)) {
189
- if (kind === 'group') {
190
- console.log(`\n${issuerHost} created the pod at ${pod} — a suffixed pod.`);
191
- console.log('WebFinger is answered only for a subdomained pod, so nobody could find this group.');
192
- console.log('The pod exists; no actor was published.');
193
- process.exit(0);
194
- }
195
- // A path pod's address lives at the gateway; nothing to warn about.
196
- fronted = true;
197
- console.log(`${issuerHost} makes suffixed pods, so your address will be @${handle}@${gatewayHost}.`);
198
- }
199
- }
200
-
201
- const { mintCredential } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
202
- // New credentials only: one already registered keeps the name it was minted
203
- // under, so existing pods stay as they are unless they are set up again.
204
- const credential = await mintCredential({ origin: issuer, email, password, name: 'fedipod' });
205
- const rec = {
206
- ...credential,
207
- remotePod: pod.endsWith('/') ? pod : pod + '/',
208
- createdAt: new Date().toISOString(),
209
- // The private half goes on THIS machine, exactly as the browser setup does
210
- // (lib/setup.mjs). Omitting it here meant the two paths produced different
211
- // installs from the same answers: the CLI put the timeline, contacts,
212
- // blocklist and notifications on the pod — the layout the relay design
213
- // exists to avoid, and the one that makes receiving a post cost pod writes.
214
- // It also made provisioning write a tree it did not need, which is where a
215
- // slow server showed it up.
216
- privateRoot: flag('private-root')
217
- || pathToFileURL(path.join(HOME, 'private')).href + '/',
218
- ...(root ? { root } : {}),
219
- ...(flag('keys') === 'pod' ? { keysMode: 'pod' } : {}),
220
- ...(has('rotate-key') ? { rotateKeyOnce: true } : {}),
221
- // What shape this install is. Both setup paths stamp it, so `upgrade` can
222
- // tell an old install from a new one rather than inferring it.
223
- layout: (await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url))).CURRENT_LAYOUT,
224
- };
225
- fs.mkdirSync(HOME, { recursive: true, mode: 0o700 });
226
- writeJsonAtomic(path.join(HOME, 'credential.json'), rec);
227
- // The one you just made is the one you are using.
228
- if (rootOf(HOME) === AP_ROOT) recordLastUsed(AP_ROOT, path.basename(HOME));
229
- recordAgent({ port: PORT, handle }); // later commands need no --port
230
- console.log(`credential minted and saved to ${path.join(HOME, 'credential.json')}`);
231
-
232
- let gatewayCfg = null;
233
- if (fronted) {
234
- const { takeGatewayAddress } = await import(new URL('../../../../lib/device/setup.mjs', import.meta.url));
235
- const urls = apUrls(pod, root || DEFAULT_ROOT);
236
- console.log(`taking a gateway address at ${gatewayHost}`);
237
- gatewayCfg = await takeGatewayAddress({
238
- home: HOME, credential: rec, gatewayOrigin, handle,
239
- podHome: urls.home, actorUrl: urls.actor, kind, log: (...a) => console.log('[setup]', ...a),
240
- });
241
- }
242
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
243
- const agent = new Agent({ home: HOME, log: (...a) => console.log('[setup]', ...a) });
244
- await agent.bootstrap({ handle, name, root, kind, approveJoins, summary, icon, gateway: gatewayCfg });
245
- await agent.connect({ repair: false }); // publishProfile below is the publish
246
- await agent.publisher.publishProfile();
247
- await agent.store.flush();
248
- // Where the account lives, in the pod's public type index — made first on the yes.
249
- await place.recordPlace(agent.remote, rec.remotePod, `${rec.remotePod}${root}ap/actor`, { create: createIndex })
250
- .then(() => console.log('recorded where the account lives in your public type index'))
251
- .catch((e) => { console.error(`could not record where the account lives in your type index: ${e.message}`); process.exitCode = 1; });
252
- const finalHost = gatewayCfg ? gatewayHost : webfingerHost(rec.remotePod);
253
- const what = kind === 'group' ? 'group' : 'actor';
254
- console.log(finalHost
255
- ? `${what} published: @${handle}@${finalHost}`
256
- : `${what} published, but not reachable as a handle \u2014 ${rec.remotePod} is a suffixed pod`);
257
-
258
- // Straight into serving — setup ends with a working client in the browser.
259
- const { startAdmin } = await import(new URL('../../../../lib/device/admin/index.mjs', import.meta.url));
260
- const { hostLabel } = await import(new URL('../../../../lib/shared/guard.mjs', import.meta.url));
261
- startAdmin({ port: PORT, handle, gateToken: process.env.AP_GATE_TOKEN || '', agent, log: (...a) => console.log('[ap]', ...a) });
262
- const shutdown = () => {
263
- setTimeout(() => process.exit(0), 1500).unref(); // never hang a stop on a slow pod
264
- try { fs.rmSync(path.join(HOME, 'agent.pid'), { force: true }); } catch {}
265
- Promise.allSettled([agent.store.flush(), agent.lease?.release()]).finally(() => process.exit(0));
266
- };
267
- process.on('SIGINT', shutdown);
268
- process.on('SIGTERM', shutdown);
269
- // The named origin, and the instance to log the client into is that same
270
- // origin. Opening the shared one and then telling you to log in there is how
271
- // two identities end up sharing a browser storage bucket, and a client on the
272
- // shared origin shows whichever account it happens to hold.
273
- const label = hostLabel(handle);
274
- const authority = `${label ? label + '.' : ''}localhost:${PORT}`;
275
- const url = `http://${authority}/`;
276
- if (kind === 'group') {
277
- console.log(`group running on ${url} — see \`fedipod members\``);
278
- } else {
279
- console.log(`agent running — opening ${url} (log in with instance ${authority})`);
280
- openBrowser(url);
281
- }
282
- }
283
-
284
- export async function rotateKey() {
285
- requireIdentity();
286
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
287
- const agent = new Agent({ home: HOME, log: (...a) => console.log('[rotate-key]', ...a) });
288
- // A home whose keys.json is gone or truncated cannot connect() at all:
289
- // resolveKeys refuses to mint over a key the actor already publishes, which
290
- // is the right default — minting silently would invalidate every signature
291
- // the other device can still make. It did leave the advice that refusal
292
- // prints ("run fedipod rotate-key") a dead end, though, because this
293
- // command connects first and meets the same refusal. --force arms the
294
- // one-shot rotation in the credential so the connect can get past it.
295
- const forced = has('force');
296
- const rotateCredPath = path.join(HOME, 'credential.json');
297
- if (forced) {
298
- const cred = JSON.parse(fs.readFileSync(rotateCredPath, 'utf8'));
299
- writeJsonAtomic(rotateCredPath, { ...cred, rotateKeyOnce: true });
300
- console.log('--force: the replacement key is minted as the agent connects\n');
301
- }
302
- // Read-only until you say yes: connecting for real acquires the lease and
303
- // starts the whole active agent — a destructive inbox drain, a channel
304
- // subscription, ACL probes and a tag-feed sweep — before the prompt.
305
- if (!await agent.connect({ act: false })) {
306
- console.error('nothing to rotate — no configured agent in this AP_HOME');
307
- process.exit(2);
308
- }
309
- const cfg = agent.store.getConfig();
310
- console.log(`\nRotating the signing key for @${cfg.handle}@${new URL(cfg.remotePod).host}\n`);
311
- console.log(' · a new keypair replaces the one in this home');
312
- console.log(' · the actor document is republished so other servers learn it');
313
- console.log(' · ANY OTHER DEVICE holding the old key stops being able to sign\n');
314
- const ans = has('yes') ? 'y' : await ask('rotate now? (y/n)', 'n');
315
- endAsking();
316
- if (!/^y/i.test(ans)) {
317
- // --force arms the one-shot rotation before the prompt, so the preview
318
- // connect can read past the mint refusal. Declining has to disarm it, or
319
- // "key unchanged" would be a lie: the next ordinary start would rotate,
320
- // and nothing on that path republishes the actor.
321
- if (forced) {
322
- try {
323
- const { rotateKeyOnce, ...rest } = JSON.parse(fs.readFileSync(rotateCredPath, 'utf8'));
324
- writeJsonAtomic(rotateCredPath, rest);
325
- } catch { /* the credential moved under us; the flag goes with it */ }
326
- }
327
- console.log('key unchanged');
328
- process.exit(0);
329
- }
330
- await agent.connect(); // now it may act
331
- if (forced) {
332
- // connect() has already minted it; all that is left is telling the
333
- // fediverse. Calling rotateKey here would mint a second one for nothing.
334
- await agent.publisher.publishProfile();
335
- console.log('rotated and republished');
336
- } else {
337
- const r = await agent.rotateKey();
338
- console.log(r.changed ? 'rotated and republished' : 'no change — the key was already fresh');
339
- }
340
- await finish(agent);
341
- }
342
-
343
- export async function revokeCredential() {
344
- // The credential file cannot be protected from anything running as you —
345
- // so the answer to a suspected leak is to kill it server-side, fast.
346
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
347
- const { revokeCredentialViaAccount } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
348
- const agent = new Agent({ home: HOME, log: () => {} });
349
- const cred = agent.readCredential();
350
- if (!cred) { console.error('no credential to revoke'); process.exit(2); }
351
- const email = flag('email');
352
- if (!email) { console.error('need --email <account email> (the account password is prompted)'); process.exit(2); }
353
- const password = process.env.AP_PASSWORD || await askHidden(`password for ${email} at ${cred.issuerOrigin}: `);
354
- const ok = await revokeCredentialViaAccount({
355
- origin: cred.issuerOrigin, email, password, resource: cred.resource,
356
- }).catch(e => { console.error(`revoke failed: ${e.message}`); return false; });
357
- if (ok) {
358
- fs.rmSync(path.join(HOME, 'credential.json'), { force: true });
359
- console.log('credential revoked server-side and deleted locally — run setup again to reconnect');
360
- } else {
361
- console.error('server did not confirm revocation — revoke it from the account dashboard');
362
- console.error(`(credential resource: ${cred.resource || 'unknown — dashboard only'})`);
363
- process.exit(1);
364
- }
365
- }
366
-
367
- export async function tokens() {
368
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
369
- const { RemotePod } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
370
- const { apUrls } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
371
- const agent = new Agent({ home: HOME, log: () => {} });
372
- const cred = agent.readCredential();
373
- if (!cred) { console.error('no credential — run setup first'); process.exit(2); }
374
- agent.remote = new RemotePod(cred);
375
- await agent.remote.warmup();
376
- agent.urls = apUrls(cred.remotePod, cred.root);
377
- agent.store.attach(agent.privateStorage(cred, 'state')); // honours privateRoot
378
- await agent.store.load();
379
- const recs = agent.store.read('masto-tokens.json', [])
380
- .map(r => (typeof r === 'string' ? { token: r, createdAt: null } : r));
381
- if (has('revoke-all')) {
382
- agent.store.write('masto-tokens.json', []);
383
- await agent.store.flush();
384
- console.log(`revoked ${recs.length} token(s) — every logged-in client must log in again`);
385
- } else if (flag('revoke')) {
386
- const prefix = flag('revoke');
387
- const kept = recs.filter(r => !r.token.startsWith(prefix));
388
- agent.store.write('masto-tokens.json', kept);
389
- await agent.store.flush();
390
- console.log(`revoked ${recs.length - kept.length} token(s) matching "${prefix}"`);
391
- } else {
392
- if (!recs.length) console.log('no client tokens issued');
393
- for (const r of recs) {
394
- const age = r.createdAt ? `${Math.round((Date.now() - r.createdAt) / 86400000)}d old` : 'undated';
395
- console.log(`${r.token.slice(0, 8)}… ${age}`);
396
- }
397
- console.log('\nrevoke with: fedipod tokens --revoke <prefix> (or --revoke-all)');
398
- }
399
- }
400
-
401
- export async function passwd() {
402
- requireIdentity();
403
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
404
- const { hashPassword } = await import(new URL('../../../../lib/client/masto/index.mjs', import.meta.url));
405
- const { RemotePod } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
406
- const { apUrls } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
407
- const agent = new Agent({ home: HOME, log: () => {} });
408
- const cred = agent.readCredential();
409
- if (!cred) { console.error('no credential — run setup first'); process.exit(2); }
410
- const pw = await askHidden('new UI password: ');
411
- if (!pw) { console.error('empty password — aborted'); process.exit(2); }
412
- agent.remote = new RemotePod(cred);
413
- await agent.remote.warmup();
414
- agent.urls = apUrls(cred.remotePod, cred.root);
415
- agent.store.attach(agent.privateStorage(cred, 'state')); // honours privateRoot
416
- await agent.store.load();
417
- const config = agent.store.getConfig();
418
- if (!config) { console.error('pod state empty — run setup first'); process.exit(2); }
419
- agent.store.setConfig({ ...config, uiPassword: hashPassword(pw) });
420
- await agent.store.flush();
421
- console.log('UI password set — /oauth/authorize now shows a login form (restart a running agent to pick it up)');
422
- }
423
-
424
- export async function keys() {
425
- // Where the signing key lives; `--to pod` moves it into pod state — with
426
- // the state store on a pod every device reaches, that is what lets them
427
- // all sign as one actor. `--to local` flips back: the next start adopts
428
- // the pod copy onto this machine and removes it from the pod.
429
- requireIdentity();
430
- const localKeyFile = path.join(HOME, 'keys.json');
431
- const to = flag('to');
432
- if (!to) {
433
- const cred0 = JSON.parse(fs.readFileSync(path.join(HOME, 'credential.json'), 'utf8'));
434
- console.log(fs.existsSync(localKeyFile)
435
- ? `signing key: ${tildify(localKeyFile)} (this machine only)`
436
- : cred0.keysMode === 'pod'
437
- ? 'signing key: pod state (shared by every device that reaches the state store)'
438
- : 'signing key: none found here — it mints on the next start');
439
- process.exit(0);
440
- }
441
- if (!['pod', 'local'].includes(to)) {
442
- console.error('usage: fedipod keys [--to pod|local]');
443
- process.exit(2);
444
- }
445
- // The running agent holds the key and the config in memory — stop it first.
446
- const answering = await localFetch(HOME, PORT, `/status`).then(r => r.ok).catch(() => false);
447
- if (answering) {
448
- console.error(`an agent is answering on :${PORT} — stop it first (fedipod stop), then re-run`);
449
- process.exit(2);
450
- }
451
- const credPath = path.join(HOME, 'credential.json');
452
- const cred = JSON.parse(fs.readFileSync(credPath, 'utf8'));
453
- if (to === 'local') {
454
- if (cred.keysMode !== 'pod') { console.log('keys are already local'); process.exit(0); }
455
- delete cred.keysMode;
456
- writeJsonAtomic(credPath, cred);
457
- console.log('keys set to local — the next start adopts the pod copy onto this machine and removes it from the pod');
458
- process.exit(0);
459
- }
460
- if (cred.keysMode === 'pod' && !fs.existsSync(localKeyFile)) {
461
- console.log('keys are already pod-held');
462
- process.exit(0);
463
- }
464
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
465
- const { RemotePod } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
466
- const { apUrls } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
467
- const { moveKeysToPod } = await import(new URL('../../../../lib/core/keys.mjs', import.meta.url));
468
- const agent = new Agent({ home: HOME, log: () => {} });
469
- agent.remote = new RemotePod(cred);
470
- await agent.remote.warmup();
471
- agent.store.attach(agent.privateStorage(cred, 'state'));
472
- await agent.store.load();
473
- const gwActor = agent.store.getConfig()?.gateway?.frontActor;
474
- const urls = apUrls(cred.remotePod, cred.root,
475
- gwActor ? { publicBase: gwActor.replace(/ap\/actor\/?$/, '') } : undefined);
476
- try {
477
- await moveKeysToPod(agent.store, { localDir: HOME, actorId: urls.actor, log: console.log });
478
- } catch (e) {
479
- console.error(e.message);
480
- process.exit(1);
481
- }
482
- cred.keysMode = 'pod';
483
- writeJsonAtomic(credPath, cred);
484
- if (cred.privateRoot) {
485
- console.log(`note: this identity's state store is ${cred.privateRoot} — devices share the key`);
486
- console.log('only when the state store is a pod they can all reach (`fedipod state --to pod`).');
487
- }
488
- console.log('done — restart the agent');
489
- }