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