fedipod-server 0.28.1 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -34
- package/config/server.json +22 -0
- package/dist/claims.js +3 -2
- package/dist/directory.d.ts +2 -0
- package/dist/door.d.ts +4 -0
- package/dist/door.js +31 -0
- package/dist/fedipod.d.ts +16 -0
- package/dist/fedipod.js +13 -0
- package/dist/front.d.ts +3 -0
- package/dist/front.js +94 -0
- package/dist/handler.d.ts +39 -101
- package/dist/handler.js +86 -617
- package/dist/handler.jsonld +6 -30
- package/dist/identities.d.ts +62 -0
- package/dist/identities.js +236 -0
- package/dist/mounts.d.ts +43 -0
- package/dist/mounts.js +123 -0
- package/dist/opt-in.d.ts +46 -0
- package/dist/opt-in.js +176 -0
- package/dist/store-pod.js +37 -0
- package/package.json +10 -18
- package/lib/client/c2s.mjs +0 -582
- package/lib/client/localapi.mjs +0 -87
- package/lib/client/masto/accounts.mjs +0 -309
- package/lib/client/masto/body.mjs +0 -156
- package/lib/client/masto/index.mjs +0 -206
- package/lib/client/masto/instance.mjs +0 -112
- package/lib/client/masto/media.mjs +0 -79
- package/lib/client/masto/oauth.mjs +0 -656
- package/lib/client/masto/render.mjs +0 -518
- package/lib/client/masto/statuses.mjs +0 -372
- package/lib/client/masto/timelines.mjs +0 -438
- package/lib/client/oidc-auth.mjs +0 -62
- package/lib/client/streaming.mjs +0 -154
- package/lib/client/webpush.mjs +0 -98
- package/lib/connections/acctfeed.mjs +0 -257
- package/lib/connections/atproto.mjs +0 -309
- package/lib/connections/bskyfeed.mjs +0 -243
- package/lib/connections/bskygroup.mjs +0 -162
- package/lib/connections/fediacct.mjs +0 -253
- package/lib/connections/import.mjs +0 -357
- package/lib/connections/tagfeed.mjs +0 -212
- package/lib/connections/vault.mjs +0 -114
- package/lib/core/as2.mjs +0 -206
- package/lib/core/contexts/activitystreams.json +0 -379
- package/lib/core/contexts/anno.json +0 -126
- package/lib/core/contexts/did-v1.json +0 -57
- package/lib/core/contexts/fep-5711.json +0 -36
- package/lib/core/contexts/gotosocial.json +0 -86
- package/lib/core/contexts/identity-v1.json +0 -152
- package/lib/core/contexts/index.mjs +0 -63
- package/lib/core/contexts/join-lemmy.json +0 -33
- package/lib/core/contexts/joinmastodon.json +0 -28
- package/lib/core/contexts/litepub-0.1.json +0 -60
- package/lib/core/contexts/map.json +0 -19
- package/lib/core/contexts/miscellany.json +0 -19
- package/lib/core/contexts/quotes.json +0 -18
- package/lib/core/contexts/schemaorg.json +0 -8845
- package/lib/core/contexts/security-data-integrity-v1.json +0 -78
- package/lib/core/contexts/security-data-integrity-v2.json +0 -81
- package/lib/core/contexts/security-multikey-v1.json +0 -35
- package/lib/core/contexts/security-v1.json +0 -74
- package/lib/core/contexts/webfinger.json +0 -10
- package/lib/core/deliver.mjs +0 -371
- package/lib/core/graphview.mjs +0 -327
- package/lib/core/intake/activities.mjs +0 -633
- package/lib/core/intake/activity.mjs +0 -318
- package/lib/core/intake/channel.mjs +0 -144
- package/lib/core/intake/group.mjs +0 -256
- package/lib/core/intake/index.mjs +0 -701
- package/lib/core/intake/notes.mjs +0 -360
- package/lib/core/intake/verify.mjs +0 -142
- package/lib/core/keys.mjs +0 -153
- package/lib/core/lease.mjs +0 -206
- package/lib/core/polls.mjs +0 -105
- package/lib/core/profile-page.mjs +0 -104
- package/lib/core/proof.mjs +0 -79
- package/lib/core/publisher/collections.mjs +0 -237
- package/lib/core/publisher/index.mjs +0 -500
- package/lib/core/publisher/notes.mjs +0 -453
- package/lib/core/publisher/questions.mjs +0 -239
- package/lib/core/publisher/restore.mjs +0 -224
- package/lib/core/shapes/activitystreams.ttl +0 -157
- package/lib/core/shapes/index.mjs +0 -132
- package/lib/core/shapes/shapes-text.mjs +0 -13
- package/lib/core/social.mjs +0 -531
- package/lib/core/storage.mjs +0 -176
- package/lib/core/store.mjs +0 -568
- package/lib/core/wire-quotes.mjs +0 -71
- package/lib/core/wire.mjs +0 -889
- package/lib/device/account.mjs +0 -87
- package/lib/device/admin/index.mjs +0 -13
- package/lib/device/admin/origins.mjs +0 -35
- package/lib/device/admin/routes/connections.mjs +0 -144
- package/lib/device/admin/routes/gateway.mjs +0 -199
- package/lib/device/admin/routes/lifecycle.mjs +0 -200
- package/lib/device/admin/routes/owner.mjs +0 -322
- package/lib/device/admin/routes/setup.mjs +0 -412
- package/lib/device/admin/routes/social.mjs +0 -188
- package/lib/device/admin/server.mjs +0 -95
- package/lib/device/admin/static.mjs +0 -247
- package/lib/device/admin/surface.mjs +0 -315
- package/lib/device/certs.mjs +0 -281
- package/lib/device/cli/commands/account.mjs +0 -586
- package/lib/device/cli/commands/run.mjs +0 -278
- package/lib/device/cli/commands/service.mjs +0 -221
- package/lib/device/cli/commands/setup.mjs +0 -447
- package/lib/device/cli/commands/state.mjs +0 -561
- package/lib/device/cli/context.mjs +0 -288
- package/lib/device/export-collections.mjs +0 -161
- package/lib/device/gateway-move.mjs +0 -58
- package/lib/device/home.mjs +0 -161
- package/lib/device/migrate.mjs +0 -115
- package/lib/device/ports.mjs +0 -27
- package/lib/device/remote.mjs +0 -54
- package/lib/device/setup.mjs +0 -459
- package/lib/device/update.mjs +0 -96
- package/lib/gateway/caches.mjs +0 -36
- package/lib/gateway/directory.mjs +0 -90
- package/lib/gateway/front-core.mjs +0 -970
- package/lib/gateway/gateway-core.mjs +0 -165
- package/lib/gateway/headers.mjs +0 -49
- package/lib/gateway/httpsig.mjs +0 -159
- package/lib/gateway/notices.mjs +0 -84
- package/lib/gateway/quiet.mjs +0 -189
- package/lib/pod/README.md +0 -61
- package/lib/pod/actor.mjs +0 -96
- package/lib/pod/collection.mjs +0 -77
- package/lib/pod/containers.mjs +0 -140
- package/lib/pod/discovery.mjs +0 -46
- package/lib/pod/featured.mjs +0 -18
- package/lib/pod/followers.mjs +0 -24
- package/lib/pod/following.mjs +0 -10
- package/lib/pod/http.mjs +0 -74
- package/lib/pod/inbox.mjs +0 -166
- package/lib/pod/links.mjs +0 -35
- package/lib/pod/media.mjs +0 -27
- package/lib/pod/notes.mjs +0 -80
- package/lib/pod/notifications.mjs +0 -89
- package/lib/pod/outbox.mjs +0 -18
- package/lib/pod/package.json +0 -19
- package/lib/pod/policy.mjs +0 -58
- package/lib/pod/private.mjs +0 -19
- package/lib/pod/root.mjs +0 -104
- package/lib/pod/state.mjs +0 -40
- package/lib/pod/transport.mjs +0 -525
- package/lib/pod/urls.mjs +0 -85
- package/lib/server/embed.mjs +0 -423
- package/lib/session/README.md +0 -137
- package/lib/session/demo.html +0 -94
- package/lib/session/fedi-account.mjs +0 -408
- package/lib/session/fedi-login.mjs +0 -123
- package/lib/session/oidc-session.mjs +0 -233
- package/lib/session/package.json +0 -49
- package/lib/shared/guard.mjs +0 -213
- package/lib/shared/links.mjs +0 -9
- package/lib/shared/safefetch.mjs +0 -235
- package/lib/shared/ua.mjs +0 -29
- package/phanpy/dist/404.html +0 -40
- package/phanpy/dist/_headers +0 -2
- package/phanpy/dist/apple-touch-icon.png +0 -0
- package/phanpy/dist/assets/ICONS-DIPJeU0C.js +0 -2
- package/phanpy/dist/assets/ICONS-DIPJeU0C.js.map +0 -1
- package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js +0 -183
- package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
- package/phanpy/dist/assets/Temml-CCjoacWt.woff2 +0 -0
- package/phanpy/dist/assets/__vite-browser-external-C7iut881.js +0 -2
- package/phanpy/dist/assets/__vite-browser-external-C7iut881.js.map +0 -1
- package/phanpy/dist/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
- package/phanpy/dist/assets/catch-up-O5q5C75Z.png +0 -0
- package/phanpy/dist/assets/chunk-aKtaBQYM.js +0 -1
- package/phanpy/dist/assets/compose-CFEx7wb4.js +0 -2
- package/phanpy/dist/assets/compose-CFEx7wb4.js.map +0 -1
- package/phanpy/dist/assets/compose-ZJN5xSb4.js +0 -35
- package/phanpy/dist/assets/compose-ZJN5xSb4.js.map +0 -1
- package/phanpy/dist/assets/debug.module-YFQgwnIr.js +0 -52
- package/phanpy/dist/assets/debug.module-YFQgwnIr.js.map +0 -1
- package/phanpy/dist/assets/dom-p1YcJ5Rw.js +0 -2
- package/phanpy/dist/assets/dom-p1YcJ5Rw.js.map +0 -1
- package/phanpy/dist/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
- package/phanpy/dist/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
- package/phanpy/dist/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
- package/phanpy/dist/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
- package/phanpy/dist/assets/icons/add-circle-line-WD0mwORD.js +0 -1
- package/phanpy/dist/assets/icons/alert-line-CpFUMf9s.js +0 -1
- package/phanpy/dist/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
- package/phanpy/dist/assets/icons/announcement-line-5nwaJFJm.js +0 -1
- package/phanpy/dist/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
- package/phanpy/dist/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
- package/phanpy/dist/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
- package/phanpy/dist/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
- package/phanpy/dist/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
- package/phanpy/dist/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
- package/phanpy/dist/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
- package/phanpy/dist/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
- package/phanpy/dist/assets/icons/at-line-CF66Bznk.js +0 -1
- package/phanpy/dist/assets/icons/attachment-line-BY8It-l9.js +0 -1
- package/phanpy/dist/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
- package/phanpy/dist/assets/icons/board-line-C0UWXyA6.js +0 -1
- package/phanpy/dist/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
- package/phanpy/dist/assets/icons/building-5-line-Dd59MzbO.js +0 -1
- package/phanpy/dist/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
- package/phanpy/dist/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
- package/phanpy/dist/assets/icons/calendar-month-line-vommts2C.js +0 -1
- package/phanpy/dist/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
- package/phanpy/dist/assets/icons/camera-line-Cv69MEei.js +0 -1
- package/phanpy/dist/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
- package/phanpy/dist/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
- package/phanpy/dist/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
- package/phanpy/dist/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
- package/phanpy/dist/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
- package/phanpy/dist/assets/icons/clipboard-line-BBp364gJ.js +0 -1
- package/phanpy/dist/assets/icons/close-circle-line-CICdiuGz.js +0 -1
- package/phanpy/dist/assets/icons/close-line-DYrFWcjv.js +0 -1
- package/phanpy/dist/assets/icons/cloud-line-tiQAbah8.js +0 -1
- package/phanpy/dist/assets/icons/code-line-fAl8iiV3.js +0 -1
- package/phanpy/dist/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
- package/phanpy/dist/assets/icons/copy-2-line-CLW69yF5.js +0 -1
- package/phanpy/dist/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
- package/phanpy/dist/assets/icons/document-3-line-DBGNhAg2.js +0 -1
- package/phanpy/dist/assets/icons/document-line-C7mb9sb7.js +0 -1
- package/phanpy/dist/assets/icons/down-line-BGqSSThd.js +0 -1
- package/phanpy/dist/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
- package/phanpy/dist/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
- package/phanpy/dist/assets/icons/exit-line-Dc07BS-x.js +0 -1
- package/phanpy/dist/assets/icons/external-link-line-BvpSkmjO.js +0 -1
- package/phanpy/dist/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
- package/phanpy/dist/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
- package/phanpy/dist/assets/icons/filter-2-line-B_mR2usy.js +0 -1
- package/phanpy/dist/assets/icons/filter-line-C_nm-3cU.js +0 -1
- package/phanpy/dist/assets/icons/flag-1-line-C2HB05I0.js +0 -1
- package/phanpy/dist/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
- package/phanpy/dist/assets/icons/formula-line-DLrt2d6j.js +0 -1
- package/phanpy/dist/assets/icons/grid-line-CgUmEikf.js +0 -1
- package/phanpy/dist/assets/icons/group-line-C5fnX0wU.js +0 -1
- package/phanpy/dist/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
- package/phanpy/dist/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
- package/phanpy/dist/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
- package/phanpy/dist/assets/icons/heart-line-CJ7K47J4.js +0 -1
- package/phanpy/dist/assets/icons/history-2-line-kWWvFzqv.js +0 -1
- package/phanpy/dist/assets/icons/history-line-bGQiwbTH.js +0 -1
- package/phanpy/dist/assets/icons/home-3-line-fRU1zeLG.js +0 -1
- package/phanpy/dist/assets/icons/information-line-iNk6-sOY.js +0 -1
- package/phanpy/dist/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
- package/phanpy/dist/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
- package/phanpy/dist/assets/icons/layout-5-line-B_znt5wO.js +0 -1
- package/phanpy/dist/assets/icons/left-line-eUw0tya4.js +0 -1
- package/phanpy/dist/assets/icons/lightning-line-DaKoDdix.js +0 -1
- package/phanpy/dist/assets/icons/link-2-line-DCqLmMA7.js +0 -1
- package/phanpy/dist/assets/icons/list-check-line-BAxosBh9.js +0 -1
- package/phanpy/dist/assets/icons/lock-line-CPoaXeUW.js +0 -1
- package/phanpy/dist/assets/icons/mail-line-B0P8aa1L.js +0 -1
- package/phanpy/dist/assets/icons/moon-line-CEqNAToP.js +0 -1
- package/phanpy/dist/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
- package/phanpy/dist/assets/icons/more-3-line-BIiVjYTz.js +0 -1
- package/phanpy/dist/assets/icons/notification-line-BZZq2Gtu.js +0 -1
- package/phanpy/dist/assets/icons/pencil-line-CKh8-A1v.js +0 -1
- package/phanpy/dist/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
- package/phanpy/dist/assets/icons/pin-line-DpTolyhs.js +0 -1
- package/phanpy/dist/assets/icons/play-fill-B0-G_8lX.js +0 -1
- package/phanpy/dist/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
- package/phanpy/dist/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
- package/phanpy/dist/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
- package/phanpy/dist/assets/icons/radar-line-CKyroTth.js +0 -1
- package/phanpy/dist/assets/icons/react-line-CoIKhhtK.js +0 -1
- package/phanpy/dist/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
- package/phanpy/dist/assets/icons/right-line-B3KWJaqc.js +0 -1
- package/phanpy/dist/assets/icons/rocket-line-4KZl537D.js +0 -1
- package/phanpy/dist/assets/icons/round-fill-C69NTrZ0.js +0 -1
- package/phanpy/dist/assets/icons/round-line-B9k_1uo-.js +0 -1
- package/phanpy/dist/assets/icons/route-line-B28ReHcE.js +0 -1
- package/phanpy/dist/assets/icons/rows-4-line-CrBniagM.js +0 -1
- package/phanpy/dist/assets/icons/scan-line-DSf74YdP.js +0 -1
- package/phanpy/dist/assets/icons/search-2-line-B6geIU1z.js +0 -1
- package/phanpy/dist/assets/icons/settings-3-line-azJwK47w.js +0 -1
- package/phanpy/dist/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
- package/phanpy/dist/assets/icons/share-2-line-D5MxWjrm.js +0 -1
- package/phanpy/dist/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
- package/phanpy/dist/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
- package/phanpy/dist/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
- package/phanpy/dist/assets/icons/time-line-BF3eet1v.js +0 -1
- package/phanpy/dist/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
- package/phanpy/dist/assets/icons/translate-line-BFWol2Ce.js +0 -1
- package/phanpy/dist/assets/icons/unlock-line-X_x5vwv3.js +0 -1
- package/phanpy/dist/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
- package/phanpy/dist/assets/icons/user-4-line-BVSynZCp.js +0 -1
- package/phanpy/dist/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
- package/phanpy/dist/assets/icons/user-add-line-BbXdHG4z.js +0 -1
- package/phanpy/dist/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
- package/phanpy/dist/assets/icons/user-follow-line-BXux0wSd.js +0 -1
- package/phanpy/dist/assets/icons/user-star-line-DdYlpHLU.js +0 -1
- package/phanpy/dist/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
- package/phanpy/dist/assets/icons/user-x-line-DIDgNlPH.js +0 -1
- package/phanpy/dist/assets/icons/volume-line-Bs390KQt.js +0 -1
- package/phanpy/dist/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
- package/phanpy/dist/assets/icons/walk-line-yNXfB-md.js +0 -1
- package/phanpy/dist/assets/icons/world-2-line-CenkGIwj.js +0 -1
- package/phanpy/dist/assets/icons/zoom-in-line-CaENUphf.js +0 -1
- package/phanpy/dist/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
- package/phanpy/dist/assets/instances-BNPptnn-.json +0 -333
- package/phanpy/dist/assets/locales/ar-SA-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/ca-ES-DHRW86Tz.js +0 -1
- package/phanpy/dist/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
- package/phanpy/dist/assets/locales/de-DE-ByRPMRFy.js +0 -1
- package/phanpy/dist/assets/locales/eo-UY-CPC7wLCS.js +0 -1
- package/phanpy/dist/assets/locales/es-ES-dJa0Fd9t.js +0 -1
- package/phanpy/dist/assets/locales/eu-ES-C3djlPR2.js +0 -1
- package/phanpy/dist/assets/locales/fa-IR-DTT490Ck.js +0 -1
- package/phanpy/dist/assets/locales/fi-FI-B23MCPuz.js +0 -1
- package/phanpy/dist/assets/locales/fr-FR-BcaQsO5C.js +0 -1
- package/phanpy/dist/assets/locales/gl-ES-BR-CVKBN.js +0 -1
- package/phanpy/dist/assets/locales/he-IL-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/hu-HU-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/it-IT-C1136UFV.js +0 -1
- package/phanpy/dist/assets/locales/ja-JP-CRZmRAhD.js +0 -1
- package/phanpy/dist/assets/locales/kab-Cz8xH_TT.js +0 -1
- package/phanpy/dist/assets/locales/ko-KR-CG9UiY4o.js +0 -1
- package/phanpy/dist/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
- package/phanpy/dist/assets/locales/nb-NO-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
- package/phanpy/dist/assets/locales/oc-FR-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/pl-PL-DkwGXf6P.js +0 -1
- package/phanpy/dist/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
- package/phanpy/dist/assets/locales/pt-BR-nGL0HdFS.js +0 -1
- package/phanpy/dist/assets/locales/pt-PT-Cp17aj2z.js +0 -1
- package/phanpy/dist/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
- package/phanpy/dist/assets/locales/th-TH-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/tok-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/tr-TR-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/locales/uk-UA-C5E3dFBf.js +0 -1
- package/phanpy/dist/assets/locales/zh-CN-BHJi7_et.js +0 -1
- package/phanpy/dist/assets/locales/zh-TW-CfheRbCu.js +0 -1
- package/phanpy/dist/assets/main-BdqNbG-a.js +0 -26
- package/phanpy/dist/assets/main-BdqNbG-a.js.map +0 -1
- package/phanpy/dist/assets/mock-home-DGhR__He.js +0 -2
- package/phanpy/dist/assets/mock-home-DGhR__He.js.map +0 -1
- package/phanpy/dist/assets/multi-column-ROck0NVt.jpg +0 -0
- package/phanpy/dist/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
- package/phanpy/dist/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
- package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js +0 -2
- package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js.map +0 -1
- package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js +0 -20
- package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js.map +0 -1
- package/phanpy/dist/assets/style-B1iLPTPR.css +0 -2
- package/phanpy/dist/assets/temml-DuyIQMei.js +0 -97
- package/phanpy/dist/assets/temml-DuyIQMei.js.map +0 -1
- package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js +0 -2
- package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
- package/phanpy/dist/assets/year-in-posts-B2lywqdx.png +0 -0
- package/phanpy/dist/assets/year-in-posts-DJv_star.js +0 -3
- package/phanpy/dist/assets/year-in-posts-DJv_star.js.map +0 -1
- package/phanpy/dist/compose/index.html +0 -20
- package/phanpy/dist/favicon.ico +0 -0
- package/phanpy/dist/index.html +0 -73
- package/phanpy/dist/logo-192.png +0 -0
- package/phanpy/dist/logo-512.png +0 -0
- package/phanpy/dist/logo-badge-72.png +0 -0
- package/phanpy/dist/logo-maskable-512.png +0 -0
- package/phanpy/dist/logo-monochrome-512.png +0 -0
- package/phanpy/dist/logo-monochrome-maskable-512.png +0 -0
- package/phanpy/dist/manifest.webmanifest +0 -1
- package/phanpy/dist/og-image-2.jpg +0 -0
- package/phanpy/dist/og-image.png +0 -0
- package/phanpy/dist/robots.txt +0 -2
- package/phanpy/dist/sw.js +0 -2
- package/phanpy/dist/sw.js.map +0 -1
- package/phanpy/dist/version.json +0 -1
- package/run-agent.mjs +0 -897
- package/vendor/gate.cjs +0 -138
- package/vendor/idp-grant.cjs +0 -394
- package/vendor/jfetch.cjs +0 -16
- package/web/admin/actors.js +0 -145
- package/web/admin/bar.css +0 -126
- package/web/admin/bar.js +0 -99
- package/web/admin/client/client.js +0 -66
- package/web/admin/client/index.html +0 -69
- package/web/admin/client-pick.js +0 -79
- package/web/admin/common.js +0 -23
- package/web/admin/connections.js +0 -112
- package/web/admin/gateway.js +0 -133
- package/web/admin/group.js +0 -258
- package/web/admin/index.html +0 -603
- package/web/admin/notices-bar.js +0 -90
- package/web/admin/oauth-signin.mjs +0 -37
- package/web/admin/record.js +0 -390
- package/web/admin/setup/index.html +0 -241
- package/web/admin/setup/setup.js +0 -326
- package/web/admin/tokens.css +0 -68
- package/web/admin/upkeep.js +0 -177
- package/web/admin/window.css +0 -55
- package/web/admin/window.js +0 -136
- package/web/app/README.md +0 -81
- package/web/app/admin-facade.mjs +0 -588
- package/web/app/agent.mjs +0 -663
- package/web/app/atproto-browser.mjs +0 -86
- package/web/app/authorize_interaction.html +0 -56
- package/web/app/authorize_interaction.js +0 -69
- package/web/app/boot.mjs +0 -576
- package/web/app/deliver-relay.mjs +0 -129
- package/web/app/dist/boot.js +0 -34218
- package/web/app/dist/boot.js.map +0 -7
- package/web/app/dist/sw.js +0 -72810
- package/web/app/dist/sw.js.map +0 -7
- package/web/app/fediacct-browser.mjs +0 -146
- package/web/app/gateway-move.mjs +0 -60
- package/web/app/idb-kv.mjs +0 -35
- package/web/app/index.html +0 -242
- package/web/app/keys-browser.mjs +0 -71
- package/web/app/keystore.mjs +0 -82
- package/web/app/oidc-session.mjs +0 -6
- package/web/app/pod-auth.mjs +0 -248
- package/web/app/pod-remote.mjs +0 -84
- package/web/app/shims/_globals.mjs +0 -2
- package/web/app/shims/fedify-sig.mjs +0 -77
- package/web/app/shims/node-crypto.mjs +0 -113
- package/web/app/shims/node-fs.mjs +0 -17
- package/web/app/shims/node-path.mjs +0 -19
- package/web/app/shims/node-url.mjs +0 -7
- package/web/app/shims/prelude.js +0 -58
- package/web/app/shims/safefetch.mjs +0 -58
- package/web/app/shims/shapes-text.mjs +0 -8
- package/web/app/shims/web-push.mjs +0 -14
- package/web/app/signup.mjs +0 -318
- package/web/app/sw-src.mjs +0 -220
- package/web/app/update.js +0 -70
- package/web/front/admin.html +0 -55
- package/web/front/admin.js +0 -89
- package/web/front/install.sh +0 -69
- package/web/front/new-account.html +0 -35
- package/web/front/new-account.js +0 -13
- package/web/front/notices.html +0 -69
- package/web/front/notices.js +0 -107
- package/web/front/run.html +0 -58
- package/web/front/run.js +0 -195
- package/web/front/solid-oidc-client.js +0 -6
- package/web/icons/forum.svg +0 -11
- package/web/icons/gateway.svg +0 -14
- package/web/icons/local.svg +0 -11
package/web/front/run.js
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
// run.js — the opt-in / opt-out page's script, in a file of its own.
|
|
2
|
-
//
|
|
3
|
-
// It lived inline in run.html until 2026-09-09. Out here the page can be served
|
|
4
|
-
// under `script-src 'self'`, which is what stops a stray bit of markup from
|
|
5
|
-
// becoming running code; inline script cannot be told apart from injected
|
|
6
|
-
// script by any policy. Served by the front beside the page it belongs to.
|
|
7
|
-
//
|
|
8
|
-
// A module, because it awaits an import of /solid-oidc-client.js at the top
|
|
9
|
-
// level — which is itself the proof this mechanism works: that file has been
|
|
10
|
-
// loaded from a route by this page all along.
|
|
11
|
-
const $ = (id) => document.getElementById(id);
|
|
12
|
-
|
|
13
|
-
// The Solid-OIDC client for the sign-in round trip. Constructed once; the
|
|
14
|
-
// redirect state (PKCE, csrf) lives in this tab's sessionStorage, so the same
|
|
15
|
-
// session finishes the login on the way back.
|
|
16
|
-
// This page's own address. The identity provider is told it and sends the
|
|
17
|
-
// reader back to it, so a hard-coded name would end the sign-in on a page that
|
|
18
|
-
// does not exist wherever the operator put this one.
|
|
19
|
-
const HERE = location.origin + location.pathname.replace(/\/$/u, '');
|
|
20
|
-
let session = null;
|
|
21
|
-
try {
|
|
22
|
-
const { SessionCore } = await import('/solid-oidc-client.js');
|
|
23
|
-
session = new SessionCore({ redirect_uris: [HERE], client_name: 'FediPod gateway' });
|
|
24
|
-
} catch { /* leave null — the "did not load" notes below fire */ }
|
|
25
|
-
|
|
26
|
-
// What this server knows before anything is typed. 501: it runs no
|
|
27
|
-
// identities. A pod server that issued the reader's session names their pod
|
|
28
|
-
// and its address, and the page shows one button per pod. Not signed in
|
|
29
|
-
// there: one button, to its login. A Gateway knows nothing: the form below.
|
|
30
|
-
let offered = true;
|
|
31
|
-
const say = (tag, text) => { const e = document.createElement(tag); e.textContent = text; return e; };
|
|
32
|
-
(async () => {
|
|
33
|
-
const res = await fetch('/api/agent', { credentials: 'same-origin', headers: { accept: 'application/json' } }).catch(() => null);
|
|
34
|
-
const d = res && res.ok ? await res.json().catch(() => ({})) : {};
|
|
35
|
-
const n = $('run-note');
|
|
36
|
-
if (!res || res.status === 501) {
|
|
37
|
-
offered = false;
|
|
38
|
-
n.hidden = false;
|
|
39
|
-
n.textContent = 'This server does not run identities. Your agent stays where it is.';
|
|
40
|
-
} else if (d.session === 'none') {
|
|
41
|
-
$('run-form').hidden = true;
|
|
42
|
-
showSignIn(d.loginUrl);
|
|
43
|
-
} else if (d.session === 'ok' && Array.isArray(d.pods) && d.pods.length) {
|
|
44
|
-
$('run-form').hidden = true;
|
|
45
|
-
showPods(d.pods);
|
|
46
|
-
}
|
|
47
|
-
runFormCheck();
|
|
48
|
-
})();
|
|
49
|
-
|
|
50
|
-
async function refreshKnown() {
|
|
51
|
-
const res = await fetch('/api/agent', { credentials: 'same-origin', headers: { accept: 'application/json' } }).catch(() => null);
|
|
52
|
-
const d = res && res.ok ? await res.json().catch(() => ({})) : {};
|
|
53
|
-
if (d.session === 'ok' && Array.isArray(d.pods) && d.pods.length) showPods(d.pods);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function showSignIn(loginUrl) {
|
|
57
|
-
const k = $('run-known');
|
|
58
|
-
k.hidden = false;
|
|
59
|
-
k.replaceChildren();
|
|
60
|
-
k.append(say('p', 'You are not signed in at this server.'));
|
|
61
|
-
if (loginUrl) {
|
|
62
|
-
const go = say('button', 'Sign in');
|
|
63
|
-
go.type = 'button'; go.className = 'primary';
|
|
64
|
-
go.onclick = () => { location.href = loginUrl; };
|
|
65
|
-
const p = document.createElement('p'); p.className = 'actions'; p.append(go);
|
|
66
|
-
k.append(p, say('p', 'Sign in, then come back to this page.'));
|
|
67
|
-
k.lastChild.className = 'hint';
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function showPods(pods) {
|
|
72
|
-
const k = $('run-known');
|
|
73
|
-
k.hidden = false;
|
|
74
|
-
k.replaceChildren();
|
|
75
|
-
for (const pod of pods) {
|
|
76
|
-
const box = document.createElement('div'); box.className = 'pod';
|
|
77
|
-
// The names stand out from the sentences around them.
|
|
78
|
-
const line = (before, id, after = '.') => { const p = say('p', before); p.append(say('code', id), after); return p; };
|
|
79
|
-
box.append(line('Solid Identity (WebID): ', pod.webId, ''));
|
|
80
|
-
const actions = document.createElement('p'); actions.className = 'actions';
|
|
81
|
-
box.append(line('Fediverse Identity: ', pod.address, ''));
|
|
82
|
-
if (pod.running) {
|
|
83
|
-
const links = say('p', 'Manage your account: ');
|
|
84
|
-
const m = say('a', pod.manage.split('?')[0]); m.href = pod.manage;
|
|
85
|
-
links.append(m);
|
|
86
|
-
box.append(links);
|
|
87
|
-
const stop = say('button', 'Close this Fediverse account'); stop.type = 'button'; stop.className = 'primary';
|
|
88
|
-
stop.onclick = () => runStart('opt-out', pod.podBase);
|
|
89
|
-
actions.append(stop);
|
|
90
|
-
} else {
|
|
91
|
-
const go = say('button', 'Create a Fediverse account'); go.type = 'button'; go.className = 'primary';
|
|
92
|
-
go.onclick = () => runStart('opt-in', pod.podBase);
|
|
93
|
-
actions.append(go);
|
|
94
|
-
}
|
|
95
|
-
box.append(actions);
|
|
96
|
-
k.append(box);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function runFormCheck() {
|
|
101
|
-
let ok = false;
|
|
102
|
-
try { ok = /^https?:$/.test(new URL($('run-pod-url').value.trim()).protocol); } catch { /* not yet */ }
|
|
103
|
-
const issuerOk = /^https?:\/\/\S+/.test($('run-issuer').value.trim());
|
|
104
|
-
$('run-continue').disabled = !(offered && ok && issuerOk);
|
|
105
|
-
$('run-leave').disabled = !(offered && ok && issuerOk);
|
|
106
|
-
}
|
|
107
|
-
$('run-pod-url').addEventListener('input', () => {
|
|
108
|
-
runFormCheck();
|
|
109
|
-
// The identity provider is usually the server itself — still editable.
|
|
110
|
-
try {
|
|
111
|
-
const u = new URL($('run-pod-url').value.trim());
|
|
112
|
-
const apex = u.hostname.split('.').slice(1).join('.');
|
|
113
|
-
if (!$('run-issuer').value && apex) $('run-issuer').value = `${u.protocol}//${apex}${u.port ? ':' + u.port : ''}`;
|
|
114
|
-
} catch { /* not a URL yet */ }
|
|
115
|
-
runFormCheck();
|
|
116
|
-
});
|
|
117
|
-
$('run-issuer').addEventListener('input', runFormCheck);
|
|
118
|
-
// A browser that puts back what was in these boxes — a reload, the back
|
|
119
|
-
// button, its own remembered values — fills them without anybody typing, and
|
|
120
|
-
// no typing meant the button was never asked to wake up. It stayed grey over
|
|
121
|
-
// a filled-in form, with nothing to say why.
|
|
122
|
-
runFormCheck();
|
|
123
|
-
|
|
124
|
-
const runStart = async (action, podBase = null) => {
|
|
125
|
-
const n = $('run-note');
|
|
126
|
-
const u = new URL(podBase || $('run-pod-url').value.trim());
|
|
127
|
-
if (u.pathname === '') u.pathname = '/';
|
|
128
|
-
if (!u.pathname.endsWith('/')) u.pathname += '/';
|
|
129
|
-
u.search = ''; u.hash = '';
|
|
130
|
-
const p = { podBase: u.href, action };
|
|
131
|
-
|
|
132
|
-
// A pod server issued the session this page is being read with, so ask it
|
|
133
|
-
// first: where it knows who you are, there is nothing to sign in to again.
|
|
134
|
-
// A Gateway fronting somebody else's pod answers 401 here and the login
|
|
135
|
-
// below is the only way.
|
|
136
|
-
n.hidden = false;
|
|
137
|
-
n.textContent = 'asking the server…';
|
|
138
|
-
const known = await fetch('/api/agent', {
|
|
139
|
-
method: 'POST', credentials: 'same-origin',
|
|
140
|
-
headers: { 'content-type': 'application/json' },
|
|
141
|
-
body: JSON.stringify(p),
|
|
142
|
-
}).catch(() => null);
|
|
143
|
-
if (known && known.status !== 401) { await showReply(known, p); return; }
|
|
144
|
-
|
|
145
|
-
if (!session) { n.textContent = 'the sign-in library did not load — reload and try again'; return; }
|
|
146
|
-
sessionStorage.setItem('fp-run', JSON.stringify(p));
|
|
147
|
-
session.login($('run-issuer').value.trim(), HERE)
|
|
148
|
-
.catch((e) => { n.textContent = 'sign-in failed to start: ' + e.message; });
|
|
149
|
-
};
|
|
150
|
-
$('run-continue').onclick = () => runStart('opt-in');
|
|
151
|
-
$('run-leave').onclick = () => runStart('opt-out');
|
|
152
|
-
|
|
153
|
-
// What came of it, however the server was satisfied — the session it already
|
|
154
|
-
// had, or a login proved afterwards.
|
|
155
|
-
async function showReply(res, p) {
|
|
156
|
-
const n = $('run-note');
|
|
157
|
-
n.hidden = false;
|
|
158
|
-
const d = res ? await res.json().catch(() => ({})) : {};
|
|
159
|
-
if (res && res.status === 201 && d.doorSecret) {
|
|
160
|
-
// Built as nodes, not as a string of HTML. Three of the pieces below come
|
|
161
|
-
// back from the server and one comes from sessionStorage, and pasting any
|
|
162
|
-
// of them into innerHTML means whatever markup they contain is rendered.
|
|
163
|
-
// Only the fixed wording is markup here; everything variable is text.
|
|
164
|
-
const manage = `${p.podBase.replace(/\/$/, '')}${d.doorPath}?dk-token=${encodeURIComponent(d.doorSecret)}`;
|
|
165
|
-
n.textContent = 'Your Fediverse account is ready. Manage it at ';
|
|
166
|
-
const a = say('a', p.podBase.replace(/\/$/, '') + d.doorPath); a.href = manage;
|
|
167
|
-
n.append(a, '.');
|
|
168
|
-
refreshKnown();
|
|
169
|
-
} else if (res && res.status === 200) {
|
|
170
|
-
n.textContent = 'Your Fediverse account is closed. Your pod and its data are untouched.';
|
|
171
|
-
refreshKnown();
|
|
172
|
-
} else {
|
|
173
|
-
n.textContent = (p.action === 'opt-in' ? 'opt-in' : 'opt-out') + ' failed: '
|
|
174
|
-
+ (d.error || (res ? 'HTTP ' + res.status : 'no response'));
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Back from the identity provider: finish with the proven login.
|
|
179
|
-
(async () => {
|
|
180
|
-
if (!session) return;
|
|
181
|
-
await session.handleRedirectFromLogin().catch(() => {});
|
|
182
|
-
const pending = sessionStorage.getItem('fp-run');
|
|
183
|
-
if (!session.isActive || !pending) return;
|
|
184
|
-
sessionStorage.removeItem('fp-run');
|
|
185
|
-
const p = JSON.parse(pending);
|
|
186
|
-
const n = $('run-note');
|
|
187
|
-
n.hidden = false;
|
|
188
|
-
n.textContent = 'signed in as ' + session.webId + ' — asking the server…';
|
|
189
|
-
// The signed fetch builds a DPoP proof from the URL, so it must be absolute.
|
|
190
|
-
const res = await session.authFetch(location.origin + '/api/agent', {
|
|
191
|
-
method: 'POST', headers: { 'content-type': 'application/json' },
|
|
192
|
-
body: JSON.stringify({ action: p.action, podBase: p.podBase }),
|
|
193
|
-
}).catch(() => null);
|
|
194
|
-
await showReply(res, p);
|
|
195
|
-
})();
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// @uvdsl/solid-oidc-client-browser@0.2.3 — vendored worker-free Solid-OIDC client (core build).
|
|
2
|
-
// tarball sha512-WzVlxv46EUSoqm7ovsWJRZq8KEI/CdpA9O1fXoiP8bihs2cNxPnet3YcqvIYWYMsTrf0zsR031l5s/BzQ9MEgA==
|
|
3
|
-
// license MIT — https://github.com/uvdsl/solid-oidc-client-browser
|
|
4
|
-
// Regenerate with: node scripts/pin-solid-oidc.mjs
|
|
5
|
-
var e=crypto;const t=e=>e instanceof CryptoKey;var r=async(t,r)=>{const a=`SHA-${t.slice(-3)}`;return new Uint8Array(await e.subtle.digest(a,r))};const a=new TextEncoder,n=new TextDecoder;function s(...e){const t=e.reduce(((e,{length:t})=>e+t),0),r=new Uint8Array(t);let a=0;for(const t of e)r.set(t,a),a+=t.length;return r}const i=e=>(e=>{let t=e;"string"==typeof t&&(t=a.encode(t));const r=[];for(let e=0;e<t.length;e+=32768)r.push(String.fromCharCode.apply(null,t.subarray(e,e+32768)));return btoa(r.join(""))})(e).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_"),o=e=>{let t=e;t instanceof Uint8Array&&(t=n.decode(t)),t=t.replace(/-/g,"+").replace(/_/g,"/").replace(/\s/g,"");try{return(e=>{const t=atob(e),r=new Uint8Array(t.length);for(let e=0;e<t.length;e++)r[e]=t.charCodeAt(e);return r})(t)}catch{throw new TypeError("The input to be decoded is not correctly encoded.")}};class c extends Error{constructor(e,t){super(e,t),this.code="ERR_JOSE_GENERIC",this.name=this.constructor.name,Error.captureStackTrace?.(this,this.constructor)}}c.code="ERR_JOSE_GENERIC";class d extends c{constructor(e,t,r="unspecified",a="unspecified"){super(e,{cause:{claim:r,reason:a,payload:t}}),this.code="ERR_JWT_CLAIM_VALIDATION_FAILED",this.claim=r,this.reason=a,this.payload=t}}d.code="ERR_JWT_CLAIM_VALIDATION_FAILED";class h extends c{constructor(e,t,r="unspecified",a="unspecified"){super(e,{cause:{claim:r,reason:a,payload:t}}),this.code="ERR_JWT_EXPIRED",this.claim=r,this.reason=a,this.payload=t}}h.code="ERR_JWT_EXPIRED";class l extends c{constructor(){super(...arguments),this.code="ERR_JOSE_ALG_NOT_ALLOWED"}}l.code="ERR_JOSE_ALG_NOT_ALLOWED";class p extends c{constructor(){super(...arguments),this.code="ERR_JOSE_NOT_SUPPORTED"}}p.code="ERR_JOSE_NOT_SUPPORTED";(class extends c{constructor(e="decryption operation failed",t){super(e,t),this.code="ERR_JWE_DECRYPTION_FAILED"}}).code="ERR_JWE_DECRYPTION_FAILED";(class extends c{constructor(){super(...arguments),this.code="ERR_JWE_INVALID"}}).code="ERR_JWE_INVALID";class u extends c{constructor(){super(...arguments),this.code="ERR_JWS_INVALID"}}u.code="ERR_JWS_INVALID";class f extends c{constructor(){super(...arguments),this.code="ERR_JWT_INVALID"}}f.code="ERR_JWT_INVALID";class w extends c{constructor(){super(...arguments),this.code="ERR_JWK_INVALID"}}w.code="ERR_JWK_INVALID";class y extends c{constructor(){super(...arguments),this.code="ERR_JWKS_INVALID"}}y.code="ERR_JWKS_INVALID";class m extends c{constructor(e="no applicable key found in the JSON Web Key Set",t){super(e,t),this.code="ERR_JWKS_NO_MATCHING_KEY"}}m.code="ERR_JWKS_NO_MATCHING_KEY";class g extends c{constructor(e="multiple matching keys found in the JSON Web Key Set",t){super(e,t),this.code="ERR_JWKS_MULTIPLE_MATCHING_KEYS"}}g.code="ERR_JWKS_MULTIPLE_MATCHING_KEYS";class _ extends c{constructor(e="request timed out",t){super(e,t),this.code="ERR_JWKS_TIMEOUT"}}_.code="ERR_JWKS_TIMEOUT";class S extends c{constructor(e="signature verification failed",t){super(e,t),this.code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED"}}function E(e,t="algorithm.name"){return new TypeError(`CryptoKey does not support this operation, its ${t} must be ${e}`)}function b(e,t){return e.name===t}function k(e){return parseInt(e.name.slice(4),10)}function v(e,t,...r){switch(t){case"HS256":case"HS384":case"HS512":{if(!b(e.algorithm,"HMAC"))throw E("HMAC");const r=parseInt(t.slice(2),10);if(k(e.algorithm.hash)!==r)throw E(`SHA-${r}`,"algorithm.hash");break}case"RS256":case"RS384":case"RS512":{if(!b(e.algorithm,"RSASSA-PKCS1-v1_5"))throw E("RSASSA-PKCS1-v1_5");const r=parseInt(t.slice(2),10);if(k(e.algorithm.hash)!==r)throw E(`SHA-${r}`,"algorithm.hash");break}case"PS256":case"PS384":case"PS512":{if(!b(e.algorithm,"RSA-PSS"))throw E("RSA-PSS");const r=parseInt(t.slice(2),10);if(k(e.algorithm.hash)!==r)throw E(`SHA-${r}`,"algorithm.hash");break}case"EdDSA":if("Ed25519"!==e.algorithm.name&&"Ed448"!==e.algorithm.name)throw E("Ed25519 or Ed448");break;case"Ed25519":if(!b(e.algorithm,"Ed25519"))throw E("Ed25519");break;case"ES256":case"ES384":case"ES512":{if(!b(e.algorithm,"ECDSA"))throw E("ECDSA");const r=function(e){switch(e){case"ES256":return"P-256";case"ES384":return"P-384";case"ES512":return"P-521";default:throw new Error("unreachable")}}(t);if(e.algorithm.namedCurve!==r)throw E(r,"algorithm.namedCurve");break}default:throw new TypeError("CryptoKey does not support this operation")}!function(e,t){if(t.length&&!t.some((t=>e.usages.includes(t)))){let e="CryptoKey does not support this operation, its usages must include ";if(t.length>2){const r=t.pop();e+=`one of ${t.join(", ")}, or ${r}.`}else 2===t.length?e+=`one of ${t[0]} or ${t[1]}.`:e+=`${t[0]}.`;throw new TypeError(e)}}(e,r)}function A(e,t,...r){if((r=r.filter(Boolean)).length>2){const t=r.pop();e+=`one of type ${r.join(", ")}, or ${t}.`}else 2===r.length?e+=`one of type ${r[0]} or ${r[1]}.`:e+=`of type ${r[0]}.`;return null==t?e+=` Received ${t}`:"function"==typeof t&&t.name?e+=` Received function ${t.name}`:"object"==typeof t&&null!=t&&t.constructor?.name&&(e+=` Received an instance of ${t.constructor.name}`),e}S.code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED";var T=(e,...t)=>A("Key must be ",e,...t);function P(e,t,...r){return A(`Key for the ${e} algorithm must be `,t,...r)}var R=e=>!!t(e)||"KeyObject"===e?.[Symbol.toStringTag];const I=["CryptoKey"];var C=(...e)=>{const t=e.filter(Boolean);if(0===t.length||1===t.length)return!0;let r;for(const e of t){const t=Object.keys(e);if(r&&0!==r.size)for(const e of t){if(r.has(e))return!1;r.add(e)}else r=new Set(t)}return!0};function D(e){if("object"!=typeof(t=e)||null===t||"[object Object]"!==Object.prototype.toString.call(e))return!1;var t;if(null===Object.getPrototypeOf(e))return!0;let r=e;for(;null!==Object.getPrototypeOf(r);)r=Object.getPrototypeOf(r);return Object.getPrototypeOf(e)===r}var W=(e,t)=>{if(e.startsWith("RS")||e.startsWith("PS")){const{modulusLength:r}=t.algorithm;if("number"!=typeof r||r<2048)throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`)}};function H(e){return D(e)&&"string"==typeof e.kty}var J=async t=>{if(!t.alg)throw new TypeError('"alg" argument is required when "jwk.alg" is not present');const{algorithm:r,keyUsages:a}=function(e){let t,r;switch(e.kty){case"RSA":switch(e.alg){case"PS256":case"PS384":case"PS512":t={name:"RSA-PSS",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RS256":case"RS384":case"RS512":t={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":t={name:"RSA-OAEP",hash:`SHA-${parseInt(e.alg.slice(-3),10)||1}`},r=e.d?["decrypt","unwrapKey"]:["encrypt","wrapKey"];break;default:throw new p('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break;case"EC":switch(e.alg){case"ES256":t={name:"ECDSA",namedCurve:"P-256"},r=e.d?["sign"]:["verify"];break;case"ES384":t={name:"ECDSA",namedCurve:"P-384"},r=e.d?["sign"]:["verify"];break;case"ES512":t={name:"ECDSA",namedCurve:"P-521"},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:"ECDH",namedCurve:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new p('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break;case"OKP":switch(e.alg){case"Ed25519":t={name:"Ed25519"},r=e.d?["sign"]:["verify"];break;case"EdDSA":t={name:e.crv},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new p('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break;default:throw new p('Invalid or unsupported JWK "kty" (Key Type) Parameter value')}return{algorithm:t,keyUsages:r}}(t),n=[r,t.ext??!1,t.key_ops??a],s={...t};return delete s.alg,delete s.use,e.subtle.importKey("jwk",s,...n)};const x=e=>o(e);let K,O;const j=e=>"KeyObject"===e?.[Symbol.toStringTag],N=async(e,t,r,a,n=!1)=>{let s=e.get(t);if(s?.[a])return s[a];const i=await J({...r,alg:a});return n&&Object.freeze(t),s?s[a]=i:e.set(t,{[a]:i}),i};var U=(e,t)=>{if(j(e)){let r=e.export({format:"jwk"});return delete r.d,delete r.dp,delete r.dq,delete r.p,delete r.q,delete r.qi,r.k?x(r.k):(O||(O=new WeakMap),N(O,e,r,t))}if(H(e)){if(e.k)return o(e.k);O||(O=new WeakMap);return N(O,e,e,t,!0)}return e},$=(e,t)=>{if(j(e)){let r=e.export({format:"jwk"});return r.k?x(r.k):(K||(K=new WeakMap),N(K,e,r,t))}if(H(e)){if(e.k)return o(e.k);K||(K=new WeakMap);return N(K,e,e,t,!0)}return e};async function L(e,t){if(!D(e))throw new TypeError("JWK must be an object");switch(t||(t=e.alg),e.kty){case"oct":if("string"!=typeof e.k||!e.k)throw new TypeError('missing "k" (Key Value) Parameter value');return o(e.k);case"RSA":if("oth"in e&&void 0!==e.oth)throw new p('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');case"EC":case"OKP":return J({...e,alg:t});default:throw new p('Unsupported "kty" (Key Type) Parameter value')}}const M=e=>e?.[Symbol.toStringTag],F=(e,t,r)=>{if(void 0!==t.use&&"sig"!==t.use)throw new TypeError("Invalid key for this operation, when present its use must be sig");if(void 0!==t.key_ops&&!0!==t.key_ops.includes?.(r))throw new TypeError(`Invalid key for this operation, when present its key_ops must include ${r}`);if(void 0!==t.alg&&t.alg!==e)throw new TypeError(`Invalid key for this operation, when present its alg must be ${e}`);return!0},G=(e,t,r,a)=>{if(!(t instanceof Uint8Array)){if(a&&H(t)){if(function(e){return H(e)&&"oct"===e.kty&&"string"==typeof e.k}(t)&&F(e,t,r))return;throw new TypeError('JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present')}if(!R(t))throw new TypeError(P(e,t,...I,"Uint8Array",a?"JSON Web Key":null));if("secret"!==t.type)throw new TypeError(`${M(t)} instances for symmetric algorithms must be of type "secret"`)}};function V(e,t,r,a){t.startsWith("HS")||"dir"===t||t.startsWith("PBES2")||/^A\d{3}(?:GCM)?KW$/.test(t)?G(t,r,a,e):((e,t,r,a)=>{if(a&&H(t))switch(r){case"sign":if(function(e){return"oct"!==e.kty&&"string"==typeof e.d}(t)&&F(e,t,r))return;throw new TypeError("JSON Web Key for this operation be a private JWK");case"verify":if(function(e){return"oct"!==e.kty&&void 0===e.d}(t)&&F(e,t,r))return;throw new TypeError("JSON Web Key for this operation be a public JWK")}if(!R(t))throw new TypeError(P(e,t,...I,a?"JSON Web Key":null));if("secret"===t.type)throw new TypeError(`${M(t)} instances for asymmetric algorithms must not be of type "secret"`);if("sign"===r&&"public"===t.type)throw new TypeError(`${M(t)} instances for asymmetric algorithm signing must be of type "private"`);if("decrypt"===r&&"public"===t.type)throw new TypeError(`${M(t)} instances for asymmetric algorithm decryption must be of type "private"`);if(t.algorithm&&"verify"===r&&"private"===t.type)throw new TypeError(`${M(t)} instances for asymmetric algorithm verifying must be of type "public"`);if(t.algorithm&&"encrypt"===r&&"private"===t.type)throw new TypeError(`${M(t)} instances for asymmetric algorithm encryption must be of type "public"`)})(t,r,a,e)}V.bind(void 0,!1);const q=V.bind(void 0,!0);function X(e,t,r,a,n){if(void 0!==n.crit&&void 0===a?.crit)throw new e('"crit" (Critical) Header Parameter MUST be integrity protected');if(!a||void 0===a.crit)return new Set;if(!Array.isArray(a.crit)||0===a.crit.length||a.crit.some((e=>"string"!=typeof e||0===e.length)))throw new e('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');let s;s=void 0!==r?new Map([...Object.entries(r),...t.entries()]):t;for(const t of a.crit){if(!s.has(t))throw new p(`Extension Header Parameter "${t}" is not recognized`);if(void 0===n[t])throw new e(`Extension Header Parameter "${t}" is missing`);if(s.get(t)&&void 0===a[t])throw new e(`Extension Header Parameter "${t}" MUST be integrity protected`)}return new Set(a.crit)}var z=(e,t)=>{if(void 0!==t&&(!Array.isArray(t)||t.some((e=>"string"!=typeof e))))throw new TypeError(`"${e}" option must be an array of strings`);if(t)return new Set(t)};var B=async r=>{if(r instanceof Uint8Array)return{kty:"oct",k:i(r)};if(!t(r))throw new TypeError(T(r,...I,"Uint8Array"));if(!r.extractable)throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK");const{ext:a,key_ops:n,alg:s,use:o,...c}=await e.subtle.exportKey("jwk",r);return c};async function Y(e){return B(e)}function Q(e,t){const r=`SHA-${e.slice(-3)}`;switch(e){case"HS256":case"HS384":case"HS512":return{hash:r,name:"HMAC"};case"PS256":case"PS384":case"PS512":return{hash:r,name:"RSA-PSS",saltLength:e.slice(-3)>>3};case"RS256":case"RS384":case"RS512":return{hash:r,name:"RSASSA-PKCS1-v1_5"};case"ES256":case"ES384":case"ES512":return{hash:r,name:"ECDSA",namedCurve:t.namedCurve};case"Ed25519":return{name:"Ed25519"};case"EdDSA":return{name:t.name};default:throw new p(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}async function Z(r,a,n){if("sign"===n&&(a=await $(a,r)),"verify"===n&&(a=await U(a,r)),t(a))return v(a,r,n),a;if(a instanceof Uint8Array){if(!r.startsWith("HS"))throw new TypeError(T(a,...I));return e.subtle.importKey("raw",a,{hash:`SHA-${r.slice(-3)}`,name:"HMAC"},!1,[n])}throw new TypeError(T(a,...I,"Uint8Array","JSON Web Key"))}var ee=async(t,r,a,n)=>{const s=await Z(t,r,"verify");W(t,s);const i=Q(t,s.algorithm);try{return await e.subtle.verify(i,s,a,n)}catch{return!1}};async function te(e,t,r){if(e instanceof Uint8Array&&(e=n.decode(e)),"string"!=typeof e)throw new u("Compact JWS must be a string or Uint8Array");const{0:i,1:c,2:d,length:h}=e.split(".");if(3!==h)throw new u("Invalid Compact JWS");const p=await async function(e,t,r){if(!D(e))throw new u("Flattened JWS must be an object");if(void 0===e.protected&&void 0===e.header)throw new u('Flattened JWS must have either of the "protected" or "header" members');if(void 0!==e.protected&&"string"!=typeof e.protected)throw new u("JWS Protected Header incorrect type");if(void 0===e.payload)throw new u("JWS Payload missing");if("string"!=typeof e.signature)throw new u("JWS Signature missing or incorrect type");if(void 0!==e.header&&!D(e.header))throw new u("JWS Unprotected Header incorrect type");let i={};if(e.protected)try{const t=o(e.protected);i=JSON.parse(n.decode(t))}catch{throw new u("JWS Protected Header is invalid")}if(!C(i,e.header))throw new u("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");const c={...i,...e.header};let d=!0;if(X(u,new Map([["b64",!0]]),r?.crit,i,c).has("b64")&&(d=i.b64,"boolean"!=typeof d))throw new u('The "b64" (base64url-encode payload) Header Parameter must be a boolean');const{alg:h}=c;if("string"!=typeof h||!h)throw new u('JWS "alg" (Algorithm) Header Parameter missing or invalid');const p=r&&z("algorithms",r.algorithms);if(p&&!p.has(h))throw new l('"alg" (Algorithm) Header Parameter value not allowed');if(d){if("string"!=typeof e.payload)throw new u("JWS Payload must be a string")}else if("string"!=typeof e.payload&&!(e.payload instanceof Uint8Array))throw new u("JWS Payload must be a string or an Uint8Array instance");let f=!1;"function"==typeof t?(t=await t(i,e),f=!0,q(h,t,"verify"),H(t)&&(t=await L(t,h))):q(h,t,"verify");const w=s(a.encode(e.protected??""),a.encode("."),"string"==typeof e.payload?a.encode(e.payload):e.payload);let y,m;try{y=o(e.signature)}catch{throw new u("Failed to base64url decode the signature")}if(!await ee(h,t,y,w))throw new S;if(d)try{m=o(e.payload)}catch{throw new u("Failed to base64url decode the payload")}else m="string"==typeof e.payload?a.encode(e.payload):e.payload;const g={payload:m};return void 0!==e.protected&&(g.protectedHeader=i),void 0!==e.header&&(g.unprotectedHeader=e.header),f?{...g,key:t}:g}({payload:c,protected:i,signature:d},t,r),f={payload:p.payload,protectedHeader:p.protectedHeader};return"function"==typeof t?{...f,key:p.key}:f}var re=e=>Math.floor(e.getTime()/1e3);const ae=86400,ne=/^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;var se=e=>{const t=ne.exec(e);if(!t||t[4]&&t[1])throw new TypeError("Invalid time period format");const r=parseFloat(t[2]);let a;switch(t[3].toLowerCase()){case"sec":case"secs":case"second":case"seconds":case"s":a=Math.round(r);break;case"minute":case"minutes":case"min":case"mins":case"m":a=Math.round(60*r);break;case"hour":case"hours":case"hr":case"hrs":case"h":a=Math.round(3600*r);break;case"day":case"days":case"d":a=Math.round(r*ae);break;case"week":case"weeks":case"w":a=Math.round(604800*r);break;default:a=Math.round(31557600*r)}return"-"===t[1]||"ago"===t[4]?-a:a};const ie=e=>e.toLowerCase().replace(/^application\//,"");var oe=(e,t,r={})=>{let a;try{a=JSON.parse(n.decode(t))}catch{}if(!D(a))throw new f("JWT Claims Set must be a top-level JSON object");const{typ:s}=r;if(s&&("string"!=typeof e.typ||ie(e.typ)!==ie(s)))throw new d('unexpected "typ" JWT header value',a,"typ","check_failed");const{requiredClaims:i=[],issuer:o,subject:c,audience:l,maxTokenAge:p}=r,u=[...i];void 0!==p&&u.push("iat"),void 0!==l&&u.push("aud"),void 0!==c&&u.push("sub"),void 0!==o&&u.push("iss");for(const e of new Set(u.reverse()))if(!(e in a))throw new d(`missing required "${e}" claim`,a,e,"missing");if(o&&!(Array.isArray(o)?o:[o]).includes(a.iss))throw new d('unexpected "iss" claim value',a,"iss","check_failed");if(c&&a.sub!==c)throw new d('unexpected "sub" claim value',a,"sub","check_failed");if(l&&(w=a.aud,y="string"==typeof l?[l]:l,!("string"==typeof w?y.includes(w):Array.isArray(w)&&y.some(Set.prototype.has.bind(new Set(w))))))throw new d('unexpected "aud" claim value',a,"aud","check_failed");var w,y;let m;switch(typeof r.clockTolerance){case"string":m=se(r.clockTolerance);break;case"number":m=r.clockTolerance;break;case"undefined":m=0;break;default:throw new TypeError("Invalid clockTolerance option type")}const{currentDate:g}=r,_=re(g||new Date);if((void 0!==a.iat||p)&&"number"!=typeof a.iat)throw new d('"iat" claim must be a number',a,"iat","invalid");if(void 0!==a.nbf){if("number"!=typeof a.nbf)throw new d('"nbf" claim must be a number',a,"nbf","invalid");if(a.nbf>_+m)throw new d('"nbf" claim timestamp check failed',a,"nbf","check_failed")}if(void 0!==a.exp){if("number"!=typeof a.exp)throw new d('"exp" claim must be a number',a,"exp","invalid");if(a.exp<=_-m)throw new h('"exp" claim timestamp check failed',a,"exp","check_failed")}if(p){const e=_-a.iat;if(e-m>("number"==typeof p?p:se(p)))throw new h('"iat" claim timestamp check failed (too far in the past)',a,"iat","check_failed");if(e<0-m)throw new d('"iat" claim timestamp check failed (it should be in the past)',a,"iat","check_failed")}return a};async function ce(e,t,r){const a=await te(e,t,r);if(a.protectedHeader.crit?.includes("b64")&&!1===a.protectedHeader.b64)throw new f("JWTs MUST NOT use unencoded payload");const n={payload:oe(a.protectedHeader,a.payload,r),protectedHeader:a.protectedHeader};return"function"==typeof t?{...n,key:a.key}:n}var de=async(t,r,a)=>{const n=await Z(t,r,"sign");W(t,n);const s=await e.subtle.sign(Q(t,n.algorithm),n,a);return new Uint8Array(s)};class he{constructor(e){if(!(e instanceof Uint8Array))throw new TypeError("payload must be an instance of Uint8Array");this._payload=e}setProtectedHeader(e){if(this._protectedHeader)throw new TypeError("setProtectedHeader can only be called once");return this._protectedHeader=e,this}setUnprotectedHeader(e){if(this._unprotectedHeader)throw new TypeError("setUnprotectedHeader can only be called once");return this._unprotectedHeader=e,this}async sign(e,t){if(!this._protectedHeader&&!this._unprotectedHeader)throw new u("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");if(!C(this._protectedHeader,this._unprotectedHeader))throw new u("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");const r={...this._protectedHeader,...this._unprotectedHeader};let o=!0;if(X(u,new Map([["b64",!0]]),t?.crit,this._protectedHeader,r).has("b64")&&(o=this._protectedHeader.b64,"boolean"!=typeof o))throw new u('The "b64" (base64url-encode payload) Header Parameter must be a boolean');const{alg:c}=r;if("string"!=typeof c||!c)throw new u('JWS "alg" (Algorithm) Header Parameter missing or invalid');q(c,e,"sign");let d,h=this._payload;o&&(h=a.encode(i(h))),d=this._protectedHeader?a.encode(i(JSON.stringify(this._protectedHeader))):a.encode("");const l=s(d,a.encode("."),h),p=await de(c,e,l),f={signature:i(p),payload:""};return o&&(f.payload=n.decode(h)),this._unprotectedHeader&&(f.header=this._unprotectedHeader),this._protectedHeader&&(f.protected=n.decode(d)),f}}class le{constructor(e){this._flattened=new he(e)}setProtectedHeader(e){return this._flattened.setProtectedHeader(e),this}async sign(e,t){const r=await this._flattened.sign(e,t);if(void 0===r.payload)throw new TypeError("use the flattened module for creating JWS with b64: false");return`${r.protected}.${r.payload}.${r.signature}`}}function pe(e,t){if(!Number.isFinite(t))throw new TypeError(`Invalid ${e} input`);return t}class ue{constructor(e={}){if(!D(e))throw new TypeError("JWT Claims Set MUST be an object");this._payload=e}setIssuer(e){return this._payload={...this._payload,iss:e},this}setSubject(e){return this._payload={...this._payload,sub:e},this}setAudience(e){return this._payload={...this._payload,aud:e},this}setJti(e){return this._payload={...this._payload,jti:e},this}setNotBefore(e){return"number"==typeof e?this._payload={...this._payload,nbf:pe("setNotBefore",e)}:e instanceof Date?this._payload={...this._payload,nbf:pe("setNotBefore",re(e))}:this._payload={...this._payload,nbf:re(new Date)+se(e)},this}setExpirationTime(e){return"number"==typeof e?this._payload={...this._payload,exp:pe("setExpirationTime",e)}:e instanceof Date?this._payload={...this._payload,exp:pe("setExpirationTime",re(e))}:this._payload={...this._payload,exp:re(new Date)+se(e)},this}setIssuedAt(e){return void 0===e?this._payload={...this._payload,iat:re(new Date)}:e instanceof Date?this._payload={...this._payload,iat:pe("setIssuedAt",re(e))}:this._payload="string"==typeof e?{...this._payload,iat:pe("setIssuedAt",re(new Date)+se(e))}:{...this._payload,iat:pe("setIssuedAt",e)},this}}class fe extends ue{setProtectedHeader(e){return this._protectedHeader=e,this}async sign(e,t){const r=new le(a.encode(JSON.stringify(this._payload)));if(r.setProtectedHeader(this._protectedHeader),Array.isArray(this._protectedHeader?.crit)&&this._protectedHeader.crit.includes("b64")&&!1===this._protectedHeader.b64)throw new f("JWTs MUST NOT use unencoded payload");return r.sign(e,t)}}const we=(e,t)=>{if("string"!=typeof e||!e)throw new w(`${t} missing or invalid`)};async function ye(e,t){if(!D(e))throw new TypeError("JWK must be an object");if(t??(t="sha256"),"sha256"!==t&&"sha384"!==t&&"sha512"!==t)throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"');let n;switch(e.kty){case"EC":we(e.crv,'"crv" (Curve) Parameter'),we(e.x,'"x" (X Coordinate) Parameter'),we(e.y,'"y" (Y Coordinate) Parameter'),n={crv:e.crv,kty:e.kty,x:e.x,y:e.y};break;case"OKP":we(e.crv,'"crv" (Subtype of Key Pair) Parameter'),we(e.x,'"x" (Public Key) Parameter'),n={crv:e.crv,kty:e.kty,x:e.x};break;case"RSA":we(e.e,'"e" (Exponent) Parameter'),we(e.n,'"n" (Modulus) Parameter'),n={e:e.e,kty:e.kty,n:e.n};break;case"oct":we(e.k,'"k" (Key Value) Parameter'),n={k:e.k,kty:e.kty};break;default:throw new p('"kty" (Key Type) Parameter missing or unsupported')}const s=a.encode(JSON.stringify(n));return i(await r(t,s))}function me(e){return D(e)}function ge(e){return"function"==typeof structuredClone?structuredClone(e):JSON.parse(JSON.stringify(e))}class _e{constructor(e){if(this._cached=new WeakMap,!function(e){return e&&"object"==typeof e&&Array.isArray(e.keys)&&e.keys.every(me)}(e))throw new y("JSON Web Key Set malformed");this._jwks=ge(e)}async getKey(e,t){const{alg:r,kid:a}={...e,...t?.header},n=function(e){switch("string"==typeof e&&e.slice(0,2)){case"RS":case"PS":return"RSA";case"ES":return"EC";case"Ed":return"OKP";default:throw new p('Unsupported "alg" value for a JSON Web Key Set')}}(r),s=this._jwks.keys.filter((e=>{let t=n===e.kty;if(t&&"string"==typeof a&&(t=a===e.kid),t&&"string"==typeof e.alg&&(t=r===e.alg),t&&"string"==typeof e.use&&(t="sig"===e.use),t&&Array.isArray(e.key_ops)&&(t=e.key_ops.includes("verify")),t)switch(r){case"ES256":t="P-256"===e.crv;break;case"ES256K":t="secp256k1"===e.crv;break;case"ES384":t="P-384"===e.crv;break;case"ES512":t="P-521"===e.crv;break;case"Ed25519":t="Ed25519"===e.crv;break;case"EdDSA":t="Ed25519"===e.crv||"Ed448"===e.crv}return t})),{0:i,length:o}=s;if(0===o)throw new m;if(1!==o){const e=new g,{_cached:t}=this;throw e[Symbol.asyncIterator]=async function*(){for(const e of s)try{yield await Se(t,e,r)}catch{}},e}return Se(this._cached,i,r)}}async function Se(e,t,r){const a=e.get(t)||e.set(t,{}).get(t);if(void 0===a[r]){const e=await L({...t,ext:!0},r);if(e instanceof Uint8Array||"public"!==e.type)throw new y("JSON Web Key Set members must be public keys");a[r]=e}return a[r]}function Ee(e){const t=new _e(e),r=async(e,r)=>t.getKey(e,r);return Object.defineProperties(r,{jwks:{value:()=>ge(t._jwks),enumerable:!0,configurable:!1,writable:!1}}),r}var be=async(e,t,r)=>{let a,n,s=!1;"function"==typeof AbortController&&(a=new AbortController,n=setTimeout((()=>{s=!0,a.abort()}),t));const i=await fetch(e.href,{signal:a?a.signal:void 0,redirect:"manual",headers:r.headers}).catch((e=>{if(s)throw new _;throw e}));if(void 0!==n&&clearTimeout(n),200!==i.status)throw new c("Expected 200 OK from the JSON Web Key Set HTTP response");try{return await i.json()}catch{throw new c("Failed to parse the JSON Web Key Set HTTP response as JSON")}};let ke;if("undefined"==typeof navigator||!navigator.userAgent?.startsWith?.("Mozilla/5.0 ")){ke=`${"jose"}/${"v5.10.0"}`}const ve=Symbol();class Ae{constructor(e,t){if(!(e instanceof URL))throw new TypeError("url must be an instance of URL");var r,a;this._url=new URL(e.href),this._options={agent:t?.agent,headers:t?.headers},this._timeoutDuration="number"==typeof t?.timeoutDuration?t?.timeoutDuration:5e3,this._cooldownDuration="number"==typeof t?.cooldownDuration?t?.cooldownDuration:3e4,this._cacheMaxAge="number"==typeof t?.cacheMaxAge?t?.cacheMaxAge:6e5,void 0!==t?.[ve]&&(this._cache=t?.[ve],r=t?.[ve],a=this._cacheMaxAge,"object"==typeof r&&null!==r&&"uat"in r&&"number"==typeof r.uat&&!(Date.now()-r.uat>=a)&&"jwks"in r&&D(r.jwks)&&Array.isArray(r.jwks.keys)&&Array.prototype.every.call(r.jwks.keys,D)&&(this._jwksTimestamp=this._cache.uat,this._local=Ee(this._cache.jwks)))}coolingDown(){return"number"==typeof this._jwksTimestamp&&Date.now()<this._jwksTimestamp+this._cooldownDuration}fresh(){return"number"==typeof this._jwksTimestamp&&Date.now()<this._jwksTimestamp+this._cacheMaxAge}async getKey(e,t){this._local&&this.fresh()||await this.reload();try{return await this._local(e,t)}catch(r){if(r instanceof m&&!1===this.coolingDown())return await this.reload(),this._local(e,t);throw r}}async reload(){this._pendingFetch&&("undefined"!=typeof WebSocketPair||"undefined"!=typeof navigator&&"Cloudflare-Workers"===navigator.userAgent||"undefined"!=typeof EdgeRuntime&&"vercel"===EdgeRuntime)&&(this._pendingFetch=void 0);const e=new Headers(this._options.headers);ke&&!e.has("User-Agent")&&(e.set("User-Agent",ke),this._options.headers=Object.fromEntries(e.entries())),this._pendingFetch||(this._pendingFetch=be(this._url,this._timeoutDuration,this._options).then((e=>{this._local=Ee(e),this._cache&&(this._cache.uat=Date.now(),this._cache.jwks=e),this._jwksTimestamp=Date.now(),this._pendingFetch=void 0})).catch((e=>{throw this._pendingFetch=void 0,e}))),await this._pendingFetch}}function Te(e,t){const r=new Ae(e,t),a=async(e,t)=>r.getKey(e,t);return Object.defineProperties(a,{coolingDown:{get:()=>r.coolingDown(),enumerable:!0,configurable:!1},fresh:{get:()=>r.fresh(),enumerable:!0,configurable:!1},reload:{value:()=>r.reload(),enumerable:!0,configurable:!1,writable:!1},reloading:{get:()=>!!r._pendingFetch,enumerable:!0,configurable:!1},jwks:{value:()=>r._local?.jwks(),enumerable:!0,configurable:!1,writable:!1}}),a}const Pe=o;function Re(e){const t=e?.modulusLength??2048;if("number"!=typeof t||t<2048)throw new p("Invalid or unsupported modulusLength option provided, 2048 bits or larger keys must be used");return t}async function Ie(t,r){return async function(t,r){let a,n;switch(t){case"PS256":case"PS384":case"PS512":a={name:"RSA-PSS",hash:`SHA-${t.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:Re(r)},n=["sign","verify"];break;case"RS256":case"RS384":case"RS512":a={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${t.slice(-3)}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:Re(r)},n=["sign","verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":a={name:"RSA-OAEP",hash:`SHA-${parseInt(t.slice(-3),10)||1}`,publicExponent:new Uint8Array([1,0,1]),modulusLength:Re(r)},n=["decrypt","unwrapKey","encrypt","wrapKey"];break;case"ES256":a={name:"ECDSA",namedCurve:"P-256"},n=["sign","verify"];break;case"ES384":a={name:"ECDSA",namedCurve:"P-384"},n=["sign","verify"];break;case"ES512":a={name:"ECDSA",namedCurve:"P-521"},n=["sign","verify"];break;case"Ed25519":a={name:"Ed25519"},n=["sign","verify"];break;case"EdDSA":{n=["sign","verify"];const e=r?.crv??"Ed25519";switch(e){case"Ed25519":case"Ed448":a={name:e};break;default:throw new p("Invalid or unsupported crv option provided")}break}case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{n=["deriveKey","deriveBits"];const e=r?.crv??"P-256";switch(e){case"P-256":case"P-384":case"P-521":a={name:"ECDH",namedCurve:e};break;case"X25519":case"X448":a={name:e};break;default:throw new p("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448")}break}default:throw new p('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}return e.subtle.generateKey(a,r?.extractable??!1,n)}(t,r)}const Ce=async(e,t,r)=>{const a=new URL(t),n=a.origin+a.pathname+a.search,s=new URL(e).origin,i=await fetch(`${s}/.well-known/openid-configuration`).then((e=>{if(!e.ok)throw new Error(`HTTP error! Status: ${e.status}`);return e.json()})),o=i.issuer,c=e=>e.endsWith("/")?e.slice(0,-1):e;if(c(e)!==c(o))throw new Error("RFC 9207 - iss !== idp - "+o+" !== "+e);sessionStorage.setItem("idp",o),sessionStorage.setItem("token_endpoint",i.token_endpoint),sessionStorage.setItem("jwks_uri",i.jwks_uri);let d=r?.client_id;if(!d){const e=i.registration_endpoint,t=await(async(e,t)=>{const r={...t,grant_types:["authorization_code","refresh_token"],token_endpoint_auth_method:"none",application_type:"web",subject_type:"public"};return fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)})})(e,r??{redirect_uris:[n]}).then((e=>{if(!e.ok)throw new Error(`HTTP error! Status: ${e.status}`);return e.json()}));d=t.client_id}try{new URL(d)}catch{sessionStorage.setItem("client_id",d)}const{pkce_code_verifier:h,pkce_code_challenge:l}=await De();sessionStorage.setItem("pkce_code_verifier",h);const p=window.crypto.randomUUID();sessionStorage.setItem("csrf_token",p);const u=i.authorization_endpoint+"?response_type=code"+`&redirect_uri=${encodeURIComponent(n)}&scope=openid offline_access webid`+`&client_id=${encodeURIComponent(d)}&code_challenge_method=S256`+`&code_challenge=${l}`+`&state=${p}&prompt=consent`;window.location.href=u},De=async()=>{const e=window.crypto.randomUUID()+"-"+window.crypto.randomUUID(),t=new Uint8Array(await window.crypto.subtle.digest("SHA-256",(new TextEncoder).encode(e)));return{pkce_code_verifier:e,pkce_code_challenge:btoa(String.fromCharCode(...t)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}},We=async(e,t,r,a,n,s)=>{const i=await Y(s.publicKey);i.alg="ES256";const o=await new fe({htu:n,htm:"POST"}).setIssuedAt().setJti(window.crypto.randomUUID()).setProtectedHeader({alg:"ES256",typ:"dpop+jwt",jwk:i}).sign(s.privateKey);return fetch(n,{method:"POST",headers:{dpop:o,"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",code:e,code_verifier:t,redirect_uri:r,client_id:a})})},He=async(e,t,r,a)=>{const n=await Y(a.publicKey);n.alg="ES256";const s=await new fe({htu:r,htm:"POST"}).setIssuedAt().setJti(self.crypto.randomUUID()).setProtectedHeader({alg:"ES256",typ:"dpop+jwt",jwk:n}).sign(a.privateKey);return fetch(r,{method:"POST",headers:{dpop:s,"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:t})})};var Je;!function(e){e.STATE_CHANGE="sessionStateChange",e.EXPIRATION_WARNING="sessionExpirationWarning",e.EXPIRATION="sessionExpiration"}(Je||(Je={}));class xe extends EventTarget{isActive_=!1;exp_;webId_=void 0;currentAth_=void 0;information;database;refreshPromise;resolveRefresh;rejectRefresh;constructor(e,t){super(),this.authFetch=this.authFetch.bind(this),this.information={clientDetails:e},this.database=t?.database,t?.onSessionStateChange&&this.addEventListener(Je.STATE_CHANGE,(e=>t.onSessionStateChange?.(e))),t?.onSessionExpirationWarning&&this.addEventListener(Je.EXPIRATION_WARNING,(e=>t?.onSessionExpirationWarning?.(e))),t?.onSessionExpiration&&this.addEventListener(Je.EXPIRATION,(e=>t?.onSessionExpiration?.(e)))}async login(e,t){await Ce(e,t,this.information.clientDetails)}async handleRedirectFromLogin(){const e=await(async(e,t)=>{const r=new URL(window.location.href),a=r.searchParams.get("code");if(null===a)return{clientDetails:e};const n=sessionStorage.getItem("idp");if(null===n||r.searchParams.get("iss")!==n)throw new Error("RFC 9207 - iss !== idp - "+r.searchParams.get("iss")+" !== "+n);if(r.searchParams.get("state")!==sessionStorage.getItem("csrf_token"))throw new Error("RFC 6749 - state !== csrf_token - "+r.searchParams.get("state")+" !== "+sessionStorage.getItem("csrf_token"));r.searchParams.delete("iss"),r.searchParams.delete("state"),r.searchParams.delete("code"),window.history.pushState({},document.title,r.toString());const s=sessionStorage.getItem("pkce_code_verifier");if(null===s)throw new Error("Access Token Request preparation - Could not find in sessionStorage: pkce_code_verifier");const i=e?.client_id||sessionStorage.getItem("client_id");if(!i)throw new Error("Access Token Request preparation - Could not find in sessionStorage: client_id (dynamic registration)");const o=sessionStorage.getItem("token_endpoint");if(null===o)throw new Error("Access Token Request preparation - Could not find in sessionStorage: token_endpoint");const c=await Ie("ES256"),d=await We(a,s,r.toString(),i,o,c).then((e=>{if(!e.ok)throw new Error(`HTTP error! Status: ${e.status}`);return e.json()})),h=d.access_token,l=sessionStorage.getItem("jwks_uri");if(null===l)throw new Error("Access Token validation preparation - Could not find in sessionStorage: jwks_uri");const p=Te(new URL(l)),{payload:u}=await ce(h,p,{issuer:n,audience:"solid"}),f=await ye(await Y(c.publicKey));if(u.cnf.jkt!==f)throw new Error("Access Token validation failed on `jkt`: jkt !== DPoP thumbprint - "+u.cnf.jkt+" !== "+f);if(u.client_id!==i)throw new Error("Access Token validation failed on `client_id`: JWT payload !== client_id - "+u.client_id+" !== "+i);const w={...d,dpop_key_pair:c},y={idp:n,jwks_uri:l,token_endpoint:o};return e||(e={redirect_uris:[r.toString()]}),e.client_id=i,t&&(await t.init(),await Promise.all([t.setItem("idp",n),t.setItem("jwks_uri",l),t.setItem("token_endpoint",o),t.setItem("client_id",i),t.setItem("dpop_keypair",c),t.setItem("refresh_token",d.refresh_token)]),t.close()),sessionStorage.removeItem("csrf_token"),sessionStorage.removeItem("pkce_code_verifier"),sessionStorage.removeItem("idp"),sessionStorage.removeItem("jwks_uri"),sessionStorage.removeItem("token_endpoint"),sessionStorage.removeItem("client_id"),{clientDetails:e,idpDetails:y,tokenDetails:w}})(this.information.clientDetails,this.database);e.tokenDetails&&(this.information.clientDetails=e.clientDetails,this.information.idpDetails=e.idpDetails,await this.setTokenDetails(e.tokenDetails),this.dispatchStateChangeEvent())}async restore(){if(!this.database)throw new Error("Could not refresh tokens: missing database. Provide database in sessionOption.");if(this.refreshPromise)return this.refreshPromise;this.refreshPromise=new Promise(((e,t)=>{this.resolveRefresh=e,this.rejectRefresh=t}));const e=this.isActive;return(async e=>{try{await e.init();const t=await e.getItem("client_id"),r=await e.getItem("token_endpoint"),a=await e.getItem("dpop_keypair"),n=await e.getItem("refresh_token");if(null===t||null===r||null===a||null===n)throw new Error("Could not refresh tokens: details missing from database.");const s=await He(n,t,r,a).then((e=>{if(!e.ok)throw new Error(`HTTP error! Status: ${e.status}`);return e.json()})),i=s.access_token,o=await e.getItem("idp");if(null===o)throw new Error("Access Token validation preparation - Could not find in sessionDatabase: idp");const c=await e.getItem("jwks_uri");if(null===c)throw new Error("Access Token validation preparation - Could not find in sessionDatabase: jwks_uri");const d=Te(new URL(c)),{payload:h}=await ce(i,d,{issuer:o,audience:"solid"}),l=await ye(await Y(a.publicKey));if(h.cnf.jkt!==l)throw new Error("Access Token validation failed on `jkt`: jkt !== DPoP thumbprint - "+h.cnf.jkt+" !== "+l);if(h.client_id!==t)throw new Error("Access Token validation failed on `client_id`: JWT payload !== client_id - "+h.client_id+" !== "+t);return await e.setItem("refresh_token",s.refresh_token),{...s,dpop_key_pair:a}}finally{e.close()}})(this.database).then((e=>this.setTokenDetails(e))).then((()=>this.resolveRefresh())).catch((e=>{this.isActive?(this.rejectRefresh(new Error(e||"Token refresh failed")),this.isExpired()?this.dispatchExpirationEvent():this.dispatchExpirationWarningEvent()):this.rejectRefresh(new Error("No session to restore."))})).finally((()=>{this.clearRefreshPromise(),e!==this.isActive&&this.dispatchStateChangeEvent()})),this.refreshPromise}async logout(){this.isActive_=!1,this.exp_=void 0,this.webId_=void 0,this.currentAth_=void 0,this.information.idpDetails=void 0,this.information.tokenDetails=void 0,this.refreshPromise&&this.rejectRefresh&&(this.rejectRefresh(new Error("Logout during token refresh.")),this.clearRefreshPromise()),this.database&&(await this.database.init(),await this.database.clear(),this.database.close()),this.dispatchStateChangeEvent()}async authFetch(e,t,r){if(!this.isActive)return fetch(e,t);let a,n,s;e instanceof Request?(a=new URL(e.url),n=t?.method||e?.method||"GET",s=new Headers(e.headers)):(t=t||{},a=new URL(e.toString()),n=t.method||"GET",s=t.headers?new Headers(t.headers):new Headers),await this._renewTokensIfExpired(),r=r??{htu:`${a.origin}${a.pathname}`,htm:n.toUpperCase()};const i=await this._createSignedDPoPToken(r);return s.set("dpop",i),s.set("authorization",`DPoP ${this.information.tokenDetails.access_token}`),e instanceof Request?fetch(new Request(e,{...t,headers:s})):fetch(a,{...t,headers:s})}async setTokenDetails(e){this.information.tokenDetails=e,await this._updateSessionDetailsFromToken(e.access_token)}clearRefreshPromise(){this.refreshPromise=void 0,this.resolveRefresh=void 0,this.rejectRefresh=void 0}get isActive(){return this.isActive_}get webId(){return this.webId_}isExpired(){return!this.exp_||this._isTokenExpired(this.exp_)}getExpiresIn(){return this.exp_?this._getTokenTTL(this.exp_):-1}getTokenDetails(){return this.information.tokenDetails}async _renewTokensIfExpired(){this.isExpired()&&(this.refreshPromise?await this.refreshPromise:await this.restore())}async _computeAth(e){const t=(new TextEncoder).encode(e),r=await crypto.subtle.digest("SHA-256",t),a=Array.from(new Uint8Array(r));return btoa(String.fromCharCode(...a)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async _createSignedDPoPToken(e){if(!this.information.tokenDetails||!this.currentAth_)throw new Error("Session not established.");e.ath=this.currentAth_;const t=await Y(this.information.tokenDetails.dpop_key_pair.publicKey);return new fe(e).setIssuedAt().setJti(window.crypto.randomUUID()).setProtectedHeader({alg:"ES256",typ:"dpop+jwt",jwk:t}).sign(this.information.tokenDetails.dpop_key_pair.privateKey)}async _updateSessionDetailsFromToken(e){if(e)try{const t=function(e){if("string"!=typeof e)throw new f("JWTs must use Compact JWS serialization, JWT must be a string");const{1:t,length:r}=e.split(".");if(5===r)throw new f("Only JWTs using Compact JWS serialization can be decoded");if(3!==r)throw new f("Invalid JWT");if(!t)throw new f("JWTs must contain a payload");let a,s;try{a=Pe(t)}catch{throw new f("Failed to base64url decode the payload")}try{s=JSON.parse(n.decode(a))}catch{throw new f("Failed to parse the decoded payload as JSON")}if(!D(s))throw new f("Invalid JWT Claims Set");return s}(e),r=t.webid;if(!r)throw new Error("Missing webid claim in access token");const a=t.exp;if(!a)throw new Error("Missing exp claim in access token");this.currentAth_=await this._computeAth(e),this.webId_=r,this.exp_=a,this.isActive_=!0}catch(e){await this.logout()}else await this.logout()}_isTokenExpired(e,t=0){return!("number"==typeof e&&!isNaN(e))||this._getTokenTTL(e,t)<0}_getTokenTTL(e,t=0){return e-(Math.floor(Date.now()/1e3)+t)}dispatchStateChangeEvent(){this.dispatchEvent(new CustomEvent(Je.STATE_CHANGE,{detail:{isActive:this.isActive,webId:this.webId}}))}dispatchExpirationWarningEvent(){this.dispatchEvent(new CustomEvent(Je.EXPIRATION_WARNING,{detail:{expires_in:this.getExpiresIn()}}))}dispatchExpirationEvent(){this.dispatchEvent(new CustomEvent(Je.EXPIRATION))}}export{xe as SessionCore,Je as SessionEvents};
|
|
6
|
-
|
package/web/icons/forum.svg
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2
|
-
<!-- The forum: more than one person talking. Icon "messages-square" from
|
|
3
|
-
Lucide (lucide.dev), ISC licence, © Lucide Contributors. -->
|
|
4
|
-
<title>Federated Solid Forum</title>
|
|
5
|
-
<rect width="32" height="32" rx="7" fill="#3b5bb5"/>
|
|
6
|
-
<g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2"
|
|
7
|
-
stroke-linecap="round" stroke-linejoin="round">
|
|
8
|
-
<path d="M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
|
|
9
|
-
<path d="M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1"/>
|
|
10
|
-
</g>
|
|
11
|
-
</svg>
|
package/web/icons/gateway.svg
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2
|
-
<!-- The gateway: the door your mail comes through. Icon "door-open" from
|
|
3
|
-
Lucide (lucide.dev), ISC licence, © Lucide Contributors. -->
|
|
4
|
-
<title>FediPod gateway</title>
|
|
5
|
-
<rect width="32" height="32" rx="7" fill="#b4531a"/>
|
|
6
|
-
<g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2"
|
|
7
|
-
stroke-linecap="round" stroke-linejoin="round">
|
|
8
|
-
<path d="M10 21H2"/>
|
|
9
|
-
<path d="M10 3H7a2 2 0 00-2 2v16"/>
|
|
10
|
-
<path d="M14 12h.01"/>
|
|
11
|
-
<path d="M19 21V5a2 2 0 00-1.675-1.974l-6.163-1.013A1 1 0 0010 3v18a1 1 0 001.124.992z"/>
|
|
12
|
-
<path d="M22 21h-3"/>
|
|
13
|
-
</g>
|
|
14
|
-
</svg>
|
package/web/icons/local.svg
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2
|
-
<!-- Your own pod and your own posts. Icon "house" from Lucide (lucide.dev),
|
|
3
|
-
ISC licence, © Lucide Contributors. -->
|
|
4
|
-
<title>FediPod</title>
|
|
5
|
-
<rect width="32" height="32" rx="7" fill="#2f7d4f"/>
|
|
6
|
-
<g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2"
|
|
7
|
-
stroke-linecap="round" stroke-linejoin="round">
|
|
8
|
-
<path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/>
|
|
9
|
-
<path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
|
|
10
|
-
</g>
|
|
11
|
-
</svg>
|