From a1615693ef348ab05e90c108104e3bcfdc848b2a Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Thu, 15 Oct 2026 18:34:53 -0700 Subject: [PATCH] Replace Web Push and its service worker with page notifications over SSE --- AGENTS.md | 1 + api/openapi.yaml | 49 +--- docs/operations.md | 13 +- go.mod | 16 +- go.sum | 109 ++++---- internal/api/api.gen.go | 416 ++++++++++++------------------- internal/push/push.go | 251 ------------------- internal/server/notifications.go | 21 ++ internal/server/push.go | 63 ----- internal/server/server.go | 16 -- internal/store/notifications.go | 27 ++ internal/store/push.go | 124 --------- internal/store/store.go | 3 + web/dist/app.js | 20 +- web/dist/app.js.map | 2 +- web/dist/notifications.js | 37 +++ web/dist/notifications.js.map | 1 + web/dist/settings.js | 83 ++---- web/dist/settings.js.map | 2 +- web/dist/state.js | 4 + web/dist/state.js.map | 2 +- web/dist/sw.js | 28 --- web/dist/sw.js.map | 1 - web/package.json | 2 +- web/src/api.gen.ts | 111 +-------- web/src/app.ts | 22 +- web/src/notifications.ts | 41 +++ web/src/settings.ts | 91 ++----- web/src/state.ts | 4 + web/src/sw.ts | 33 --- web/tsconfig.json | 3 +- web/tsconfig.sw.json | 8 - 32 files changed, 429 insertions(+), 1175 deletions(-) delete mode 100644 internal/push/push.go create mode 100644 internal/server/notifications.go delete mode 100644 internal/server/push.go create mode 100644 internal/store/notifications.go delete mode 100644 internal/store/push.go create mode 100644 web/dist/notifications.js create mode 100644 web/dist/notifications.js.map delete mode 100644 web/dist/sw.js delete mode 100644 web/dist/sw.js.map create mode 100644 web/src/notifications.ts delete mode 100644 web/src/sw.ts delete mode 100644 web/tsconfig.sw.json diff --git a/AGENTS.md b/AGENTS.md index c309106..356fdc4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,3 +47,4 @@ When the owner tells the lead "deploy byre", or anything that means the same, th - API types come from `api/openapi.yaml` via `openapi-typescript` (`web/src/api.gen.ts`); call the API through the typed client in `web/src/api.ts`, never raw `fetch`. - `web/dist/` is committed so `go install` needs no Node. Regenerate it with `go generate ./web` whenever `web/src/` or the spec changes. - Every view mounted into a pane returns a dispose function that removes its state subscriptions. +- Never use a service worker, for anything, including Web Push. Anything a page needs from the server comes over its SSE stream or the API. diff --git a/api/openapi.yaml b/api/openapi.yaml index 5cfebd5..771269d 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -30,7 +30,7 @@ paths: /api/me/notifications: put: operationId: updateNotificationPrefs - description: Sets which inbox items the calling user is sent push notifications for. + description: Sets which new inbox items notify the calling user in their open byre pages. requestBody: required: true content: @@ -44,27 +44,6 @@ paths: schema: { $ref: "#/components/schemas/User" } "400": { $ref: "#/components/responses/Error" } - /api/me/push-subscriptions: - post: - operationId: addPushSubscription - description: Registers a browser's push subscription for the calling user. Registering an endpoint again replaces it. - requestBody: - required: true - content: - application/json: - schema: { $ref: "#/components/schemas/PushSubscription" } - responses: - "204": - description: Registered. - "400": { $ref: "#/components/responses/Error" } - delete: - operationId: removePushSubscription - parameters: - - { name: endpoint, in: query, required: true, schema: { type: string } } - responses: - "204": - description: Removed, or was not registered. - /api/me/lead/sessions: get: operationId: listLeadSessions @@ -137,16 +116,6 @@ paths: description: Recorded. "400": { $ref: "#/components/responses/Error" } - /api/push/key: - get: - operationId: getPushKey - responses: - "200": - description: The server's VAPID public key, the applicationServerKey for PushManager.subscribe. - content: - application/json: - schema: { $ref: "#/components/schemas/PushKey" } - /api/projects: get: operationId: listProjects @@ -828,7 +797,7 @@ components: NotificationPrefs: type: object - description: Which new inbox items send this user a push notification. + description: Which new inbox items notify this user in their open byre pages. required: [blocking_questions, questions, reports, errors, rate_limits] properties: blocking_questions: { type: boolean, description: "Questions asked with blocking: true. On by default." } @@ -837,20 +806,6 @@ components: errors: { type: boolean, description: session_error items. } rate_limits: { type: boolean, description: rate_limited items. } - PushSubscription: - type: object - required: [endpoint, p256dh, auth] - properties: - endpoint: { type: string } - p256dh: { type: string, description: The subscription's p256dh key, base64url. } - auth: { type: string, description: The subscription's auth secret, base64url. } - - PushKey: - type: object - required: [public_key] - properties: - public_key: { type: string, description: Base64url, uncompressed P-256 point. } - UserUpdate: type: object required: [git_name, git_email] diff --git a/docs/operations.md b/docs/operations.md index fbe64ba..69b4622 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -10,7 +10,6 @@ - `internal/agents`: the agent session manager. It owns the running agent processes, task agents, lead agents (see "Lead agent") and reviewers (see "Reviews") alike, and records their activity as events. - `internal/claude`: the Claude Code stream-json client (see `docs/claude-protocol.md`). - `internal/codex`: the `codex app-server` JSON-RPC client, with types generated from the CLI's schema by `go generate ./internal/codex` (see `docs/codex-protocol.md`). -- `internal/push`: web push notifications for new inbox items (see "Notifications"). - `internal/tailscale`: `tailscale serve` for task previews (see "Previews"). - `web/`: the SPA, frameworkless TypeScript compiled file-by-file to ES modules (no bundler). `web/src/*.ts` is the source; `web/src/api.gen.ts` holds types generated from `api/openapi.yaml`, and `web/src/api.ts` is the typed client over them. `go generate ./web` runs `npm ci`, regenerates the types and compiles `web/dist/`, which is committed so `go install` needs no Node. The binary embeds `index.html`, `style.css`, `dist/`, `src/` (for source maps), `fonts/` and `vendor/` (Mermaid, see "Inbox"; xterm.js, see "Terminals"). `byre serve --dev` serves `./web` from disk instead (run from the repo root); pair it with `npm --prefix web exec tsc -- --watch`. @@ -176,15 +175,13 @@ Answers reach the agent as one message holding every undelivered `option` and `o ## Notifications -New inbox items are sent as web push notifications to every browser a user has turned them on in. Web push needs a secure origin and a service worker; byre gets the origin from the `tailscale serve` certificate, and serves the worker at `/sw.js` (compiled from `web/src/sw.ts` with its own `web/tsconfig.sw.json`, since it needs the WebWorker library instead of the DOM one) so its scope is the whole SPA. +An open byre page shows a browser notification for each new inbox item, raised by the page itself from the `inbox.created` events on its SSE stream (`notifyInbox` in `web/src/notifications.ts`). With no byre page open, nothing notifies. byre has no service worker and never uses one; on load the page unregisters any worker left in the browser from earlier versions and, if one was controlling the page, reloads. -- **Keys.** byre generates a VAPID key pair on its first start and keeps it in the `vapid_keys` table; `GET /api/push/key` returns the public half, which browsers pass to `PushManager.subscribe`. Replacing the keys invalidates every subscription. -- **Subscriptions.** `POST /api/me/push-subscriptions` stores a browser's endpoint, `p256dh` and `auth` in `push_subscriptions` under the calling user (re-posting an endpoint replaces it), along with `https://` plus the request's `Host`, which becomes the VAPID `sub` claim. `DELETE /api/me/push-subscriptions?endpoint=` removes one. A push service answering 404 or 410 means the subscription expired, and byre deletes it. -- **Preferences.** `users.notification_prefs` holds which item kinds notify the user, returned as `notification_prefs` on `GET /api/me` and set with `PUT /api/me/notifications`: `blocking_questions` (on by default), `questions` (non-blocking), `reports`, `errors` (`session_error`) and `rate_limits`. -- **Sending.** `internal/push` watches the event stream for `inbox.created`. The first item starts a 3-second window (`pushWindow` in `internal/server/server.go`); everything that arrives inside it goes out together, so each subscribed user gets at most one notification per window, built from the items their preferences select. One item reads `byre · ` with the question (or the report's first line, the error, or "Rate limited") as the body; several read `byre · N new inbox items` with one `: ` line each. Encryption and VAPID signing are `github.com/SherClockHolmes/webpush-go`. Notifications carry a 24-hour TTL and `Urgency: high` when any item is blocking. Delivery failures are logged, not retried. -- **Clicking** a notification opens the first item's task (`/#/task/`): the worker focuses an open byre window and tells it to switch task, or opens a new one. +- **Preferences.** `users.notification_prefs` holds which item kinds notify the user, returned as `notification_prefs` on `GET /api/me` and set with `PUT /api/me/notifications`: `blocking_questions` (on by default), `questions` (non-blocking), `reports`, `errors` (`session_error`) and `rate_limits`. The page checks them against each item as it arrives. +- **Content.** The title is `byre · ` and the body the question (or the report's first line, the error, or "Rate limited"), cut at 200 characters. The notification's tag is the item's ID, so several byre pages open in one browser show it once. +- **Clicking** a notification focuses the page and points the right pane at the item's task. -The **Settings** modal (the navbar's **Settings** button) turns notifications on or off for the current browser (asking for permission on the way) and edits the preferences. Opening it re-registers the browser's existing subscription, which restores one byre deleted as expired. +The **Settings** modal (the navbar's **Settings** button) asks the browser for notification permission and edits the preferences. In the UI each card is answered on its own; there is no batch submission. A pick-one question's choices are clickable blocks, and clicking one sends that answer at once. A choice's block (or a pick-any choice's checkbox label) holds the whole list item: its first line, which is the choice's text, and everything under it, such as an example's paragraph or code block. A pick-any question's choices are checkboxes, sent with the Submit button at the bottom of the card. Below the choices, an "Other…" block in the same style opens the only text field. A card has at most one Submit button: on a pick-any question it sends the checked choices with the Other text alongside (one `option` response), or the Other text alone as `other` when nothing is checked. A report has only an OK button, which dismisses it at once; an error has a "Reply…" block (`other`) and a Dismiss button. The Other and Reply text boxes send with the Submit button under them or on Enter (Shift+Enter for a newline), like the message box, and fold back into their block when left empty. The list updates in place: a card stays attached while its item is unchanged, so task and inbox updates from other agents don't pull focus out of a text box being typed in. diff --git a/go.mod b/go.mod index a172026..df60f28 100644 --- a/go.mod +++ b/go.mod @@ -3,21 +3,23 @@ module g.fc.run/misc/byre go 1.26.0 require ( - github.com/SherClockHolmes/webpush-go v1.4.0 // indirect + github.com/coder/websocket v1.8.15 + github.com/creack/pty v1.1.24 + github.com/getkin/kin-openapi v0.142.0 + github.com/oapi-codegen/runtime v1.7.0 + modernc.org/sqlite v1.60.1 +) + +require ( github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect - github.com/coder/websocket v1.8.15 // indirect - github.com/creack/pty v1.1.24 // indirect github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/getkin/kin-openapi v0.142.0 // indirect github.com/go-openapi/jsonpointer v0.23.1 // indirect github.com/go-openapi/swag/jsonname v0.26.0 // indirect - github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/mattn/go-isatty v0.0.24 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect github.com/oapi-codegen/oapi-codegen/v2 v2.8.0 // indirect - github.com/oapi-codegen/runtime v1.7.0 // indirect github.com/oasdiff/yaml v0.1.1 // indirect github.com/oasdiff/yaml3 v0.0.14 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect @@ -26,7 +28,6 @@ require ( github.com/speakeasy-api/openapi v1.24.0 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.46.0 // indirect golang.org/x/mod v0.41.0 // indirect golang.org/x/sync v0.23.0 // indirect golang.org/x/sys v0.48.0 // indirect @@ -36,7 +37,6 @@ require ( modernc.org/libc v1.77.1 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.12.1 // indirect - modernc.org/sqlite v1.60.1 // indirect ) tool github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen diff --git a/go.sum b/go.sum index 855ca57..420959d 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,4 @@ github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= -github.com/SherClockHolmes/webpush-go v1.4.0 h1:ocnzNKWN23T9nvHi6IfyrQjkIc0oJWv1B1pULsf9i3s= -github.com/SherClockHolmes/webpush-go v1.4.0/go.mod h1:XSq8pKX11vNV8MJEMwjrlTkxhAj1zKfxmyhdV7Pd6UA= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= @@ -13,12 +11,17 @@ github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= +github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getkin/kin-openapi v0.142.0 h1:izj0vBdFprMhitfzaX8sTqztsEQyvwhssBoB6n8NO7w= github.com/getkin/kin-openapi v0.142.0/go.mod h1:3BH9M9XDe/y9M5DSvEocVYAYq1w0qrhJHjC/vZi0AaY= @@ -26,9 +29,9 @@ github.com/go-openapi/jsonpointer v0.23.1 h1:1HBACs7XIwR2RcmItfdSFlALhGbe6S92p0r github.com/go-openapi/jsonpointer v0.23.1/go.mod h1:iWRmZTrGn7XwYhtPt/fvdSFj1OfNBngqRT2UG3BxSqY= github.com/go-openapi/swag/jsonname v0.26.0 h1:gV1NFX9M8avo0YSpmWogqfQISigCmpaiNci8cGECU5w= github.com/go-openapi/swag/jsonname v0.26.0/go.mod h1:urBBR8bZNoDYGr653ynhIx+gTeIz0ARZxHkAPktJK2M= +github.com/go-openapi/testify/v2 v2.4.2 h1:tiByHpvE9uHrrKjOszax7ZvKB7QOgizBWGBLuq0ePx4= +github.com/go-openapi/testify/v2 v2.4.2/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -42,22 +45,34 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3 h1:LMLX+LgTNWpfvCBdFebv6EsYotImrt/Ppc5cXIriCSo= +github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3/go.mod h1:jl5iWTm0/hd5PjEYEOuwAJ57L/CibdZfrqZ5XA5GrCk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oapi-codegen/nullable v1.1.0 h1:eAh8JVc5430VtYVnq00Hrbpag9PFRGWLjxR1/3KntMs= +github.com/oapi-codegen/nullable v1.1.0/go.mod h1:KUZ3vUzkmEKY90ksAmit2+5juDIhIZhfDl+0PwOQlFY= github.com/oapi-codegen/oapi-codegen/v2 v2.8.0 h1:s4hxMxuqtR8jPzXkBTtFwY/SBuj3gEAYikmbBSdtLMM= github.com/oapi-codegen/oapi-codegen/v2 v2.8.0/go.mod h1:yae2TI9IYB5vxQ35gFrpXh9L5H1eJv4MAUK1jumGMTo= github.com/oapi-codegen/runtime v1.7.0 h1:t7358VYPvNbWJ9gdAkIK/smVeHpBf6yp8VTsaZsb/7k= @@ -69,18 +84,25 @@ github.com/oasdiff/yaml3 v0.0.14/go.mod h1:csto2xfDjYccdUn/yw/bPjj/cYTdp6HtFA0J4 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/speakeasy-api/jsonpath v0.6.3 h1:c+QPwzAOdrWvzycuc9HFsIZcxKIaWcNpC+xhOW9rJxU= github.com/speakeasy-api/jsonpath v0.6.3/go.mod h1:2cXloNuQ+RSXi5HTRaeBh7JEmjRXTiaKpFTdZiL7URI= @@ -91,28 +113,17 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c= golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -120,24 +131,13 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.59.0 h1:5zfYln+w5XCxwrnMMJPufRgNoXEaGxl0wo5GqPXyues= +golang.org/x/net v0.59.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -154,44 +154,19 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.50.0 h1:c2ifzfcuY7L90lZ2aKd8S4K2NpASF08SZx9ZuJkHmSU= golang.org/x/tools v0.50.0/go.mod h1:7ulVMw3831Mwi5EZD6RomGyffr4VFjuNYXf2BbCEAV0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -208,22 +183,46 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +modernc.org/cc/v4 v4.29.7 h1:q+NXGJ0bK3b4TXFYQQVr9pYETGnmwFWkrUzJnMya/Tg= +modernc.org/cc/v4 v4.29.7/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI= +modernc.org/ccgo/v4 v4.36.1 h1:ZNIUZAryN0UgnJwtyxrdEzcFc3yD4Cu4AzjfPXsLsIE= +modernc.org/ccgo/v4 v4.36.1/go.mod h1:rrtGc2QkS239nYb/mQNuBMyjq3/y3ZXWbBjPoV3wqzA= +modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= +modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= +modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= +modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/gc/v3 v3.1.5 h1:21ldfPfRYE31Tb7B3mwAK8gy1AxP4+dKjrOQPfqakoc= +modernc.org/gc/v3 v3.1.5/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= +modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= +modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= modernc.org/libc v1.77.1 h1:Ct8j47QtiZ1Enj2DtFXQtUqrPCAjdCmPjtCuvrYQ0Hs= modernc.org/libc v1.77.1/go.mod h1:87/pZ4L6nD1zqW4nItuS12YO7hN1igAah34xjnQo/W0= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.12.1 h1:nFMiWrpStgZczNl6XI9GnIk/rWhYIyHGUaR04pGbp9g= modernc.org/memory v1.12.1/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg= +modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= modernc.org/sqlite v1.60.1 h1:/blz53O951KWFOso4QQvEs/Fq6cDBKLtMVrYNSeJVKw= modernc.org/sqlite v1.60.1/go.mod h1:1dIoEagfDE72QytD5scH1lxARtaUgKgHC/NuApA27r0= +modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/internal/api/api.gen.go b/internal/api/api.gen.go index 2f4b042..6ab07bb 100644 --- a/internal/api/api.gen.go +++ b/internal/api/api.gen.go @@ -665,7 +665,7 @@ type MessageCreate struct { Text string `json:"text"` } -// NotificationPrefs Which new inbox items send this user a push notification. +// NotificationPrefs Which new inbox items notify this user in their open byre pages. type NotificationPrefs struct { // BlockingQuestions Questions asked with blocking: true. On by default. BlockingQuestions bool `json:"blocking_questions"` @@ -749,22 +749,6 @@ type ProtocolErrors struct { Recent []ProtocolError `json:"recent"` } -// PushKey defines model for PushKey. -type PushKey struct { - // PublicKey Base64url - PublicKey string `json:"public_key"` -} - -// PushSubscription defines model for PushSubscription. -type PushSubscription struct { - // Auth The subscription's auth secret - Auth string `json:"auth"` - Endpoint string `json:"endpoint"` - - // P256dh The subscription's p256dh key - P256dh string `json:"p256dh"` -} - // Review An agent session on the vendor the task's agent doesn't use, reviewing one snapshot's change. type Review struct { // AgentSessionId The reviewer's session. @@ -971,7 +955,7 @@ type User struct { GitName string `json:"git_name"` Login string `json:"login"` - // NotificationPrefs Which new inbox items send this user a push notification. + // NotificationPrefs Which new inbox items notify this user in their open byre pages. NotificationPrefs NotificationPrefs `json:"notification_prefs"` } @@ -1008,11 +992,6 @@ type ListInboxParams struct { State *InboxState `form:"state,omitempty" json:"state,omitempty"` } -// RemovePushSubscriptionParams defines parameters for RemovePushSubscription. -type RemovePushSubscriptionParams struct { - Endpoint string `form:"endpoint" json:"endpoint"` -} - // GetTaskChangesParams defines parameters for GetTaskChanges. type GetTaskChangesParams struct { // Since A commit to compare with instead of the merge-base, such as a user.message event's head. Not allowed with snapshot. @@ -1080,9 +1059,6 @@ type UpdateNotificationPrefsJSONRequestBody = NotificationPrefs // SetPaneFocusJSONRequestBody defines body for SetPaneFocus for application/json ContentType. type SetPaneFocusJSONRequestBody = PaneFocus -// AddPushSubscriptionJSONRequestBody defines body for AddPushSubscription for application/json ContentType. -type AddPushSubscriptionJSONRequestBody = PushSubscription - // CreateProjectJSONRequestBody defines body for CreateProject for application/json ContentType. type CreateProjectJSONRequestBody = ProjectCreate @@ -1146,12 +1122,6 @@ type ServerInterface interface { // (PUT /api/me/pane-focus) SetPaneFocus(w http.ResponseWriter, r *http.Request) - // (DELETE /api/me/push-subscriptions) - RemovePushSubscription(w http.ResponseWriter, r *http.Request, params RemovePushSubscriptionParams) - - // (POST /api/me/push-subscriptions) - AddPushSubscription(w http.ResponseWriter, r *http.Request) - // (GET /api/projects) ListProjects(w http.ResponseWriter, r *http.Request) @@ -1173,9 +1143,6 @@ type ServerInterface interface { // (POST /api/projects/{projectId}/todo/tasks) StartTodoItem(w http.ResponseWriter, r *http.Request, projectId string) - // (GET /api/push/key) - GetPushKey(w http.ResponseWriter, r *http.Request) - // (GET /api/sessions/{sessionId}) GetSession(w http.ResponseWriter, r *http.Request, sessionId string) @@ -1600,53 +1567,6 @@ func (siw *ServerInterfaceWrapper) SetPaneFocus(w http.ResponseWriter, r *http.R handler.ServeHTTP(w, r) } -// RemovePushSubscription operation middleware -func (siw *ServerInterfaceWrapper) RemovePushSubscription(w http.ResponseWriter, r *http.Request) { - - var err error - _ = err - - // Parameter object where we will unmarshal all parameters from the context - var params RemovePushSubscriptionParams - - // ------------- Required query parameter "endpoint" ------------- - - err = runtime.BindQueryParameterWithOptions("form", true, true, "endpoint", r.URL.Query(), ¶ms.Endpoint, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) - if err != nil { - var requiredError *runtime.RequiredParameterError - if errors.As(err, &requiredError) { - siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "endpoint"}) - } else { - siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "endpoint", Err: err}) - } - return - } - - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.RemovePushSubscription(w, r, params) - })) - - for _, middleware := range siw.HandlerMiddlewares { - handler = middleware(handler) - } - - handler.ServeHTTP(w, r) -} - -// AddPushSubscription operation middleware -func (siw *ServerInterfaceWrapper) AddPushSubscription(w http.ResponseWriter, r *http.Request) { - - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.AddPushSubscription(w, r) - })) - - for _, middleware := range siw.HandlerMiddlewares { - handler = middleware(handler) - } - - handler.ServeHTTP(w, r) -} - // ListProjects operation middleware func (siw *ServerInterfaceWrapper) ListProjects(w http.ResponseWriter, r *http.Request) { @@ -1805,20 +1725,6 @@ func (siw *ServerInterfaceWrapper) StartTodoItem(w http.ResponseWriter, r *http. handler.ServeHTTP(w, r) } -// GetPushKey operation middleware -func (siw *ServerInterfaceWrapper) GetPushKey(w http.ResponseWriter, r *http.Request) { - - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetPushKey(w, r) - })) - - for _, middleware := range siw.HandlerMiddlewares { - handler = middleware(handler) - } - - handler.ServeHTTP(w, r) -} - // GetSession operation middleware func (siw *ServerInterfaceWrapper) GetSession(w http.ResponseWriter, r *http.Request) { @@ -2752,14 +2658,11 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/me", wrapper.GetMe) m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/me", wrapper.UpdateMe) m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/me/notifications", wrapper.UpdateNotificationPrefs) - m.HandleFunc(http.MethodDelete+" "+options.BaseURL+"/api/me/push-subscriptions", wrapper.RemovePushSubscription) - m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/me/push-subscriptions", wrapper.AddPushSubscription) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/me/lead/sessions", wrapper.ListLeadSessions) m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/me/lead/messages", wrapper.MessageLead) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/me/focus", wrapper.GetFocus) m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/me/focus", wrapper.SetFocus) m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/me/pane-focus", wrapper.SetPaneFocus) - m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/push/key", wrapper.GetPushKey) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/projects", wrapper.ListProjects) m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/projects", wrapper.CreateProject) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/projects/{projectId}", wrapper.GetProject) @@ -2806,167 +2709,162 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "7H1/cxs3suBXQfGuStZ7I8r5sVv35Lo/HNtJ9DZOdJbyUnW7KS3IaZJYDQEawIhiXP7uV+gGMJgZjDiS", - "JcW5vH9sipwBGo3uRv/Gh8lcrTdKgrRmcvJhosFslDSAf7zRWmn3Ya6kBWndR77ZVGLOrVDy+F9GSfed", - "ma9gzd2n/6lhMTmZ/I/jZtRj+tUc02gfP34sJiWYuRYbN8jkhKaZTtwP/lk31MslSHum1RwM/r3RagPa", + "7H1/cxu3kuBXQfGuStbuiHJesle3ct0fju0k3otjn6Vcqu5tSg/kNEk8DQEawIhiXP7uV+gGMJgZDDmS", + "Jdm53D82Rc4AjUZ3o3/j42Su1hslQVozOfs40WA2ShrAP15prbT7MFfSgrTuI99sKjHnVih5+k+jpPvO", + "zFew5u7Tf9WwmJxN/stpM+op/WpOabRPnz4VkxLMXIuNG2RyRtNMJ+4H/6wb6vkSpH2n1RwM/r3RagPa", "CgJtBbyyK/epPZax9fyKrYFLwziztZZMGKZrKYVcMi5LJhUzVgNfM7gGadmKG8a1FtdQsoXSDEe45AsL", - "+tLAXMnSvGBwIyyUfly7ArYhwNzgSyVhOikmIOv15OTvE3U1KQgO9yW+OPm1mNjdBhBALeRyUkxujtwL", - "R9dcS752i/r75Htc1E/uPfp47kehv974sT4Wk4obe4nwX3Lbx8IvK5AtMN3zbKuVBcZZJSQwq5iwxqNi", - "UkwWSq/dUJOSWziyYg2TYqI027qhhGXGcm2hnE5OZF1V3eV8LCYbUTpA/PdCWliCdj8YMEYoedn6vXnP", - "WG4BKcswJRlu+zm9Eidrr+5iBcwPeuBW4N7PAGS5uRqa9BpkSaTd+eljMdHwvhYaSrcjCezNgPF1WnRY", - "QndXikCkzear2b9gbh0A6TL71D3XwC2Ufm+zW9NbUnhntsuueKH0VRyxQy3Crpj/faHV+gRJh9Z4YJgo", - "mVrgV0hFduU4yf3pXmFXABtTMM7WYAxf4rfsVcXrEtgrVUIR2BC/VyXcTHPQJ9P3AXyJUx0YthDaeFJk", - "Gky9BseNwnhgA1UUbF5bxi2Liy5YLUvQjDMJW//0ZbO5LxifGScMHJDKriAOZbLQDlDVWpVQ9cF/B+9r", - "MCg/3AMvGKw3dpcIk4jqEha8ruyUvQzzMyWrHTNbYecrMGwGdgvIkIaprWzexJHzwKqtBN2HynFRpZZC", - "su1KGWAV8JJxR5aEUmECoA4pnDnqd+wWWDMzk1YV9CfScC1gC/qEcUafm2HYMwPA3uG3hy96sxhWCWMd", - "aNe402CAqdqm0lasNxWsQVpw/OgWMSnilH25mwqcOERZOY7yh8SkwCOxgvFyO2Xmczf6KY3Y+/5dnKL3", - "06tmzrbs6pyVyY7gjt22H42Uaw/yraoqtTXMcRsSIFIPfgr7suWGeYnCtsKuTthyY4/+zdOZO1CdsEZ+", - "LtxBqneeb2go91sjA9L9muPXiOQSbrIb1GPP/gqSwRNiEmXB5o6YJZvt2Gyn4QVTGteFkDK70g5n7jki", - "7Vpa0Vp4FDIos1DSGOQ2ejWD5s6J0TkpiPmSE4NkRG6RzTmCfNSS6EV6JGTPE2v5fLX2SlrnNOEebRmR", - "BbK8dPpA/ugWa77McDR+fcJKbjn7+d0PWdq7ErJMmWwhcE2lWCwmYWD3J19q1D8cyhwKJN+YlXKnZ62r", - "LHmsQa95jij8YCfsLT3BjKr1HLLgbXhOe3RAnjANG3WkoeJWXANzT06ZXzKX9Im5J5kgJcvLrK3SV1aD", - "O/FmRlW1BUd8cRxUuPJi0+nM/cUsFidsKSzKTCRvzeUyv5qAtVt0LG1v2efbVCW3DXv1JNztHF1+U6lZ", - "hiLJnrikxz8MKzMPqABll5dj3hZwd+PC10K/kVbv+isWS6lwku4+ux2mH0kXAPf+CZsuhaWv0Whxv5B8", - "hZt55USfI0DD1tzOV049xwOhFBrmVukd4zN1DW16mylVAZcOTHdw5elE/AZDXIHWgvgNqX62s4DKRtwZ", - "Ie1fv24mS9X/3boS8iqZL4EkEEDXfOG2QQYTpmALPLLQhmN+RGbdY8bynQmcGFhwSsg66T7cKBLxUYe5", - "jRLSGibVdgUaCo9MuBZzKJhR8ytABG/EpnWUlcIJdC/YcMKR+kIgk4vdBl7jIOk339KA6Vc/0eBdcsV9", - "9DM2iPbbWESaG6DUH4SxDsQerTqsB7K1sDb7DPtI9XFDJ1xrvhuWs073jMRatGRka2+0UjbVQt2P7rus", - "ELS6lnPHnXvmQ4t/7TjLL9TRhmRb0MA0uHMfyhzfdJCPKysistL5cwiPvpQ2rr3VtF80hQezY19nz33u", - "lpvlc1TzL/cY5veRweHUH2uEnDvOkkGXRbAODDlmDAo+zmoDzsBZqHltpvXGTV+ShUrWi13Bjs2gUs4q", - "VVP2kzOYkNvdm0w49RBtGlgPaAK7SvEU6gaxG63cx8FjFd63UDMsBIcP2J7D4f3Eo7HwG9iAuPf8caLj", - "1cqpCRlqKEvhsG7yKsBMSK53eSldQgW3vKqq8jLP5xqciPLb5R5hM1g4zkNGxh9v1c6ytlttUr2SlyWU", - "pFeLhcCPCC6QHYjz+yku54iajFU3wNt+tiLBXYqMiLTBrWjcpu29aJDdl1OkWRp5YNnPF98e/S9m4ca+", - "wH8dMaMwzB/rw1jzx/oYQoUbmx3jFumKoK1UVRryVqA5hT4a7zdySxovUf3p5XGUzuzBG0L3a2db9HC9", - "cSpSdkkD+MpDRcNkp3aSKTNvS3Yk/iWJ/uJBz6Z/j1hELFeWbbgEZlZqa16k9kZ4ED20XsCQuLN5d+hs", - "30F+wc3VBZ/5p02ePt0vJH6dyN7UlgzmwulgSpegp+wiaqsOLHqDFLgohkcpFik8Hb1i0EFy4RE0gL/e", - "PuwTBYgIwl5u80/lTN2cWlhnBO6YQ3ZWqfmV18L6HH2fI3hgoq49ji5JhzK33I3SjmYCrIC6SjHR3MJl", - "Jdb5EEb77GzvQhj9hKE1dWPZs7dcX5VqK9GdhLszXykxB6e8Y0SCG/bPI/aMHaKs+yc7xj//Lfy5EfOr", - "IyVRYf/nEfs7+zV97u83v6bPcbkj1yHS2WHBAkAF2652l4h1KAumEGDDngGfrzxABwZHagj6sGDrurJi", - "UwF7ZnVNPu4wz6HTX+dqvQZZQsmeoT+N6ysowwIPcLzDgvHopDFTRlg/IcH+jMSk5FX0o6tF8JyjMkOj", - "S0cCVbU7nLLWZp0w/G/K0i078e7hIvmWZopuY/fDEf1Ah91h4Uf6h5wUOYVIKC3sLqUkj8xJMVl69xV6", - "X51ptBMjLaJv4hjf0RjkEj4L0xWTb91Y+1UyDUZV13dkmfjSgOugFRQdJblQLLzzr+XkF+HI3MY5pCO5", - "x5pzFMMf3tkTzwJmlbpiGLHE78IQ6MTl5ipQZXwxWtcxstPQGT0vHLkqOQdvZIc34UYY2woMkJxHpIyW", - "67S5ObRE3/xe5KLTfJ/vipy2l6NdPwlxpU7cniRPR47a+qYh1ijVU909eHcToZ6SVkMTg+cMEVTZP2o+", - "kUBfIUToWxXylF7/ors5HXw1U+4B1+RskUYQjoY48XBnCOc+J2UJlbgG/TDnq1vDEBn6U6a11D6tdjWc", - "QU3c+8xGb++Fe+FjMXH28EhGCKvxL0UfU7pxe63RHI09ASmM3Im22KUfToJeYkAG3eAFgxs+t9WOOeWD", - "Im9RF2nUCq+ZoF8pecgpIuGhlnwcvf8dOMmviTLbKQ7k2yC3GYqpqYeb3Co9GE78z7xK3ufoPEn0MnCH", - "cUBA3tl2PyLs0lokMxxvLxFd+Fljqs3Gq7DkfS0mpTBrYUxWWU2OjdYQ4Abg0mydKGjGwM+m3oA2UA7o", - "v29JVxuibQwVZYjtm0rNmCh9ALbeuAPCfVf0t9NpxTQM7ZIRJcTdvxtBDWQnvMWALXlXhSFNgMuSVdzp", - "E0qCmbJffBJQKRYL0EnguIma4uhFK4acZC1Ep0/Qbr1bLk9bWcp/y3dsBl7zoKwkjxcNbCmuQY4w5obc", - "Bz8qKxY+re1Mw8LkghJivsL0EeEIiVQet4iSEIfeRs42tVkxmQw3Jb0i9f547eAyMGVmtv8TfvIKGTJn", - "ePGEOStkyn7COHdIGsn6hFCZz4zfsh4a9a0/wC0w/qjkUQApCpiBYRoLJDNQarTcBguZTDm/BAbr6/Wa", - "awFmhKspswXpUpupIgbbS8jR0BmXMOALQud1NjDhrMntSlTEHTOtto6MtkKWaouBCnw1xgD9QAwo58Wx", - "kZBRJjTujhEoCDDll6KtmIsNzzkvS2E2Fd9dDkYRl8JewpqLavDX8Gout2UbcheRoVYcPaEGLOMYDRcl", - "SCvs7gU5/q17egmWScWs5qICnZUpGCvYr/zQY0V7jQnM6eKyiPO274Nk9A0iGN01mSw5930nKQEJ3Z0r", - "+hpKZ/itrN2Yk+Pjf9TPn381n+00HBi2UsbiF3BC37uR6Ivj6acFNBoryiPQ+5r26I5nZIk9SWqkF6CX", - "M83lgKt4QJ0c3CENa2WHftqoy3Gu5xRtzWs9gON0d0tW8CgeUl5uWdvoBfRgH4DDqrmqBiKkd3LkcGS9", - "eW1DfjO5TL5mfxPf3OJzD/5HDXMQ1zFg1Fk2NwNJVPsynLNZFWHeA8MWdVWxCuTSrlrZFX22G5u3HNPN", - "Wk4L73HAdRCyPHB7t8Xkcnhqb7OF6BivzlpP9MHvBH8pDd8hgSIKvOQbp3TOVV2VTuxvuDZoVpUC/9Yw", - "V0spDDAj5BwwxS9kphfsCnZQOo2IVj/NOTDdDkub3421MjiFO1id3ls4bQ+MD3CM9m616fnjHj+KR2OE", - "LLsVtVn9DTJZRZt6Von55RVkYonfcAN//brW1aTvga2lg1uDs3LY2dGXf/kr5cB4FumFwJpphsA7r2fJ", - "5D0erklazAJMt2X2JyMdGOZeZQbmOh/VAlki5Plz8su//LW878T0siOqvWZFBCJOWdCSc9h6FzWEzvEt", - "vcXXZH4nyeHpmU6PlQpQNaoNFN5P7PRwJRtH74FhFPLu2yC54FQfJSGPek/e933OZAjSvpNr5lS48oRt", - "V7t8nYCQwqwexmUXDeKcw7+uMlKiVBJSxzxhpp6thb30rnqulzV6s068QbJrQl+HqMcvhCyFXJqCYdAJ", - "LTsD16CF3RVszi0sMSvKCltBwUqwXFQFpU+gYS5a+n1DWTELVA4U4nR9H03Gu1vYpPDYHxmzIULu5LUn", - "X76mMZNvvvXDP1BxTsdLnyw/67LvpWAHh3wId+7Rl3y2/u/h7Nlotd7c193TF4s42ojMB3oui4uQpn2/", - "qPdcrR3LmBXPmTH0K4amNIB7ypeobLj2Rm+aJXhg2PdvXr6OlWpbbpjlV/CAsuqa1vR+ON3gwKDDzFhf", - "VRit2Bg6c2B5VcX7bzWAT5uh1FRj47pYvWkSxkek7QzZJ32Az5RBZa1jJwYwTUF0+sULL+YWWD8JC3Ps", - "lK1j97g5/uC57uOxe+/4g/x4VyuxmIS9HfhRLJe5hEFba3kJsjzx8U5vwIIsj9TiCJ2XRD7T6Gp81vAX", - "VUCi45teT732VqmKzXlVmcMC/7h0fxTMrWFVrzm5RR2NaMY3G+Ca0p2UbLBHhOd0UOC6Eg7AWlSlSdOG", - "QyZnERfjPob5nOwKE7rv3XQjBXJgygtC3ts4T+eHi1rLNzhr9welqlcEQ+eXl+bqew9R9x0CcI9szohj", - "OWnJgYQgUoZrSGG/fI65gb00WHENl0i5+YORoPO1sjkZ/gYLnIiGQkkt2h5OFGmOrsSCibKCpnJNSEzU", - "L0fbDa2C54xAL2eXaBmOzORLilHH56lWDlO4zgwWXqbrB8PmtXbyuNqF+uq8EPBB9QHcb7y1dNl4qkcb", - "VybjWd5jjDbkkrHGSYD3cmJIT/N6ODmGR5ubhJhLx+kDfuumOl2qbcFUVTogghFwN9PTjfcOFtnMCgOX", - "80qEnc1qh/quB2OmVr6/yO/VlmGAkceVopxe8x1bKtR/VW0Zb5fl+5iRsIwsZIbHZz2/yhPZb2o9EznW", - "PQ/86HOyAgiodkvFKqzxIpouKOW8Q+bI6CtusHNA2Bba71Gb8n8RtL2OgAT/Ca/3+Djhp6It2tp73Obl", - "LiW22aYvARuE5je5z7c5iXzBzVUm+ZkbuPQ1b/18yGEf7LxSZqiCPWhbmA7lNK016CWU5Doyc669IB7p", - "L1ZVzjY9lSXcMCG9yv7z6YGhCTe8AmvBqQpGLCU52vG0wog7Z27AWjsCoh2j11D3o5Cp00MwhskcKzhu", - "cUKAL1We2j+H/gAy5I5FDdfr3vQk4zYP+62V/kn2rjCIlWRE90qmUh+p/05l+o42Lkn36INAlENrNO9r", - "blbRICEa8953RqT6Io1IO3gIZKl8nwRFpJiFjwB5X0N9G12/dU/hoDo2EqCQIZdJlrWIHT8oK9wzgZDL", - "iDOf0AcEUqhuDk0+pEO3MGwF1R14hdaAvoqB7XQ/RVppIZRWtuZXYE6SbEZ8oanMDl4xrAiiBXufib1M", - "Zs8XkihtL53AGaq10CZWKaQRM/cdBoDZsziE28v4x7//x2HBNhwdqD7U4E14ZyOAXmMuLzfs7Kd3F7fq", - "Rbf1RemUuqDsmHic+1QVkm0jLQQnkElNfhnGar56G0ZtvnrdjO+Or7DJfXNNlepS+Cz4PSRw8dPrn6Zr", - "ivO3ZbY/Ae/O58ETcJewWjvVE1fWJuZ4FnXHL5oTLCWwcGwkZUN3icY5pFPplskfmXnUBtGkyZ3g1A+u", - "Y8+GyOtHSMAJoXvpFRML2kKtoPhKEbonbDRcC1Wb1LOMdbZ5F211h0TUpGQtlwSnIbdwrNtdtGtFuWFi", - "Qa0oSPRiQaexfImJ/rp1Vg3D300Uoa1FOMLSBrdvwDM4xDfdSDk+NjT4BZXvBFlgNZeEEkdanm4CgMUk", - "SCAk9JCOj3lLSZ5xZILR0mN2kU57wWev4swXfPatn9w918x/wWdnEYQLPjv1UFzw2bsICD7kYXEL9q+f", - "+8hpN/JYUe2skGLt0PFFTrxqtd37VC8WV6FqrAaSsC9UqTLl0pgTnz28SW712It6jkVJyC2eH53C5iTv", - "KTLSOCNQlQorkvZZHB7wMP7QivPVTTNV7nzXrn5ljxvwwDAhS5AWtWCmYa2uk/5hfVHmX1rUGtGGYeGs", - "0QnzEGXMHDVwEw90CVw7NXoFvMTOAdgUIcCXUdyEGSoKSw6/YcBRmXBgF9GodfuKdUhoffrE3YAdn8k0", - "Im0xHEgO5w0Chjbs3J2jmVLzwYDAWO2NjmxFB/VYsLNQej9FD8Y9cYPHb+mWg/Zn6RWujCRa5zMaX9EP", - "wWRIT1yqstEgDwYsiry2uKcGOx66nU5P2CUEp6Tc3aTnEyrf4XxrD+gzBNbCWixjQyGfeDQpS8CdKMYh", - "YxCqZJRMJILblSGZkZ+t3dJjMkJ8r707IxyDCXztwu0UsOyW+1KJR8t8HJ2gWEzSZOLLTUhOvu0E6Gcz", - "f0qeYxaCIaT9jA0a+qi7N2Y6gI/OxPRet/4eYjh9VIlscJl5YR7cY6Q3uU/xFy9T8jWy9+yLOTrD0pef", - "+YX1cfERGXWhElV0MttpQKGnqQHl5Pn0+fQ5VciA5BsxOZl8NX0+/Yoq31eIumO+Ece8XAt53BinS8Cj", - "xqEY6eO0nJxMvgN7HoygVm3al8+fP1g/WT9DpqHsOehr0Izab6KJUxu+hKl79mNB65hViircN8pkPC/n", - "FjsyNf2+lGa1weZHsdUlFbq7QzmEpDXf0vMvqGfcboNKRQkW5sGypUTvnQXK6l7XxrIZsLMfvyvYf569", - "+a5g351+6+yVX2B2NmUvLeWl/YW9Fd9QVW4b1z/HjIIJ0QUY+41XzhI8I1jHS7FoIzg6eZp2Cz1io1f/", - "tYHlfd/dyHu/uoXZ5q7vthjE6ho+9sjwiwcjQ8R8hggxpcxRUckcrU0dc31N5J8bLsJ3HPMGv/7iq9FP", - "dwj7+IP777T8eBuLRpq5lUH/ZITT30SHyQNDLEuaPTK3RxEyud/cr++wXU6uar4GC9oZ1x8m7vQPzUbo", - "LJzQHk661Fwka+qu4NdABtRDKdn+nIg8QhcbPTplb/h8RX9Q119BnS8NvH9BvR69lMN2U4wb9p/nP/04", - "pT+NT6j4gRt7hN8cnb5mz7zbhX57X4PesbjsQ6zc0uAUEMckFPDDeFyACCMP/iAsQnMZboOrNvSJ0oC5", - "VC9ocyrg5f9GPDXtaPyT3o6Z86rC1L2m61RcBg7BJcOGVWyp/BiqaSmVE8KUykxDTPJb66xQVK395rYw", - "NSlydDoUp/9Y+DERo82QiOaHGSpJqxuktYFXfQ/e3ntNIdKve4WOM+OJhI98h/IWJ+/lWyJRevUezBmY", - "iDxmQzx02tQBFmwlliswloUuAN4d8Cy2GllyGxN1C7bYicOCqpd8xJ8i/exbUTm6YZJrTf1ymC801kiG", - "PER4DgxL+zK7YXOU+YMwNrjccmTZ2byWW/zOW/8JVBOSMccdumkLiBHkdPvpPr5hwoBbrUd+b7mdow+a", - "ikSDX0xoFgGdstdk9Ru3q07rDpWPXfo7bi0ur66+xPJl08pno7mFpJTwerYWlMHNwsMa81pa2afu0diA", - "Rs4x/8IdA2UF/vIEid4gdy70Sz9REtcy1FLnyNG3sDiNrughffX+ClmrVcYoZfD3JhenZfjOhpEI7qws", - "3kHAuaf/477i8PiDA3GPatks/xENwATHeZyivzIqbA3rPY62Rmi5n7ZGro8hbL6Fx0Qj+roGMOg0Jcfi", - "qPd4RNQZIMnt4+F8eJZOPEuPwND3RU5gWY+cu3Fsw1VrOF6EsvEhCqC68kdcJ02QWWjsxZySwoHptdZr", - "U0f3Aoy50iUZD5RJTa0hwkUizVhNW8OCnObOgOCzaV/hTnHy8ASXoOPpaG1wDxJXArXBfdzjoUWaTps/", - "9irBbf4ykKVJboHxOXIdomnsrYKCSNTQO73IIhePY7/EDgn4qDBsLcoj37Ss1VRkBVWJmooJ9TTWMAk3", - "dKFDTiPxafI/hJtDHp6Y2l1iRhHVlw82eeuioQHaauE/RejWVygpHXGLma+fIuuQoEKW/KBtdXEb8cQk", - "+6JjPL2kBBgMj7JwiwtptUgTlPBGsWFqn9M3lhwhhKThyVOoiu0dGqctNrcTtZGbRmp8hXCWWa1hW+xn", - "k/ay6TJs7J3d62ljQgJ0TgvoR58eh61yUa7/D3UDdyweRQXh1vN1m2Sc0Dkr6FoSNEVlt0dMI1Z3znIr", - "GgFLXDbn8sCydXOTRO8IblrePM4WN+OP2tqvh1AD5SfuQW1WR2l9uA8lOvHS19feYapLryp+lP8lKSW/", - "gxkxDhOYgIOpcD5DmWlYCmPRVvfqW/Zwf+cfcwe8b1HkFDUnFVKkxCsaWlYDC2/TBYwsrJDxJReS/L/Y", - "BThDYi/LMoPGR6G07jT3J7gEpfclubRkKmsSuIPqrKkDefxDKmTnjTifXlZVUOJNh6zaiyCFKIz8SPva", - "anLzxKHBiLT8GSFhGxD1ALRy/MF/2uOaSfH9SAfjnnW31/zQbpiIhft5YnLoPI61o4PMeOFLsB6fE7Go", - "aqSa2IQKcAXdhjafE/6Hzh7iXNOq0GhS12P2d8ysaJbcz6rLiZ8LunfuMWRPkhP+xIKHaGRY6jhEPpkT", - "Ic9RPpV60Pgjk0Qt0izpcP1TiOMO7TW27sd7VOhCit7WfwcWc7kfUQbi+Lf4pelSaWPxCukFrww0PSMy", - "2eJSBUT8kcSmKlUjO3830UExUt+VOS0/opsbdBn8kBgv8D6jWNJUpK6Dps6rlevuXmoa9Mf0sHewwG6d", - "7Wq9Vgmof9HwNY2UTy7g2sZM/EeSVTFv/M8nqu4bDnMG0LHvvTaobfnWbY+pbfkpBl1F+hrttf96eXb6", - "mlEvN3YFO7L3k3kpJ+hvQBc7uGHfcsmXoKfeypu1UyiDE+r4g/+0R/MMPq5HxMUYb2fsZPYocjSi4n5y", - "NIfTY+/UHCdE7wnAkBB9aa5IRKXdTWITOpKpKy5LtViwZ0vFq4KVMBfePYtZHe4bXjrD3xSU6RAzBgq6", - "x/TQtxin5K5aS/9w2k1cmOjRLf3VgE4+dLrloSBF0YrJtdjb3MvuKLEDuF7St4V2Rv6+IvQPku/TOusD", - "9IimpGx2+lRiL0uiQlrQut78PkT6Rvroom9JQ8Ge3kaeBiA/k62MSMN9jNeR/L472Yr1PfVGnhOrEmsT", - "hRPXCtMEpWJrtUYyOOEU/Nle3WtEFY4jYp+dohszpAYMKDAwJSp0o6WkKExdbaKIoUkY3RLcBJMGSO4c", - "ZNk04vpTRhcR/aueoPrctLmks90ePSa6DB7LdLxFJU7U4YfWXGjl91Nb2sg7njeNDLIG/pumSj9/hz57", - "FuvziljDX0v6RBU9Ehuvue/demGOuQTNtemHDGus6UL+VluEO3RFGHYwqNCEBPtQo0iiO0iwJihpTam2", - "EuugbyibwUmQer6C0ie3h4YERdMSUpj2pWtYSG0s8HL/QqgwAVtCDHV2CJDf1teBFmQsbKjDXZ3Vizwr", - "ND0AOjQ20NfTqrAMn5tHiwv70CyoYKZ2m2H8LdDTILNDjcIKeDllPyrLeFWpbUBLWAx26MqlGrs925ej", - "3AU+wZA8wZSnhmpQkcQzXMjOhXma+4gsJzrH8oa0pjULYOiumoGxlbmf6dMU3j1pIzm7251rAWl/Dkzo", - "sxrCeb5LjoTDQYAtbD415f8T/ayeCDNi8wz0EToDnTHyuaXWPrVgVke8tivfaHHQ+YrJAyb03Qm0S2Uz", - "vkKmUaBaArzpS8KeYe5I0hkpvIIyaMVLrK7E/BPKGG80YFbLkvIYhGYOC4fNbaxeTgjd9ba9DCXtuxRa", - "J5V9B0dsJ0bApzfJMM5eBbRAeeRe9xfJ5GXeK/XSo/BJAq/JVTwjoz7NJn/+mkLp7+weJMVa4rXu2L7A", - "bT1ewue4eQZ2CyAZxx4GdNzFSNCydTRNh44uvDF8VF6G75MwfsFDFTLUSOiTx/Eb8snjxLv775Zf8oBJ", - "r+Hi9qEQJrfz1Z9baJdCD7LITxJYKTTMrdK7Tie7oGYU8QkBJtzWjqVnsx1K1yl7Iy3+6P4qUYvGWp4K", - "Fpap2r5gUa8uGfhn3QOhJQh527DDqhPEeFcBKkIV8Gto92t3c2tVL1dsOqUSNrNbV0JeFb7VeG3ytUOR", - "afU+XfO84mZ1ZMA9ZMlEqDhFXVS7a5hWyoZOQA6WpulcCDYO6Ty/K9e8FvoHYewtVcuRKLA7uqV78f7c", - "XIS9DMe5te4z73D23FpdtzMYmqZ1sgw2Z2gZ5Zt2kiHpn6cwJT7tK5k1rLnI+Jt8x8bf00URm1Lez1nx", - "MP6bffXvCXIhrV/nzMD7blr5GSe1csONCbHiimOX7vdsxudoAeL7+ZRyh61ba8Mfr44bOzy3hlrzG98P", - "7/nz58Xt7fGepLIWMTNGt/0Z78Sgzux+054F78Zfnj8//Py1Xae4DpLkS6ZhWVdck36bd4xN2QXcWDoo", - "ba2ls5U2VBduxG9A2HnBqMMFBdf8k0yq0LPi0Y9op9Q97Bm95xT+lFzph9VlX/mBBoSj25E/9zmM3VmG", - "mSA2XHI8ELP6ehqt09Bi38lwZ5Is/cvJpfJTonRhnG6nqtpigfwQrb3wx4AGo6prJ+s94aOHL/RqSq7c", - "bfiy3cCpwPZNCNL5f31XhDvlZzsGNxYkJiAM88/pmuJFYxo2PDwD/FE7/pjr5b/frKvfvWGQI93QMOhe", - "vP7Vn1MyoPvu6fXz86YqELNHyFtJ9+D7iySOhMxmqDDpKKSqdoW/ihTb2w/o+nhxhJKxZzf24ksiOf75", - "pAd5SGoZDkMFr2XH6em9nHm3JspOcoi23AWN27DA2h6syaHqT7EUsmALbuzRQuktD8XcDWDzFcyvVLh3", - "17sXdGL55Eye4DRo8OXv7Yih/FsuOBDxfoMi6WcaylRDUOlZ544Fqmm0h2lSp7/9oBlBSDfLUoMx3VlD", - "VC1cm9ZOQegaDp0E0H4mgvczxJl5pYGXO7qDIVusrJeQN+6+fBLjbh0vowjd+pX2N0b8AaL6x4Gbn17K", - "xDy61iWu4XqQW9m8uXImiVEXiY7C5c6p9otKzK3xeSxLkEg4csn8RyjJHpiy8+TiSQ9Omt2HZGlCJk6r", - "Ll9Yn40uYS91D9Lv6e+eeOVxns+g+8xJeBPa99/m2qC7S3rkBjcbZcKZQ39cukeLxBPsDgYUkvranytc", - "VGbOK59K3Mq0dC8zWa9nFJfztzGulLEFU9eg2fcXF2fnRXKbC4ny/AVNA+3LzpoLC56i0JHuKhhdYUWw", - "ff6+hzFkE92N+GiB2soGdJKl0jrfsrv17gk3692d9uoPs1WZ7hh9PH/2PSpakmegY8fnsxX7MlK7t7MP", - "5K351jMl6c7x6uZ2rnk+VZQyONPU5IdPFm3fYf3EpT5jTuYkpf+PcRzHq3/HCNbkluW2oRBOXZ5efj3+", - "dqMrcCRm8/c0nybXNI87iP3dz2ob4kzeK+aM36FD+jzi4SnkUbx/fGy/nADdH0D4B1Ddfh0vlL56NGOl", - "yA4kx4zRihHtK78MdXz+Gvdc/Taq4I2/N8m2JIYoYmNm6kXaksXolHEEJmTt3Q3JAL6ZjZLXoA1dRkQJ", - "m8YqFeuK2zmRdBuMT99NLn29OqS4bCKmDlKpHlpkt1LT4kX/oucSSBmR7jelclOqq2rujveX1Wrfzcav", - "KYzP8QK4eGNujkW/VfrqvEkr/e9yzr2CPV6hNhyv+wVm52p+BdYHHOguyDQb0o9RMM7wyhVmVlBVTnlw", - "2kATzgjOFKTjyjizC8WvWMRrOYNVzZqiTk9mpG9sQ6PGePvkCq8MndMV3RvtWLb0njm8m6i2m9prJo7L", - "wBSMV3hppQ8fhlIgmpNuFg7ajfTvdh713gcjfgO8shnv44o/rlRFN3Gx9Ia36FoFjx64EcEhS+tE1vAV", - "fHNVAvv6+fPn0RfnHg9XdfuKHA3c3BphSS6oGxFkCRfDDUrF2y+Zyw+K18zde9BuGOcLYuKO8optNhuy", - "bAg2XN/8545F1snNXlkej91Pu3o+3t1MB4+j1UHXXanAyAObzUCN94o9Zo+6MMdQnzr/e7h2a/qH3eGP", - "H/9fAAAA//8=", + "+tLAXMnSPGNwIyyUfly7ArYhwNzgSyVhOikmIOv15OzvE3U1KQgO9yW+OPm9mNjdBhBALeRyUkxuTtwL", + "J9dcS752i/r75Cdc1Fv3Hn0896PQX6/8WJ+KScWNvUT4L7ntY+G3FcgWmO55ttXKAuOsEhKYVUxY41Ex", + "KSYLpdduqEnJLZxYsYZJMVGabd1QwjJjubZQTidnsq6q7nI+FZONKB0g/nshLSxBux8MGCOUvGz93rxn", + "LLeAlGWYkgy3/ZxeiZO1V3exAuYHPXIrcO9nALLcXA1Neg2yJNLu/PSpmGj4UAsNpduRBPZmwPg6LTos", + "obsrRSDSZvPV7J8wtw6AdJl96p5r4BZKv7fZrektKbwz22VXvFD6Ko7YoRZhV8z/vtBqfYakQ2s8MkyU", + "TC3wK6Qiu3Kc5P50r7ArgI0pGGdrMIYv8Vv2ouJ1CeyFKqEIbIjfqxJupjnok+n7AD7HqY4MWwhtPCky", + "DaZeg+NGYTywgSoKNq8t45bFRResliVoxpmErX/6stncZ4zPjBMGDkhlVxCHMlloB6hqrUqo+uC/hw81", + "GJQf7oFnDNYbu0uESUR1CQteV3bKnof5mZLVjpmtsPMVGDYDuwVkSMPUVjZv4sh5YNVWgu5D5bioUksh", + "2XalDLAKeMm4I0tCqTABUIcUzhz1O3YLrJmZSasK+hNpuBawBX3GOKPPzTDsiQFg7/Hb42e9WQyrhLEO", + "tGvcaTDAVG1TaSvWmwrWIC04fnSLmBRxyr7cTQVOHKKsHEf5Q2JS4JFYwXi5nTLzuRv9NY3Y+/59nKL3", + "04tmzrbs6pyVyY7gju3bj0bKtQf5QVWV2hrmuA0JEKkHP4V92XLDvERhW2FXZ2y5sSf/4unMHahOWCM/", + "F+4g1TvPNzSU+62RAel+zfFrRHIJN9kN6rFnfwXJ4AkxibJgc0fMks12bLbT8IwpjetCSJldaYcz9xyR", + "di2taC08ChmUWShpDHIbvZpBc+fE6JwUxHzJiUEyIrfI5hxBPmpJ9CI9ErLnibV8vlp7Ja1zmnCPtozI", + "AlleOn0gf3SLNV9mOBq/PmMlt5z9+v7nLO1dCVmmTLYQuKZSLBaTMLD7ky816h8OZQ4Fkm/MSrnTs9ZV", + "ljzWoNc8RxR+sDP2hp5gRtV6DlnwNjynPTogz5iGjTrRUHErroG5J6fML5lL+sTck0yQkuVl1lbpK6vB", + "nXgzo6ragiO+OA4qXHmx6XTm/mIWizO2FBZlJpK35nKZX03A2h4dS9s9+7xPVXLbcFBPwt3O0eX3lZpl", + "KJLsiUt6/OOwMnOPClB2eTnmbQF3Oy58KfQrafWuv2KxlAon6e6z22H6kXQBcO+fselSWPoajRb3C8lX", + "uJlXTvQ5AjRsze185dRzPBBKoWFuld4xPlPX0Ka3mVIVcOnAdAdXnk7EHzDEFWgtiD+Q6mc7C6hsxJ0R", + "0v6375rJUvV/t66EvErmSyAJBNA1X7htkMGEKdgCjyy04ZgfkVn3mLF8ZwInBhacErLOug83ikR81GFu", + "o4S0hkm1XYGGwiMTrsUcCmbU/AoQwRuxaR1lpXAC3Qs2nHCkvhDI5GK3gZc4SPrNDzRg+tVbGrxLrriP", + "fsYG0X4bi0hzA5T6szDWgdijVYf1QLYW1uaQYR+pPm7ohGvNd8Ny1umekViLloxs7Y1WyqZaqPvRfZcV", + "glbXcu6488B8aPGvHWf5hTrakGwLGpgGd+5DmeObDvJxZUVEVjp/DuHRl9LGtbeaDoum8GB27Ovsuc/d", + "crN8jmr+5QHD/C4yOJz6Y42Qc8dZMuiyCNaRIceMQcHHWW3AGTgLNa/NtN646UuyUMl6sSvYsRlUylml", + "asreOoMJud29yYRTD9GmgfWAJrCrFE+hbhC70cp9HDxW4UMLNcNCcPiA7TkcPkw8Ggu/gQ2IB88fJzpe", + "rJyakKGGshQO6yavAsyE5HqXl9IlVLDnVVWVl3k+1+BElN8u9wibwcJxHjIy/rhXO8vabrVJ9UpellCS", + "Xi0WAj8iuEB2IM7vp7icI2oyVt0Ab/vZigR3KTIi0ga3onGbtveiQXZfTpFmaeSRZb9e/HDy35mFG/sM", + "/3XEjMIwf6wPY80f62MIFW5sdow90hVBW6mqNOStQHMKfTTeb+SWNF6i+tPL4yid2YM3hO6Xzrbo4Xrj", + "VKTskgbwlYeKhslO7SRTZt6W7Ej8SxL9xYOeTf8esYhYrizbcAnMrNTWPEvtjfAgemi9gCFxZ/Pu0Nmh", + "g/yCm6sLPvNPmzx9ul9I/DqRvaktGcyF08GULkFP2UXUVh1Y9AYpcFEMj1IsUng6esWgg+TCI2gAf719", + "OCQKEBGEvdzmv5YzdfPawjojcMccsrNKza+8Ftbn6LscwQMTde1xdEk6lLnlbpR2NBNgBdRVionmFi4r", + "sc6HMNpnZ3sXwuhnDK2pG8uevOH6qlRbie4k3J35Sok5OOUdIxLcsH+csCfsGGXdP9gp/vkv4c+NmF+d", + "KIkK+z9O2N/Z7+lzf7/5PX2Oyx25DpHOjgsWACrYdrW7RKxDWTCFABv2BPh85QE6MjhSQ9DHBVvXlRWb", + "CtgTq2vycYd5jp3+OlfrNcgSSvYE/WlcX0EZFniE4x0XjEcnjZkywvoZCfYnJCYlr6IfXS2C5xyVGRpd", + "OhKoqt3xlLU264zhf1OWbtmZdw8Xybc0U3Qbux9O6Ac67I4LP9J/ykmRU4iE0sLuUkryyJwUk6V3X6H3", + "1ZlGOzHSIvo+jvEjjUEu4XdhumLygxvrsEqmwajq+pYsE18acB20gqKjJBeKhff+tZz8IhyZfZxDOpJ7", + "rDlHMfzhnT3xLGBWqSuGEUv8LgyBTlxurgJVxhejdR0jOw2d0fPCkauSc/BGdngTboSxrcAAyXlEymi5", + "TpubQ0v0zR9ELjrND/muyGl7Odr1kxBX6sTtSfJ05KitbxpijVI91d2DdzcR6ilpNTQxeM4QQZX9o+Yz", + "CfQFQoS+VSFf0+vfdDeng69mygPgmpwt0gjC0RAnHu4M4dzlpCyhEteg7+d8dWsYIkN/yrSW2qfVroYz", + "qIl7n9no7b1wL3wqJs4eHskIYTX+pehjSjfuoDWao7FHIIWRO9EWu/TDWdBLDMigGzxjcMPnttoxp3xQ", + "5C3qIo1a4TUT9CslDzlFJDzUko+j978DJ/k1UWY7xYF8G+Q2QzE19XCTW6UHw5n/mVfJ+xydJ4leBu4w", + "DgjIO9vuRoRdWotkhuMdJKILP2tMtdl4FZa8r8WkFGYtjMkqq8mx0RoC3ABcmq0TBc0Y+NnUG9AGygH9", + "9w3pakO0jaGiDLF9X6kZE6UPwNYbd0C474r+djqtmIahXTKihLj7tyOogeyENxiwJe+qMKQJcFmyijt9", + "QkkwU/abTwIqxWIBOgkcN1FTHL1oxZCTrIXo9AnarXfL5WkrS/lv+I7NwGselJXk8aKBLcU1yBHG3JD7", + "4BdlxcKntb3TsDC5oISYrzB9RDhCIpWHSffijlBH/kb0SArNHGFhDJptHJhTUi9SJ5BXEi4Db2Ym/V/h", + "J6+XIY+GF8+YM0am7C2Gu0PuSNY1hDp9ZvyWEdFocf0B9sD4i5InAaQoZwaGaQyRzECp7bIPFrKccu4J", + "jNnX6zXXAswIj1NmC9KlNlNFDLaXkCOld1zCgEsIfdjZ+IQzKrcrURGTzLTaOlraClmqLcYr8NUYCvQD", + "MaDUF8dNQkbR0Hg9RqAgwJRfirZiLjY858MshdlUfHc5GExcCnsJay6qwV/Dq7kUl21IYUSuWnF0iBqw", + "jGNQXJQgrbC7Z+T/t+7pJVgmFbOaiwp0VrRgyOCwDkSPFe01JjCni8sizpvA95LYN4hg9NpkkuXc953c", + "BCR0d7zoayid/beydmPOTk//s3769Nu5E1NHhq2UsfgFnNH3biT64nT6eXGNxpjyCPQupwMq5DsyyB4l", + "Q9IL0MuZ5nLAYzygVQ7ukIa1skM/bdTlOA90irbmtR7Acbrb5Sx4FA/pMHvWNnoBPdgH4LBqrqqBQOmt", + "/DkcWW9e25DmTJ6T79j/FN/vcb0HN6SGOYjrGDfqLJubgVyqQ4nO2eSKMO+RYYu6qlgFcmlXrSSLPtuN", + "TV+OWWct34V3POA6CFkeuIPbYnKpPLU33UKQjFfvWk/0we/EgCkb3yGBAgu85Bune85VXZVO7G+4Nmhd", + "lQL/1jBXSykMMCPkHEjL8gnqBbuCHZROI6LVT3N+TLfD0uZ3Y60MTuEOVqf+Fk7pA+PjHKOdXG16/nTA", + "neLRGCHLbcX7eKh0JL70tkKTM5ykFafHAD1WKsDTtDZQeA+jU92cBRscfUeGUbC0r7bmwhp9JIYM3AMZ", + "w3cR4xAERCdLyZ365Rnbrnb5DHMhhVndj7MnmlI5V3FdZQirVBJSly5hpp6thb30Tl6ulzX6Qc68Drtr", + "gibHqPothCyFXJqCYbgCjQED16CF3RVszi0sMZ/GCltBwUqwXFQFBd7RpBMtlbChrJg/KAdKOLpWc5Mr", + "7RY2KTz2R3r7iZA7GdHJly9pzOSbH/zw91TW0fHvJsvPOnt7ybvBlRsCZQeOWJ/n/SXcBBut1pu7Ogr6", + "GieONiJmTs9lcRESfO8WL52rtWMZs+I5zZd+xaCGBnBP+eKGDdfeTkrzy44M++nV85exxmnLDbP8Cu5R", + "Vl3Tmj4MB6qPDLpajPX1aNHwiUEXB5Y/3bznTwP4hAtKajQ2rovVmybVeETCx5BK2wf4nTJ4vndMiwCm", + "KYhOv3nmxdwCK+9gYU7d+XzqHjenHz3XfTp1751+lJ9ua1gUk7C3Az+K5TKXamZrLS9Blmc+UuZtHpDl", + "iVqcoNuLyGcanVRPGv6i2jl0mdLrqb/XKlWxOa8qc1zgH5fuj4K5NazqNSeHmqMRzfhmA1xTooySDfaI", + "8JzaAlxXwgFYi6o0acJpyAEs4mLcxzCfk11hQve9m26kQA5MeUHIexPn6fxwUWv5Cmft/qBU9YJg6Pzy", + "3Fz95CHqvkMAHpDNGXEsJy05kBBEynANKRyWzzGrrJdAKa7hEik3fzASdL7KMifDX2FpDNFQKMZEddWJ", + "Is3R+1QwUVbQ1DwJiSne5WhVs1UqmxHo5ewSjYmROWBJGeP4DMfKYQrXmcHC83T9YNi81k4eV7tQmZsX", + "Aj4cO4D7jVewLxvn5mh93GSckQfsl4ZcMgYcCfBeNgXpaV4PJ1/iaAuFEHPpOH3A1dnUNUu1LZiqSgdE", + "MAJuZ6248d7DIhuTN3A5r0TY2ax2qG97MGaqrPuL/EltGYameFwpyuk137GlQv1X1ZbxdkG3jzYIy8io", + "Ynh81vOrPJH9odYzkWPd88CPPpsngIBqt1SswuogoumCkpU7ZI6MvuIGa87DttB+j9qU/4OgHbQdE/wn", + "vN7j44SfirZoa+9xm5e7lNhmm74EbBCa3+Q+3+Yk8gU3V5m0WW7g0ldL9TPpht1280qZodrnoG1hIo3T", + "tNagl1CSt8HMufaCeKSLUVU52/S1LOGGCelV9l9fHxmacMMrsBacqmDEUpJvFk8rjNVy5gastSMg2jF6", + "DXU/CrY5PQSjX8yxguMWJwT4UuWp/WuoLJch6yhquF73picZt3nY99aIJ3mfwiBWkhHdK5kab6T+WxV4", + "O9q4JN2jDwJRDq3RfKi5WUWDhGjMO2wZkeqzNJbp4CGQpfIV9opIMQsfAfKhhnofXb9xT+GgOpagU5SJ", + "yyQ/V8ReEZRP7JlAyGXEmU8FAwIp1MWG9hDSoVsYtoLqFrxCa0BfxcB2up8irbQQSitb8yswZ0keHL7Q", + "1PQGrxjWktCCvc/EXiaz50sQlLaXTuAMZelrE/Pb0yCL+w5jhuxJHMLtZfzjX//9uGAbbgyUwTvtTXhn", + "I4BeYxYoN+zd2/cXe/WifR01OkUSKDsmHuc+yYFk20gLwQlkUpOfh7Gar96EUZuvXjbju+MrbHLfXFOl", + "uhQ+f/oACVy8ffl2uqbQcFtm+xPw9nwePAG3icS0kwRxZW1ijmdRd/yiOcFSAgvHRlJwcpsAjkM6Ff2Y", + "/JGZR20QTZrcCU794DpW+0deP0ECTgjdS68Yi24LtYJc8kWou99ouBaqNqlnGSs08y7a6hYpjEmxUy59", + "SkNu4VjxuWhXGXLDxIKaGJDoxVJAY/kSU8R166wahr+bW0Bbi3CEpQ1u34BncIhvusFVfGxo8Asq/Aiy", + "wGouCSWOtDzdBACLSZBASOghkRszXpIM1cgEo6XH7CKd9oLPXsSZL/jsBz+5e66Z/4LP3kUQLvjstYfi", + "gs/eR0DwIQ+LW7B//dwH27rBqoqqLoUUa4eOb3LiVavtwad64ZsKVWM1kL57oUqVKbTFbOrs4U1yq8de", + "1K0qSkJu8fzolMQmqTKRkcYZgapUWMtyyOLwgIfxh1acr4uZqXLn+z31a0LcgEeGCVmCtKgFMw1rdZ10", + "nuqLMv/SotaINowkZo1OmIdGGJmjBm7igS6Ba6dGr4CXWHOO5fQBvoziJsxQOVFy+A0DjsqEA7uIRq3b", + "V6xgQevTp3wG7PjklxEJb+FAcjhvEDC0YefuHM0UKQ8GBMZqb3RkKzqox4KdhdL7KXowHogbPHwzsBy0", + "v0qvcGUk0TqfBPeCfggmQ3riUn2GBnk0YFHktcUD1bvx0O30CML+EjglZX0m3YJQ+Q7nW3vAYlJLWpvF", + "AigU8olHE3nYCSZpHDIGoUpGyUQiuF0Zkhn52drNICYjxPfauzPCMZjA1y75TQHLbrlPsn+wZLnROW3F", + "RCZZrZebkNa67wTo58F+TmpcFoIhpP2Kpf191N0ZMx3ARyfvea9bfw8xnD6quDK4zLwwD+4x0pvcp/iL", + "lyn56so7dlQcnZTnC5f8wvq4+ISMulCJKjqZ7TSg0NPUunDydPp0+pRqK0DyjZicTb6dPp1+SzXTK0Td", + "Kd+IU16uhTxtjNMl4FHjUIz08bqcnE1+BHsejKBWVdPfnj69t06kfoZMK9Jz0NegGTVuRBOnNnwJU/fs", + "p4LWMasU1UZvlMl4Xs4t9vJpOkUpzWqDbXNik0QqkXaHcghJa76l559Rt7HdBpWKEizMg2VLucE7C5QI", + "vK6NZTNg7375sWD/8e7VjwX78fUPzl75DWbvpuy5pVSmf2NvxPdUz9nG9a8xo2BCdAHGfu+VswTPCNbp", + "UizaCI5OnqZQv0ds9Oo/N7C867sbeedXtzDb3PbdFoNYXcOnHhl+c29kiJjPECH2N3VUVDJHa1PHXN8R", + "+eeGi/CdxlSz7775dvTTHcI+/ej+e11+2seikWb2MuhfjHD6m+gweWSIZUmzR+b2KEIm95v73S22y8lV", + "zddgQTvj+uPEnf6hTQWdhRPaw0mXmotkTd0V/B7IgLrvJNufE5En6GKjR6fsFZ+v6A/qFyuoZ6KBD8+o", + "S6CXctioiHHD/uP87S9T+tP4hIqfubEn+M3J65fsiXe70G8fatA7Fpd9jDU/GpwC4piEAn4YjwsQYeTB", + "H4RFaEvCbXDVhg5DGjCX6hltTgW8/B+Ip6aRiX/S2zFzXlWYutf0K4rLwCG4ZNjqiC2VH0M1zYhyQpiy", + "X2mISX5rnRWKqrXf3BamJkWOTofi9J8KPyZitBkS0Xw/QyVpdYO0NvCq797ae6+pXfn9oNBxZjyR8Inv", + "bd3i5IN8SyRKr96BOQMTkcdsiIdeNxVkBVuJ5QqMZaF+3LsDnsQmFUtuY6JuwRY7cVxQwYuP+FOkn/0g", + "Kkc3THKtqdMK8yWqGsmQhwjPkWFpR183bI4yfxbGBpdbjiw7m9dyi9966z+DakIy5rhDN20eMIKc9p/u", + "40vtB9xqPfJ7w+0cfdBUXhj8YkKzCOiUvSSr37hdxTJDXyzXpb/T1uLy6upzLHw1rXw2mltISgmvZ2tB", + "GdwsPKwxr6WVfeoeja1L5BzzL9wxUFbg2+5L9Aa5c6FfLYiSuJahCjdHjr75wevoih7SV++ukLWaLIxS", + "Br80uTgtw/fEi0Rwa2XxFgLOPf3vdxWHpx8diAdUy2b5D2gAJjjO4xT9lVFha1jvYbQ1QsvdtDVyfQxh", + "8w08JBrR1zWAQacpORZHvccjos4ASW4fD+f9s3TiWXoAhr4rcgLLeuTcjmMbrlrD6SJUGg9RAJUiP+A6", + "aYLMQmMX35QUjkyvKVubOrpXJ8yVLsl4oExqaioQrqBoxmoa4hXkNHcGBJ9N+wp3ipP7J7gEHY9Ha4N7", + "kLgSqIHqwx4PLdJ02vypVwn2+ctAlia5P8TnyHWIprG3CgoiUSvo9AqEXDyO/RaL6vFRYdhalCe+3VWr", + "HcUKqhI1FRPqaaxhEm7oKoCcRuLT5H8Od07cPzG1+4uMIqq/3dvkrStqBmirhf8UoVtfoaR0xC1mvn6O", + "rEOCClnyg7bVxT7iiUn2Rcd4ek4JMBgeZeH+D9JqkSYo4Y1iw9R4pW8sOUIIScOTx1AV2zs0Tlts7rVp", + "IzeN1BC31llmtYZt93dCaaN/b0OUnCrQD0E9DG/lQl3/DyoI7mw8iVrC3kN2m6Sd0GEr6FYLtEdlt7dI", + "I1t3znwrGilLrDbn8siydXMRQe8cblqlPMwWN+OP2trvhlAD5WfsQVrEklXSnOh412TmP7zYCPlSIyTG", + "86oKalXU0/wp3l4EHVFh5AfazlanikcO1kSk5RnWSUOPqHugldOP/tMBYznF9wNJqQPrbq/5vg3jiIW7", + "2cY5dJ7Gar5BZrzwRTEPz4lY5jLy4G6ct7iCbleKrwn/xYCqT5xrWjnzTTJxzMeNse5myf08p5z4uaA7", + "pB5C9iRZuo8seIhGhqWOQ+SjmXV5jvLJrYPqOCmIapHmrYarXEJkbWivsQ033olAzeV7W/8jWMyufUAZ", + "iOPv8RTSBbHG4nWwC14ZaKr4M/m7UgVE/JnEpipVIzu/mOigqJXvsJoWhFAXdl0GzxB6cL0VH4tMitSY", + "aypvWtnH7qWm2XZM2HkPC2y5166fahXl+RcNX9NI+XAv1zbmRj+QrIqZvH89UXXXAEUwi08/+k8HNK9g", + "dT+g1Bnjf4m9lR5EjkRU3E2O5HB66t0s44TIHQEYEiLPzRWxaNpvIbbFIpmy4rJUiwV7slS8KlgJc+Ed", + "Rhhndt/wkoEsTUEejRjDLOhOvmPfLpfSTWot/cNpZ1xhoo+p9NdcOf7o9O9CQYKiBdP9sE+vl11RYgVw", + "vaRrC62M/HlB6B8k38d1HwboEU1JId/0S7L9qZAWtK43X4ZIX0kf7/BNMsj93NvI1wHIr2QrI9JwH2Nr", + "/S+7k63ow2Nv5DmxKrE2UThxrTCNmzw2e2okgxNOwbnm1Z1GVOE4Inb+KLpRDCoJR4GBSRqhpSKlaWAy", + "XRPXCG2L6MbLxr09QHLnIMumNdBfMt6B6F/1BNXXps0kvbYO6DHRZH4o02mPSpiog/etudDK76a2tJF3", + "Om9Kq7MG7qumbjh/HzR7EiuGilhVXEv6RDUGEltBue/demGO0c3mCuBjhlWfdLl0q1D7FnXawwa2Cm0R", + "sJkqiiTqp49VCkmzPLWVWJl5Q/FVJ0Hq+QpKn24bSqSLpkmdMO0LhLC001jg5eGFUKo0FqkP1ZoHyPdV", + "mtOCjIUN9dyqs3qRZ4WmKrlDYwOdBq0Ky/DZQrS4sA/NggpmarcZxt9oOg0yO2RNr4CXU/aLsoxXldoG", + "tITFYM+gXPKj27NDWZNd4BMMyTNMwmioBhVJPMOF7Fz+pLkPD3Gic0y4TqvssgA2F7r3YGzlEmc6x4R3", + "z9pIzu5254or2p8jEzo/htuDfd8OCceDAFvYfG4S8mf6GT0RZsTmO9An6AxzxsjXluz32IJZnfDarnzr", + "t0HnI0YyTegEEmiXEvl9zn6jQLUEeNMpgT3BpJCkV0t4BWXQipdY74XRcMphbTRgVsuSgqpCM4eF4+Zm", + "QS8nhO56m56HIttdCq2Tyr6nHDY4IuDT6xAYZy8CWqA8ca/72xDyMu+Feu5R+CiBx+Q+iZFRj2aTv35N", + "ofT3zw6SYi3ximIsqHZbjxdKOW6egd0CSMaxqpqOuxgJWbaOpunQ0YW3347K1PeV2+MXPJSzT61NPnsc", + "vyGfPU68h/qAufZwaXjhEuKhEB6389VfW2iXQg+yyFuZ3tLf7q0V1IwiPiHAhJuHsRhmtkPpOmWv/K3+", + "ePU3atFYXVDBwjJV22cs6tUl87f34wOhSQF527DnoxPE2D0dFaEK+DW0O0i7ubWqlys2nVJRjdmtKyGv", + "Ct/8uDb5aobItPqQrnlecbM6MeAesmQiVJyiDqrdx0grZUNvEgdL0wYrBNuGdJ4vyjUvhf5ZGLunjjIS", + "BfZrtnS501+bi7C72ji31l3mHfJpvcdePCZr5jq28TZnaGLj2wiSIemfpzAdPu1rKzWsucj4m3wPuS/p", + "ooht8u7mrLgf/82hitwEuZBW1HJm4EM30fUdJ7Vyw40JsdKKY9/gD2zG52gB4vv5JFeHrb3Vqg9XWYo9", + "Z1tDrfmN79D19OnTYn/Drkep9UPMjNFtf8Uu/dQr2m/ak+Dd+LenT4+/fm3XKa6DJPmcaVjWFdek3+Yd", + "Y1N2ATeWDkpba+lspQ1VqhrxBxB2njGquafgmn+SSRWq6B/8iHZK3f2e0QdO4VuJ6QfVZV/4gQaEo9uR", + "v/Y5jP0ihpkgtoBxPBCz2noardPQYie8cIuLLP3LyQXJU6J0YZxup6raYsnuEK0988cA3W7vZL0nfPTw", + "he4xyb2RDV+2W8oU2FAGQTr/3z8W4X7k2Y7BjQWJCQjD/PN6TfGiMSXk988Af9YeJOZ6+a836+qLtzBx", + "pBtamNyJ17/9a0oGdN89vn5+3tQpYfYIeSvpTmff2v5EyGyGCpOOQqpqV/j79LDh9oCuj63slYxdhLE7", + "WBLJ8c8nXZFDUstwGCp4LTtOT+/lzLs1UXaSQ7TlLmjchgXb1LgM4evRxFLIgi24sScLpbc8lJc2gOH9", + "5ypcHundCzqxfHImT3AaNPjyNwnEUP6elusidlwvkg6LoXAuBJWedLq+0yXa9jhNavT92JsRhHSzLDUY", + "0501RNXCRU7tFISu4dBJgOxnIng/Q5yZVxp4uaOu8NnySb2EvHH3t0cx7taxPX7oH66072H/J4jqnwZu", + "fnwpE/PoWtdKhgsL9rJ5cwlGEqMuEh2Fy51T7ReVmFvj81iWIJFw5JL5j1CSPTBl58lVeB6cNLsPydKE", + "TJxWpbCwPhtbwkHqHqTf11888crjPJ9B95WT8CY0FN/n2qDbFHrkBjcbZcKZQ39cukeLxBPsDgYUknjt", + "tTs2uKjMnCN96GtoZVritdmyXs8oLpfciV0wdQ2a/XRx8e68SO6XIFGevzJmoKHSu6aF+mMU+lH39NEV", + "RgTb1+97GEM20d2IjxaorWxAJ1kqrfMtu1vvH3Gz3t9qr/40W5Wp1+/j+auvmm9JnoEeAl/PVhzKSO3e", + "Fz2Qt+abYZSkO8fLZNu55vlUUcrgTFOT7z9ZtH2r7iOXuow5mZOU/j/HcRwvIx0jWJN7X9uGQjh1eXod", + "7/j7Vq7AkZjN3xz7Ork4dtxB7G+jVdsQZ/JeMWf8Dh3S5xEPjyGP4o3IYzt4BOj+BMI/gOr263Sh9NWD", + "GStFdiA5ZoxWjOhQ+WGoY/MXS+fql1EFb/y96Z36yBBFbBVL3RFbshidMo7AhKy9uyEZwHfWUPIatKHr", + "UShh01ilYl1tOyeS7qfw6bvJNZRXxxSXTcTUUSrVQ9PeVmpavHpc9FwCKSPSjYtUbkl1Vc1t1v76TO1b", + "a/g1hfE5XkkV7/DMsegPSl+dN2ml/7+c8aBgj5c6DcfrfoPZuZpfgfUBB7qdLs2G9GMUjDO8BIKZFVSV", + "Ux6cNtCEM4IzBem4Ms7sQvErFvGiwGBVM6phxJ77RGakb2xD67h4H94KLzGc06XBG+1YtvSeObwtpbab", + "2msmjsvAFIxXeI2eDx+GUiCak+46DdqN9O92HvXeByP+ALxEFm8Iij+uVEV3A7H0zqnoWgWPHrgRwSFL", + "60TW8BV8c1UC++7p06fRF+ceD5cH+4ocDdzsjbAkV2aNCLKEq6oGpeL+a6/yg+LFV3cetBvG+YaYuKO8", + "YuO/hiwbgg0Xyv61Y5F1ctdQlsdjP8auno+3ydLB42h10HVXKjDyyGYzUONNRw/ZMCvMMdQ0y/8eLgKa", + "/ml3+NOn/xsAAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/push/push.go b/internal/push/push.go deleted file mode 100644 index 4a9a4eb..0000000 --- a/internal/push/push.go +++ /dev/null @@ -1,251 +0,0 @@ -package push - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "log/slog" - "net/http" - "strings" - "time" - - "github.com/SherClockHolmes/webpush-go" - - "g.fc.run/misc/byre/internal/api" - "g.fc.run/misc/byre/internal/store" -) - -type Message struct { - Title string `json:"title"` - Body string `json:"body"` - URL string `json:"url"` -} - -type Notifier struct { - store *store.Store - keys store.VAPIDKeys - window time.Duration - items chan api.InboxItem - done chan struct{} - exited chan struct{} -} - -func New(st *store.Store, window time.Duration) (*Notifier, error) { - ctx := context.Background() - keys, err := st.GetVAPIDKeys(ctx) - if errors.Is(err, store.ErrNotFound) { - priv, pub, err := webpush.GenerateVAPIDKeys() - if err != nil { - return nil, err - } - keys, err = st.InitVAPIDKeys(ctx, store.VAPIDKeys{Public: pub, Private: priv}) - if err != nil { - return nil, err - } - } else if err != nil { - return nil, err - } - - n := &Notifier{ - store: st, - keys: keys, - window: window, - items: make(chan api.InboxItem, 256), - done: make(chan struct{}), - exited: make(chan struct{}), - } - go n.run() - return n, nil -} - -func (n *Notifier) PublicKey() string { - return n.keys.Public -} - -func (n *Notifier) Close() { - close(n.done) - <-n.exited -} - -func (n *Notifier) Observe(ev api.Event) { - if ev.Kind != "inbox.created" { - return - } - - b, err := json.Marshal(ev.Payload) - if err != nil { - slog.Error("push: encode inbox item", "err", err) - return - } - item := api.InboxItem{} - err = json.Unmarshal(b, &item) - if err != nil { - slog.Error("push: decode inbox item", "err", err) - return - } - - select { - case n.items <- item: - default: - slog.Warn("push: queue full, dropping notification", "item", item.Id) - } -} - -func (n *Notifier) run() { - defer close(n.exited) - - pending := []api.InboxItem{} - var flush <-chan time.Time - for { - select { - case item := <-n.items: - pending = append(pending, item) - if flush == nil { - flush = time.After(n.window) - } - case <-flush: - n.send(pending) - pending = []api.InboxItem{} - flush = nil - case <-n.done: - return - } - } -} - -func Wants(p api.NotificationPrefs, item api.InboxItem) bool { - switch item.Kind { - case api.Question: - if item.Blocking { - return p.BlockingQuestions - } - return p.Questions - case api.Report: - return p.Reports - case api.SessionError: - return p.Errors - case api.RateLimited: - return p.RateLimits - } - return false -} - -func (n *Notifier) send(items []api.InboxItem) { - ctx := context.Background() - targets, err := n.store.PushTargets(ctx) - if err != nil { - slog.Error("push: list subscriptions", "err", err) - return - } - - titles := map[string]string{} - for _, item := range items { - if _, ok := titles[item.TaskId]; ok { - continue - } - t, err := n.store.GetTask(ctx, item.TaskId) - if err != nil { - slog.Error("push: get task", "task", item.TaskId, "err", err) - return - } - titles[item.TaskId] = t.Title - } - - for _, target := range targets { - wanted := []api.InboxItem{} - for _, item := range items { - if Wants(target.Prefs, item) { - wanted = append(wanted, item) - } - } - if len(wanted) == 0 { - continue - } - n.deliver(ctx, target.Subscription, Compose(wanted, titles), urgency(wanted)) - } -} - -func urgency(items []api.InboxItem) webpush.Urgency { - for _, item := range items { - if item.Blocking { - return webpush.UrgencyHigh - } - } - return webpush.UrgencyNormal -} - -func Compose(items []api.InboxItem, titles map[string]string) Message { - first := items[0] - url := "/#/task/" + first.TaskId - if len(items) == 1 { - return Message{Title: "byre · " + titles[first.TaskId], Body: itemText(first), URL: url} - } - - lines := []string{} - for _, item := range items { - lines = append(lines, titles[item.TaskId]+": "+itemText(item)) - } - return Message{Title: fmt.Sprintf("byre · %d new inbox items", len(items)), Body: strings.Join(lines, "\n"), URL: url} -} - -func itemText(item api.InboxItem) string { - text := "" - switch item.Kind { - case api.Question: - text, _ = item.Payload["question"].(string) - case api.Report: - text, _ = item.Payload["text"].(string) - case api.SessionError: - e, _ := item.Payload["error"].(string) - text = "Error: " + e - case api.RateLimited: - text = "Rate limited" - } - text, _, _ = strings.Cut(strings.TrimSpace(text), "\n") - runes := []rune(text) - if len(runes) > 200 { - text = string(runes[:199]) + "…" - } - return text -} - -func (n *Notifier) deliver(ctx context.Context, sub store.PushSubscription, msg Message, u webpush.Urgency) { - payload, err := json.Marshal(msg) - if err != nil { - slog.Error("push: encode message", "err", err) - return - } - - ctx, cancel := context.WithTimeout(ctx, 15*time.Second) - defer cancel() - resp, err := webpush.SendNotificationWithContext(ctx, payload, &webpush.Subscription{ - Endpoint: sub.Endpoint, - Keys: webpush.Keys{P256dh: sub.P256dh, Auth: sub.Auth}, - }, &webpush.Options{ - Subscriber: sub.Subscriber, - TTL: 24 * 60 * 60, - Urgency: u, - VAPIDPublicKey: n.keys.Public, - VAPIDPrivateKey: n.keys.Private, - }) - if err != nil { - slog.Warn("push: send", "user", sub.UserLogin, "err", err) - return - } - defer resp.Body.Close() - - if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusGone { - slog.Info("push: subscription expired", "user", sub.UserLogin, "status", resp.StatusCode) - err = n.store.RemovePushSubscription(ctx, sub.Endpoint, sub.UserLogin, "byre") - if err != nil { - slog.Error("push: remove subscription", "err", err) - } - return - } - if resp.StatusCode >= 300 { - body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096)) - slog.Warn("push: rejected", "user", sub.UserLogin, "status", resp.StatusCode, "body", string(body)) - } -} diff --git a/internal/server/notifications.go b/internal/server/notifications.go new file mode 100644 index 0000000..c16ecb4 --- /dev/null +++ b/internal/server/notifications.go @@ -0,0 +1,21 @@ +package server + +import ( + "net/http" + + "g.fc.run/misc/byre/internal/api" +) + +func (s *Server) UpdateNotificationPrefs(w http.ResponseWriter, r *http.Request) { + req := api.NotificationPrefs{} + if !readJSON(w, r, &req) { + return + } + + u, err := s.store.UpdateNotificationPrefs(r.Context(), actor(r), req) + if err != nil { + writeStoreError(w, err) + return + } + writeJSON(w, http.StatusOK, u) +} diff --git a/internal/server/push.go b/internal/server/push.go deleted file mode 100644 index 444dce2..0000000 --- a/internal/server/push.go +++ /dev/null @@ -1,63 +0,0 @@ -package server - -import ( - "errors" - "net/http" - "net/url" - - "g.fc.run/misc/byre/internal/api" - "g.fc.run/misc/byre/internal/store" -) - -func (s *Server) UpdateNotificationPrefs(w http.ResponseWriter, r *http.Request) { - req := api.NotificationPrefs{} - if !readJSON(w, r, &req) { - return - } - - u, err := s.store.UpdateNotificationPrefs(r.Context(), actor(r), req) - if err != nil { - writeStoreError(w, err) - return - } - writeJSON(w, http.StatusOK, u) -} - -func (s *Server) AddPushSubscription(w http.ResponseWriter, r *http.Request) { - req := api.PushSubscription{} - if !readJSON(w, r, &req) { - return - } - - endpoint, err := url.Parse(req.Endpoint) - if err != nil || endpoint.Scheme != "https" || endpoint.Host == "" || req.P256dh == "" || req.Auth == "" { - writeError(w, http.StatusBadRequest, errors.New("an https endpoint, p256dh and auth are required")) - return - } - - err = s.store.AddPushSubscription(r.Context(), store.PushSubscription{ - Endpoint: req.Endpoint, - UserLogin: actor(r), - P256dh: req.P256dh, - Auth: req.Auth, - Subscriber: "https://" + r.Host, - }) - if err != nil { - writeStoreError(w, err) - return - } - w.WriteHeader(http.StatusNoContent) -} - -func (s *Server) RemovePushSubscription(w http.ResponseWriter, r *http.Request, params api.RemovePushSubscriptionParams) { - err := s.store.RemovePushSubscription(r.Context(), params.Endpoint, actor(r), actor(r)) - if err != nil { - writeStoreError(w, err) - return - } - w.WriteHeader(http.StatusNoContent) -} - -func (s *Server) GetPushKey(w http.ResponseWriter, r *http.Request) { - writeJSON(w, http.StatusOK, api.PushKey{PublicKey: s.notifier.PublicKey()}) -} diff --git a/internal/server/server.go b/internal/server/server.go index ff95db4..c516148 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -18,7 +18,6 @@ import ( "g.fc.run/misc/byre/internal/agents" "g.fc.run/misc/byre/internal/api" "g.fc.run/misc/byre/internal/git" - "g.fc.run/misc/byre/internal/push" "g.fc.run/misc/byre/internal/store" "g.fc.run/misc/byre/internal/todo" ) @@ -26,7 +25,6 @@ import ( type Server struct { store *store.Store agents *agents.Manager - notifier *push.Notifier hub *hub terminals *terminals startedAt time.Time @@ -57,16 +55,9 @@ func New(dataDir string, portFirst int, spa fs.FS) (*Server, error) { return nil, err } - s.notifier, err = push.New(s.store, pushWindow) - if err != nil { - s.store.Close() - return nil, fmt.Errorf("start push notifier: %w", err) - } - s.agents = agents.New(s.store, filepath.Join(dataDir, "worktrees"), filepath.Join(dataDir, "leads"), filepath.Join(dataDir, "codex")) err = s.agents.Recover(context.Background()) if err != nil { - s.notifier.Close() s.store.Close() return nil, fmt.Errorf("recover sessions: %w", err) } @@ -75,11 +66,8 @@ func New(dataDir string, portFirst int, spa fs.FS) (*Server, error) { return s, nil } -const pushWindow = 3 * time.Second - func (s *Server) publish(ev api.Event) { s.hub.publish(ev) - s.notifier.Observe(ev) s.agents.Observe(ev) if (ev.Kind == "task.merged" || ev.Kind == "task.discarded") && ev.TaskId != nil { s.terminals.close(*ev.TaskId) @@ -90,15 +78,11 @@ func (s *Server) publish(ev api.Event) { func (s *Server) Close() error { s.terminals.closeAll() s.agents.Close() - s.notifier.Close() return s.store.Close() } func (s *Server) Handler() http.Handler { mux := http.NewServeMux() - mux.HandleFunc("GET /sw.js", func(w http.ResponseWriter, r *http.Request) { - http.ServeFileFS(w, r, s.spa, "dist/sw.js") - }) api.HandlerWithOptions(s, api.StdHTTPServerOptions{ BaseRouter: mux, Middlewares: []api.MiddlewareFunc{s.identify}, diff --git a/internal/store/notifications.go b/internal/store/notifications.go new file mode 100644 index 0000000..755beb9 --- /dev/null +++ b/internal/store/notifications.go @@ -0,0 +1,27 @@ +package store + +import ( + "context" + "database/sql" + "encoding/json" + + "g.fc.run/misc/byre/internal/api" +) + +func (s *Store) UpdateNotificationPrefs(ctx context.Context, login string, prefs api.NotificationPrefs) (api.User, error) { + b, err := json.Marshal(prefs) + if err != nil { + return api.User{}, err + } + err = s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { + _, err := tx.ExecContext(ctx, `UPDATE users SET notification_prefs = ? WHERE login = ?`, string(b), login) + if err != nil { + return err + } + return emit(api.Event{Kind: "user.updated", Actor: login, Payload: map[string]any{"login": login}}) + }) + if err != nil { + return api.User{}, err + } + return s.GetUser(ctx, login) +} diff --git a/internal/store/push.go b/internal/store/push.go deleted file mode 100644 index 9825e59..0000000 --- a/internal/store/push.go +++ /dev/null @@ -1,124 +0,0 @@ -package store - -import ( - "context" - "database/sql" - "encoding/json" - "errors" - - "g.fc.run/misc/byre/internal/api" -) - -func (s *Store) UpdateNotificationPrefs(ctx context.Context, login string, prefs api.NotificationPrefs) (api.User, error) { - b, err := json.Marshal(prefs) - if err != nil { - return api.User{}, err - } - err = s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - _, err := tx.ExecContext(ctx, `UPDATE users SET notification_prefs = ? WHERE login = ?`, string(b), login) - if err != nil { - return err - } - return emit(api.Event{Kind: "user.updated", Actor: login, Payload: map[string]any{"login": login}}) - }) - if err != nil { - return api.User{}, err - } - return s.GetUser(ctx, login) -} - -type VAPIDKeys struct { - Public string - Private string -} - -func (s *Store) GetVAPIDKeys(ctx context.Context) (VAPIDKeys, error) { - k := VAPIDKeys{} - err := s.db.QueryRowContext(ctx, `SELECT public_key, private_key FROM vapid_keys WHERE id = 1`).Scan(&k.Public, &k.Private) - if errors.Is(err, sql.ErrNoRows) { - return k, ErrNotFound - } - return k, err -} - -func (s *Store) InitVAPIDKeys(ctx context.Context, k VAPIDKeys) (VAPIDKeys, error) { - err := s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - _, err := tx.ExecContext(ctx, `INSERT INTO vapid_keys (id, public_key, private_key) VALUES (1, ?, ?) ON CONFLICT (id) DO NOTHING`, k.Public, k.Private) - return err - }) - if err != nil { - return VAPIDKeys{}, err - } - return s.GetVAPIDKeys(ctx) -} - -type PushSubscription struct { - Endpoint string - UserLogin string - P256dh string - Auth string - Subscriber string -} - -func (s *Store) AddPushSubscription(ctx context.Context, sub PushSubscription) error { - return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - _, err := tx.ExecContext(ctx, ` - INSERT INTO push_subscriptions (endpoint, user_login, p256dh, auth, subscriber, created_at) VALUES (?, ?, ?, ?, ?, ?) - ON CONFLICT (endpoint) DO UPDATE SET user_login = excluded.user_login, p256dh = excluded.p256dh, auth = excluded.auth, - subscriber = excluded.subscriber - `, sub.Endpoint, sub.UserLogin, sub.P256dh, sub.Auth, sub.Subscriber, now()) - if err != nil { - return err - } - return emit(api.Event{Kind: "push.subscribed", Actor: sub.UserLogin, Payload: map[string]any{"login": sub.UserLogin}}) - }) -} - -func (s *Store) RemovePushSubscription(ctx context.Context, endpoint, login, actor string) error { - return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { - res, err := tx.ExecContext(ctx, `DELETE FROM push_subscriptions WHERE endpoint = ? AND user_login = ?`, endpoint, login) - if err != nil { - return err - } - n, err := res.RowsAffected() - if err != nil { - return err - } - if n == 0 { - return nil - } - return emit(api.Event{Kind: "push.unsubscribed", Actor: actor, Payload: map[string]any{"login": login}}) - }) -} - -type PushTarget struct { - Subscription PushSubscription - Prefs api.NotificationPrefs -} - -func (s *Store) PushTargets(ctx context.Context) ([]PushTarget, error) { - rows, err := s.db.QueryContext(ctx, ` - SELECT p.endpoint, p.user_login, p.p256dh, p.auth, p.subscriber, u.notification_prefs - FROM push_subscriptions p JOIN users u ON u.login = p.user_login ORDER BY p.created_at - `) - if err != nil { - return nil, err - } - defer rows.Close() - - targets := []PushTarget{} - for rows.Next() { - t := PushTarget{} - prefs := "" - err = rows.Scan(&t.Subscription.Endpoint, &t.Subscription.UserLogin, &t.Subscription.P256dh, &t.Subscription.Auth, &t.Subscription.Subscriber, &prefs) - if err != nil { - return nil, err - } - err = json.Unmarshal([]byte(prefs), &t.Prefs) - if err != nil { - return nil, err - } - targets = append(targets, t) - } - return targets, rows.Err() -} diff --git a/internal/store/store.go b/internal/store/store.go index e716ca4..7a589a3 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -315,6 +315,9 @@ CREATE TABLE task_inputs ( created_at TEXT NOT NULL ); CREATE INDEX task_inputs_task ON task_inputs(task_id, id); +`}, {"drop-web-push", ` +DROP TABLE push_subscriptions; +DROP TABLE vapid_keys; `}} const ( diff --git a/web/dist/app.js b/web/dist/app.js index 11226d0..c1d2367 100644 --- a/web/dist/app.js +++ b/web/dist/app.js @@ -73,14 +73,20 @@ async function main() { }); addEventListener("hashchange", route); route(); - if ("serviceWorker" in navigator) { - navigator.serviceWorker.onmessage = (e) => { - location.hash = new URL(e.data.open, location.origin).hash; - }; - await navigator.serviceWorker.register("/sw.js"); - } } -main().catch((err) => { +async function start() { + if ("serviceWorker" in navigator) { + for (const reg of await navigator.serviceWorker.getRegistrations()) { + await reg.unregister(); + } + if (navigator.serviceWorker.controller) { + location.reload(); + return; + } + } + await main(); +} +start().catch((err) => { replace(document.body, h("pre", { class: "fatal" }, `byre failed to start: ${errorText(err)}`)); }); //# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/web/dist/app.js.map b/web/dist/app.js.map index f2e6b7f..91b892e 100644 --- a/web/dist/app.js.map +++ b/web/dist/app.js.map @@ -1 +1 @@ -{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/dist/notifications.js b/web/dist/notifications.js new file mode 100644 index 0000000..7417371 --- /dev/null +++ b/web/dist/notifications.js @@ -0,0 +1,37 @@ +import { findTask, focusTask, state } from "./state.js"; +function wants(p, item) { + switch (item.kind) { + case "question": + return item.blocking ? p.blocking_questions : p.questions; + case "report": + return p.reports; + case "session_error": + return p.errors; + case "rate_limited": + return p.rate_limits; + } +} +function itemText(item) { + const p = item.payload; + const text = item.kind === "question" ? String(p["question"] ?? "") + : item.kind === "report" ? String(p["text"] ?? "") + : item.kind === "session_error" ? `Error: ${String(p["error"] ?? "")}` + : "Rate limited"; + const line = text.trim().split("\n")[0] ?? ""; + return line.length > 200 ? `${line.slice(0, 199)}…` : line; +} +export function notifyInbox(item) { + if (!("Notification" in window) || Notification.permission !== "granted" || !state.me || !wants(state.me.notification_prefs, item)) { + return; + } + const title = findTask(item.task_id)?.title; + const n = new Notification(title ? `byre · ${title}` : "byre", { body: itemText(item), tag: item.id }); + n.onclick = () => { + window.focus(); + if (item.task_id) { + focusTask(item.task_id); + } + n.close(); + }; +} +//# sourceMappingURL=notifications.js.map \ No newline at end of file diff --git a/web/dist/notifications.js.map b/web/dist/notifications.js.map new file mode 100644 index 0000000..49456b6 --- /dev/null +++ b/web/dist/notifications.js.map @@ -0,0 +1 @@ +{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExD,SAAS,KAAK,CAAC,CAAoB,EAAE,IAAe;IAClD,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,UAAU;YACb,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5D,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC,OAAO,CAAC;QACnB,KAAK,eAAe;YAClB,OAAO,CAAC,CAAC,MAAM,CAAC;QAClB,KAAK,cAAc;YACjB,OAAO,CAAC,CAAC,WAAW,CAAC;IACzB,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,IAAe;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;IACvB,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACtD,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAClD,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE;gBACtE,CAAC,CAAC,cAAc,CAAC;IACnB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,OAAO,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAe;IACzC,IAAI,CAAC,CAAC,cAAc,IAAI,MAAM,CAAC,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,kBAAkB,EAAE,IAAI,CAAC,EAAE,CAAC;QACnI,OAAO;IACT,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC;IAC5C,MAAM,CAAC,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACvG,CAAC,CAAC,OAAO,GAAG,GAAG,EAAE;QACf,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;QACD,CAAC,CAAC,KAAK,EAAE,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/web/dist/settings.js b/web/dist/settings.js index 1d706ca..eb978a2 100644 --- a/web/dist/settings.js +++ b/web/dist/settings.js @@ -1,4 +1,4 @@ -import { del, get, post, put } from "./api.js"; +import { put } from "./api.js"; import { errorText, h, openPanel, replace, showAlert } from "./dom.js"; import { on, state } from "./state.js"; const kinds = [ @@ -34,84 +34,31 @@ function mountSettings(root) { return h("label", {}, box, " ", label); })); }; - let disposed = false; - const renderDevice = async () => { - const status = await deviceStatus(); - if (disposed) { + const renderDevice = () => { + if (!("Notification" in window)) { + replace(device, h("p", { class: "hint" }, "This browser doesn't support notifications.")); return; } - if (status.kind === "unsupported") { - replace(device, h("p", { class: "hint" }, "This browser doesn't support web push.")); - return; - } - if (status.kind === "denied") { + if (Notification.permission === "denied") { replace(device, h("p", { class: "hint" }, "Notifications are blocked for this site in the browser's settings.")); return; } - const button = h("button", {}, status.sub ? "Turn off on this browser" : "Turn on for this browser"); + if (Notification.permission === "granted") { + replace(device, h("p", {}, "This browser shows notifications while a byre page is open.")); + return; + } + const button = h("button", {}, "Turn on for this browser"); button.onclick = async () => { button.disabled = true; - try { - if (status.sub) { - await disable(status.sub); - } - else { - await enable(status.reg); - } - } - catch (err) { - void showAlert(errorText(err)); - } - await renderDevice(); + await Notification.requestPermission(); + renderDevice(); }; - replace(device, h("p", {}, status.sub ? "This browser receives notifications." : "This browser doesn't receive notifications."), button); + replace(device, h("p", {}, "This browser doesn't show notifications."), button); }; replace(root, h("div", { class: "settings-view" }, h("h2", {}, "Notifications"), device, prefs)); const off = on("me", renderPrefs); renderPrefs(); - void renderDevice().catch((err) => replace(device, h("p", { class: "error-text" }, errorText(err)))); - return () => { - disposed = true; - off(); - }; -} -async function deviceStatus() { - if (!("serviceWorker" in navigator) || !("PushManager" in window) || !("Notification" in window)) { - return { kind: "unsupported" }; - } - if (Notification.permission === "denied") { - return { kind: "denied" }; - } - const reg = await navigator.serviceWorker.ready; - const sub = await reg.pushManager.getSubscription(); - if (sub) { - await register(sub); - } - return { kind: "ready", reg, sub }; -} -async function enable(reg) { - const permission = await Notification.requestPermission(); - if (permission !== "granted") { - return; - } - const key = await get("/api/push/key"); - const sub = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: base64url(key.public_key) }); - await register(sub); -} -async function disable(sub) { - await del("/api/me/push-subscriptions", { query: { endpoint: sub.endpoint } }); - await sub.unsubscribe(); -} -async function register(sub) { - const keys = sub.toJSON().keys ?? {}; - await post("/api/me/push-subscriptions", { body: { endpoint: sub.endpoint, p256dh: keys["p256dh"] ?? "", auth: keys["auth"] ?? "" } }); -} -function base64url(s) { - const bin = atob(s.replace(/-/g, "+").replace(/_/g, "/")); - const out = new Uint8Array(bin.length); - for (let i = 0; i < bin.length; i++) { - out[i] = bin.charCodeAt(i); - } - return out; + renderDevice(); + return off; } //# sourceMappingURL=settings.js.map \ No newline at end of file diff --git a/web/dist/settings.js.map b/web/dist/settings.js.map index 9a2c8fd..20e144a 100644 --- a/web/dist/settings.js.map +++ b/web/dist/settings.js.map @@ -1 +1 @@ -{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAA0B,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,KAAK,GAAsD;IAC/D,EAAE,GAAG,EAAE,oBAAoB,EAAE,KAAK,EAAE,oBAAoB,EAAE;IAC1D,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,wBAAwB,EAAE;IACrD,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE;IAC3C,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,gBAAgB,EAAE;IAC1C,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;CAC7C,CAAC;AAEF,MAAM,UAAU,YAAY;IAC1B,SAAS,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,aAAa,CAAC,IAAiB;IACtC,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IAErD,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;QACpB,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,CAAC,KAAK,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QACD,OAAO,CACL,KAAK,EACL,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,iBAAiB,CAAC,EAClC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;YAC9B,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAClF,GAAG,CAAC,QAAQ,GAAG,KAAK,IAAI,EAAE;gBACxB,IAAI,CAAC;oBACH,KAAK,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,uBAAuB,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC5G,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,KAAK,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;gBACjC,CAAC;gBACD,WAAW,EAAE,CAAC;YAChB,CAAC,CAAC;YACF,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC;IAEF,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;QAC9B,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QACpC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAClC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,wCAAwC,CAAC,CAAC,CAAC;YACrF,OAAO;QACT,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,oEAAoE,CAAC,CAAC,CAAC;YACjH,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC;QACrG,MAAM,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE;YAC1B,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;YACvB,IAAI,CAAC;gBACH,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;oBACf,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC5B,CAAC;qBAAM,CAAC;oBACN,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;YACjC,CAAC;YACD,MAAM,YAAY,EAAE,CAAC;QACvB,CAAC,CAAC;QACF,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC,6CAA6C,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3I,CAAC,CAAC;IAEF,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACjG,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAClC,WAAW,EAAE,CAAC;IACd,KAAK,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9G,OAAO,GAAG,EAAE;QACV,QAAQ,GAAG,IAAI,CAAC;QAChB,GAAG,EAAE,CAAC;IACR,CAAC,CAAC;AACJ,CAAC;AAOD,KAAK,UAAU,YAAY;IACzB,IAAI,CAAC,CAAC,eAAe,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc,IAAI,MAAM,CAAC,EAAE,CAAC;QACjG,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IACjC,CAAC;IACD,IAAI,YAAY,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACzC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC5B,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC;IAChD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;IACpD,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACrC,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,GAA8B;IAClD,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,iBAAiB,EAAE,CAAC;IAC1D,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,oBAAoB,EAAE,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IACxH,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,GAAqB;IAC1C,MAAM,GAAG,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC/E,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAqB;IAC3C,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;IACrC,MAAM,IAAI,CAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;AACzI,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"} \ No newline at end of file +{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/dist/state.js b/web/dist/state.js index bedd0f7..8e43e92 100644 --- a/web/dist/state.js +++ b/web/dist/state.js @@ -1,4 +1,5 @@ import { get, put, subscribe } from "./api.js"; +import { notifyInbox } from "./notifications.js"; export const tabs = ["transcript", "changes", "files", "terminal", "preview", "inbox", "reviews", "project"]; export const state = { me: undefined, @@ -258,6 +259,9 @@ export function handleEvent(ev) { } break; case "inbox.created": + notifyInbox(ev.payload); + void loadInbox(); + break; case "inbox.updated": void loadInbox(); break; diff --git a/web/dist/state.js.map b/web/dist/state.js.map index cf434ae..fd2956d 100644 --- a/web/dist/state.js.map +++ b/web/dist/state.js.map @@ -1 +1 @@ -{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/dist/sw.js b/web/dist/sw.js deleted file mode 100644 index 4951ca2..0000000 --- a/web/dist/sw.js +++ /dev/null @@ -1,28 +0,0 @@ -"use strict"; -const sw = self; -sw.addEventListener("install", () => { - void sw.skipWaiting(); -}); -sw.addEventListener("activate", (e) => { - e.waitUntil(sw.clients.claim()); -}); -sw.addEventListener("push", (e) => { - const msg = e.data?.json(); - e.waitUntil(sw.registration.showNotification(msg.title, { body: msg.body, data: { url: msg.url } })); -}); -sw.addEventListener("notificationclick", (e) => { - e.notification.close(); - const url = e.notification.data.url; - e.waitUntil(openTask(url)); -}); -async function openTask(url) { - const windows = await sw.clients.matchAll({ type: "window", includeUncontrolled: true }); - const win = windows[0]; - if (!win) { - await sw.clients.openWindow(url); - return; - } - win.postMessage({ open: url }); - await win.focus(); -} -//# sourceMappingURL=sw.js.map \ No newline at end of file diff --git a/web/dist/sw.js.map b/web/dist/sw.js.map deleted file mode 100644 index f14d603..0000000 --- a/web/dist/sw.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"sw.js","sourceRoot":"","sources":["../src/sw.ts"],"names":[],"mappings":";AAAA,MAAM,EAAE,GAAG,IAA2C,CAAC;AAIvD,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE;IAClC,KAAK,EAAE,CAAC,WAAW,EAAE,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE;IACpC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;IAChC,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,EAAiB,CAAC;IAC1C,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;AACvG,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE;IAC7C,CAAC,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;IACvB,MAAM,GAAG,GAAI,CAAC,CAAC,YAAY,CAAC,IAAwB,CAAC,GAAG,CAAC;IACzD,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,QAAQ,CAAC,GAAW;IACjC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;IACzF,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IACD,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/B,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;AACpB,CAAC"} \ No newline at end of file diff --git a/web/package.json b/web/package.json index 1a1a9ff..0efc5b6 100644 --- a/web/package.json +++ b/web/package.json @@ -3,7 +3,7 @@ "private": true, "type": "module", "scripts": { - "generate": "openapi-typescript ../api/openapi.yaml --output src/api.gen.ts && rm -rf dist && tsc && tsc --project tsconfig.sw.json && mkdir -p vendor && cp node_modules/mermaid/dist/mermaid.min.js vendor/ && cp node_modules/mermaid/LICENSE vendor/mermaid.LICENSE && cp node_modules/@xterm/xterm/lib/xterm.mjs node_modules/@xterm/xterm/css/xterm.css node_modules/@xterm/addon-fit/lib/addon-fit.mjs vendor/ && cp node_modules/@xterm/xterm/LICENSE vendor/xterm.LICENSE && cp node_modules/@xterm/addon-fit/LICENSE vendor/addon-fit.LICENSE" + "generate": "openapi-typescript ../api/openapi.yaml --output src/api.gen.ts && rm -rf dist && tsc && mkdir -p vendor && cp node_modules/mermaid/dist/mermaid.min.js vendor/ && cp node_modules/mermaid/LICENSE vendor/mermaid.LICENSE && cp node_modules/@xterm/xterm/lib/xterm.mjs node_modules/@xterm/xterm/css/xterm.css node_modules/@xterm/addon-fit/lib/addon-fit.mjs vendor/ && cp node_modules/@xterm/xterm/LICENSE vendor/xterm.LICENSE && cp node_modules/@xterm/addon-fit/LICENSE vendor/addon-fit.LICENSE" }, "devDependencies": { "@xterm/addon-fit": "0.11.0", diff --git a/web/src/api.gen.ts b/web/src/api.gen.ts index 5eba1f4..278230b 100644 --- a/web/src/api.gen.ts +++ b/web/src/api.gen.ts @@ -28,7 +28,7 @@ export interface paths { cookie?: never; }; get?: never; - /** @description Sets which inbox items the calling user is sent push notifications for. */ + /** @description Sets which new inbox items notify the calling user in their open byre pages. */ put: operations["updateNotificationPrefs"]; post?: never; delete?: never; @@ -37,23 +37,6 @@ export interface paths { patch?: never; trace?: never; }; - "/api/me/push-subscriptions": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** @description Registers a browser's push subscription for the calling user. Registering an endpoint again replaces it. */ - post: operations["addPushSubscription"]; - delete: operations["removePushSubscription"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; "/api/me/lead/sessions": { parameters: { query?: never; @@ -122,22 +105,6 @@ export interface paths { patch?: never; trace?: never; }; - "/api/push/key": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get: operations["getPushKey"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; "/api/projects": { parameters: { query?: never; @@ -780,7 +747,7 @@ export interface components { git_email: string; notification_prefs: components["schemas"]["NotificationPrefs"]; }; - /** @description Which new inbox items send this user a push notification. */ + /** @description Which new inbox items notify this user in their open byre pages. */ NotificationPrefs: { /** @description Questions asked with blocking: true. On by default. */ blocking_questions: boolean; @@ -793,17 +760,6 @@ export interface components { /** @description rate_limited items. */ rate_limits: boolean; }; - PushSubscription: { - endpoint: string; - /** @description The subscription's p256dh key */ - p256dh: string; - /** @description The subscription's auth secret */ - auth: string; - }; - PushKey: { - /** @description Base64url */ - public_key: string; - }; UserUpdate: { git_name: string; git_email: string; @@ -1320,49 +1276,6 @@ export interface operations { 400: components["responses"]["Error"]; }; }; - addPushSubscription: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["PushSubscription"]; - }; - }; - responses: { - /** @description Registered. */ - 204: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - 400: components["responses"]["Error"]; - }; - }; - removePushSubscription: { - parameters: { - query: { - endpoint: string; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Removed, or was not registered. */ - 204: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; listLeadSessions: { parameters: { query?: never; @@ -1477,26 +1390,6 @@ export interface operations { 400: components["responses"]["Error"]; }; }; - getPushKey: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The server's VAPID public key, the applicationServerKey for PushManager.subscribe. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["PushKey"]; - }; - }; - }; - }; listProjects: { parameters: { query?: never; diff --git a/web/src/app.ts b/web/src/app.ts index 9590515..40d62ce 100644 --- a/web/src/app.ts +++ b/web/src/app.ts @@ -83,15 +83,21 @@ async function main(): Promise { addEventListener("hashchange", route); route(); - - if ("serviceWorker" in navigator) { - navigator.serviceWorker.onmessage = (e: MessageEvent<{ open: string }>) => { - location.hash = new URL(e.data.open, location.origin).hash; - }; - await navigator.serviceWorker.register("/sw.js"); - } } -main().catch((err: unknown) => { +async function start(): Promise { + if ("serviceWorker" in navigator) { + for (const reg of await navigator.serviceWorker.getRegistrations()) { + await reg.unregister(); + } + if (navigator.serviceWorker.controller) { + location.reload(); + return; + } + } + await main(); +} + +start().catch((err: unknown) => { replace(document.body, h("pre", { class: "fatal" }, `byre failed to start: ${errorText(err)}`)); }); diff --git a/web/src/notifications.ts b/web/src/notifications.ts new file mode 100644 index 0000000..db14672 --- /dev/null +++ b/web/src/notifications.ts @@ -0,0 +1,41 @@ +import type { InboxItem, NotificationPrefs } from "./api.js"; +import { findTask, focusTask, state } from "./state.js"; + +function wants(p: NotificationPrefs, item: InboxItem): boolean { + switch (item.kind) { + case "question": + return item.blocking ? p.blocking_questions : p.questions; + case "report": + return p.reports; + case "session_error": + return p.errors; + case "rate_limited": + return p.rate_limits; + } +} + +function itemText(item: InboxItem): string { + const p = item.payload; + const text = + item.kind === "question" ? String(p["question"] ?? "") + : item.kind === "report" ? String(p["text"] ?? "") + : item.kind === "session_error" ? `Error: ${String(p["error"] ?? "")}` + : "Rate limited"; + const line = text.trim().split("\n")[0] ?? ""; + return line.length > 200 ? `${line.slice(0, 199)}…` : line; +} + +export function notifyInbox(item: InboxItem): void { + if (!("Notification" in window) || Notification.permission !== "granted" || !state.me || !wants(state.me.notification_prefs, item)) { + return; + } + const title = findTask(item.task_id)?.title; + const n = new Notification(title ? `byre · ${title}` : "byre", { body: itemText(item), tag: item.id }); + n.onclick = () => { + window.focus(); + if (item.task_id) { + focusTask(item.task_id); + } + n.close(); + }; +} diff --git a/web/src/settings.ts b/web/src/settings.ts index f45519c..a35e310 100644 --- a/web/src/settings.ts +++ b/web/src/settings.ts @@ -1,4 +1,4 @@ -import { del, get, post, put, type NotificationPrefs } from "./api.js"; +import { put, type NotificationPrefs } from "./api.js"; import { errorText, h, openPanel, replace, showAlert } from "./dom.js"; import { on, state } from "./state.js"; @@ -42,94 +42,33 @@ function mountSettings(root: HTMLElement): () => void { ); }; - let disposed = false; - const renderDevice = async () => { - const status = await deviceStatus(); - if (disposed) { + const renderDevice = () => { + if (!("Notification" in window)) { + replace(device, h("p", { class: "hint" }, "This browser doesn't support notifications.")); return; } - if (status.kind === "unsupported") { - replace(device, h("p", { class: "hint" }, "This browser doesn't support web push.")); - return; - } - if (status.kind === "denied") { + if (Notification.permission === "denied") { replace(device, h("p", { class: "hint" }, "Notifications are blocked for this site in the browser's settings.")); return; } + if (Notification.permission === "granted") { + replace(device, h("p", {}, "This browser shows notifications while a byre page is open.")); + return; + } - const button = h("button", {}, status.sub ? "Turn off on this browser" : "Turn on for this browser"); + const button = h("button", {}, "Turn on for this browser"); button.onclick = async () => { button.disabled = true; - try { - if (status.sub) { - await disable(status.sub); - } else { - await enable(status.reg); - } - } catch (err) { - void showAlert(errorText(err)); - } - await renderDevice(); + await Notification.requestPermission(); + renderDevice(); }; - replace(device, h("p", {}, status.sub ? "This browser receives notifications." : "This browser doesn't receive notifications."), button); + replace(device, h("p", {}, "This browser doesn't show notifications."), button); }; replace(root, h("div", { class: "settings-view" }, h("h2", {}, "Notifications"), device, prefs)); const off = on("me", renderPrefs); renderPrefs(); - void renderDevice().catch((err: unknown) => replace(device, h("p", { class: "error-text" }, errorText(err)))); + renderDevice(); - return () => { - disposed = true; - off(); - }; -} - -type DeviceStatus = - | { kind: "unsupported" } - | { kind: "denied" } - | { kind: "ready"; reg: ServiceWorkerRegistration; sub: PushSubscription | null }; - -async function deviceStatus(): Promise { - if (!("serviceWorker" in navigator) || !("PushManager" in window) || !("Notification" in window)) { - return { kind: "unsupported" }; - } - if (Notification.permission === "denied") { - return { kind: "denied" }; - } - const reg = await navigator.serviceWorker.ready; - const sub = await reg.pushManager.getSubscription(); - if (sub) { - await register(sub); - } - return { kind: "ready", reg, sub }; -} - -async function enable(reg: ServiceWorkerRegistration): Promise { - const permission = await Notification.requestPermission(); - if (permission !== "granted") { - return; - } - const key = await get("/api/push/key"); - const sub = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: base64url(key.public_key) }); - await register(sub); -} - -async function disable(sub: PushSubscription): Promise { - await del("/api/me/push-subscriptions", { query: { endpoint: sub.endpoint } }); - await sub.unsubscribe(); -} - -async function register(sub: PushSubscription): Promise { - const keys = sub.toJSON().keys ?? {}; - await post("/api/me/push-subscriptions", { body: { endpoint: sub.endpoint, p256dh: keys["p256dh"] ?? "", auth: keys["auth"] ?? "" } }); -} - -function base64url(s: string): Uint8Array { - const bin = atob(s.replace(/-/g, "+").replace(/_/g, "/")); - const out = new Uint8Array(bin.length); - for (let i = 0; i < bin.length; i++) { - out[i] = bin.charCodeAt(i); - } - return out; + return off; } diff --git a/web/src/state.ts b/web/src/state.ts index 3c1ed99..999083c 100644 --- a/web/src/state.ts +++ b/web/src/state.ts @@ -1,4 +1,5 @@ import { get, put, subscribe, type AgentSession, type ByreEvent, type Focus, type InboxItem, type Project, type Snapshot, type Task, type TaskTab, type User } from "./api.js"; +import { notifyInbox } from "./notifications.js"; export type Topic = | "me" @@ -316,6 +317,9 @@ export function handleEvent(ev: ByreEvent): void { } break; case "inbox.created": + notifyInbox(ev.payload as unknown as InboxItem); + void loadInbox(); + break; case "inbox.updated": void loadInbox(); break; diff --git a/web/src/sw.ts b/web/src/sw.ts deleted file mode 100644 index d884531..0000000 --- a/web/src/sw.ts +++ /dev/null @@ -1,33 +0,0 @@ -const sw = self as unknown as ServiceWorkerGlobalScope; - -type PushMessage = { title: string; body: string; url: string }; - -sw.addEventListener("install", () => { - void sw.skipWaiting(); -}); - -sw.addEventListener("activate", (e) => { - e.waitUntil(sw.clients.claim()); -}); - -sw.addEventListener("push", (e) => { - const msg = e.data?.json() as PushMessage; - e.waitUntil(sw.registration.showNotification(msg.title, { body: msg.body, data: { url: msg.url } })); -}); - -sw.addEventListener("notificationclick", (e) => { - e.notification.close(); - const url = (e.notification.data as { url: string }).url; - e.waitUntil(openTask(url)); -}); - -async function openTask(url: string): Promise { - const windows = await sw.clients.matchAll({ type: "window", includeUncontrolled: true }); - const win = windows[0]; - if (!win) { - await sw.clients.openWindow(url); - return; - } - win.postMessage({ open: url }); - await win.focus(); -} diff --git a/web/tsconfig.json b/web/tsconfig.json index 2216e17..f76f82c 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -12,6 +12,5 @@ "sourceMap": true, "skipLibCheck": true }, - "include": ["src"], - "exclude": ["src/sw.ts"] + "include": ["src"] } diff --git a/web/tsconfig.sw.json b/web/tsconfig.sw.json deleted file mode 100644 index ee004db..0000000 --- a/web/tsconfig.sw.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "lib": ["ES2023", "WebWorker"] - }, - "include": ["src/sw.ts"], - "exclude": [] -}