fedipod-server 0.29.0 → 0.31.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 (444) hide show
  1. package/README.md +16 -6
  2. package/dist/claims.d.ts +2 -0
  3. package/dist/claims.js +13 -4
  4. package/dist/door.d.ts +4 -0
  5. package/dist/door.js +31 -0
  6. package/dist/fedipod.d.ts +15 -0
  7. package/dist/fedipod.js +13 -0
  8. package/dist/front.d.ts +3 -0
  9. package/dist/front.js +92 -0
  10. package/dist/handler.d.ts +36 -101
  11. package/dist/handler.js +93 -644
  12. package/dist/handler.jsonld +2 -30
  13. package/dist/identities.d.ts +71 -0
  14. package/dist/identities.js +236 -0
  15. package/dist/mounts.d.ts +43 -0
  16. package/dist/mounts.js +123 -0
  17. package/dist/opt-in.d.ts +46 -0
  18. package/dist/opt-in.js +176 -0
  19. package/dist/private-read.d.ts +4 -0
  20. package/dist/private-read.js +34 -0
  21. package/package.json +12 -20
  22. package/lib/client/c2s.mjs +0 -636
  23. package/lib/client/localapi.mjs +0 -87
  24. package/lib/client/masto/accounts.mjs +0 -310
  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 -387
  65. package/lib/core/graphview.mjs +0 -327
  66. package/lib/core/intake/activities.mjs +0 -649
  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 -258
  70. package/lib/core/intake/index.mjs +0 -732
  71. package/lib/core/intake/notes.mjs +0 -367
  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/place.mjs +0 -82
  76. package/lib/core/polls.mjs +0 -105
  77. package/lib/core/profile-page.mjs +0 -104
  78. package/lib/core/proof.mjs +0 -79
  79. package/lib/core/publisher/collections.mjs +0 -272
  80. package/lib/core/publisher/index.mjs +0 -522
  81. package/lib/core/publisher/notes.mjs +0 -519
  82. package/lib/core/publisher/own.mjs +0 -143
  83. package/lib/core/publisher/questions.mjs +0 -241
  84. package/lib/core/publisher/restore.mjs +0 -224
  85. package/lib/core/shapes/activitystreams.ttl +0 -157
  86. package/lib/core/shapes/index.mjs +0 -132
  87. package/lib/core/shapes/shapes-text.mjs +0 -13
  88. package/lib/core/social.mjs +0 -561
  89. package/lib/core/storage.mjs +0 -176
  90. package/lib/core/store.mjs +0 -578
  91. package/lib/core/wire-quotes.mjs +0 -71
  92. package/lib/core/wire.mjs +0 -925
  93. package/lib/device/account.mjs +0 -87
  94. package/lib/device/admin/index.mjs +0 -13
  95. package/lib/device/admin/origins.mjs +0 -35
  96. package/lib/device/admin/routes/connections.mjs +0 -144
  97. package/lib/device/admin/routes/gateway.mjs +0 -199
  98. package/lib/device/admin/routes/lifecycle.mjs +0 -200
  99. package/lib/device/admin/routes/owner.mjs +0 -322
  100. package/lib/device/admin/routes/setup.mjs +0 -428
  101. package/lib/device/admin/routes/social.mjs +0 -188
  102. package/lib/device/admin/server.mjs +0 -95
  103. package/lib/device/admin/static.mjs +0 -247
  104. package/lib/device/admin/surface.mjs +0 -315
  105. package/lib/device/certs.mjs +0 -281
  106. package/lib/device/cli/commands/account.mjs +0 -586
  107. package/lib/device/cli/commands/run.mjs +0 -278
  108. package/lib/device/cli/commands/service.mjs +0 -221
  109. package/lib/device/cli/commands/setup.mjs +0 -489
  110. package/lib/device/cli/commands/state.mjs +0 -561
  111. package/lib/device/cli/context.mjs +0 -288
  112. package/lib/device/export-collections.mjs +0 -161
  113. package/lib/device/gateway-move.mjs +0 -58
  114. package/lib/device/home.mjs +0 -161
  115. package/lib/device/migrate.mjs +0 -115
  116. package/lib/device/ports.mjs +0 -27
  117. package/lib/device/remote.mjs +0 -54
  118. package/lib/device/setup.mjs +0 -496
  119. package/lib/device/update.mjs +0 -96
  120. package/lib/gateway/caches.mjs +0 -36
  121. package/lib/gateway/directory.mjs +0 -90
  122. package/lib/gateway/front-core.mjs +0 -966
  123. package/lib/gateway/gateway-core.mjs +0 -244
  124. package/lib/gateway/headers.mjs +0 -49
  125. package/lib/gateway/httpsig.mjs +0 -159
  126. package/lib/gateway/notices.mjs +0 -84
  127. package/lib/gateway/quiet.mjs +0 -189
  128. package/lib/gateway/relay-extras.mjs +0 -89
  129. package/lib/gateway/token-claims.mjs +0 -16
  130. package/lib/pod/README.md +0 -61
  131. package/lib/pod/actor.mjs +0 -96
  132. package/lib/pod/collection.mjs +0 -77
  133. package/lib/pod/containers.mjs +0 -140
  134. package/lib/pod/discovery.mjs +0 -46
  135. package/lib/pod/featured.mjs +0 -18
  136. package/lib/pod/followers.mjs +0 -24
  137. package/lib/pod/following.mjs +0 -10
  138. package/lib/pod/http.mjs +0 -74
  139. package/lib/pod/inbox.mjs +0 -166
  140. package/lib/pod/links.mjs +0 -35
  141. package/lib/pod/location.mjs +0 -52
  142. package/lib/pod/media.mjs +0 -27
  143. package/lib/pod/notes.mjs +0 -78
  144. package/lib/pod/notifications.mjs +0 -89
  145. package/lib/pod/outbox.mjs +0 -18
  146. package/lib/pod/package.json +0 -19
  147. package/lib/pod/policy.mjs +0 -58
  148. package/lib/pod/private.mjs +0 -19
  149. package/lib/pod/root.mjs +0 -104
  150. package/lib/pod/state.mjs +0 -40
  151. package/lib/pod/transport.mjs +0 -674
  152. package/lib/pod/type-index.mjs +0 -101
  153. package/lib/pod/urls.mjs +0 -91
  154. package/lib/server/embed.mjs +0 -424
  155. package/lib/session/README.md +0 -137
  156. package/lib/session/demo.html +0 -94
  157. package/lib/session/fedi-account.mjs +0 -417
  158. package/lib/session/fedi-login.mjs +0 -123
  159. package/lib/session/oidc-session.mjs +0 -233
  160. package/lib/session/package.json +0 -49
  161. package/lib/shared/guard.mjs +0 -213
  162. package/lib/shared/links.mjs +0 -9
  163. package/lib/shared/safefetch.mjs +0 -235
  164. package/lib/shared/ua.mjs +0 -29
  165. package/phanpy/dist/404.html +0 -40
  166. package/phanpy/dist/_headers +0 -2
  167. package/phanpy/dist/apple-touch-icon.png +0 -0
  168. package/phanpy/dist/assets/ICONS-DIPJeU0C.js +0 -2
  169. package/phanpy/dist/assets/ICONS-DIPJeU0C.js.map +0 -1
  170. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js +0 -183
  171. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
  172. package/phanpy/dist/assets/Temml-CCjoacWt.woff2 +0 -0
  173. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js +0 -2
  174. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js.map +0 -1
  175. package/phanpy/dist/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
  176. package/phanpy/dist/assets/catch-up-O5q5C75Z.png +0 -0
  177. package/phanpy/dist/assets/chunk-aKtaBQYM.js +0 -1
  178. package/phanpy/dist/assets/compose-CFEx7wb4.js +0 -2
  179. package/phanpy/dist/assets/compose-CFEx7wb4.js.map +0 -1
  180. package/phanpy/dist/assets/compose-ZJN5xSb4.js +0 -35
  181. package/phanpy/dist/assets/compose-ZJN5xSb4.js.map +0 -1
  182. package/phanpy/dist/assets/debug.module-YFQgwnIr.js +0 -52
  183. package/phanpy/dist/assets/debug.module-YFQgwnIr.js.map +0 -1
  184. package/phanpy/dist/assets/dom-p1YcJ5Rw.js +0 -2
  185. package/phanpy/dist/assets/dom-p1YcJ5Rw.js.map +0 -1
  186. package/phanpy/dist/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
  187. package/phanpy/dist/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
  188. package/phanpy/dist/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
  189. package/phanpy/dist/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
  190. package/phanpy/dist/assets/icons/add-circle-line-WD0mwORD.js +0 -1
  191. package/phanpy/dist/assets/icons/alert-line-CpFUMf9s.js +0 -1
  192. package/phanpy/dist/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
  193. package/phanpy/dist/assets/icons/announcement-line-5nwaJFJm.js +0 -1
  194. package/phanpy/dist/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
  195. package/phanpy/dist/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
  196. package/phanpy/dist/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
  197. package/phanpy/dist/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
  198. package/phanpy/dist/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
  199. package/phanpy/dist/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
  200. package/phanpy/dist/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
  201. package/phanpy/dist/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
  202. package/phanpy/dist/assets/icons/at-line-CF66Bznk.js +0 -1
  203. package/phanpy/dist/assets/icons/attachment-line-BY8It-l9.js +0 -1
  204. package/phanpy/dist/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
  205. package/phanpy/dist/assets/icons/board-line-C0UWXyA6.js +0 -1
  206. package/phanpy/dist/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
  207. package/phanpy/dist/assets/icons/building-5-line-Dd59MzbO.js +0 -1
  208. package/phanpy/dist/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
  209. package/phanpy/dist/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
  210. package/phanpy/dist/assets/icons/calendar-month-line-vommts2C.js +0 -1
  211. package/phanpy/dist/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
  212. package/phanpy/dist/assets/icons/camera-line-Cv69MEei.js +0 -1
  213. package/phanpy/dist/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
  214. package/phanpy/dist/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
  215. package/phanpy/dist/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
  216. package/phanpy/dist/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
  217. package/phanpy/dist/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
  218. package/phanpy/dist/assets/icons/clipboard-line-BBp364gJ.js +0 -1
  219. package/phanpy/dist/assets/icons/close-circle-line-CICdiuGz.js +0 -1
  220. package/phanpy/dist/assets/icons/close-line-DYrFWcjv.js +0 -1
  221. package/phanpy/dist/assets/icons/cloud-line-tiQAbah8.js +0 -1
  222. package/phanpy/dist/assets/icons/code-line-fAl8iiV3.js +0 -1
  223. package/phanpy/dist/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
  224. package/phanpy/dist/assets/icons/copy-2-line-CLW69yF5.js +0 -1
  225. package/phanpy/dist/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
  226. package/phanpy/dist/assets/icons/document-3-line-DBGNhAg2.js +0 -1
  227. package/phanpy/dist/assets/icons/document-line-C7mb9sb7.js +0 -1
  228. package/phanpy/dist/assets/icons/down-line-BGqSSThd.js +0 -1
  229. package/phanpy/dist/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
  230. package/phanpy/dist/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
  231. package/phanpy/dist/assets/icons/exit-line-Dc07BS-x.js +0 -1
  232. package/phanpy/dist/assets/icons/external-link-line-BvpSkmjO.js +0 -1
  233. package/phanpy/dist/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
  234. package/phanpy/dist/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
  235. package/phanpy/dist/assets/icons/filter-2-line-B_mR2usy.js +0 -1
  236. package/phanpy/dist/assets/icons/filter-line-C_nm-3cU.js +0 -1
  237. package/phanpy/dist/assets/icons/flag-1-line-C2HB05I0.js +0 -1
  238. package/phanpy/dist/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
  239. package/phanpy/dist/assets/icons/formula-line-DLrt2d6j.js +0 -1
  240. package/phanpy/dist/assets/icons/grid-line-CgUmEikf.js +0 -1
  241. package/phanpy/dist/assets/icons/group-line-C5fnX0wU.js +0 -1
  242. package/phanpy/dist/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
  243. package/phanpy/dist/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
  244. package/phanpy/dist/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
  245. package/phanpy/dist/assets/icons/heart-line-CJ7K47J4.js +0 -1
  246. package/phanpy/dist/assets/icons/history-2-line-kWWvFzqv.js +0 -1
  247. package/phanpy/dist/assets/icons/history-line-bGQiwbTH.js +0 -1
  248. package/phanpy/dist/assets/icons/home-3-line-fRU1zeLG.js +0 -1
  249. package/phanpy/dist/assets/icons/information-line-iNk6-sOY.js +0 -1
  250. package/phanpy/dist/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
  251. package/phanpy/dist/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
  252. package/phanpy/dist/assets/icons/layout-5-line-B_znt5wO.js +0 -1
  253. package/phanpy/dist/assets/icons/left-line-eUw0tya4.js +0 -1
  254. package/phanpy/dist/assets/icons/lightning-line-DaKoDdix.js +0 -1
  255. package/phanpy/dist/assets/icons/link-2-line-DCqLmMA7.js +0 -1
  256. package/phanpy/dist/assets/icons/list-check-line-BAxosBh9.js +0 -1
  257. package/phanpy/dist/assets/icons/lock-line-CPoaXeUW.js +0 -1
  258. package/phanpy/dist/assets/icons/mail-line-B0P8aa1L.js +0 -1
  259. package/phanpy/dist/assets/icons/moon-line-CEqNAToP.js +0 -1
  260. package/phanpy/dist/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
  261. package/phanpy/dist/assets/icons/more-3-line-BIiVjYTz.js +0 -1
  262. package/phanpy/dist/assets/icons/notification-line-BZZq2Gtu.js +0 -1
  263. package/phanpy/dist/assets/icons/pencil-line-CKh8-A1v.js +0 -1
  264. package/phanpy/dist/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
  265. package/phanpy/dist/assets/icons/pin-line-DpTolyhs.js +0 -1
  266. package/phanpy/dist/assets/icons/play-fill-B0-G_8lX.js +0 -1
  267. package/phanpy/dist/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
  268. package/phanpy/dist/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
  269. package/phanpy/dist/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
  270. package/phanpy/dist/assets/icons/radar-line-CKyroTth.js +0 -1
  271. package/phanpy/dist/assets/icons/react-line-CoIKhhtK.js +0 -1
  272. package/phanpy/dist/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
  273. package/phanpy/dist/assets/icons/right-line-B3KWJaqc.js +0 -1
  274. package/phanpy/dist/assets/icons/rocket-line-4KZl537D.js +0 -1
  275. package/phanpy/dist/assets/icons/round-fill-C69NTrZ0.js +0 -1
  276. package/phanpy/dist/assets/icons/round-line-B9k_1uo-.js +0 -1
  277. package/phanpy/dist/assets/icons/route-line-B28ReHcE.js +0 -1
  278. package/phanpy/dist/assets/icons/rows-4-line-CrBniagM.js +0 -1
  279. package/phanpy/dist/assets/icons/scan-line-DSf74YdP.js +0 -1
  280. package/phanpy/dist/assets/icons/search-2-line-B6geIU1z.js +0 -1
  281. package/phanpy/dist/assets/icons/settings-3-line-azJwK47w.js +0 -1
  282. package/phanpy/dist/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
  283. package/phanpy/dist/assets/icons/share-2-line-D5MxWjrm.js +0 -1
  284. package/phanpy/dist/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
  285. package/phanpy/dist/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
  286. package/phanpy/dist/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
  287. package/phanpy/dist/assets/icons/time-line-BF3eet1v.js +0 -1
  288. package/phanpy/dist/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
  289. package/phanpy/dist/assets/icons/translate-line-BFWol2Ce.js +0 -1
  290. package/phanpy/dist/assets/icons/unlock-line-X_x5vwv3.js +0 -1
  291. package/phanpy/dist/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
  292. package/phanpy/dist/assets/icons/user-4-line-BVSynZCp.js +0 -1
  293. package/phanpy/dist/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
  294. package/phanpy/dist/assets/icons/user-add-line-BbXdHG4z.js +0 -1
  295. package/phanpy/dist/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
  296. package/phanpy/dist/assets/icons/user-follow-line-BXux0wSd.js +0 -1
  297. package/phanpy/dist/assets/icons/user-star-line-DdYlpHLU.js +0 -1
  298. package/phanpy/dist/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
  299. package/phanpy/dist/assets/icons/user-x-line-DIDgNlPH.js +0 -1
  300. package/phanpy/dist/assets/icons/volume-line-Bs390KQt.js +0 -1
  301. package/phanpy/dist/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
  302. package/phanpy/dist/assets/icons/walk-line-yNXfB-md.js +0 -1
  303. package/phanpy/dist/assets/icons/world-2-line-CenkGIwj.js +0 -1
  304. package/phanpy/dist/assets/icons/zoom-in-line-CaENUphf.js +0 -1
  305. package/phanpy/dist/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
  306. package/phanpy/dist/assets/instances-BNPptnn-.json +0 -333
  307. package/phanpy/dist/assets/locales/ar-SA-CfheRbCu.js +0 -1
  308. package/phanpy/dist/assets/locales/ca-ES-DHRW86Tz.js +0 -1
  309. package/phanpy/dist/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
  310. package/phanpy/dist/assets/locales/de-DE-ByRPMRFy.js +0 -1
  311. package/phanpy/dist/assets/locales/eo-UY-CPC7wLCS.js +0 -1
  312. package/phanpy/dist/assets/locales/es-ES-dJa0Fd9t.js +0 -1
  313. package/phanpy/dist/assets/locales/eu-ES-C3djlPR2.js +0 -1
  314. package/phanpy/dist/assets/locales/fa-IR-DTT490Ck.js +0 -1
  315. package/phanpy/dist/assets/locales/fi-FI-B23MCPuz.js +0 -1
  316. package/phanpy/dist/assets/locales/fr-FR-BcaQsO5C.js +0 -1
  317. package/phanpy/dist/assets/locales/gl-ES-BR-CVKBN.js +0 -1
  318. package/phanpy/dist/assets/locales/he-IL-CfheRbCu.js +0 -1
  319. package/phanpy/dist/assets/locales/hu-HU-CfheRbCu.js +0 -1
  320. package/phanpy/dist/assets/locales/it-IT-C1136UFV.js +0 -1
  321. package/phanpy/dist/assets/locales/ja-JP-CRZmRAhD.js +0 -1
  322. package/phanpy/dist/assets/locales/kab-Cz8xH_TT.js +0 -1
  323. package/phanpy/dist/assets/locales/ko-KR-CG9UiY4o.js +0 -1
  324. package/phanpy/dist/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
  325. package/phanpy/dist/assets/locales/nb-NO-CfheRbCu.js +0 -1
  326. package/phanpy/dist/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
  327. package/phanpy/dist/assets/locales/oc-FR-CfheRbCu.js +0 -1
  328. package/phanpy/dist/assets/locales/pl-PL-DkwGXf6P.js +0 -1
  329. package/phanpy/dist/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
  330. package/phanpy/dist/assets/locales/pt-BR-nGL0HdFS.js +0 -1
  331. package/phanpy/dist/assets/locales/pt-PT-Cp17aj2z.js +0 -1
  332. package/phanpy/dist/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
  333. package/phanpy/dist/assets/locales/th-TH-CfheRbCu.js +0 -1
  334. package/phanpy/dist/assets/locales/tok-CfheRbCu.js +0 -1
  335. package/phanpy/dist/assets/locales/tr-TR-CfheRbCu.js +0 -1
  336. package/phanpy/dist/assets/locales/uk-UA-C5E3dFBf.js +0 -1
  337. package/phanpy/dist/assets/locales/zh-CN-BHJi7_et.js +0 -1
  338. package/phanpy/dist/assets/locales/zh-TW-CfheRbCu.js +0 -1
  339. package/phanpy/dist/assets/main-BdqNbG-a.js +0 -26
  340. package/phanpy/dist/assets/main-BdqNbG-a.js.map +0 -1
  341. package/phanpy/dist/assets/mock-home-DGhR__He.js +0 -2
  342. package/phanpy/dist/assets/mock-home-DGhR__He.js.map +0 -1
  343. package/phanpy/dist/assets/multi-column-ROck0NVt.jpg +0 -0
  344. package/phanpy/dist/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
  345. package/phanpy/dist/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
  346. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js +0 -2
  347. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js.map +0 -1
  348. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js +0 -20
  349. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js.map +0 -1
  350. package/phanpy/dist/assets/style-B1iLPTPR.css +0 -2
  351. package/phanpy/dist/assets/temml-DuyIQMei.js +0 -97
  352. package/phanpy/dist/assets/temml-DuyIQMei.js.map +0 -1
  353. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js +0 -2
  354. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
  355. package/phanpy/dist/assets/year-in-posts-B2lywqdx.png +0 -0
  356. package/phanpy/dist/assets/year-in-posts-DJv_star.js +0 -3
  357. package/phanpy/dist/assets/year-in-posts-DJv_star.js.map +0 -1
  358. package/phanpy/dist/compose/index.html +0 -20
  359. package/phanpy/dist/favicon.ico +0 -0
  360. package/phanpy/dist/index.html +0 -73
  361. package/phanpy/dist/logo-192.png +0 -0
  362. package/phanpy/dist/logo-512.png +0 -0
  363. package/phanpy/dist/logo-badge-72.png +0 -0
  364. package/phanpy/dist/logo-maskable-512.png +0 -0
  365. package/phanpy/dist/logo-monochrome-512.png +0 -0
  366. package/phanpy/dist/logo-monochrome-maskable-512.png +0 -0
  367. package/phanpy/dist/manifest.webmanifest +0 -1
  368. package/phanpy/dist/og-image-2.jpg +0 -0
  369. package/phanpy/dist/og-image.png +0 -0
  370. package/phanpy/dist/robots.txt +0 -2
  371. package/phanpy/dist/sw.js +0 -2
  372. package/phanpy/dist/sw.js.map +0 -1
  373. package/phanpy/dist/version.json +0 -1
  374. package/run-agent.mjs +0 -899
  375. package/vendor/gate.cjs +0 -138
  376. package/vendor/idp-grant.cjs +0 -394
  377. package/vendor/jfetch.cjs +0 -16
  378. package/web/admin/actors.js +0 -147
  379. package/web/admin/bar.css +0 -126
  380. package/web/admin/bar.js +0 -99
  381. package/web/admin/client/client.js +0 -66
  382. package/web/admin/client/index.html +0 -69
  383. package/web/admin/client-pick.js +0 -79
  384. package/web/admin/common.js +0 -23
  385. package/web/admin/connections.js +0 -112
  386. package/web/admin/gateway.js +0 -133
  387. package/web/admin/group.js +0 -258
  388. package/web/admin/index.html +0 -612
  389. package/web/admin/notices-bar.js +0 -90
  390. package/web/admin/oauth-signin.mjs +0 -37
  391. package/web/admin/record.js +0 -393
  392. package/web/admin/setup/index.html +0 -257
  393. package/web/admin/setup/setup.js +0 -339
  394. package/web/admin/tokens.css +0 -68
  395. package/web/admin/upkeep.js +0 -177
  396. package/web/admin/window.css +0 -55
  397. package/web/admin/window.js +0 -136
  398. package/web/app/README.md +0 -81
  399. package/web/app/admin-facade.mjs +0 -588
  400. package/web/app/agent.mjs +0 -672
  401. package/web/app/atproto-browser.mjs +0 -86
  402. package/web/app/authorize_interaction.html +0 -56
  403. package/web/app/authorize_interaction.js +0 -69
  404. package/web/app/boot.mjs +0 -616
  405. package/web/app/deliver-relay.mjs +0 -129
  406. package/web/app/dist/boot.js +0 -34562
  407. package/web/app/dist/boot.js.map +0 -7
  408. package/web/app/dist/sw.js +0 -73456
  409. package/web/app/dist/sw.js.map +0 -7
  410. package/web/app/fediacct-browser.mjs +0 -146
  411. package/web/app/gateway-move.mjs +0 -60
  412. package/web/app/idb-kv.mjs +0 -35
  413. package/web/app/index.html +0 -258
  414. package/web/app/keys-browser.mjs +0 -71
  415. package/web/app/keystore.mjs +0 -82
  416. package/web/app/oidc-session.mjs +0 -6
  417. package/web/app/pod-auth.mjs +0 -248
  418. package/web/app/pod-remote.mjs +0 -84
  419. package/web/app/shims/_globals.mjs +0 -2
  420. package/web/app/shims/fedify-sig.mjs +0 -77
  421. package/web/app/shims/node-crypto.mjs +0 -113
  422. package/web/app/shims/node-fs.mjs +0 -17
  423. package/web/app/shims/node-path.mjs +0 -19
  424. package/web/app/shims/node-url.mjs +0 -7
  425. package/web/app/shims/prelude.js +0 -58
  426. package/web/app/shims/safefetch.mjs +0 -58
  427. package/web/app/shims/shapes-text.mjs +0 -8
  428. package/web/app/shims/web-push.mjs +0 -14
  429. package/web/app/signup.mjs +0 -357
  430. package/web/app/sw-src.mjs +0 -220
  431. package/web/app/update.js +0 -70
  432. package/web/front/admin.html +0 -55
  433. package/web/front/admin.js +0 -89
  434. package/web/front/install.sh +0 -69
  435. package/web/front/new-account.html +0 -35
  436. package/web/front/new-account.js +0 -13
  437. package/web/front/notices.html +0 -69
  438. package/web/front/notices.js +0 -107
  439. package/web/front/run.html +0 -64
  440. package/web/front/run.js +0 -221
  441. package/web/front/solid-oidc-client.js +0 -6
  442. package/web/icons/forum.svg +0 -11
  443. package/web/icons/gateway.svg +0 -14
  444. 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
- }