fedipod-server 0.29.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. package/README.md +11 -6
  2. package/dist/door.d.ts +4 -0
  3. package/dist/door.js +31 -0
  4. package/dist/fedipod.d.ts +16 -0
  5. package/dist/fedipod.js +13 -0
  6. package/dist/front.d.ts +3 -0
  7. package/dist/front.js +94 -0
  8. package/dist/handler.d.ts +36 -101
  9. package/dist/handler.js +85 -645
  10. package/dist/handler.jsonld +2 -30
  11. package/dist/identities.d.ts +62 -0
  12. package/dist/identities.js +236 -0
  13. package/dist/mounts.d.ts +43 -0
  14. package/dist/mounts.js +123 -0
  15. package/dist/opt-in.d.ts +46 -0
  16. package/dist/opt-in.js +176 -0
  17. package/package.json +10 -18
  18. package/lib/client/c2s.mjs +0 -636
  19. package/lib/client/localapi.mjs +0 -87
  20. package/lib/client/masto/accounts.mjs +0 -310
  21. package/lib/client/masto/body.mjs +0 -156
  22. package/lib/client/masto/index.mjs +0 -206
  23. package/lib/client/masto/instance.mjs +0 -112
  24. package/lib/client/masto/media.mjs +0 -79
  25. package/lib/client/masto/oauth.mjs +0 -656
  26. package/lib/client/masto/render.mjs +0 -518
  27. package/lib/client/masto/statuses.mjs +0 -372
  28. package/lib/client/masto/timelines.mjs +0 -438
  29. package/lib/client/oidc-auth.mjs +0 -62
  30. package/lib/client/streaming.mjs +0 -154
  31. package/lib/client/webpush.mjs +0 -98
  32. package/lib/connections/acctfeed.mjs +0 -257
  33. package/lib/connections/atproto.mjs +0 -309
  34. package/lib/connections/bskyfeed.mjs +0 -243
  35. package/lib/connections/bskygroup.mjs +0 -162
  36. package/lib/connections/fediacct.mjs +0 -253
  37. package/lib/connections/import.mjs +0 -357
  38. package/lib/connections/tagfeed.mjs +0 -212
  39. package/lib/connections/vault.mjs +0 -114
  40. package/lib/core/as2.mjs +0 -206
  41. package/lib/core/contexts/activitystreams.json +0 -379
  42. package/lib/core/contexts/anno.json +0 -126
  43. package/lib/core/contexts/did-v1.json +0 -57
  44. package/lib/core/contexts/fep-5711.json +0 -36
  45. package/lib/core/contexts/gotosocial.json +0 -86
  46. package/lib/core/contexts/identity-v1.json +0 -152
  47. package/lib/core/contexts/index.mjs +0 -63
  48. package/lib/core/contexts/join-lemmy.json +0 -33
  49. package/lib/core/contexts/joinmastodon.json +0 -28
  50. package/lib/core/contexts/litepub-0.1.json +0 -60
  51. package/lib/core/contexts/map.json +0 -19
  52. package/lib/core/contexts/miscellany.json +0 -19
  53. package/lib/core/contexts/quotes.json +0 -18
  54. package/lib/core/contexts/schemaorg.json +0 -8845
  55. package/lib/core/contexts/security-data-integrity-v1.json +0 -78
  56. package/lib/core/contexts/security-data-integrity-v2.json +0 -81
  57. package/lib/core/contexts/security-multikey-v1.json +0 -35
  58. package/lib/core/contexts/security-v1.json +0 -74
  59. package/lib/core/contexts/webfinger.json +0 -10
  60. package/lib/core/deliver.mjs +0 -387
  61. package/lib/core/graphview.mjs +0 -327
  62. package/lib/core/intake/activities.mjs +0 -649
  63. package/lib/core/intake/activity.mjs +0 -318
  64. package/lib/core/intake/channel.mjs +0 -144
  65. package/lib/core/intake/group.mjs +0 -258
  66. package/lib/core/intake/index.mjs +0 -732
  67. package/lib/core/intake/notes.mjs +0 -367
  68. package/lib/core/intake/verify.mjs +0 -142
  69. package/lib/core/keys.mjs +0 -153
  70. package/lib/core/lease.mjs +0 -206
  71. package/lib/core/place.mjs +0 -82
  72. package/lib/core/polls.mjs +0 -105
  73. package/lib/core/profile-page.mjs +0 -104
  74. package/lib/core/proof.mjs +0 -79
  75. package/lib/core/publisher/collections.mjs +0 -272
  76. package/lib/core/publisher/index.mjs +0 -522
  77. package/lib/core/publisher/notes.mjs +0 -519
  78. package/lib/core/publisher/own.mjs +0 -143
  79. package/lib/core/publisher/questions.mjs +0 -241
  80. package/lib/core/publisher/restore.mjs +0 -224
  81. package/lib/core/shapes/activitystreams.ttl +0 -157
  82. package/lib/core/shapes/index.mjs +0 -132
  83. package/lib/core/shapes/shapes-text.mjs +0 -13
  84. package/lib/core/social.mjs +0 -561
  85. package/lib/core/storage.mjs +0 -176
  86. package/lib/core/store.mjs +0 -578
  87. package/lib/core/wire-quotes.mjs +0 -71
  88. package/lib/core/wire.mjs +0 -925
  89. package/lib/device/account.mjs +0 -87
  90. package/lib/device/admin/index.mjs +0 -13
  91. package/lib/device/admin/origins.mjs +0 -35
  92. package/lib/device/admin/routes/connections.mjs +0 -144
  93. package/lib/device/admin/routes/gateway.mjs +0 -199
  94. package/lib/device/admin/routes/lifecycle.mjs +0 -200
  95. package/lib/device/admin/routes/owner.mjs +0 -322
  96. package/lib/device/admin/routes/setup.mjs +0 -428
  97. package/lib/device/admin/routes/social.mjs +0 -188
  98. package/lib/device/admin/server.mjs +0 -95
  99. package/lib/device/admin/static.mjs +0 -247
  100. package/lib/device/admin/surface.mjs +0 -315
  101. package/lib/device/certs.mjs +0 -281
  102. package/lib/device/cli/commands/account.mjs +0 -586
  103. package/lib/device/cli/commands/run.mjs +0 -278
  104. package/lib/device/cli/commands/service.mjs +0 -221
  105. package/lib/device/cli/commands/setup.mjs +0 -489
  106. package/lib/device/cli/commands/state.mjs +0 -561
  107. package/lib/device/cli/context.mjs +0 -288
  108. package/lib/device/export-collections.mjs +0 -161
  109. package/lib/device/gateway-move.mjs +0 -58
  110. package/lib/device/home.mjs +0 -161
  111. package/lib/device/migrate.mjs +0 -115
  112. package/lib/device/ports.mjs +0 -27
  113. package/lib/device/remote.mjs +0 -54
  114. package/lib/device/setup.mjs +0 -496
  115. package/lib/device/update.mjs +0 -96
  116. package/lib/gateway/caches.mjs +0 -36
  117. package/lib/gateway/directory.mjs +0 -90
  118. package/lib/gateway/front-core.mjs +0 -966
  119. package/lib/gateway/gateway-core.mjs +0 -244
  120. package/lib/gateway/headers.mjs +0 -49
  121. package/lib/gateway/httpsig.mjs +0 -159
  122. package/lib/gateway/notices.mjs +0 -84
  123. package/lib/gateway/quiet.mjs +0 -189
  124. package/lib/gateway/relay-extras.mjs +0 -89
  125. package/lib/gateway/token-claims.mjs +0 -16
  126. package/lib/pod/README.md +0 -61
  127. package/lib/pod/actor.mjs +0 -96
  128. package/lib/pod/collection.mjs +0 -77
  129. package/lib/pod/containers.mjs +0 -140
  130. package/lib/pod/discovery.mjs +0 -46
  131. package/lib/pod/featured.mjs +0 -18
  132. package/lib/pod/followers.mjs +0 -24
  133. package/lib/pod/following.mjs +0 -10
  134. package/lib/pod/http.mjs +0 -74
  135. package/lib/pod/inbox.mjs +0 -166
  136. package/lib/pod/links.mjs +0 -35
  137. package/lib/pod/location.mjs +0 -52
  138. package/lib/pod/media.mjs +0 -27
  139. package/lib/pod/notes.mjs +0 -78
  140. package/lib/pod/notifications.mjs +0 -89
  141. package/lib/pod/outbox.mjs +0 -18
  142. package/lib/pod/package.json +0 -19
  143. package/lib/pod/policy.mjs +0 -58
  144. package/lib/pod/private.mjs +0 -19
  145. package/lib/pod/root.mjs +0 -104
  146. package/lib/pod/state.mjs +0 -40
  147. package/lib/pod/transport.mjs +0 -674
  148. package/lib/pod/type-index.mjs +0 -101
  149. package/lib/pod/urls.mjs +0 -91
  150. package/lib/server/embed.mjs +0 -424
  151. package/lib/session/README.md +0 -137
  152. package/lib/session/demo.html +0 -94
  153. package/lib/session/fedi-account.mjs +0 -417
  154. package/lib/session/fedi-login.mjs +0 -123
  155. package/lib/session/oidc-session.mjs +0 -233
  156. package/lib/session/package.json +0 -49
  157. package/lib/shared/guard.mjs +0 -213
  158. package/lib/shared/links.mjs +0 -9
  159. package/lib/shared/safefetch.mjs +0 -235
  160. package/lib/shared/ua.mjs +0 -29
  161. package/phanpy/dist/404.html +0 -40
  162. package/phanpy/dist/_headers +0 -2
  163. package/phanpy/dist/apple-touch-icon.png +0 -0
  164. package/phanpy/dist/assets/ICONS-DIPJeU0C.js +0 -2
  165. package/phanpy/dist/assets/ICONS-DIPJeU0C.js.map +0 -1
  166. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js +0 -183
  167. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
  168. package/phanpy/dist/assets/Temml-CCjoacWt.woff2 +0 -0
  169. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js +0 -2
  170. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js.map +0 -1
  171. package/phanpy/dist/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
  172. package/phanpy/dist/assets/catch-up-O5q5C75Z.png +0 -0
  173. package/phanpy/dist/assets/chunk-aKtaBQYM.js +0 -1
  174. package/phanpy/dist/assets/compose-CFEx7wb4.js +0 -2
  175. package/phanpy/dist/assets/compose-CFEx7wb4.js.map +0 -1
  176. package/phanpy/dist/assets/compose-ZJN5xSb4.js +0 -35
  177. package/phanpy/dist/assets/compose-ZJN5xSb4.js.map +0 -1
  178. package/phanpy/dist/assets/debug.module-YFQgwnIr.js +0 -52
  179. package/phanpy/dist/assets/debug.module-YFQgwnIr.js.map +0 -1
  180. package/phanpy/dist/assets/dom-p1YcJ5Rw.js +0 -2
  181. package/phanpy/dist/assets/dom-p1YcJ5Rw.js.map +0 -1
  182. package/phanpy/dist/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
  183. package/phanpy/dist/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
  184. package/phanpy/dist/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
  185. package/phanpy/dist/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
  186. package/phanpy/dist/assets/icons/add-circle-line-WD0mwORD.js +0 -1
  187. package/phanpy/dist/assets/icons/alert-line-CpFUMf9s.js +0 -1
  188. package/phanpy/dist/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
  189. package/phanpy/dist/assets/icons/announcement-line-5nwaJFJm.js +0 -1
  190. package/phanpy/dist/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
  191. package/phanpy/dist/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
  192. package/phanpy/dist/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
  193. package/phanpy/dist/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
  194. package/phanpy/dist/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
  195. package/phanpy/dist/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
  196. package/phanpy/dist/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
  197. package/phanpy/dist/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
  198. package/phanpy/dist/assets/icons/at-line-CF66Bznk.js +0 -1
  199. package/phanpy/dist/assets/icons/attachment-line-BY8It-l9.js +0 -1
  200. package/phanpy/dist/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
  201. package/phanpy/dist/assets/icons/board-line-C0UWXyA6.js +0 -1
  202. package/phanpy/dist/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
  203. package/phanpy/dist/assets/icons/building-5-line-Dd59MzbO.js +0 -1
  204. package/phanpy/dist/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
  205. package/phanpy/dist/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
  206. package/phanpy/dist/assets/icons/calendar-month-line-vommts2C.js +0 -1
  207. package/phanpy/dist/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
  208. package/phanpy/dist/assets/icons/camera-line-Cv69MEei.js +0 -1
  209. package/phanpy/dist/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
  210. package/phanpy/dist/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
  211. package/phanpy/dist/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
  212. package/phanpy/dist/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
  213. package/phanpy/dist/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
  214. package/phanpy/dist/assets/icons/clipboard-line-BBp364gJ.js +0 -1
  215. package/phanpy/dist/assets/icons/close-circle-line-CICdiuGz.js +0 -1
  216. package/phanpy/dist/assets/icons/close-line-DYrFWcjv.js +0 -1
  217. package/phanpy/dist/assets/icons/cloud-line-tiQAbah8.js +0 -1
  218. package/phanpy/dist/assets/icons/code-line-fAl8iiV3.js +0 -1
  219. package/phanpy/dist/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
  220. package/phanpy/dist/assets/icons/copy-2-line-CLW69yF5.js +0 -1
  221. package/phanpy/dist/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
  222. package/phanpy/dist/assets/icons/document-3-line-DBGNhAg2.js +0 -1
  223. package/phanpy/dist/assets/icons/document-line-C7mb9sb7.js +0 -1
  224. package/phanpy/dist/assets/icons/down-line-BGqSSThd.js +0 -1
  225. package/phanpy/dist/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
  226. package/phanpy/dist/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
  227. package/phanpy/dist/assets/icons/exit-line-Dc07BS-x.js +0 -1
  228. package/phanpy/dist/assets/icons/external-link-line-BvpSkmjO.js +0 -1
  229. package/phanpy/dist/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
  230. package/phanpy/dist/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
  231. package/phanpy/dist/assets/icons/filter-2-line-B_mR2usy.js +0 -1
  232. package/phanpy/dist/assets/icons/filter-line-C_nm-3cU.js +0 -1
  233. package/phanpy/dist/assets/icons/flag-1-line-C2HB05I0.js +0 -1
  234. package/phanpy/dist/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
  235. package/phanpy/dist/assets/icons/formula-line-DLrt2d6j.js +0 -1
  236. package/phanpy/dist/assets/icons/grid-line-CgUmEikf.js +0 -1
  237. package/phanpy/dist/assets/icons/group-line-C5fnX0wU.js +0 -1
  238. package/phanpy/dist/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
  239. package/phanpy/dist/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
  240. package/phanpy/dist/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
  241. package/phanpy/dist/assets/icons/heart-line-CJ7K47J4.js +0 -1
  242. package/phanpy/dist/assets/icons/history-2-line-kWWvFzqv.js +0 -1
  243. package/phanpy/dist/assets/icons/history-line-bGQiwbTH.js +0 -1
  244. package/phanpy/dist/assets/icons/home-3-line-fRU1zeLG.js +0 -1
  245. package/phanpy/dist/assets/icons/information-line-iNk6-sOY.js +0 -1
  246. package/phanpy/dist/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
  247. package/phanpy/dist/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
  248. package/phanpy/dist/assets/icons/layout-5-line-B_znt5wO.js +0 -1
  249. package/phanpy/dist/assets/icons/left-line-eUw0tya4.js +0 -1
  250. package/phanpy/dist/assets/icons/lightning-line-DaKoDdix.js +0 -1
  251. package/phanpy/dist/assets/icons/link-2-line-DCqLmMA7.js +0 -1
  252. package/phanpy/dist/assets/icons/list-check-line-BAxosBh9.js +0 -1
  253. package/phanpy/dist/assets/icons/lock-line-CPoaXeUW.js +0 -1
  254. package/phanpy/dist/assets/icons/mail-line-B0P8aa1L.js +0 -1
  255. package/phanpy/dist/assets/icons/moon-line-CEqNAToP.js +0 -1
  256. package/phanpy/dist/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
  257. package/phanpy/dist/assets/icons/more-3-line-BIiVjYTz.js +0 -1
  258. package/phanpy/dist/assets/icons/notification-line-BZZq2Gtu.js +0 -1
  259. package/phanpy/dist/assets/icons/pencil-line-CKh8-A1v.js +0 -1
  260. package/phanpy/dist/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
  261. package/phanpy/dist/assets/icons/pin-line-DpTolyhs.js +0 -1
  262. package/phanpy/dist/assets/icons/play-fill-B0-G_8lX.js +0 -1
  263. package/phanpy/dist/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
  264. package/phanpy/dist/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
  265. package/phanpy/dist/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
  266. package/phanpy/dist/assets/icons/radar-line-CKyroTth.js +0 -1
  267. package/phanpy/dist/assets/icons/react-line-CoIKhhtK.js +0 -1
  268. package/phanpy/dist/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
  269. package/phanpy/dist/assets/icons/right-line-B3KWJaqc.js +0 -1
  270. package/phanpy/dist/assets/icons/rocket-line-4KZl537D.js +0 -1
  271. package/phanpy/dist/assets/icons/round-fill-C69NTrZ0.js +0 -1
  272. package/phanpy/dist/assets/icons/round-line-B9k_1uo-.js +0 -1
  273. package/phanpy/dist/assets/icons/route-line-B28ReHcE.js +0 -1
  274. package/phanpy/dist/assets/icons/rows-4-line-CrBniagM.js +0 -1
  275. package/phanpy/dist/assets/icons/scan-line-DSf74YdP.js +0 -1
  276. package/phanpy/dist/assets/icons/search-2-line-B6geIU1z.js +0 -1
  277. package/phanpy/dist/assets/icons/settings-3-line-azJwK47w.js +0 -1
  278. package/phanpy/dist/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
  279. package/phanpy/dist/assets/icons/share-2-line-D5MxWjrm.js +0 -1
  280. package/phanpy/dist/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
  281. package/phanpy/dist/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
  282. package/phanpy/dist/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
  283. package/phanpy/dist/assets/icons/time-line-BF3eet1v.js +0 -1
  284. package/phanpy/dist/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
  285. package/phanpy/dist/assets/icons/translate-line-BFWol2Ce.js +0 -1
  286. package/phanpy/dist/assets/icons/unlock-line-X_x5vwv3.js +0 -1
  287. package/phanpy/dist/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
  288. package/phanpy/dist/assets/icons/user-4-line-BVSynZCp.js +0 -1
  289. package/phanpy/dist/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
  290. package/phanpy/dist/assets/icons/user-add-line-BbXdHG4z.js +0 -1
  291. package/phanpy/dist/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
  292. package/phanpy/dist/assets/icons/user-follow-line-BXux0wSd.js +0 -1
  293. package/phanpy/dist/assets/icons/user-star-line-DdYlpHLU.js +0 -1
  294. package/phanpy/dist/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
  295. package/phanpy/dist/assets/icons/user-x-line-DIDgNlPH.js +0 -1
  296. package/phanpy/dist/assets/icons/volume-line-Bs390KQt.js +0 -1
  297. package/phanpy/dist/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
  298. package/phanpy/dist/assets/icons/walk-line-yNXfB-md.js +0 -1
  299. package/phanpy/dist/assets/icons/world-2-line-CenkGIwj.js +0 -1
  300. package/phanpy/dist/assets/icons/zoom-in-line-CaENUphf.js +0 -1
  301. package/phanpy/dist/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
  302. package/phanpy/dist/assets/instances-BNPptnn-.json +0 -333
  303. package/phanpy/dist/assets/locales/ar-SA-CfheRbCu.js +0 -1
  304. package/phanpy/dist/assets/locales/ca-ES-DHRW86Tz.js +0 -1
  305. package/phanpy/dist/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
  306. package/phanpy/dist/assets/locales/de-DE-ByRPMRFy.js +0 -1
  307. package/phanpy/dist/assets/locales/eo-UY-CPC7wLCS.js +0 -1
  308. package/phanpy/dist/assets/locales/es-ES-dJa0Fd9t.js +0 -1
  309. package/phanpy/dist/assets/locales/eu-ES-C3djlPR2.js +0 -1
  310. package/phanpy/dist/assets/locales/fa-IR-DTT490Ck.js +0 -1
  311. package/phanpy/dist/assets/locales/fi-FI-B23MCPuz.js +0 -1
  312. package/phanpy/dist/assets/locales/fr-FR-BcaQsO5C.js +0 -1
  313. package/phanpy/dist/assets/locales/gl-ES-BR-CVKBN.js +0 -1
  314. package/phanpy/dist/assets/locales/he-IL-CfheRbCu.js +0 -1
  315. package/phanpy/dist/assets/locales/hu-HU-CfheRbCu.js +0 -1
  316. package/phanpy/dist/assets/locales/it-IT-C1136UFV.js +0 -1
  317. package/phanpy/dist/assets/locales/ja-JP-CRZmRAhD.js +0 -1
  318. package/phanpy/dist/assets/locales/kab-Cz8xH_TT.js +0 -1
  319. package/phanpy/dist/assets/locales/ko-KR-CG9UiY4o.js +0 -1
  320. package/phanpy/dist/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
  321. package/phanpy/dist/assets/locales/nb-NO-CfheRbCu.js +0 -1
  322. package/phanpy/dist/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
  323. package/phanpy/dist/assets/locales/oc-FR-CfheRbCu.js +0 -1
  324. package/phanpy/dist/assets/locales/pl-PL-DkwGXf6P.js +0 -1
  325. package/phanpy/dist/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
  326. package/phanpy/dist/assets/locales/pt-BR-nGL0HdFS.js +0 -1
  327. package/phanpy/dist/assets/locales/pt-PT-Cp17aj2z.js +0 -1
  328. package/phanpy/dist/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
  329. package/phanpy/dist/assets/locales/th-TH-CfheRbCu.js +0 -1
  330. package/phanpy/dist/assets/locales/tok-CfheRbCu.js +0 -1
  331. package/phanpy/dist/assets/locales/tr-TR-CfheRbCu.js +0 -1
  332. package/phanpy/dist/assets/locales/uk-UA-C5E3dFBf.js +0 -1
  333. package/phanpy/dist/assets/locales/zh-CN-BHJi7_et.js +0 -1
  334. package/phanpy/dist/assets/locales/zh-TW-CfheRbCu.js +0 -1
  335. package/phanpy/dist/assets/main-BdqNbG-a.js +0 -26
  336. package/phanpy/dist/assets/main-BdqNbG-a.js.map +0 -1
  337. package/phanpy/dist/assets/mock-home-DGhR__He.js +0 -2
  338. package/phanpy/dist/assets/mock-home-DGhR__He.js.map +0 -1
  339. package/phanpy/dist/assets/multi-column-ROck0NVt.jpg +0 -0
  340. package/phanpy/dist/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
  341. package/phanpy/dist/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
  342. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js +0 -2
  343. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js.map +0 -1
  344. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js +0 -20
  345. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js.map +0 -1
  346. package/phanpy/dist/assets/style-B1iLPTPR.css +0 -2
  347. package/phanpy/dist/assets/temml-DuyIQMei.js +0 -97
  348. package/phanpy/dist/assets/temml-DuyIQMei.js.map +0 -1
  349. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js +0 -2
  350. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
  351. package/phanpy/dist/assets/year-in-posts-B2lywqdx.png +0 -0
  352. package/phanpy/dist/assets/year-in-posts-DJv_star.js +0 -3
  353. package/phanpy/dist/assets/year-in-posts-DJv_star.js.map +0 -1
  354. package/phanpy/dist/compose/index.html +0 -20
  355. package/phanpy/dist/favicon.ico +0 -0
  356. package/phanpy/dist/index.html +0 -73
  357. package/phanpy/dist/logo-192.png +0 -0
  358. package/phanpy/dist/logo-512.png +0 -0
  359. package/phanpy/dist/logo-badge-72.png +0 -0
  360. package/phanpy/dist/logo-maskable-512.png +0 -0
  361. package/phanpy/dist/logo-monochrome-512.png +0 -0
  362. package/phanpy/dist/logo-monochrome-maskable-512.png +0 -0
  363. package/phanpy/dist/manifest.webmanifest +0 -1
  364. package/phanpy/dist/og-image-2.jpg +0 -0
  365. package/phanpy/dist/og-image.png +0 -0
  366. package/phanpy/dist/robots.txt +0 -2
  367. package/phanpy/dist/sw.js +0 -2
  368. package/phanpy/dist/sw.js.map +0 -1
  369. package/phanpy/dist/version.json +0 -1
  370. package/run-agent.mjs +0 -899
  371. package/vendor/gate.cjs +0 -138
  372. package/vendor/idp-grant.cjs +0 -394
  373. package/vendor/jfetch.cjs +0 -16
  374. package/web/admin/actors.js +0 -147
  375. package/web/admin/bar.css +0 -126
  376. package/web/admin/bar.js +0 -99
  377. package/web/admin/client/client.js +0 -66
  378. package/web/admin/client/index.html +0 -69
  379. package/web/admin/client-pick.js +0 -79
  380. package/web/admin/common.js +0 -23
  381. package/web/admin/connections.js +0 -112
  382. package/web/admin/gateway.js +0 -133
  383. package/web/admin/group.js +0 -258
  384. package/web/admin/index.html +0 -612
  385. package/web/admin/notices-bar.js +0 -90
  386. package/web/admin/oauth-signin.mjs +0 -37
  387. package/web/admin/record.js +0 -393
  388. package/web/admin/setup/index.html +0 -257
  389. package/web/admin/setup/setup.js +0 -339
  390. package/web/admin/tokens.css +0 -68
  391. package/web/admin/upkeep.js +0 -177
  392. package/web/admin/window.css +0 -55
  393. package/web/admin/window.js +0 -136
  394. package/web/app/README.md +0 -81
  395. package/web/app/admin-facade.mjs +0 -588
  396. package/web/app/agent.mjs +0 -672
  397. package/web/app/atproto-browser.mjs +0 -86
  398. package/web/app/authorize_interaction.html +0 -56
  399. package/web/app/authorize_interaction.js +0 -69
  400. package/web/app/boot.mjs +0 -616
  401. package/web/app/deliver-relay.mjs +0 -129
  402. package/web/app/dist/boot.js +0 -34562
  403. package/web/app/dist/boot.js.map +0 -7
  404. package/web/app/dist/sw.js +0 -73456
  405. package/web/app/dist/sw.js.map +0 -7
  406. package/web/app/fediacct-browser.mjs +0 -146
  407. package/web/app/gateway-move.mjs +0 -60
  408. package/web/app/idb-kv.mjs +0 -35
  409. package/web/app/index.html +0 -258
  410. package/web/app/keys-browser.mjs +0 -71
  411. package/web/app/keystore.mjs +0 -82
  412. package/web/app/oidc-session.mjs +0 -6
  413. package/web/app/pod-auth.mjs +0 -248
  414. package/web/app/pod-remote.mjs +0 -84
  415. package/web/app/shims/_globals.mjs +0 -2
  416. package/web/app/shims/fedify-sig.mjs +0 -77
  417. package/web/app/shims/node-crypto.mjs +0 -113
  418. package/web/app/shims/node-fs.mjs +0 -17
  419. package/web/app/shims/node-path.mjs +0 -19
  420. package/web/app/shims/node-url.mjs +0 -7
  421. package/web/app/shims/prelude.js +0 -58
  422. package/web/app/shims/safefetch.mjs +0 -58
  423. package/web/app/shims/shapes-text.mjs +0 -8
  424. package/web/app/shims/web-push.mjs +0 -14
  425. package/web/app/signup.mjs +0 -357
  426. package/web/app/sw-src.mjs +0 -220
  427. package/web/app/update.js +0 -70
  428. package/web/front/admin.html +0 -55
  429. package/web/front/admin.js +0 -89
  430. package/web/front/install.sh +0 -69
  431. package/web/front/new-account.html +0 -35
  432. package/web/front/new-account.js +0 -13
  433. package/web/front/notices.html +0 -69
  434. package/web/front/notices.js +0 -107
  435. package/web/front/run.html +0 -64
  436. package/web/front/run.js +0 -221
  437. package/web/front/solid-oidc-client.js +0 -6
  438. package/web/icons/forum.svg +0 -11
  439. package/web/icons/gateway.svg +0 -14
  440. package/web/icons/local.svg +0 -11
