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,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. |