@@ -1,177 +0,0 @@
1
- // upkeep.js — upkeep and the lifecycle: the output pane, drain, recover,
2
- // log and dead letters; the confirmations for rotate, retire and move; and
3
- // the inbox backlog panel.
4
-
5
- // Which button filled the output pane, so clicking that one again closes it
6
- // rather than re-fetching the same thing under an already-open panel.
7
- let outputSource = null;
8
-
9
- const OUTPUT_TITLES = { log: 'Log', deadletter: 'Dead letters', drain: 'Inbox drain', rebuild: 'Recovered posts' };
10
- const output = (obj, source = null) => {
11
- closePanels('output');
12
- outputSource = source;
13
- solWindow.show('output', OUTPUT_TITLES[source] || 'Output');
14
- $('output').textContent = typeof obj === 'string' ? obj : JSON.stringify(obj, null, 2);
15
- };
16
-
17
- const showingFrom = (source) => outputSource === source && solWindow.openId() === 'output';
18
-
19
- // Drain is the one that does work rather than reveals it, so a second click
20
- // re-runs instead of closing. It can take a while — the agent joins a sweep
21
- // already in flight and queues another after it — and a button that looks dead
22
- // for a minute reads as broken.
23
- $('do-drain').addEventListener('click', async (ev) => {
24
- const b = ev.currentTarget;
25
- b.disabled = true;
26
- b.textContent = 'draining…';
27
- say('draining the inbox — if a sweep is already running this waits for it to finish');
28
- const r = await write('/drain', {}, 'inbox drained');
29
- b.disabled = false;
30
- b.textContent = 'Drain the inbox';
31
- if (r) {
32
- const box = r.inbox || {};
33
- say(`inbox drained — ${box.count ?? 0} still waiting`);
34
- output(r, 'drain');
35
- }
36
- });
37
-
38
- // Like the drain, this does work rather than reveals it, so a second click
39
- // re-runs. Nothing here can lose anything: it only adds posts back.
40
- $('do-rebuild').addEventListener('click', async (ev) => {
41
- const b = ev.currentTarget;
42
- b.disabled = true;
43
- b.textContent = 'recovering…';
44
- say('reading what the pod still holds — one request per post, so this takes a moment');
45
- const r = await write('/rebuild', {}, 'checked');
46
- b.disabled = false;
47
- b.textContent = 'Recover posts';
48
- if (!r) return;
49
- if (r.why) { say(r.why, 'err'); return; }
50
- if (!r.landed) { say('recovered posts could NOT be saved — see the log', 'err'); return; }
51
- say(r.recovered
52
- ? `recovered ${r.recovered} post(s) the pod had and this machine did not`
53
- : `nothing was missing — the pod indexed ${r.indexed} post(s), all of them already here`);
54
- output(r, 'rebuild');
55
- });
56
-
57
- $('do-log').addEventListener('click', async () => {
58
- if (showingFrom('log')) { closePanels(); return; }
59
- const { json } = await api('/log');
60
- output((json?.lines || []).slice(-60).join('\n') || 'nothing logged yet', 'log');
61
- });
62
-
63
- $('do-deadletter').addEventListener('click', async () => {
64
- if (showingFrom('deadletter')) { closePanels(); return; }
65
- const { json } = await api('/deadletter');
66
- output(json?.items?.length ? json.items : 'no dead letters', 'deadletter');
67
- });
68
-
69
- // ---- lifecycle ----
70
- // None of these can be taken back by clicking again, so the button only opens
71
- // the matching warning in the markup; the second click is the one that acts.
72
- // Retire also wants the handle typed, because a misclick cannot produce it.
73
-
74
- const LIFECYCLE = {
75
- 'rotate-key': { path: '/rotate-key', title: 'Rotate the signing key', done: (r) => (r.changed ? 'rotated and republished' : 'no change — the key was already fresh') },
76
- retire: { path: '/retire', title: 'Retire this identity', go: 'Retire it', danger: true, done: (r) => `retired ${r.deletedAt}: Delete delivered to ${r.inboxes} inbox(es)` },
77
- move: { path: '/move', title: 'Transfer this account away', go: 'Transfer it', focus: 'move-target',
78
- done: (r) => `transferred to ${r.target}: Move delivered to ${r.inboxes} inbox(es), unfollowed ${r.unfollowed}/${r.following}` },
79
- // The address at the gateway, not the identity: the pod keeps everything.
80
- 'close-address': { path: '/gateway/close', title: 'Close this address', go: 'Close it', danger: true, focus: 'confirm-handle-close',
81
- done: (r) => (r.closed ? 'closed — this address is gone for good; everything on your pod is untouched' : 'not closed') },
82
- };
83
- let pending = null;
84
-
85
- const closeConfirm = () => closePanels();
86
-
87
- for (const btn of document.querySelectorAll('[data-confirm]')) {
88
- btn.addEventListener('click', () => {
89
- const what = btn.dataset.confirm;
90
- // The same button again closes its question rather than re-asking it.
91
- if (pending === what && solWindow.openId() === 'confirm-form') { closePanels(); return; }
92
- closePanels(); // including whatever else was open
93
- pending = what;
94
- const spec = LIFECYCLE[what];
95
- $(`warn-${what}`).hidden = false;
96
- solWindow.show('confirm-form', spec.title);
97
- $('confirm-go').className = spec.danger ? 'danger' : 'primary';
98
- $('confirm-go').textContent = spec.go || 'Confirm';
99
- if (spec.focus) $(spec.focus).focus();
100
- else if (what === 'retire') $('confirm-handle').focus();
101
- });
102
- }
103
-
104
- // Offered from inside the retire warning: someone reading it has already said
105
- // what they want ("not this account, here, any more") and these are the two
106
- // answers that are not destruction. Switching panels rather than closing means
107
- // they do not have to go and find the button themselves.
108
- const openConfirm = (what) => {
109
- closePanels(); // or `show` toggles: same panel, different warning
110
- document.querySelector(`[data-confirm="${what}"]`).click();
111
- };
112
- // Park lives on the status control now; from inside the retire warning it is
113
- // still one click — close the question and park.
114
- $('go-park').addEventListener('click', () => { closePanels(); setStatus(true); });
115
- $('go-move').addEventListener('click', () => openConfirm('move'));
116
-
117
- $('confirm-cancel').addEventListener('click', () => { closeConfirm(); say('nothing changed'); });
118
-
119
- $('confirm-form').addEventListener('submit', async (ev) => {
120
- ev.preventDefault();
121
- if (!pending) return;
122
- const what = pending;
123
- const body = what === 'retire' ? { confirm: $('confirm-handle').value.trim() }
124
- : what === 'move' ? { target: $('move-target').value.trim(), confirm: $('confirm-handle-move').value.trim() }
125
- : what === 'close-address' ? { confirm: $('confirm-handle-close').value.trim() }
126
- : {};
127
- if (what === 'move' && !body.target) { say('name the account to transfer to', 'err'); return; }
128
- $('confirm-go').disabled = true;
129
- say(`${what} — this talks to the pod and to other servers, so it takes a moment`);
130
- const r = await write(LIFECYCLE[what].path, body, what);
131
- $('confirm-go').disabled = false;
132
- if (!r) return; // write() already said why
133
- closeConfirm();
134
- say(LIFECYCLE[what].done(r));
135
- load(); // mode, and whether it is retired, both changed
136
- });
137
-
138
- // ---- inbox ----
139
- // Only appears when there is enough waiting to be worth a decision. The agent
140
- // drains oldest-first regardless; this exists to let the owner say "do not
141
- // bother with that fortnight", which is not a call an agent should make on
142
- // someone's mail by itself.
143
- const INBOX_PROMPT_AT = 500;
144
- let dismissed = false;
145
-
146
- async function renderInbox() {
147
- const { json: st } = await api('/status');
148
- // A state document the last load could not read is a timeline or a contact
149
- // list quietly missing; the page says which, under the facts.
150
- const skipped = st?.stateSkipped || [];
151
- const line = $('state-skipped');
152
- line.hidden = !skipped.length;
153
- line.textContent = skipped.length
154
- ? `${skipped.length} state document${skipped.length === 1 ? '' : 's'} could not be read on the last load: ${skipped.join(', ')}.`
155
- : '';
156
- if (dismissed) return;
157
- const box = st?.inbox;
158
- const panel = $('pane-inbox');
159
- if (!box || box.count < INBOX_PROMPT_AT) { panel.hidden = true; return; }
160
- const mb = box.bytes >= 1048576
161
- ? `${(box.bytes / 1048576).toFixed(1)} MB` : `${Math.round(box.bytes / 1024)} kB`;
162
- const since = box.oldest ? new Date(box.oldest).toLocaleDateString() : 'unknown';
163
- $('inbox-summary').textContent =
164
- `${box.count.toLocaleString()} deliveries waiting (${mb}), the oldest from ${since}.`;
165
- // One request each to read and delete, and the agent holds itself to 60 a
166
- // minute, so the honest number is minutes not seconds.
167
- $('inbox-warn').hidden = box.count < 2000;
168
- $('inbox-warn').textContent = box.count >= 2000
169
- ? `At 60 requests a minute this is roughly ${Math.ceil(box.count * 2 / 60)} minutes of `
170
- + 'draining if you keep everything. Discarding the old content is much quicker.'
171
- : '';
172
- panel.hidden = false;
173
- }
174
-
175
- // The gateway, as a facts row under software: attach through a multi-user
176
- // front with this agent's own credential, detach back to the pod inbox. The
177
- // forms live in the floating window, like every other disclosure.
@@ -1,55 +0,0 @@
1
- /* window.css — the floating panel every page of ours puts a form in.
2
- Shared like bar.css, so the three surfaces cannot drift apart. */
3
-
4
- /* Fixed, so it floats over the page rather than pushing it about — which is
5
- what the accordions did, moving the line you were reading every time one
6
- opened. Resizing is the browser's own grip: `resize` needs `overflow` set to
7
- anything but visible, which is also what keeps a long form inside the frame. */
8
- #win {
9
- position: fixed; z-index: 40;
10
- top: 5rem; left: 50%; transform: translateX(-50%);
11
- width: min(46rem, calc(100vw - 2rem));
12
- /* Tall enough for what is in it and no taller: a fixed height made a short
13
- panel roomy and a long one scroll for no reason. `auto` up to a cap, so it
14
- only ever scrolls when the content genuinely will not fit the screen — and
15
- the moment you drag the corner, that inline height wins over both. */
16
- height: auto;
17
- min-width: 18rem; min-height: 8rem;
18
- max-width: 100vw; max-height: calc(100vh - 7rem);
19
- resize: both; overflow: hidden;
20
- display: flex; flex-direction: column;
21
- /* Raised, like the bar: it sits ON the page, so it takes the same colour the
22
- bar does rather than the page's own. The shadow lifts it; the colour says
23
- which layer it belongs to. */
24
- background: var(--raised); color: CanvasText;
25
- border: 1px solid var(--btn-edge); border-radius: .5rem;
26
- box-shadow: 0 .6rem 2rem #0004;
27
- }
28
- /* Dragged by the bar, so the grab area is obvious and a text selection inside
29
- the form never moves the window. */
30
- /* Its own title bar keeps a rule: this one IS two surfaces meeting inside a
31
- single small box, where a tone change alone is too quiet to read as a grab
32
- handle. Different problem from the page bar, different answer. */
33
- #win-bar {
34
- flex: 0 0 auto; display: flex; align-items: baseline; gap: .6rem;
35
- padding: .45rem .7rem; cursor: move; user-select: none;
36
- border-bottom: 1px solid var(--btn-edge); border-radius: .5rem .5rem 0 0;
37
- background: var(--surface);
38
- }
39
- #win-title { flex: 1 1 auto; font-weight: 600; color: var(--heading); }
40
- /* 24x24 is the 2.5.8 minimum; at .1rem of vertical padding this came out
41
- 21.6px tall, which is a small target for the one control that dismisses the
42
- thing covering your page. Same glyph, same place, bigger hit area. */
43
- #win-close {
44
- font: inherit; line-height: 1; cursor: pointer;
45
- min-width: 24px; min-height: 24px; padding: .2rem .5rem;
46
- display: inline-flex; align-items: center; justify-content: center;
47
- border: 0; background: none; color: var(--link);
48
- }
49
- /* The window scrolls, never the page — same rule the rest of the app follows. */
50
- #win-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: .2rem 1rem 1rem; }
51
- #win-body > * { margin-top: .6rem; }
52
- #win-body pre { overflow-x: auto; background: #0001; padding: .6rem; border-radius: .3rem;
53
- font-size: .9rem; }
54
- /* Dragging with the pointer over the frame would otherwise select text inside it. */
55
- body.dragging { user-select: none; }
@@ -1,136 +0,0 @@
1
- // window.js — the floating panel, shared by every page of ours.
2
- //
3
- // It replaces the accordions. Those opened at the foot of the page and pushed
4
- // whatever you were reading out from under you; worse, only one could be open,
5
- // so looking at the log meant closing the form you were filling in. A window
6
- // floats over the page instead, and you can move it off whatever it covers.
7
- //
8
- // Resizing is the browser's own grip (`resize: both`), so there is no drag
9
- // maths here beyond moving it. Nothing is created in script: every panel is
10
- // declared in the page's markup inside #win-body, and this only shows one.
11
-
12
- (() => {
13
- const win = document.getElementById('win');
14
- if (!win) return;
15
- const bar = document.getElementById('win-bar');
16
- const title = document.getElementById('win-title');
17
- const body = document.getElementById('win-body');
18
-
19
- // Every direct child of the body is a panel; showing one hides the rest.
20
- const panels = () => [...body.children];
21
- let open = null;
22
- // Where focus was when the window opened, so closing can put it back. Without
23
- // this, Escape from inside the panel drops focus on <body> and the tab order
24
- // restarts from the top of the page.
25
- let returnTo = null;
26
-
27
- // It IS a dialog, so it says so — and a dialog that opens without taking
28
- // focus leaves a keyboard user tabbing forward through the rest of the page
29
- // to find it, and a screen-reader user with no announcement that anything
30
- // happened at all. It also sits over the control that opened it, so moving
31
- // focus in is what stops that control being focused-but-obscured.
32
- win.setAttribute('role', 'dialog');
33
- win.setAttribute('aria-modal', 'false'); // the page behind stays usable
34
- win.setAttribute('aria-labelledby', 'win-title');
35
-
36
- // The first focusable that is actually SHOWING. A plain querySelector matches
37
- // elements inside hidden sub-blocks (a confirm panel has one warning block per
38
- // action, all but one hidden), and .focus() on a display:none element is a
39
- // silent no-op — so a dialog whose first match is hidden would open with focus
40
- // still outside it. offsetParent is null for anything display:none.
41
- const focusFirst = () => {
42
- const panel = panels().find(p => !p.hidden);
43
- if (!panel) { document.getElementById('win-close')?.focus(); return; }
44
- const candidates = panel.querySelectorAll(
45
- 'input:not([type=hidden]), select, textarea, button, [href], [tabindex]:not([tabindex="-1"])',
46
- );
47
- // Prefer a non-committing control: never open a destructive dialog with a
48
- // submit/confirm button pre-focused where a stray Enter would fire it.
49
- let firstVisible = null;
50
- for (const el of candidates) {
51
- if (el.offsetParent === null && el !== document.body) continue; // hidden
52
- if (!firstVisible) firstVisible = el;
53
- const commits = el.type === 'submit' || /\bconfirm-go\b/.test(el.id);
54
- if (!commits) { el.focus(); return; }
55
- }
56
- (firstVisible || document.getElementById('win-close'))?.focus();
57
- };
58
-
59
- const close = () => {
60
- win.hidden = true;
61
- for (const p of panels()) p.hidden = true;
62
- const was = open;
63
- open = null;
64
- // Only if focus is still ours to move: the user may have clicked away.
65
- const back = returnTo;
66
- returnTo = null;
67
- if (back && document.contains(back) && win.contains(document.activeElement)) back.focus();
68
- else if (back && document.contains(back) && document.activeElement === document.body) back.focus();
69
- win.dispatchEvent(new CustomEvent('win:closed', { detail: { was } }));
70
- };
71
-
72
- // Returns false when it CLOSED an already-open panel, so a button can toggle
73
- // itself without every caller repeating the check.
74
- const show = (id, label) => {
75
- if (open === id && !win.hidden) { close(); return false; }
76
- const opener = document.activeElement;
77
- for (const p of panels()) p.hidden = p.id !== id;
78
- title.textContent = label || '';
79
- win.hidden = false;
80
- open = id;
81
- clampIntoView();
82
- if (opener && opener !== document.body && !win.contains(opener)) returnTo = opener;
83
- focusFirst();
84
- return true;
85
- };
86
-
87
- // A window remembers where it was left, so it does not jump back to the
88
- // middle every time — but only within the page, because a position saved on a
89
- // wide screen is off-screen on a narrow one and there is nothing to grab.
90
- let placed = false;
91
- function clampIntoView() {
92
- if (!placed) return;
93
- const r = win.getBoundingClientRect();
94
- const x = Math.min(Math.max(r.left, 0), Math.max(0, innerWidth - r.width));
95
- const y = Math.min(Math.max(r.top, 0), Math.max(0, innerHeight - r.height));
96
- moveTo(x, y);
97
- }
98
- function moveTo(x, y) {
99
- win.style.transform = 'none'; // the centring transform, undone once moved
100
- win.style.left = `${x}px`;
101
- win.style.top = `${y}px`;
102
- placed = true;
103
- }
104
-
105
- let drag = null;
106
- bar.addEventListener('pointerdown', (e) => {
107
- if (e.target.closest('button')) return; // the close button is not a handle
108
- const r = win.getBoundingClientRect();
109
- drag = { dx: e.clientX - r.left, dy: e.clientY - r.top };
110
- bar.setPointerCapture(e.pointerId);
111
- document.body.classList.add('dragging');
112
- });
113
- bar.addEventListener('pointermove', (e) => {
114
- if (!drag) return;
115
- const r = win.getBoundingClientRect();
116
- moveTo(Math.min(Math.max(e.clientX - drag.dx, 0), Math.max(0, innerWidth - r.width)),
117
- Math.min(Math.max(e.clientY - drag.dy, 0), Math.max(0, innerHeight - r.height)));
118
- });
119
- const endDrag = (e) => {
120
- if (!drag) return;
121
- drag = null;
122
- try { bar.releasePointerCapture(e.pointerId); } catch { /* already released */ }
123
- document.body.classList.remove('dragging');
124
- };
125
- bar.addEventListener('pointerup', endDrag);
126
- bar.addEventListener('pointercancel', endDrag);
127
- addEventListener('resize', clampIntoView);
128
-
129
- document.getElementById('win-close').addEventListener('click', close);
130
- // Escape closes it, which is what every floating thing does and what people
131
- // try first when a window is covering the thing they wanted to read.
132
- addEventListener('keydown', (e) => { if (e.key === 'Escape' && !win.hidden) close(); });
133
-
134
- // The whole API: open a declared panel by id, close, and ask what is open.
135
- window.solWindow = { show, close, openId: () => (win.hidden ? null : open) };
136
- })();
package/web/app/README.md DELETED
@@ -1,81 +0,0 @@
1
- # web/app — FediPod in the browser
2
-
3
- The in-browser build: sign up and run a FediPod account in a tab, no install.
4
- See `claude/plans/browser-agent.md` for the whole design and status.
5
-
6
- | file | what |
7
- |---|---|
8
- | `pod-auth.mjs` | A CSS account API client, browser-native: create an account + pod, mint a client credential, and a DPoP-bound `fetch`. Since 1.28.0 the app itself uses none of it — a pod is made on the provider's own page and the app runs on the pod's Solid-OIDC login — but the harnesses do, to make scratch pods and stand in for a login form. The twin of `lib/device/account.mjs` + `vendor/idp-grant.cjs`. |
9
- | `keystore.mjs` | WebCrypto RSA/Ed25519 key generation. The key is stored on the pod as it is, in the owner-only state container, since 1.28.0 (2026-09-22); `unwrapKeys` remains for accounts from before then, whose key is under the sign-up password until it is opened once. |
10
- | `keys-browser.mjs` | Importing a keys record for signing, and finding one: this browser's opened copy in IndexedDB first, else the pod's, read with the pod session. A pre-1.28.0 envelope raises `KeyPasswordNeeded`, which `boot.mjs` answers with the open-once pane; the same pane offers a new key to someone who no longer has that password. |
11
- | `signup.mjs` | The `fedipod setup` flow, in the browser, up to publish, on the pod session the person already holds: pod check, gateway attach, key stored on the pod (owner-only ACL written *before* the key), config. Takes no password and no credential. Also `readAccount` (what the pod already holds) and `moveIn` (an address at another gateway moving here: attach fronted, rewrite the config with the old actor as an alias, restamp the key, leave the Move pending). |
12
- | `gateway-move.mjs` | The pending half of a move, run when the agent goes active under the new ids: tells the old gateway (`/api/move`) and sends the Move to every follower from the old actor, signed under the old key id through the old relay. Safe to run again. |
13
- | `shims/fedify-sig.mjs` | Browser stand-in for `@fedify/fedify/sig` (which will not bundle for a browser). `sign()` returns signed headers as data for the relay; `signRequest()` wraps it Fedify-shaped. Proven byte-identical to Fedify. |
14
- | `shims/node-crypto.mjs` | Browser stand-in for `node:crypto` — the small synchronous slice the agent uses, via crypto-browserify, plus native WebCrypto. |
15
- | `shims/safefetch.mjs` | Browser stand-in for `lib/shared/safefetch.mjs`. Pinning and the private-address checks are unnecessary here (a browser closes DNS rebinding itself); the BYTE BUDGET is not, so `readCapped` streams and stops at the cap exactly as the Node one does. |
16
- | `dist/` | The bundled agent, built by `scripts/build-app.mjs`. Committed like `phanpy/dist`, regenerated on release. (Not present until the agent entry is built.) |
17
-
18
- Build: `node scripts/build-app.mjs`. Tests live in `claude/validation/`:
19
- `signup-browser/`, `signing-shim/`, `agent-bundle/`.
20
-
21
- ## The agent (built 2026-09-07)
22
-
23
- | file | what |
24
- |---|---|
25
- | `pod-remote.mjs` | RemotePod over the DPoP session — the agent's pod I/O, ACLs and deletion deny-list, browser-native. |
26
- | `keys-browser.mjs` | Load the signing key into WebCrypto. |
27
- | `deliver-relay.mjs` | lib's Deliverer, sending through the relay (a browser cannot set Date/Host). |
28
- | `agent.mjs` | Wires lib's store, publisher, intake and Mastodon facade with the browser edges. |
29
- | `sw-src.mjs` | The service worker that hosts the agent and answers the facade (Mastodon paths + the owner/manage paths); static files fall through. Built to `dist/sw.js`. |
30
- | `boot.mjs` | Page side: sign in at the pod (also the first half of sign-up), the identity screen on the way back, sign in by address, register the worker, route into `/admin/client/`; `?signout` / `?add` teardown. Built to `dist/boot.js`. |
31
- | `shims/` | Browser stand-ins the bundle needs: `node-crypto`, `node-path`, `node-url`, `node-fs`, `web-push`, `safefetch`, `prelude` (process + Buffer). |
32
-
33
- ## The manage surface & connected accounts (built 2026-09-08)
34
-
35
- The owner's record/manage page is the SAME `web/admin` UI the Node agent serves,
36
- reused as static files under `/admin/` (staged by `scripts/stage-site.mjs`); the
37
- worker answers the data endpoints it calls. See
38
- `claude/plans/browser-manage-surface.md` for the whole design and status, and
39
- `claude/plans/post-as-connected-account.md` for the deferred "post as" plan.
40
-
41
- | file | what |
42
- |---|---|
43
- | `admin-facade.mjs` | Answers the owner/manage endpoints (`/status`, `/config`, `/gateway`, `/alias`, `/rotate-key`, `/rebuild`, `/move`, `/retire`, `/inbox/prune`, `/deadletter`, `/blocks`, `/atproto*`, `/fediacct*`) over the browser agent, mirroring `lib/device/admin.mjs`. Personal only. |
44
- | `atproto-browser.mjs` | The Bluesky connection (`lib/connections/atproto.mjs`) with a per-connection storage choice — IndexedDB (this browser) or owner-only pod state — plus pause. |
45
- | `fediacct-browser.mjs` | Connections to fediverse accounts on other servers (`lib/connections/fediacct.mjs`): the OAuth dance, the same storage choice, and a best-effort server-side revoke on disconnect. |
46
- | `idb-kv.mjs` | The per-origin IndexedDB key/value store the two connectors use for "on this device, never the pod" credentials. |
47
-
48
- `agent.mjs` also holds the single-active-agent **lease** (`lib/core/lease.mjs`) — a
49
- second device runs read-only until it takes over — and starts the drain/mirrors
50
- only when it is the active holder.
51
-
52
- Build: `node scripts/build-app.mjs --entry web/app/sw-src.mjs --out web/app/dist/sw.js` and `--entry web/app/boot.mjs --out web/app/dist/boot.js`, then `node scripts/stage-site.mjs` to assemble `web/app/site/` (the front, the worker, Phanpy under `/app/`, and `web/admin` under `/admin/`).
53
-
54
- Tests: `claude/smoke-tests/admin-facade-smoke.mjs`, and eight harnesses in
55
- `claude/validation/browser-agent/` that drive a real Chrome against a scratch
56
- Solid server — `run` (the agent and the facade), `sw-run` (the same through the
57
- service worker, plus media upload and notification paging), `full-run` (the
58
- staged site, sign-up to Phanpy rendering), `unlock-run` (a browser with no opened
59
- key, and a pre-1.28.0 account opened once), `oidc-run`, `resume-run`,
60
- `gateway-run`, and `provider-csp-run` (the sign-up page's own policy, read from
61
- the browser's refusal reports). Four helpers sit beside them: `idp-login.mjs`
62
- fills the pod's login and consent screens, `page-signup.mjs` drives the page
63
- through sign-up the way a person does since 1.28.0 (pod first, then the pod's
64
- login, then the identity screen), `worker-log.mjs` reads the agent's console
65
- out of the service worker, and the attach and relay stubs in `sw-run.mjs` stand
66
- in for the front.
67
-
68
- ## What this build does not have
69
-
70
- Declared rather than pretended: each is omitted from the instance document, so
71
- a client hides the control instead of offering one that quietly does nothing.
72
- See the `MastoApi` options in `agent.mjs`.
73
-
74
- | | why |
75
- |---|---|
76
- | **Streaming** | a service worker answers fetches, not sockets. No streaming URL is advertised, so clients poll. |
77
- | **Web push** | `shims/web-push.mjs` is a no-op. `vapid` is omitted, and a client that subscribes anyway gets a 422 rather than a subscription nothing will push to. |
78
- | **Scheduled posts** | nothing runs between now and the scheduled time. A `scheduled_at` is refused with a 422 that says so — accepting one was silent loss. |
79
- | **Groups** | sign-up makes personal identities only (`signup.mjs`), and the moderation surface is not here. Joining a group works; hosting one needs the DeviceAgent. See `groups.md`. |
80
- | **Changing where the address lives** | the shape is chosen at sign-up (`signup.mjs`): on the pod, `@you@yourpod` with the gateway as a mail door, or at the gateway, `@you@front` — and a suffixed pod is always fronted. `admin-facade.mjs` refuses changing it afterwards, because a rename needs a restart a browser does not have. |
81
- | **Moving the private half** | `/state-move` is about filesystem paths and `credential.json`. A browser has neither; its private half is always on the pod. |