From 358708886250d31686fa408297386fcce09e8cf9 Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Tue, 29 Sep 2026 16:47:46 +0200 Subject: [PATCH 01/14] Add plan for API v2 and granular API key support --- docs/plans/apiv2-granular-api-keys.md | 516 ++++++++++++++++++++++++++ 1 file changed, 516 insertions(+) create mode 100644 docs/plans/apiv2-granular-api-keys.md diff --git a/docs/plans/apiv2-granular-api-keys.md b/docs/plans/apiv2-granular-api-keys.md new file mode 100644 index 0000000..9296a0c --- /dev/null +++ b/docs/plans/apiv2-granular-api-keys.md @@ -0,0 +1,516 @@ +# Plan: support API v2 and granular API key access (anytype-heart v0.51.3) + +Revision 2. It includes the findings of a three-lens review (correctness, +security, UX/rollout) against the heart `v0.51.3` tag. + +## Background + +anytype-heart v0.51.3 ships the JSON API v2 (`/v2/*`) and per-key access +control for API keys. + +**What changed in heart (v0.50.4 → v0.51.3):** + +- `model.Account.Auth.AppInfo` gained **one** field, `grant` + (`AppGrant`). `expireAt`, `scope` and `isActive` already existed. What's + new is that heart now validates `expireAt` when a key is created (must be + 0 or a future unix time in **seconds**) and checks it on every request. +- `AppGrant` = `spaceIds` **or** `allSpaces`, plus `perm` + (`Read` = 0, `ReadWrite` = 1). Because `Read` is the zero value, **a grant + without a `perm` is read-only**. +- `AccountLocalLinkCreateApp` checks that the name is set and at most 128 + bytes, that the scope is `Limited` or `JsonAPI` (never `Full`), that + `expireAt` is valid, and that the grant has the right shape. Only + `JsonAPI` keys can have a grant. +- New `AccountLocalLinkUpdateApp(appHash, grant)` replaces the **whole** + grant, and sending no grant removes it. It can't change scope, expiry or + name. It rejects a grant on a key that isn't `JsonAPI`. + Heart evicts cached HTTP sessions, so the change applies from the next + request. +- New `AccountLocalLinkApproveChallenge`, which only the desktop UI can + call (`Full` scope). The **gRPC-session** pairing flow is deprecated, but + JSON API auth still uses the same challenge flow. +- Key format: v0.51.3 creates prefixed `JsonAPI` keys and saves keys that + carry a grant in a v2 file format. **v0.50.4 can read neither.** + +**Which keys each API accepts:** + +| Key | `/v1` | `/v2` | direct gRPC | +|---|---|---|---| +| `Limited` (what the CLI creates today) | ✅ | ❌ 403 "create a new api key with JsonAPI scope" | ✅ `limitedScopeMethods` allowlist (ObjectSearch, ListenSessionEvents, …) | +| `JsonAPI`, no grant | ✅ | ✅ (heart calls it "legacy", suggests reissuing) | ❌ | +| `JsonAPI`, `allSpaces` + `ReadWrite` | ✅ (tech space **included**) | ✅ (tech space **excluded**) | ❌ | +| `JsonAPI`, any other grant | ❌ | ✅ within the grant | ❌ | + +On `/v1`, only keys with no grant or `allSpaces` + `ReadWrite` get through +(`ensureUngrantedKey` / `ApiGrant.IsUnrestricted`). An `allSpaces` grant +never covers the tech space on `/v2`; the tech space has to be listed +explicitly. + +**Other changes in v0.51.3 that affect the CLI:** + +- **Go 1.26.5** is required (`go.mod`). The CLI is on 1.25.7, and CI, + release and CodeQL use `go-version: "1.25"`. +- The HTTP API (`/v1` and `/v2`) now checks Host and Origin. Non-localhost + hostnames need `ANYTYPE_API_ALLOWED_HOSTS`, and browser origins need + `ANYTYPE_API_ALLOWED_ORIGINS`. This affects the remote and reverse-proxy + setups the README recommends. +- Heart's own gRPC-Web proxy (`cmd/grpcserver/proxy.go`) rejects requests + from untrusted origins/hosts before they reach any handler, and turns + WebSockets off by default (`ANYTYPE_GRPCWEB_ALLOWED_ORIGINS`, + `ANYTYPE_GRPCWEB_ALLOWED_HOSTS`, `ANYTYPE_GRPCWEB_ENABLE_WEBSOCKETS`). + The CLI's `core/grpcserver/server.go` accepts every origin and allows + WebSockets. +- The tantivy version stays at v1.0.6, so no change is needed there. + +## Goals + +1. Keys created by the CLI work on `/v2`. +2. Users can create keys limited to chosen spaces, read-only access, and an + expiry date. The CLI never creates a key with more access than the user + asked for. +3. Users can see and change a key's access. Widening access requires + explicit confirmation. +4. Existing setups keep working after upgrading, or there's a documented + migration: `/v1` keys, gRPC integrations, remote/proxy deployments. + +## Non-goals + +- A CLI client for the `/v2` REST endpoints. +- Pairing approval on a headless server (see Phase 6). Headless users create + keys directly. + +## Key decisions + +- **D1 — No default access: the user must choose spaces and permission + (option C).** `apikey create` needs: + - exactly one of `--space ` (repeatable) or `--all-spaces`, and + - exactly one of `--read-only` or `--read-write`. + + If either choice is missing, it creates nothing and prints what's needed, + with the user's spaces (name + ID) for `--space`. The CLI never picks which + spaces a key can reach or whether it can write. + - This is a **breaking change** for scripts that run + `apikey create ` without flags. They fail loudly instead of + getting a key with broad access. The release notes say so and show the + `--all-spaces --read-write` equivalent of today's behaviour. + - Rejected: A (no grant by default, which heart treats as legacy) and B + (`allSpaces` by default, which gives broad access without an explicit + decision). +- **D1a — The CLI never creates or sets a key with no grant.** Every key it + creates, and every `update` it sends, carries a grant. There's no + `--unrestricted` flag. The only thing a no-grant key adds over + `--all-spaces` is `/v2` access to the tech space, and that stays possible by listing it + explicitly with `--space `. Existing no-grant keys (made by + other clients) are shown and can be narrowed, but never re-created or + widened back to no grant. +- **D2 — Never trust the server to apply what was asked.** After any create + or update, read the key back with `ListApps` and compare. If the result + doesn't match, revoke (for create) and fail. Together with a server + version check beforehand, this closes the gap where a new CLI talks to an + older running service (see Phase 2). +- **D3 — No secrets in listings.** `list`, including `--json`, prints + selected fields only. It never prints `appKey`. Only `create` prints the + secret, once. +- **D4 — `update` merges with the current grant.** The CLI reads the + current grant, applies only the dimensions the user changed (spaces or + permission), and sends the whole result. It never sends an empty grant + (D1a). + +--- + +## Phase 1: dependency, toolchain and transport upgrade + +**Files:** `go.mod`, `go.sum`, `.github/workflows/{ci,release,codeql}.yml`, +`Makefile` / Dockerfile if they pin Go, `core/grpcserver/server.go`, `README.md`, +`SELF-HOSTED.md`, `CLAUDE.md` (Go version) + +- [ ] `go get github.com/anyproto/anytype-heart@v0.51.3 && go mod tidy` + (this raises the `go` line to `1.26.5`). +- [ ] Move CI, release and CodeQL to Go 1.26.5+. Check that the + `golangci-lint` version supports it. Update build requirements in + `CLAUDE.md` / `README.md` and the Dockerfile base image. +- [ ] Copy heart's `replace` directives (Go ignores them in dependencies): + - [ ] `github.com/libp2p/zeroconf/v2 => github.com/anyproto/zeroconf/v2 v2.2.1-0.20260709212715-528971bb5854` (changed in v0.51.x) + - [ ] Add the ones the CLI was already missing, and check each one: + `gogo/protobuf`, `dgraph-io/badger/v4`, `dgraph-io/ristretto`, + `multiformats/go-multiaddr`, `genproto/googleapis/rpc`, + `araddon/dateparse`, `dsoprea/go-jpeg-image-structure/v2` + (exact versions: heart `v0.51.3:go.mod`). +- [ ] **gRPC-Web transport:** bring over heart's `proxy.go` policy. Build + the `localorigin` policy from `ANYTYPE_GRPCWEB_ALLOWED_{ORIGINS,HOSTS}` + (allowing file:// and the webclipper extension, as heart does). Reject + untrusted requests before they reach any handler. Turn WebSockets off + unless `ANYTYPE_GRPCWEB_ENABLE_WEBSOCKETS=1`. Also add heart's + interceptor that copies the Origin header from gRPC metadata into the + request context. +- [ ] **Remote/proxy setups:** document `ANYTYPE_API_ALLOWED_HOSTS` / + `ANYTYPE_API_ALLOWED_ORIGINS` (and the gRPC-Web equivalents) in + `README.md` and `SELF-HOSTED.md`, including how to set them for + `anytype service install`. +- [ ] Verify with `make build`, `make test`, `make lint`, and cross-compile + for every release platform. +- [ ] Smoke tests: + - `/v1` and `/v2` respond on `localhost:31012`. + - Through a custom hostname or reverse proxy: rejected by default, + accepted once the allow-list is set. + - gRPC-Web: a disallowed Origin gets 403; a WebSocket upgrade gets 403 by + default. + +**Estimate:** 1–1.5 days (toolchain + transport + deployment docs; the +dependency bump itself is the small part). + +--- + +## Phase 2: switch keys to `JsonAPI`, safely + +**Files:** `core/apikey.go`, `cmd/auth/apikey/create/create.go` + +- [ ] Create keys with `Scope: model.AccountAuth_JsonAPI` and a grant. +- [ ] **Space and permission choices are required (D1):** + - Add `--space ` (repeatable) / `--all-spaces`, and + `--read-only` / `--read-write`. Exactly one from each pair must be + given. + - If either is missing, fail with usage (listing the user's spaces when + the space choice is missing). Nothing is sent to the server. + - Resolve spaces as described in Phase 3 → Rules. + - `Perm` is always set explicitly from the flag. + - These flags come in this PR, not Phase 3, because switching to `JsonAPI` + needs a grant and the CLI won't pick one for the user. +- [ ] **Server capability check before creating a key:** call + `AppGetVersion`. If the running server is older than v0.51.3, or + reports no version, stop with *"the running Anytype service is older + than this CLI; run `anytype service restart`"*. `anytype update` swaps + the binary without restarting the service, so this situation is + common. v0.50.4 would silently drop the grant and the expiry. + *Check first:* does the embedded heart report its real version through + `AppGetVersion` (ldflags)? If not, compare the CLI's own version, + exposed by the server, instead. +- [ ] **Read back after creating (D2):** `ListApps` → find the new key by + name + creation time (or by `appHash` if CreateApp returns it) → + compare scope, grant and expiry. On any difference: `RevokeApp` and + return an error. This protects against any server that ignores fields. +- [ ] Manual check: the new key gets 200 from `GET /v2/auth/whoami` and from + `GET /v1/spaces`. + +**Migration guidance (ships in this PR, README "Upgrading to API v2"):** + +1. `JsonAPI` keys **cannot call gRPC methods directly**. Integrations that + use a `Limited` key over gRPC (ObjectSearch, ListenSessionEvents, …) + should keep that key. +2. Moving a REST integration to `/v2`: create the new key → check the client + works → switch its credentials → `apikey revoke` the old one. +3. Keep **the same key name** when replacing a key. On `/v2`, deleting an + object requires the key's name to match the name recorded when the + object was created, so renaming loses the ability to delete what the old + key created. +4. Downgrading: keys created or updated by v0.51.3+ **don't work** on + v0.50.x. Keep the old keys until the upgrade is confirmed. + +**Estimate:** 1 day (includes resolving spaces). + +--- + +## Phase 3: expiry and output flags on `apikey create` + +**Files:** `cmd/auth/apikey/create/create.go`, `core/apikey.go`, new +`core/apikeygrant.go` (parsing flags, resolving spaces, describing +grants and compatibility) + +### Command + +``` +anytype auth apikey create + (--space ... | --all-spaces) # required, exactly one (Phase 2) + (--read-only | --read-write) # required, exactly one (Phase 2) + [--expires ] # e.g. 30d, 12h, 2026-12-31 + [--json] # {"id","name","key","scope","grant","expiresAt","compat":{"v1","v2"}} +``` + +### Rules + +- Exactly one of `--space` / `--all-spaces` and exactly one of + `--read-only` / `--read-write` are required; the flags in each pair can't + be combined (D1). A space picker in the terminal could come later; a missing + choice is never filled in automatically. +- There's no way to create a key without a grant (D1a). +- **Resolving spaces:** + - Resolve every argument once, before anything is sent, to a **full + space ID** using `core.ListSpaces`. + - An exact full ID takes priority over a name. Names must match exactly + one space; if a name matches several or none, fail and list the + candidates (name + ID). + - v2 short references are rejected. + - Duplicates are removed. The tech space is only reachable by its explicit + ID, with a warning. + - The resolved list (name + full ID) is what's displayed and what's sent. +- **Expiry:** Go durations + a `d` suffix, or `YYYY-MM-DD` (end of day, + local time), converted to unix **seconds**. Must be in the future. Heart + treats a key as expired once `now > expireAt`. +- **Name:** not empty, ≤ 128 bytes, never truncated. Warn if another key + already has the same name: on `/v2` both keys would be able to delete each + other's objects within their grants. + +### Output + +- The secret is printed **once**, on its own line. With `--json`, it goes + in the `key` field. +- Print the scope, a readable grant (spaces by name + short ID, read or + read-write), the expiry, and **which APIs the key works with** (`v1 ✅/❌`, + `v2 ✅`) using the table in Background. For example, + `--all-spaces --read-only` → `v1 ❌`. +- The docs show how to pipe or capture the key. Examples never put a real + key on the command line. + +**Estimate:** ~1 day including tests. + +--- + +## Phase 4: `apikey list` and `apikey update` + +### 4a. `apikey list` + +**Files:** `cmd/auth/apikey/list/list.go` + +- [ ] Columns: `NAME ID SCOPE ACCESS EXPIRES APIS SESSION CREATED` + - `ACCESS`: `all:rw`, `all:ro`, ` spaces:rw|ro`, `—` for `Limited`, + or `unrestricted` for existing no-grant `JsonAPI` keys created by other + clients (never shown as "full", which could be confused with `Full` + scope). + - `EXPIRES`: `never`, a date, or `expired`. + - `APIS`: which APIs the key works with, e.g. `v1,v2`, `v2`, + `v1,grpc` (`Limited`). + - `SESSION`: `active` if heart has a live session for the key + (`isActive`). This doesn't mean the key is valid. +- [ ] Drop the key-prefix column. +- [ ] `--json`: selected fields only (D3), and **no `appKey`**. Emit `[]` + when there are no keys, RFC 3339 timestamps, and the full grant with + space IDs. Diagnostics go to stderr. +- [ ] A footer hint for `Limited` keys: they don't work on `/v2`; link to the + migration section. +- [ ] A footer hint for no-grant `JsonAPI` keys: suggest narrowing them with + `apikey update --all-spaces` (or `--space …`). + +### 4b. `apikey update ` (new) + +**Files:** new `cmd/auth/apikey/update/update.go`, registered in +`cmd/auth/apikey/apikey.go`; `core/apikey.go` gets `UpdateAPIKeyGrant` + +``` +anytype auth apikey update + [--space ]... | [--all-spaces] # replace the spaces + [--add-space ]... [--remove-space ]... # edit the list + [--read-only | --read-write] + [--yes] +``` + +This is a separate command, not a flag on `create`: `create` makes a new +secret and requires every choice, while `update` keeps the same key and +changes only what you pass. + +**Finding the key:** the argument is matched first as an exact key ID +(`appHash`), then as an exact key name. If several keys have that name, +fail and list them (name, ID, created) so the user can pass the ID. + +**Space flags:** + +- `--space` / `--all-spaces` replace the whole set and can't be combined + with `--add-space` / `--remove-space`. +- `--add-space` / `--remove-space` edit the current list and can be used + together. Both resolve names like `--space` (Phase 3 → Rules). + - Adding a space the key already has, or removing one it doesn't have, + is a no-op for that space; the command says so. + - Removing the **last** space → error pointing to + `apikey revoke `, because heart rejects an empty grant. + - On an `allSpaces` key (or an existing no-grant key), there's no list to + edit. `--remove-space` fails and suggests `--space …`. `--add-space` of an ordinary space is a no-op (already + included); `--add-space ` fails and suggests `--space` with + an explicit list, since `allSpaces` never covers the tech space. + +How it works (D4): + +1. Find the key (above) via `ListApps`. If it isn't `JsonAPI`, refuse and + point to recreating it (heart rejects grants on `Limited` keys). +2. Work out the new grant from the current one: + - `--space` **replaces** the set of spaces; `--all-spaces` sets it to + all spaces; `--add-space` / `--remove-space` edit the current list. + With none of these, the current spaces are kept. + - `--read-only` / `--read-write` set the permission. With neither, the + current permission is kept. + - A key with no grant counts as "all spaces including the tech space, + read-write". So a permission flag alone → `allSpaces` + that + permission; `--space` alone → those spaces + `ReadWrite`. Every result + is a narrowing. + - The result always has a grant (D1a); no flag can remove it. + - No flags that change anything → error. If the new grant equals the + current one → "no change", exit 0. +3. Show **before → after** (spaces by name + ID, permission, which APIs the + key works with, including losing `/v1`). +4. If the change widens access (below), ask for confirmation. Without a + TTY, refuse unless `--yes` is given. +5. Just before sending, **read `ListApps` again**. If the grant changed + since step 1, stop and ask the user to retry. Heart has no conditional + update, so this only narrows the race window; it doesn't close it (see + the upstream ask below). +6. Send the whole grant, then read it back (D2). + +**When a change widens access.** It widens access if the new grant allows +any capability the old one didn't. Compare with space IDs deduplicated, and +treat `allSpaces` as "all current and future spaces except the tech space": + +- any space in the new set that isn't in the old one (`{A}→{B}` widens even + though the count is the same); +- a list of spaces → `allSpaces` (adds future spaces, even if the list had + every current space); +- `allSpaces` → a list containing the tech space; +- `Read` → `ReadWrite` on any space still granted (even if other spaces + are removed); +- anything that makes the key usable on `/v1` again. + +**Documented limitations:** + +- `update` can't change the scope, the expiry or the name; recreate the key + for those. +- A key can't be widened back to no grant. For `/v2` tech-space access, + list the tech space with `--space`. +- An open `/v2` chat stream keeps its old grant and isn't cut off at expiry + until it reconnects (heart only checks at the start of a request). + +**Upstream asks (heart), to file separately:** + +- `UpdateApp` with an "expected current grant" (compare-and-swap); +- cancel open streams when a key expires or its grant is edited; +- confirm that `AppGetVersion` reports the embedded heart version. + +**Estimate:** 1.5–2 days including tests. + +--- + +## Phase 5: shell mode (required) + +**Files:** `cmd/shell/shell.go` + +The new flags make existing shell-mode bugs matter: + +- [ ] Parse input with quotes (e.g. `github.com/google/shlex`), so + `--space "My Team"` works. +- [ ] Reset flag values between commands: create the command tree for every + line, or reset each flag and its `Changed` state. Otherwise `--yes` or + `--space` from one command carries over into the next. +- [ ] Confirmation prompts work in the shell (they read the same TTY). +- [ ] Make completion include the `apikey` subcommands and their flags + (it currently only goes two levels deep). + +**Estimate:** 0.5 day. Ships with PR 2/3, not as a follow-up. + +--- + +## Phase 6: optional follow-ups + +- [ ] **Pairing approval on a headless server.** The pairing challenge is + still how the **JSON API** authenticates, and on a headless server + nothing can approve it. Recommendation: **defer** until a concrete + integration can't accept a key created manually. If it's built, it + must: + - show the caller exactly as the event reports it (process path, origin) + and the permission it asked for; + - collect an explicit scope and grant, resolved as in Phase 3; + - require explicit approval; + - show the returned 4-digit code **only** to the person approving, + never solving it automatically or writing it to logs. + + Keys paired this way can't have an expiry. + +--- + +## Testing + +The repo's tests use the standard `testing` package, so follow that style. +Table-driven cases: + +- **Parsing `--expires`:** durations, `d` suffix, dates, past/now/negative + values, garbage. +- **Building a grant from flags:** every valid and invalid combination, + that `Perm` is always set explicitly, and that a missing space choice or + a missing permission choice is an error that sends nothing to the + server. +- **Never sending an empty grant (D1a):** every `create` and `update` path + sends a grant that isn't nil, including `update` on an existing no-grant + key. +- **Resolving spaces:** exact ID, name, ambiguous, unknown, duplicates, the + tech space, short references. +- **Merging for `update`:** keeping the current value when a flag is + omitted, replacing the set, permission only on a key with no grant, no + change, conflicting flags. +- **`--add-space` / `--remove-space`:** adding to and removing from a list, + both in one command, a no-op add or remove, removing the last space + (error), `--remove-space` on an `allSpaces` or no-grant key (error), adding + the tech space to an `allSpaces` key (error), combining with `--space` or + `--all-spaces` (error). +- **Finding the key for `update`:** exact ID, exact name, a name shared by + several keys (error listing them), unknown. +- **Detecting widened access** — every case in Phase 4b, plus the matching + narrowing cases, including `all:ro → [tech]:ro` and `[A,B]:ro → A:rw`. +- **Which APIs a key works with:** no grant, all/rw, all/ro, a list of + spaces, `Limited`, expired. +- **Output:** neither the table nor `--json` from `list` contains any key. + `create --json` contains it exactly once. +- **Read-back (D2):** a fake server that drops the grant or expiry → the key + is revoked and the command fails. +- **Shell:** consecutive commands don't carry flag values over; quoted + arguments work. + +Manual end-to-end against `anytype serve`: + +1. `--space A --read-only`: `/v2` read in A → 200; write in A → 403; space + B → 403; `/v1` → refused. +2. `--all-spaces --read-only`: `/v2` read → 200; `/v1` → refused. +3. `--all-spaces --read-write`: `/v1` + `/v2` → 200; `/v2` tech space → + 403. No space flag, or no permission flag → error, no key created (with + and without a TTY). +4. After a first request (so heart caches the session), `update` narrows + RW→RO and A+B→A → the next request is denied, including losing `/v1`. +5. `update` that widens access → asks for confirmation; cancelling changes + nothing; without a TTY and without `--yes` → refused, nothing changes. +6. `--expires 1m` → 401 "expired" after a minute, including for a key + whose session is already cached. The key and its grant survive a service + restart. +7. An old `Limited` key: `/v1` 200, `/v2` 403, gRPC methods on the allowlist + still work; `update` on it → refused, pointing to recreating it. +8. A new CLI talking to a **v0.50.4** service that is still running → + `create --space X` fails and **no key is created**. +9. Downgrade: an existing old key still works on v0.50.4; the release notes + say keys created by the new CLI don't. + +## Rollout + +1. **PR 1:** Phases 1 + 2. The toolchain, dependency bump, transport + protection, `JsonAPI` scope with required space and permission choices, + the version check, + read-back after create, and the migration and deployment docs. +2. **PR 2:** Phase 3 + 4a + the shell parsing/flag-reset parts of Phase 5. +3. **PR 3:** Phase 4b + the rest of Phase 5. +4. The upstream heart asks and Phase 6 as separate issues. + +Release notes for PR 1: + +- the Go toolchain requirement; +- Host/Origin allow-lists for remote setups; +- gRPC-Web WebSockets are now off by default; +- new keys are `JsonAPI` (no gRPC access); +- **breaking:** `apikey create` needs `--space …` or `--all-spaces`, and + `--read-only` or `--read-write`; +- the downgrade caveat; +- `anytype service restart` after updating. + +**Total estimate:** ~6–7 days. + +## Open questions + +1. Should `apikey create` also offer `--scope limited`, for integrations that + still need gRPC access? The recommendation is no unless someone asks for + it; point them to existing keys. +2. Does the embedded server report heart's version through + `AppGetVersion`? This determines how the Phase 2 version check is built. +3. Headless pairing approval (Phase 6): is it needed by Raycast, MCP or + web-clipper users on servers? From 330155ec7b5484101d2ac57f695962e6fb15b0fa Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Tue, 29 Sep 2026 17:06:23 +0200 Subject: [PATCH 02/14] Bump anytype-heart to v0.51.3 and Go toolchain to 1.26.5 Sync replace directives with heart (zeroconf bump, plus previously missing gogo/protobuf, badger, ristretto, go-multiaddr, genproto rpc, dateparse, go-jpeg-image-structure). Move CI/release/CodeQL to Go 1.26 and golangci-lint to v2.12.2. --- .github/workflows/ci.yml | 4 +- .github/workflows/codeql.yml | 2 +- .github/workflows/release.yml | 2 +- CLAUDE.md | 2 +- Makefile | 2 +- README.md | 2 +- go.mod | 122 +++---- go.sum | 659 +++++++--------------------------- 8 files changed, 198 insertions(+), 597 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 11fa105..9b256d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v6 with: - go-version: "1.25" + go-version: "1.26" - name: Download dependencies run: go mod download @@ -41,7 +41,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v6 with: - go-version: "1.25" + go-version: "1.26" - name: Download dependencies run: go mod download diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9dd3a95..de38daa 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -63,7 +63,7 @@ jobs: if: matrix.language == 'go' uses: actions/setup-go@v6 with: - go-version: "1.25" + go-version: "1.26" # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a63bab3..2969baa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,7 +30,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v6 with: - go-version: "1.25" + go-version: "1.26" cache: false - name: Resolve release tag diff --git a/CLAUDE.md b/CLAUDE.md index 00bc402..5eacba9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,7 +38,7 @@ make build-windows-amd64 - **CGO**: The build requires CGO_ENABLED=1 due to tantivy (full-text search library) dependencies - **Tantivy Library**: Automatically downloaded for your platform during `make build` - **C Compiler**: Required for CGO and linking tantivy library (clang on macOS, gcc on Linux, mingw on Windows) -- **Go 1.25+**: Required for building the project +- **Go 1.26.5+**: Required for building the project ## Development Workflow diff --git a/Makefile b/Makefile index 450a98d..e2cb8af 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ TANTIVY_LIB_PATH ?= dist/tantivy TANTIVY_MARKER = $(TANTIVY_LIB_PATH)/.version-$(TANTIVY_VERSION) CGO_LDFLAGS := -L$(TANTIVY_LIB_PATH) -GOLANGCI_LINT_VERSION := v2.7.2 +GOLANGCI_LINT_VERSION := v2.12.2 ##@ Build diff --git a/README.md b/README.md index ad047b2..70fbcd5 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ anytype-cli/ #### Prerequisites -- Go 1.25 or later +- Go 1.26.5 or later - Git - Make - C compiler (gcc or clang, for CGO) diff --git a/go.mod b/go.mod index 943e2ff..56775c7 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/anyproto/anytype-cli -go 1.25.7 +go 1.26.5 require ( - github.com/anyproto/any-sync v0.12.3 - github.com/anyproto/anytype-heart v0.50.4 - github.com/cheggaaa/mb/v3 v3.0.2 + github.com/anyproto/any-sync v0.13.3 + github.com/anyproto/anytype-heart v0.51.3 + github.com/cheggaaa/mb/v3 v3.0.3 github.com/chzyer/readline v1.5.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 @@ -13,21 +13,20 @@ require ( github.com/kardianos/service v1.2.4 github.com/spf13/cobra v1.10.2 github.com/zalando/go-keyring v0.2.8 - golang.org/x/mod v0.35.0 - google.golang.org/grpc v1.80.0 + golang.org/x/mod v0.41.0 + google.golang.org/grpc v1.81.1 gopkg.in/yaml.v3 v3.0.1 ) require ( filippo.io/edwards25519 v1.2.0 // indirect github.com/JohannesKaufmann/html-to-markdown v1.6.0 // indirect - github.com/KyleBanks/depth v1.2.1 // indirect github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260416073033-7c2071eaa8d4 // indirect github.com/PuerkitoBio/goquery v1.12.0 // indirect - github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect - github.com/anyproto/any-store v0.4.6 // indirect + github.com/anyproto/any-block v0.0.0-20260919082013-9906a7c36b68 // indirect + github.com/anyproto/any-store v1.0.2 // indirect github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20260407134332-83cc769fbbb8 // indirect github.com/anyproto/anytype-push-server/pushclient v0.0.0-20260407093150-0b14187dfd27 // indirect github.com/anyproto/go-bip39 v1.0.0 // indirect @@ -43,11 +42,6 @@ require ( github.com/avast/retry-go/v4 v4.7.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd v0.25.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.6 // indirect - github.com/btcsuite/btcd/btcutil v1.1.6 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect - github.com/btcsuite/btcutil v1.0.3-0.20220129005943-27c39e0ab4f9 // indirect github.com/bytedance/gopkg v0.1.4 // indirect github.com/bytedance/sonic v1.15.0 // indirect github.com/bytedance/sonic/loader v0.5.1 // indirect @@ -58,12 +52,12 @@ require ( github.com/cloudwego/base64x v0.1.6 // indirect github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect github.com/danieljoos/wincred v1.2.3 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect github.com/desertbit/timer v1.0.1 // indirect github.com/dgraph-io/badger/v4 v4.9.1 // indirect - github.com/dgraph-io/ristretto/v2 v2.4.0 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da // indirect github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8 // indirect github.com/didip/tollbooth/v8 v8.0.1 // indirect github.com/disintegration/imaging v1.6.2 // indirect @@ -90,16 +84,6 @@ require ( github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-openapi/jsonpointer v0.23.1 // indirect - github.com/go-openapi/jsonreference v0.21.5 // indirect - github.com/go-openapi/spec v0.22.4 // indirect - github.com/go-openapi/swag/conv v0.26.0 // indirect - github.com/go-openapi/swag/jsonname v0.26.0 // indirect - github.com/go-openapi/swag/jsonutils v0.26.0 // indirect - github.com/go-openapi/swag/loading v0.26.0 // indirect - github.com/go-openapi/swag/stringutils v0.26.0 // indirect - github.com/go-openapi/swag/typeutils v0.26.0 // indirect - github.com/go-openapi/swag/yamlutils v0.26.0 // indirect github.com/go-pkgz/expirable-cache/v3 v3.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -120,6 +104,8 @@ require ( github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/geo v0.0.0-20260415063119-550b242b3150 // indirect + github.com/golang/glog v1.2.5 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v1.0.0 // indirect github.com/google/flatbuffers v25.12.19+incompatible // indirect @@ -140,36 +126,36 @@ require ( github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/bbloom v0.1.0 // indirect - github.com/ipfs/boxo v0.38.0 // indirect + github.com/ipfs/boxo v0.42.2 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect - github.com/ipfs/go-block-format v0.2.3 // indirect - github.com/ipfs/go-cid v0.6.1 // indirect - github.com/ipfs/go-cidutil v0.1.1 // indirect - github.com/ipfs/go-datastore v0.9.1 // indirect + github.com/ipfs/go-block-format v0.2.4 // indirect + github.com/ipfs/go-cid v0.6.2 // indirect + github.com/ipfs/go-cidutil v0.1.2 // indirect + github.com/ipfs/go-datastore v0.9.2 // indirect github.com/ipfs/go-ds-flatfs v0.6.0 // indirect github.com/ipfs/go-dsqueue v0.2.0 // indirect - github.com/ipfs/go-ipld-format v0.6.3 // indirect + github.com/ipfs/go-ipld-format v0.6.4 // indirect github.com/ipfs/go-ipld-legacy v0.3.0 // indirect github.com/ipfs/go-log v1.0.5 // indirect - github.com/ipfs/go-log/v2 v2.9.1 // indirect + github.com/ipfs/go-log/v2 v2.9.2 // indirect github.com/ipfs/go-metrics-interface v0.3.0 // indirect github.com/ipld/go-codec-dagpb v1.7.0 // indirect - github.com/ipld/go-ipld-prime v0.22.0 // indirect + github.com/ipld/go-ipld-prime v0.24.0 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/joho/godotenv v1.5.1 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.18.5 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/klauspost/compress v1.19.1 // indirect + github.com/klauspost/cpuid/v2 v2.4.0 // indirect github.com/kovidgoyal/imaging v1.6.4 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-libp2p v0.48.0 // indirect + github.com/libp2p/go-libp2p v0.49.0 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect github.com/matishsiao/goInfo v0.0.0-20241216093258-66a9250504d6 // indirect - github.com/mattn/go-isatty v0.0.21 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect github.com/mattn/go-sqlite3 v1.14.42 // indirect github.com/mb0/diff v0.0.0-20131118162322-d8d9a906c24d // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect @@ -198,30 +184,29 @@ require ( github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20250313105119-ba97887b0a25 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/polydawn/refmt v0.89.1-0.20231129105047-37766d95467a // indirect + github.com/polydawn/refmt v0.90.0 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_golang v1.24.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.67.5 // indirect - github.com/prometheus/procfs v0.20.1 // indirect + github.com/prometheus/common v0.70.1 // indirect + github.com/prometheus/procfs v0.21.1 // indirect github.com/quic-go/qpack v0.6.0 // indirect - github.com/quic-go/quic-go v0.59.0 // indirect - github.com/quic-go/webtransport-go v0.10.0 // indirect + github.com/quic-go/quic-go v0.62.0 // indirect + github.com/quic-go/webtransport-go v0.12.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/cors v1.11.1 // indirect github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect github.com/samber/lo v1.53.0 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sasha-s/go-deadlock v0.3.9 // indirect + github.com/sashabaranov/go-openai v1.41.2 // indirect github.com/shirou/gopsutil/v4 v4.26.3 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect github.com/stretchr/objx v0.5.3 // indirect - github.com/stretchr/testify v1.11.1 // indirect - github.com/sv-tools/openapi v0.4.0 // indirect - github.com/swaggo/swag/v2 v2.0.0-rc5 // indirect + github.com/stretchr/testify v1.12.1 // indirect github.com/tetratelabs/wazero v1.11.0 // indirect github.com/tklauser/go-sysconf v0.3.16 // indirect github.com/tklauser/numcpus v0.11.0 // indirect @@ -238,28 +223,28 @@ require ( github.com/zeebo/errs v1.4.0 // indirect go.abhg.dev/goldmark/wikilink v0.6.0 // indirect go.mongodb.org/mongo-driver/v2 v2.5.1 // indirect + go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/otel v1.43.0 // indirect - go.opentelemetry.io/otel/metric v1.43.0 // indirect - go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/otel v1.44.0 // indirect + go.opentelemetry.io/otel/metric v1.44.0 // indirect + go.opentelemetry.io/otel/trace v1.44.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.1 // indirect - go.yaml.in/yaml/v2 v2.4.4 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect + go.uber.org/zap v1.28.0 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect golang.org/x/arch v0.26.0 // indirect - golang.org/x/crypto v0.50.0 // indirect - golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect + golang.org/x/crypto v0.57.0 // indirect + golang.org/x/exp v0.0.0-20260718201538-764159d718ef // indirect golang.org/x/image v0.38.0 // indirect - golang.org/x/net v0.53.0 // indirect + golang.org/x/net v0.59.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/text v0.36.0 // indirect + golang.org/x/sync v0.23.0 // indirect + golang.org/x/sys v0.48.0 // indirect + golang.org/x/text v0.42.0 // indirect golang.org/x/time v0.15.0 // indirect - golang.org/x/tools v0.44.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect - google.golang.org/protobuf v1.36.11 // indirect + golang.org/x/tools v0.50.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/protobuf v1.36.12 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect lukechampine.com/blake3 v1.4.1 // indirect @@ -268,16 +253,23 @@ require ( modernc.org/memory v1.11.0 // indirect modernc.org/sqlite v1.49.1 // indirect nhooyr.io/websocket v1.8.17 // indirect - storj.io/drpc v0.0.34 // indirect + storj.io/drpc v1.0.0 // indirect zombiezen.com/go/sqlite v1.4.2 // indirect ) replace ( github.com/JohannesKaufmann/html-to-markdown => github.com/anyproto/html-to-markdown v0.0.0-20231025221133-830bf0a6f139 + github.com/araddon/dateparse => github.com/mehanizm/dateparse v0.0.0-20210806203422-f82c8742c9f8 github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.22.1 github.com/btcsuite/btcutil => github.com/btcsuite/btcd/btcutil v1.1.5 + github.com/dgraph-io/badger/v4 => github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580 + github.com/dgraph-io/ristretto => github.com/anyproto/ristretto v0.1.2-0.20240221153107-2b23839cc50c + github.com/dsoprea/go-jpeg-image-structure/v2 => github.com/dchesterton/go-jpeg-image-structure/v2 v2.0.0-20240318203529-c3eea088bd38 + github.com/gogo/protobuf => github.com/anyproto/protobuf v1.3.3-0.20240201225420-6e325cf0ac38 github.com/ipfs/go-ds-flatfs => github.com/anyproto/go-ds-flatfs v0.0.0-20250828183910-d49f5b2d567f github.com/ipfs/go-log/v2 => github.com/anyproto/go-log/v2 v2.1.2-0.20220721095711-bcf09ff293b2 - github.com/libp2p/zeroconf/v2 => github.com/anyproto/zeroconf/v2 v2.2.1-0.20240228113933-f90a5cc4439d + github.com/libp2p/zeroconf/v2 => github.com/anyproto/zeroconf/v2 v2.2.1-0.20260709212715-528971bb5854 + github.com/multiformats/go-multiaddr => github.com/anyproto/go-multiaddr v0.8.1-0.20250307125826-51ba58e2ebc7 + google.golang.org/genproto/googleapis/rpc => google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 gopkg.in/Graylog2/go-gelf.v2 => github.com/anyproto/go-gelf v0.0.0-20210418191311-774bd5b016e7 ) diff --git a/go.sum b/go.sum index 6ba05eb..e8e55df 100644 --- a/go.sum +++ b/go.sum @@ -1,49 +1,11 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= -github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260416073033-7c2071eaa8d4 h1:/97whAzwYxMNHXeTfhAtCRzNCpyblmxCtSYpsfzCszM= @@ -54,31 +16,31 @@ github.com/PuerkitoBio/goquery v1.12.0/go.mod h1:802ej+gV2y7bbIhOIoPY5sT183ZW0YF github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= -github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 h1:iW0a5ljuFxkLGPNem5Ui+KBjFJzKg4Fv2fnxe4dvzpM= github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA= github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/anyproto/any-store v0.4.6 h1:opnTUGfuHa/VA9Incu6iLEy3WsQ4mb2o1oAXGDysH0s= -github.com/anyproto/any-store v0.4.6/go.mod h1:Npi35qMUVZ8ouiV4o9AqpZDs6LbDOF+5ZLlVijXofFM= -github.com/anyproto/any-sync v0.12.3 h1:ZZcP1btTphrecBlqtkhE4famrYw8Qo90nGBhLmAJNuo= -github.com/anyproto/any-sync v0.12.3/go.mod h1:flF0NT1NPB/6K+JjEVHZTBzTXPflM6jqgFIKTsponV8= -github.com/anyproto/anytype-heart v0.50.4 h1:BIn/lQ6W/Du7UeUZFU7bS33i+Qaycc0XlJtkp/B5beE= -github.com/anyproto/anytype-heart v0.50.4/go.mod h1:7pRTg9vHhBXL2sPSTGr+51X88rSUDPvhj1bxWOtOmv4= +github.com/anyproto/any-block v0.0.0-20260919082013-9906a7c36b68 h1:7EAL+fDiqZs/1R52STcE1tFcnGGwDYC7KeMk+4q/VKQ= +github.com/anyproto/any-block v0.0.0-20260919082013-9906a7c36b68/go.mod h1:ctWUBba2Nm+mHwkh4bBej57avQHaW2HDzDZDSlbVchs= +github.com/anyproto/any-store v1.0.2 h1:vQvgKKDDmM0j9EheBWGq8bMVU7Oi3061DKJFG8D3sTQ= +github.com/anyproto/any-store v1.0.2/go.mod h1:8cqb52gjZSaYnlybugqpSqSG1RQygY96D2vWMbSJsLo= +github.com/anyproto/any-sync v0.13.3 h1:tNsrh7HSe4+p/bbvMdh2OuRiVMzSefrYpPxu/6tDjdU= +github.com/anyproto/any-sync v0.13.3/go.mod h1:J+/XaGglDbK4o67YnmDK7GDHS5pqjByshR+7m7j5pYs= +github.com/anyproto/anytype-heart v0.51.3 h1:EvVvGKKbYLwTjwMWqEP9BT5fLeZ8gDyjGcYVkOHPM6o= +github.com/anyproto/anytype-heart v0.51.3/go.mod h1:s0+4XvNVXBLU3iZFphLt9hZY42axzQrqe0mjfNE76rk= github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20260407134332-83cc769fbbb8 h1:Oaz1B7AUr/4U/kVDBafZ7sP8VCWSYQ51fo6G2T8smH4= github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20260407134332-83cc769fbbb8/go.mod h1:lRppnNvn5vAw/ASBOYV6LTYPqEg+XC34AzloxK1E/Ac= github.com/anyproto/anytype-push-server/pushclient v0.0.0-20260407093150-0b14187dfd27 h1:O/n87PsZozTtfIbKOad8lS2safL/A1CuzFNrLbin18M= github.com/anyproto/anytype-push-server/pushclient v0.0.0-20260407093150-0b14187dfd27/go.mod h1:1m8LlK1kjKKP3qt/HfOOJLlpKndQoOP4kSErjhXljsM= +github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580 h1:Ba80IlCCxkZ9H1GF+7vFu/TSpPvbpDCxXJ5ogc4euYc= +github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580/go.mod h1:T/uWAYxrXdaXw64ihI++9RMbKTCpKd/yE9+saARew7k= github.com/anyproto/go-bip39 v1.0.0 h1:T6/7WowKYDeyuX/QyXtt98ZX0XXaoOh17M/LFF2M5yk= github.com/anyproto/go-bip39 v1.0.0/go.mod h1:l0rcxmXRyiWAYzE1noMAc4qbeNrbhUwxM3rqSO9ILwo= github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY= @@ -87,6 +49,8 @@ github.com/anyproto/go-ds-flatfs v0.0.0-20250828183910-d49f5b2d567f h1:OBqi9bWQi github.com/anyproto/go-ds-flatfs v0.0.0-20250828183910-d49f5b2d567f/go.mod h1:TtwE6xpVzRMpWDipS1FHEJYxB7YjGNEFZxUXOhTSGGk= github.com/anyproto/go-log/v2 v2.1.2-0.20220721095711-bcf09ff293b2 h1:X8xiwPlNiSQs1HKguhZyHYs4XFQLWsj566bFsRjN7hM= github.com/anyproto/go-log/v2 v2.1.2-0.20220721095711-bcf09ff293b2/go.mod h1:TMD+iYDL/QBjspKUN0Ypxpr2IMAz3uGUAsbCeClDQ+4= +github.com/anyproto/go-multiaddr v0.8.1-0.20250307125826-51ba58e2ebc7 h1:SD0mX7Ds438ZP6J1g7qpXN4naRi/Naa0umTvlTba76c= +github.com/anyproto/go-multiaddr v0.8.1-0.20250307125826-51ba58e2ebc7/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438 h1:flfZXdcXB2iVHrTZDwSMlJ7RCRS/ydiPw63xWr+waSU= github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438/go.mod h1:cmdcU4pcVTftMlM89z+d8dLBJc02HtY5tI12yQucUxM= github.com/anyproto/go-slip10 v1.0.1 h1:Pa/OpYoOE668fip4ygAd4T07chLBx4XoBa5fwnGq0/M= @@ -101,14 +65,16 @@ github.com/anyproto/html-to-markdown v0.0.0-20231025221133-830bf0a6f139 h1:Wp9z0 github.com/anyproto/html-to-markdown v0.0.0-20231025221133-830bf0a6f139/go.mod h1:1zaDDQVWTRwNksmTUTkcVXqgNF28YHiEUIm8FL9Z+II= github.com/anyproto/lexid v0.0.6 h1:lTJd9K11vU1xoBs1dkZVv8VtYfCBo373lNd9kAgXEio= github.com/anyproto/lexid v0.0.6/go.mod h1:2RfpYiZkgoNmSDklXdwCCwGlso1FIp9Te8ZtoF3/Ehg= +github.com/anyproto/protobuf v1.3.3-0.20240201225420-6e325cf0ac38 h1:80jke82/c+bNQQpnx4VO3Mi/lAxARyyfUpZvFaPxdzE= +github.com/anyproto/protobuf v1.3.3-0.20240201225420-6e325cf0ac38/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/anyproto/ristretto v0.1.2-0.20240221153107-2b23839cc50c h1:GicoaTUyB2mtCIl3YMrO0OzysqRT5GA4vuvDsqEkhSM= +github.com/anyproto/ristretto v0.1.2-0.20240221153107-2b23839cc50c/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/anyproto/tantivy-go v1.0.6 h1:8FI8otTeq5OFXK7Fw7vwG2vrwW1R1Yvcbiy4rO4YfoQ= github.com/anyproto/tantivy-go v1.0.6/go.mod h1:LtipOpRjGtcYMGcop6gQN7rVl1Pc6BlIs9BTMqeWMsk= -github.com/anyproto/zeroconf/v2 v2.2.1-0.20240228113933-f90a5cc4439d h1:5bj7nX/AS8sxGpTIrapE7PC4oPlhkHMwMqXlJbUHBlg= -github.com/anyproto/zeroconf/v2 v2.2.1-0.20240228113933-f90a5cc4439d/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= +github.com/anyproto/zeroconf/v2 v2.2.1-0.20260709212715-528971bb5854 h1:9Hwnz/eHgLqchu42c0EjSRMgzabVJnbX4QOxGIs3frw= +github.com/anyproto/zeroconf/v2 v2.2.1-0.20260709212715-528971bb5854/go.mod h1:2KV4b7s+6Jfu0HM826dXIAh2Ln5EXcnpt/cW1TWFWBo= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA= -github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -128,26 +94,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= -github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= -github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.6 h1:IzlsEr9olcSRKB/n7c4351F3xHKxS2lma+1UFGCYd4E= -github.com/btcsuite/btcd/btcec/v2 v2.3.6/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= -github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= -github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= -github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= -github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= @@ -167,15 +113,12 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/webp v1.4.0 h1:6DA2pkkRUPnbOHvvsmGI3He1hBKf/bkRlniAiSGuEko= github.com/chai2010/webp v1.4.0/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU= -github.com/cheggaaa/mb/v3 v3.0.2 h1:jd1Xx0zzihZlXL6HmnRXVCI1BHuXz/kY+VzX9WbvNDU= -github.com/cheggaaa/mb/v3 v3.0.2/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/cheggaaa/mb/v3 v3.0.3 h1:vnS0l+7T0N5w2D0g98e3GobdFVq5mWYLIkZO2IILeSs= +github.com/cheggaaa/mb/v3 v3.0.3/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= @@ -183,19 +126,14 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI= github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf h1:dwGgBWn84wUS1pVikGiruW+x5XM4amhjaZO20vCjay4= github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= @@ -210,21 +148,17 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/dchesterton/go-jpeg-image-structure/v2 v2.0.0-20240318203529-c3eea088bd38 h1:GDvo0S+xL3iMJYofhBVQVM6EuAcTCoEV1096iN1pedI= +github.com/dchesterton/go-jpeg-image-structure/v2 v2.0.0-20240318203529-c3eea088bd38/go.mod h1:WaARaUjQuSuDCDFAiU/GwzfxMTJBulfEhqEA2Tx6B4Y= github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo= github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= -github.com/dgraph-io/badger/v4 v4.9.1 h1:DocZXZkg5JJHJPtUErA0ibyHxOVUDVoXLSCV6t8NC8w= -github.com/dgraph-io/badger/v4 v4.9.1/go.mod h1:5/MEx97uzdPUHR4KtkNt8asfI2T4JiEiQlV7kWUo8c0= -github.com/dgraph-io/ristretto/v2 v2.4.0 h1:I/w09yLjhdcVD2QV192UJcq8dPBaAJb9pOuMyNy0XlU= -github.com/dgraph-io/ristretto/v2 v2.4.0/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8 h1:OtSeLS5y0Uy01jaKK4mA/WVIYtpzVm63vLVAPzJXigg= @@ -233,6 +167,8 @@ github.com/didip/tollbooth/v8 v8.0.1 h1:VAAapTo1t4Bn6bbpcHjuovwoa9u3JH++wgjbpWv+ github.com/didip/tollbooth/v8 v8.0.1/go.mod h1:oEd9l+ep373d7DmvKLc0a5gasPOev2mTewi6KPQBGJ4= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E= github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8= github.com/dsoprea/go-exif/v3 v3.0.0-20210428042052-dca55bf8ca15/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk= @@ -244,8 +180,6 @@ github.com/dsoprea/go-exif/v3 v3.0.1/go.mod h1:10HkA1Wz3h398cDP66L+Is9kKDmlqlIJG github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM= github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413 h1:YDRiMEm32T60Kpm35YzOK9ZHgjsS1Qrid+XskNcsdp8= github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM= -github.com/dsoprea/go-jpeg-image-structure/v2 v2.0.0-20221012074422-4f3f7e934102 h1:gmTXQdSuuuORRFPTS2uaYpAXU5oUNkXdeYSlZe5NvsE= -github.com/dsoprea/go-jpeg-image-structure/v2 v2.0.0-20221012074422-4f3f7e934102/go.mod h1:WaARaUjQuSuDCDFAiU/GwzfxMTJBulfEhqEA2Tx6B4Y= github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA= github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8= github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6VQyQsfD7NnEC8BZuFpz45PgY+pH8YTg= @@ -262,6 +196,7 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4G github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= @@ -274,9 +209,6 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.17.2 h1:ag6geu0kn8Hv5FLKTpH+Hm2DHD+iuFtuqKxEuwUsDOI= github.com/ethereum/go-ethereum v1.17.2/go.mod h1:KHcRXfGOUfUmKg51IhQ0IowiqZ6PqZf08CMtk0g5K1o= @@ -292,7 +224,6 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gammazero/chanqueue v1.1.2 h1:dZEsxlyANZMyeTRemABqZF8QM9BnE4NBI43Oh3y5fIU= @@ -316,8 +247,6 @@ github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWE github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -334,33 +263,6 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-openapi/jsonpointer v0.23.1 h1:1HBACs7XIwR2RcmItfdSFlALhGbe6S92p0ry4d1GWg4= -github.com/go-openapi/jsonpointer v0.23.1/go.mod h1:iWRmZTrGn7XwYhtPt/fvdSFj1OfNBngqRT2UG3BxSqY= -github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE= -github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw= -github.com/go-openapi/spec v0.22.4 h1:4pxGjipMKu0FzFiu/DPwN3CTBRlVM2yLf/YTWorYfDQ= -github.com/go-openapi/spec v0.22.4/go.mod h1:WQ6Ai0VPWMZgMT4XySjlRIE6GP1bGQOtEThn3gcWLtQ= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag/conv v0.26.0 h1:5yGGsPYI1ZCva93U0AoKi/iZrNhaJEjr324YVsiD89I= -github.com/go-openapi/swag/conv v0.26.0/go.mod h1:tpAmIL7X58VPnHHiSO4uE3jBeRamGsFsfdDeDtb5ECE= -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/swag/jsonutils v0.26.0 h1:FawFML2iAXsPqmERscuMPIHmFsoP1tOqWkxBaKNMsnA= -github.com/go-openapi/swag/jsonutils v0.26.0/go.mod h1:2VmA0CJlyFqgawOaPI9psnjFDqzyivIqLYN34t9p91E= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0 h1:apqeINu/ICHouqiRZbyFvuDge5jCmmLTqGQ9V95EaOM= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0/go.mod h1:AyM6QT8uz5IdKxk5akv0y6u4QvcL9GWERt0Jx/F/R8Y= -github.com/go-openapi/swag/loading v0.26.0 h1:Apg6zaKhCJurpJer0DCxq99qwmhFddBhaMX7kilDcko= -github.com/go-openapi/swag/loading v0.26.0/go.mod h1:dBxQ/6V2uBaAQdevN18VELE6xSpJWZxLX4txe12JwDg= -github.com/go-openapi/swag/stringutils v0.26.0 h1:qZQngLxs5s7SLijc3N2ZO+fUq2o8LjuWAASSrJuh+xg= -github.com/go-openapi/swag/stringutils v0.26.0/go.mod h1:sWn5uY+QIIspwPhvgnqJsH8xqFT2ZbYcvbcFanRyhFE= -github.com/go-openapi/swag/typeutils v0.26.0 h1:2kdEwdiNWy+JJdOvu5MA2IIg2SylWAFuuyQIKYybfq4= -github.com/go-openapi/swag/typeutils v0.26.0/go.mod h1:oovDuIUvTrEHVMqWilQzKzV4YlSKgyZmFh7AlfABNVE= -github.com/go-openapi/swag/yamlutils v0.26.0 h1:H7O8l/8NJJQ/oiReEN+oMpnGMyt8G0hl460nRZxhLMQ= -github.com/go-openapi/swag/yamlutils v0.26.0/go.mod h1:1evKEGAtP37Pkwcc7EWMF0hedX0/x3Rkvei2wtG/TbU= -github.com/go-openapi/testify/enable/yaml/v2 v2.4.2 h1:5zRca5jw7lzVREKCZVNBpysDNBjj74rBh0N2BGQbSR0= -github.com/go-openapi/testify/enable/yaml/v2 v2.4.2/go.mod h1:XVevPw5hUXuV+5AkI1u1PeAm27EQVrhXTTCPAF85LmE= -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-pkgz/expirable-cache/v3 v3.1.0 h1:s05P851/O6QJ6Mc+7o2bh9aGtD3romB1SxDTXifdoqc= github.com/go-pkgz/expirable-cache/v3 v3.1.0/go.mod h1:6pVgNleydKPj0J2/mzrI02/RDo4ivKx5v2XlNmIjhjo= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -384,7 +286,6 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= -github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= @@ -396,7 +297,6 @@ github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= @@ -405,11 +305,6 @@ github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q8 github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs= @@ -424,23 +319,18 @@ github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgR github.com/golang/geo v0.0.0-20260415063119-550b242b3150 h1:F5CQANtNulclG+xJt370ohUujAEHq2XNBBAjkoSukQI= github.com/golang/geo v0.0.0-20260415063119-550b242b3150/go.mod h1:Mymr9kRGDc64JPr03TSZmuIBODZ3KyswLzm1xL0HFA8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= +github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 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= @@ -450,9 +340,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -466,43 +353,20 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 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.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/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.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0= github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gopherjs/gopherjs v1.20.1 h1:22uLWFvVcxhJ+j3dJ99NNfwGyHynxCmjhYsrcwqbY60= github.com/gopherjs/gopherjs v1.20.1/go.mod h1:h+FTmmLgbXMmmtuZFp9bUqXciN429Wx0sJEJuMnpyfM= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -525,10 +389,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vb github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= @@ -548,9 +409,10 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 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/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= @@ -571,8 +433,6 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -581,18 +441,18 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/ipfs/bbloom v0.1.0 h1:nIWwfIE3AaG7RCDQIsrUonGCOTp7qSXzxH7ab/ss964= github.com/ipfs/bbloom v0.1.0/go.mod h1:lDy3A3i6ndgEW2z1CaRFvDi5/ZTzgM1IxA/pkL7Wgts= -github.com/ipfs/boxo v0.38.0 h1:Kt/swuNXAtVXs7EP6KEjB5+2lo5/tTrvWzjakQ8IiOo= -github.com/ipfs/boxo v0.38.0/go.mod h1:A6DRpImSXihx6MiEHOeBjXqleDqK5JX3yWDxM0WygPo= +github.com/ipfs/boxo v0.42.2 h1:c/lP/MQ2ChmfQ5I0JokqK53bAZuMsNjGia9sHc/RkqU= +github.com/ipfs/boxo v0.42.2/go.mod h1:Izfi844gxRpk7VYbgtMOufY811ohXciUvdgSwd+uPuo= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= -github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk= -github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA= -github.com/ipfs/go-cid v0.6.1 h1:T5TnNb08+ueovG76Z5gx1L4Y7QOaGTXHg1F6raWFxIc= -github.com/ipfs/go-cid v0.6.1/go.mod h1:zrY0SwOhjrrIdfPQ/kf+k1sXyJ0QE7cMxfCployLBs0= -github.com/ipfs/go-cidutil v0.1.1 h1:COuby6H8C2ml0alvHYX3WdbFM4F07YtbY0UlT5j+sgI= -github.com/ipfs/go-cidutil v0.1.1/go.mod h1:SCoUftGEUgoXe5Hjeyw5CiLZF8cwYn/TbtpFQXJCP6k= -github.com/ipfs/go-datastore v0.9.1 h1:67Po2epre/o0UxrmkzdS9ZTe2GFGODgTd2odx8Wh6Yo= -github.com/ipfs/go-datastore v0.9.1/go.mod h1:zi07Nvrpq1bQwSkEnx3bfjz+SQZbdbWyCNvyxMh9pN0= +github.com/ipfs/go-block-format v0.2.4 h1:pgsT9i8zB4YQkBIQRrBwqbQiXPogRCiQnfxd2bC4koI= +github.com/ipfs/go-block-format v0.2.4/go.mod h1:YpXrOge8ARskfuJuqjvJTYr4v6o9IZWgK2EEIMAhpcU= +github.com/ipfs/go-cid v0.6.2 h1:VuGwJd+KJTaMJ4S4d5EEf9SXc17YUblS5axCbocn9YE= +github.com/ipfs/go-cid v0.6.2/go.mod h1:Xhwg8NzHeK9xPCEZkCw4idzPiuNMpX3fARuI5Iwj1Lo= +github.com/ipfs/go-cidutil v0.1.2 h1:Sbktesx5tEFtyj4iqFe3asn35WR5Wokt8nHp6Eq/5HM= +github.com/ipfs/go-cidutil v0.1.2/go.mod h1:IGpYxfTJb75D1/ah7XTBEndyKw+NVMoAHgIUQrj8qbg= +github.com/ipfs/go-datastore v0.9.2 h1:HJOgAmvWPRMHiwD8JHBzGZQNTKhuFGYfp8bNPwye28g= +github.com/ipfs/go-datastore v0.9.2/go.mod h1:VIjDxnINIcCqBMaB8LGggHfYY7PalKWfPtRMFeOU4q4= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ds-leveldb v0.5.2 h1:6nmxlQ2zbp4LCNdJVsmHfs9GP0eylfBNxpmY1csp0x0= @@ -603,8 +463,8 @@ github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1I github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-pq v0.0.4 h1:U7jjENWJd1jhcrR8X/xHTaph14PTAK9O+yaLJbjqgOw= github.com/ipfs/go-ipfs-pq v0.0.4/go.mod h1:9UdLOIIb99IFrgT0Fc53pvbvlJBhpUb4GJuAQf3+O2A= -github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8= -github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk= +github.com/ipfs/go-ipld-format v0.6.4 h1:NikmzItTDyQO0WkJI3rC2TGv4OFKOqM/DvcOCZZXuwM= +github.com/ipfs/go-ipld-format v0.6.4/go.mod h1:1WGiDa1Nv8dXNQBknGQYe+9OF8IoNrErvN76BYvlaIA= github.com/ipfs/go-ipld-legacy v0.3.0 h1:7XhFKkRyCvP5upOlQfKUFIqL3S5DEZnbUE4bQmQ/tNE= github.com/ipfs/go-ipld-legacy v0.3.0/go.mod h1:Ukef9ARQiX+RVetwH2XiReLgJvQDEXcUPszrZ1KRjKI= github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= @@ -613,14 +473,14 @@ github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6 github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY= github.com/ipfs/go-peertaskqueue v0.8.3 h1:tBPpGJy+A92RqtRFq5amJn0Uuj8Pw8tXi0X3eHfHM8w= github.com/ipfs/go-peertaskqueue v0.8.3/go.mod h1:OqVync4kPOcXEGdj/LKvox9DCB5mkSBeXsPczCxLtYA= -github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc= -github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o= -github.com/ipfs/go-unixfsnode v1.10.3 h1:c8sJjuGNkxXAQH75P+f5ngPda/9T+DrboVA0TcDGvGI= -github.com/ipfs/go-unixfsnode v1.10.3/go.mod h1:2Jlc7DoEwr12W+7l8Hr6C7XF4NHST3gIkqSArLhGSxU= +github.com/ipfs/go-test v0.4.1 h1:n6uNSakIgpTQIRorqNg2O02aMIFDLQk2z4rBfrlD3Uw= +github.com/ipfs/go-test v0.4.1/go.mod h1:QmvVBf9kClNtRuFow4DASq03eFvjKla4Fy/UAkeeLO8= +github.com/ipfs/go-unixfsnode v1.10.6 h1:0rnKD4azJad4cT8t6wITqNl9Q0GTjB+YRBfMQ39C7Sw= +github.com/ipfs/go-unixfsnode v1.10.6/go.mod h1:u/9Ukl+XYpfKTMu+NXQqxbzAJVTwSCoyTYBGgE+JdSE= github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0= github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM= -github.com/ipld/go-ipld-prime v0.22.0 h1:YJhDhjEOvOYaqshd3b4atIWUoRg/rKrgmwCyUHwlbuY= -github.com/ipld/go-ipld-prime v0.22.0/go.mod h1:ol7vKxOOVgEh0iAPuiDalM+0gScXVMA5ZZa4DVrTnEA= +github.com/ipld/go-ipld-prime v0.24.0 h1:6th8Z6Peh5bCWuRAVZcDO1sHzZdVF6F2cCCDG3681tg= +github.com/ipld/go-ipld-prime v0.24.0/go.mod h1:DYZxr/5caLNFbcuU6zLOgwSW7CgUEoC4wJiZMEU8Zhs= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jarcoal/httpmock v1.0.4 h1:jp+dy/+nonJE4g4xbVtl9QdrUNbn6/3hDT5R4nDIZnA= @@ -634,17 +494,13 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= @@ -655,23 +511,20 @@ github.com/kardianos/service v1.2.4 h1:XNlGtZOYNx2u91urOdg/Kfmc+gfmuIo1Dd3rEi2Og github.com/kardianos/service v1.2.4/go.mod h1:E4V9ufUuY82F7Ztlu1eN9VXWIQxg8NoLQlmFe0MtrXc= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= -github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw= +github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= -github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= +github.com/koron/go-ssdp v0.9.1 h1:zvxbAAuJftJIZ8Jh8mda+LI7V92hYZf/sKprmOxpxwA= +github.com/koron/go-ssdp v0.9.1/go.mod h1:C43c047jWkDaeg9YuZlSh/QGqOieuWV6dbhWi/jcaLk= github.com/kovidgoyal/imaging v1.6.4 h1:K0idhRPXnRrJBKnBYcTfI1HTWSNDeAn7hYDvf9I0dCk= github.com/kovidgoyal/imaging v1.6.4/go.mod h1:bEIgsaZmXlvFfkv/CUxr9rJook6AQkJnpB5EPosRfRY= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -689,10 +542,12 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784= github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo= -github.com/libp2p/go-libp2p v0.48.0 h1:h2BrLAgrj7X8bEN05K7qmrjpNHYA+6tnsGRdprjTnvo= -github.com/libp2p/go-libp2p v0.48.0/go.mod h1:Q1fBZNdmC2Hf82husCTfkKJVfHm2we5zk+NWmOGEmWk= +github.com/libp2p/go-libp2p v0.49.0 h1:ibXuYPIHmMIPShob1BktQvSuFQkq/MemhQOLKfGujjw= +github.com/libp2p/go-libp2p v0.49.0/go.mod h1:lzjVcOBk5fCn1QD2XbSOKLZesB6gEsry8SLjCsAAGT4= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= +github.com/libp2p/go-libp2p-kad-dht v0.42.1 h1:b560sbk3L2WIgkY08VgQQSqXJfHgBTr6tmymfW+GaZY= +github.com/libp2p/go-libp2p-kad-dht v0.42.1/go.mod h1:WgImeG7wsNVtUkHVBQSSVaQ4IJR2NUVlSdn5scSI49Y= github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg= github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= @@ -701,14 +556,13 @@ github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0 github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-netroute v0.4.0 h1:sZZx9hyANYUx9PZyqcgE/E1GUG3iEtTZHUEvdtXT7/Q= github.com/libp2p/go-netroute v0.4.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= -github.com/libp2p/go-yamux/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg= -github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= +github.com/libp2p/go-yamux/v5 v5.1.0 h1:8Qlxj4E9JGJAQVW6+uj2o7mqkqsIVlSUGmTWhlXzoHE= +github.com/libp2p/go-yamux/v5 v5.1.0/go.mod h1:tgIQ07ObtRR/I0IWsFOyQIL9/dR5UXgc2s8xKmNZv1o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak= github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/matishsiao/goInfo v0.0.0-20241216093258-66a9250504d6 h1:BIv50poKtm6s4vUlN6J2qAOARALk4ACAwM9VRmKPyiI= @@ -718,8 +572,8 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= -github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= +github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-sqlite3 v1.14.42 h1:MigqEP4ZmHw3aIdIT7T+9TLa90Z6smwcthx+Azv4Cgo= @@ -727,10 +581,11 @@ github.com/mattn/go-sqlite3 v1.14.42/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kb github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mb0/diff v0.0.0-20131118162322-d8d9a906c24d h1:eAS2t2Vy+6psf9LZ4T5WXWsbkBt3Tu5PWekJy5AGyEU= github.com/mb0/diff v0.0.0-20131118162322-d8d9a906c24d/go.mod h1:3YMHqrw2Qu3Liy82v4QdAG17e9k91HZ7w3hqlpWqhDo= +github.com/mehanizm/dateparse v0.0.0-20210806203422-f82c8742c9f8 h1:SA/3Lk2gFZilCejaXeCTkA3+MHt9uI9ogzx45F/nOFE= +github.com/mehanizm/dateparse v0.0.0-20210806203422-f82c8742c9f8/go.mod h1:cBDq2yLJ1Hr7GOJxsu46m4vzUyPslmbimCrvSg6wxXU= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= @@ -744,7 +599,6 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -758,10 +612,8 @@ github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aG github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= -github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw= -github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= -github.com/multiformats/go-multiaddr-dns v0.5.0 h1:p/FTyHKX0nl59f+S+dEUe8HRK+i5Ow/QHMw8Nh3gPCo= -github.com/multiformats/go-multiaddr-dns v0.5.0/go.mod h1:yJ349b8TPIAANUyuOzn1oz9o22tV9f+06L+cCeMxC14= +github.com/multiformats/go-multiaddr-dns v0.6.0 h1:yKIW08WJHSPJ8bDAT2O/5fypCaUu9Bjl8r/1eJ4XAW8= +github.com/multiformats/go-multiaddr-dns v0.6.0/go.mod h1:dwIQwdORZfnNQCeS7xLXyn+7626oRmMsVP30Uronhf0= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multibase v0.3.0 h1:8helZD2+4Db7NNWFiktk2NePbF0boolBe6bDQvM4r68= @@ -789,8 +641,6 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 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/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= @@ -798,7 +648,6 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/oov/psd v0.0.0-20260122084234-c463b6a89e2f h1:67UmABhaufAdSFaRO/wcaTn0XgHWCirjwfFf21ZNPAc= github.com/oov/psd v0.0.0-20260122084234-c463b6a89e2f/go.mod h1:GHI1bnmAcbp96z6LNfBJvtrjxhaXGkbsk967utPlvL8= @@ -824,7 +673,6 @@ github.com/otiai10/opengraph/v2 v2.2.0/go.mod h1:tX5Dg72DBqE1dJc0cOKX8RUHbQqJOVi github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM= github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= @@ -838,14 +686,13 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20250313105119-ba97887b0a25 h1:S1hI5JiKP7883xBzZAr1ydcxrKNSVNm7+3+JwjxZEsg= github.com/planetscale/vtprotobuf v0.6.1-0.20250313105119-ba97887b0a25/go.mod h1:ZQntvDG8TkPgljxtA0R9frDoND4QORU1VXz015N5Ks4= 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/polydawn/refmt v0.89.1-0.20231129105047-37766d95467a h1:cgqrm0F3zwf9IPzca7xN4w+Zy6MC9ZkPvAC8QEWa/iQ= -github.com/polydawn/refmt v0.89.1-0.20231129105047-37766d95467a/go.mod h1:ocZfO/tLSHqfScRDNTJbAJR1by4D1lewauX9OwTaPuY= +github.com/polydawn/refmt v0.90.0 h1:58BfEsP+G4uIRD9ApJTFsag+Mw+QQlZuH9uI/lPmjfY= +github.com/polydawn/refmt v0.90.0/go.mod h1:XAlDMOunevTYDsZtOKQd8itHXFMsX/QtDkPHaj6ZLxk= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= @@ -854,8 +701,8 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= -github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU= +github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -869,28 +716,29 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= -github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY= +github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= -github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= +github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI= +github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY= +github.com/quic-go/go-ossfuzz-seeds v0.1.0 h1:APacT+iIaNF6fd8AGEiN3bT/Jtkd2jz4v4TzM7MFjy0= +github.com/quic-go/go-ossfuzz-seeds v0.1.0/go.mod h1:3IOHRbJIc+L6YKMwfDtJAM9Vj9k0YY4muhuyUYk5tbk= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= -github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= -github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= -github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= -github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= +github.com/quic-go/quic-go v0.62.0 h1:ZHDjCk5OacATwGvs8PWE97CTvX7AqZiVoW7++ZOXTf8= +github.com/quic-go/quic-go v0.62.0/go.mod h1:RAro2j2yN9a9EiPACLHT9IB2NXCvGQmmo/alT0yYI0w= +github.com/quic-go/webtransport-go v0.12.0 h1:CpnKNwZvdV0LD73xoHO8QaR0NI3llqpWRwnazdZS0sE= +github.com/quic-go/webtransport-go v0.12.0/go.mod h1:GHne8aRFJ24h73pAMrcywXtuaz/ShBXCLXLvG/NPFdU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= 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/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= @@ -905,8 +753,12 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM= github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +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/sasha-s/go-deadlock v0.3.9 h1:fiaT9rB7g5sr5ddNZvlwheclN9IP86eFW9WgqlEQV+w= github.com/sasha-s/go-deadlock v0.3.9/go.mod h1:KuZj51ZFmx42q/mPaYbRk0P1xcwe697zsJKE03vD4/Y= +github.com/sashabaranov/go-openai v1.41.2 h1:vfPRBZNMpnqu8ELsclWcAvF19lDNgh1t6TVfFFOPiSM= +github.com/sashabaranov/go-openai v1.41.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y= @@ -916,15 +768,11 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc= github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= -github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -936,19 +784,14 @@ github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= @@ -966,21 +809,14 @@ github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+Q github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/sv-tools/openapi v0.4.0 h1:UhD9DVnGox1hfTePNclpUzUFgos57FvzT2jmcAuTOJ4= -github.com/sv-tools/openapi v0.4.0/go.mod h1:kD/dG+KP0+Fom1r6nvcj/ORtLus8d8enXT6dyRZDirE= -github.com/swaggo/swag/v2 v2.0.0-rc5 h1:fK7d6ET9rrEsdB8IyuwXREWMcyQN3N7gawGFbbrjgHk= -github.com/swaggo/swag/v2 v2.0.0-rc5/go.mod h1:kCL8Fu4Zl8d5tB2Bgj96b8wRowwrwk175bZHXfuGVFI= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA= @@ -1000,13 +836,10 @@ github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4= github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE= github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y= -github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= -github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1017,9 +850,7 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -1042,32 +873,25 @@ go.abhg.dev/goldmark/wikilink v0.6.0 h1:SKZANgMD7GMbaU0kBKTh52Ea9k3A3Y5ZifHoEPC1 go.abhg.dev/goldmark/wikilink v0.6.0/go.mod h1:Sfaovp00aAVJ5khqIeDTTgkIfZrcurmJGlbntCJUbJY= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.mongodb.org/mongo-driver/v2 v2.5.1 h1:j2U/Qp+wvueSpqitLCSZPT/+ZpVc1xzuwdHWwl7d8ro= go.mongodb.org/mongo-driver/v2 v2.5.1/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= -go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= -go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo= -go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= -go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= -go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1091,50 +915,40 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= -go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= +go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= +go.yaml.in/yaml/v4 v4.0.0-rc.6 h1:1h7H1ohdUh93/FyE4YaDa1Zh64K6VVbjF4K6WUxMtH4= +go.yaml.in/yaml/v4 v4.0.0-rc.6/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4= golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= 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.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= +golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= -golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= +golang.org/x/exp v0.0.0-20260718201538-764159d718ef h1:LkZ48HFgy/TvhTI0bcWkjgFkgLyKUwcTbDjS0DUjw+A= +golang.org/x/exp v0.0.0-20260718201538-764159d718ef/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1144,34 +958,21 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/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.9.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.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1184,66 +985,38 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= 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.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +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/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1252,10 +1025,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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= @@ -1263,8 +1033,8 @@ 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.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +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-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1278,53 +1048,25 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1335,118 +1077,69 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.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.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +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.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= 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.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/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.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= +golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= 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.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +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= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1454,112 +1147,37 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= +google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1570,10 +1188,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= +google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1581,10 +1197,11 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/dnaeon/go-vcr.v4 v4.0.7 h1:Mq/RF+mq3QwtEunJSsoTbYPt3elSAmdJhAxrEaqr88I= +gopkg.in/dnaeon/go-vcr.v4 v4.0.7/go.mod h1:cRwV/njsN/D8qNJu4NAXWswz6b4OUh3rMIu4SObbLBg= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -1593,7 +1210,6 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1607,12 +1223,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= modernc.org/cc/v4 v4.27.3 h1:uNCgn37E5U09mTv1XgskEVUJ8ADKpmFMPxzGJ0TSo+U= @@ -1646,12 +1258,9 @@ modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y= nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -storj.io/drpc v0.0.34 h1:q9zlQKfJ5A7x8NQNFk8x7eKUF78FMhmAbZLnFK+og7I= -storj.io/drpc v0.0.34/go.mod h1:Y9LZaa8esL1PW2IDMqJE7CFSNq7d5bQ3RI7mGPtmKMg= +storj.io/drpc v1.0.0 h1:1Xf1KCXXbV1viIfN56eqdJ3cNwpAL7OKwQkpS6ksing= +storj.io/drpc v1.0.0/go.mod h1:Y9LZaa8esL1PW2IDMqJE7CFSNq7d5bQ3RI7mGPtmKMg= zombiezen.com/go/sqlite v1.4.2 h1:KZXLrBuJ7tKNEm+VJcApLMeQbhmAUOKA5VWS93DfFRo= zombiezen.com/go/sqlite v1.4.2/go.mod h1:5Kd4taTAD4MkBzT25mQ9uaAlLjyR0rFhsR6iINO70jc= From 908d73eebfedab6e5dd25b3749dfe5729dc437ac Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Tue, 29 Sep 2026 17:11:17 +0200 Subject: [PATCH 03/14] Guard the gRPC-Web proxy with heart's origin policy Port anytype-heart's cmd/grpcserver proxy policy: reject untrusted origins/hosts before dispatch, disable grpc-websockets unless ANYTYPE_GRPCWEB_ENABLE_WEBSOCKETS=1, honor ANYTYPE_GRPCWEB_ALLOWED_{ORIGINS,HOSTS}, and carry the Origin metadata into the request context. --- core/grpcserver/proxy.go | 90 +++++++++++++ core/grpcserver/proxy_test.go | 231 ++++++++++++++++++++++++++++++++++ core/grpcserver/server.go | 12 +- 3 files changed, 326 insertions(+), 7 deletions(-) create mode 100644 core/grpcserver/proxy.go create mode 100644 core/grpcserver/proxy_test.go diff --git a/core/grpcserver/proxy.go b/core/grpcserver/proxy.go new file mode 100644 index 0000000..df8e99e --- /dev/null +++ b/core/grpcserver/proxy.go @@ -0,0 +1,90 @@ +//go:build !nogrpcserver + +package grpcserver + +import ( + "context" + "net/http" + "os" + + "github.com/anyproto/anytype-heart/util/localorigin" + "github.com/improbable-eng/grpc-web/go/grpcweb" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +// Mirrors anytype-heart's cmd/grpcserver/proxy.go, which the CLI cannot import. + +// envAllowedOrigins adds comma-separated exact origins to the gRPC-Web allowlist. +const envAllowedOrigins = "ANYTYPE_GRPCWEB_ALLOWED_ORIGINS" + +// envAllowedHosts adds comma-separated Host header values to the allowlist, for +// servers bound to a routable interface and reached by name. +const envAllowedHosts = "ANYTYPE_GRPCWEB_ALLOWED_HOSTS" + +// envEnableWebsockets re-enables the grpc-websockets transport, which is still +// origin-checked when on. +const envEnableWebsockets = "ANYTYPE_GRPCWEB_ENABLE_WEBSOCKETS" + +// newOriginPolicy builds the allowlist guarding the gRPC-Web proxy: loopback +// origins, the desktop app's file:// renderer and the Webclipper extension, +// plus whatever the operator configured. +func newOriginPolicy(allowedOrigins, allowedHosts string) *localorigin.Policy { + return localorigin.New(allowedOrigins, + localorigin.AllowFileOrigin(), + localorigin.AllowHosts(allowedHosts), + localorigin.AllowWebclipperExtension(), + ) +} + +// websocketsEnabled reports whether the grpc-websockets transport is on. It is +// off by default: WebSocket handshakes skip the CORS preflight, so it would let +// any site reach the RPC surface directly. +func websocketsEnabled() bool { + return os.Getenv(envEnableWebsockets) == "1" +} + +func wrapOptions(policy *localorigin.Policy, withWebsockets bool) []grpcweb.Option { + opts := []grpcweb.Option{grpcweb.WithOriginFunc(policy.AllowOrigin)} + if withWebsockets { + opts = append(opts, + grpcweb.WithWebsockets(true), + grpcweb.WithWebsocketOriginFunc(policy.AllowRequest), + ) + } + return opts +} + +// newProxyHandler serves gRPC-Web only to callers the policy trusts. grpcweb's +// CORS layer does not reject a disallowed origin on a non-preflight request (it +// only omits the Access-Control-* headers and dispatches anyway), so the +// request is rejected here before it reaches the handler. +func newProxyHandler(webrpc *grpcweb.WrappedGrpcServer, policy *localorigin.Policy, withWebsockets bool) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + isWebsocket := webrpc.IsGrpcWebSocketRequest(r) + if isWebsocket && !withWebsockets { + http.Error(w, "grpc-websockets transport is disabled", http.StatusForbidden) + return + } + if !webrpc.IsGrpcWebRequest(r) && !webrpc.IsAcceptableGrpcCorsRequest(r) && !isWebsocket { + return + } + if !policy.AllowRequest(r) { + log.Warnf("rejected grpc-web request from untrusted origin %q (host %q)", r.Header.Get("Origin"), r.Host) + http.Error(w, "forbidden origin", http.StatusForbidden) + return + } + webrpc.ServeHTTP(w, r) + } +} + +// originInterceptor carries the Origin forwarded by the gRPC-Web proxy into the +// request context, so localorigin.OriginFromContext works on this transport. +func originInterceptor() grpc.UnaryServerInterceptor { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + if md, ok := metadata.FromIncomingContext(ctx); ok { + ctx = localorigin.WithOrigin(ctx, localorigin.OriginFromMetadata(md)) + } + return handler(ctx, req) + } +} diff --git a/core/grpcserver/proxy_test.go b/core/grpcserver/proxy_test.go new file mode 100644 index 0000000..6c2aa5b --- /dev/null +++ b/core/grpcserver/proxy_test.go @@ -0,0 +1,231 @@ +//go:build !nogrpcserver + +package grpcserver + +import ( + "context" + "net/http" + "net/http/httptest" + "strings" + "sync/atomic" + "testing" + + "github.com/anyproto/anytype-heart/util/localorigin" + "github.com/improbable-eng/grpc-web/go/grpcweb" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +const proxyHost = "127.0.0.1:31011" + +const probedMethod = "/anytype.ClientCommands/AccountLocalLinkNewChallenge" + +// newTestProxy wires the real grpcweb wrapper, with the options production +// uses, in front of a sentinel that records whether the RPC was dispatched. +func newTestProxy(t *testing.T, policy *localorigin.Policy, withWebsockets bool) (http.HandlerFunc, *atomic.Bool) { + t.Helper() + + var dispatched atomic.Bool + sentinel := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + dispatched.Store(true) + w.WriteHeader(http.StatusOK) + }) + + // WrapServer registers the real gRPC methods; WrapHandler does not, so + // register the probed endpoint to keep the CORS preflight check faithful. + opts := append(wrapOptions(policy, withWebsockets), grpcweb.WithEndpointsFunc(func() []string { + return []string{probedMethod} + })) + webrpc := grpcweb.WrapHandler(sentinel, opts...) + return newProxyHandler(webrpc, policy, withWebsockets), &dispatched +} + +func newGrpcWebRequest(host, origin string) *http.Request { + r := httptest.NewRequest(http.MethodPost, probedMethod, strings.NewReader("")) + r.Host = host + r.Header.Set("Content-Type", "application/grpc-web+proto") + r.Header.Set("X-Grpc-Web", "1") + if origin != "" { + r.Header.Set("Origin", origin) + } + return r +} + +func newWebsocketRequest(host, origin string) *http.Request { + r := httptest.NewRequest(http.MethodGet, probedMethod, nil) + r.Host = host + r.Header.Set("Connection", "Upgrade") + r.Header.Set("Upgrade", "websocket") + r.Header.Set("Sec-Websocket-Protocol", "grpc-websockets") + r.Header.Set("Sec-Websocket-Version", "13") + r.Header.Set("Sec-Websocket-Key", "dGhlIHNhbXBsZSBub25jZQ==") + if origin != "" { + r.Header.Set("Origin", origin) + } + return r +} + +func TestProxyHandlerRejectsUntrustedOriginBeforeDispatch(t *testing.T) { + tests := []struct { + name string + host string + origin string + }{ + {"malicious site", proxyHost, "https://evil.com"}, + {"malicious site on the proxy port", proxyHost, "https://evil.com:31011"}, + {"sandboxed iframe or data url", proxyHost, "null"}, + {"non-loopback lan origin", proxyHost, "http://192.168.1.5:3030"}, + {"dns rebinding", "evil.com:31011", ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + handler, dispatched := newTestProxy(t, newOriginPolicy("", ""), false) + w := httptest.NewRecorder() + + handler(w, newGrpcWebRequest(tt.host, tt.origin)) + + if w.Code != http.StatusForbidden { + t.Errorf("status = %d, want %d", w.Code, http.StatusForbidden) + } + if dispatched.Load() { + t.Error("the rpc must not reach the handler") + } + }) + } +} + +func TestProxyHandlerAllowsTrustedCallers(t *testing.T) { + tests := []struct { + name string + origin string + headers map[string]string + }{ + {"packaged electron renderer", "", map[string]string{"Sec-Fetch-Site": "cross-site", "Sec-Fetch-Mode": "cors"}}, + {"native client", "", nil}, + {"web build on a loopback origin", "http://127.0.0.1:3030", nil}, + {"electron dev renderer", "http://localhost:8080", nil}, + {"webclipper extension", "chrome-extension://jbnammhjiplhpjfncnlejjjejghimdkf", nil}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + handler, dispatched := newTestProxy(t, newOriginPolicy("", ""), false) + w := httptest.NewRecorder() + req := newGrpcWebRequest(proxyHost, tt.origin) + for k, v := range tt.headers { + req.Header.Set(k, v) + } + + handler(w, req) + + if w.Code == http.StatusForbidden { + t.Errorf("status = %d, want not forbidden", w.Code) + } + if !dispatched.Load() { + t.Error("the rpc should reach the handler") + } + }) + } +} + +func TestProxyHandlerHonorsConfiguredAllowlists(t *testing.T) { + t.Run("an allowed host is accepted", func(t *testing.T) { + handler, dispatched := newTestProxy(t, newOriginPolicy("", "anytype.example.com"), false) + w := httptest.NewRecorder() + + handler(w, newGrpcWebRequest("anytype.example.com:31011", "")) + + if w.Code == http.StatusForbidden || !dispatched.Load() { + t.Errorf("status = %d, dispatched = %v; want the allowed host to pass", w.Code, dispatched.Load()) + } + }) + + t.Run("an allowed origin is accepted", func(t *testing.T) { + handler, dispatched := newTestProxy(t, newOriginPolicy("http://192.168.1.5:3030", ""), false) + w := httptest.NewRecorder() + + handler(w, newGrpcWebRequest(proxyHost, "http://192.168.1.5:3030")) + + if w.Code == http.StatusForbidden || !dispatched.Load() { + t.Errorf("status = %d, dispatched = %v; want the allowed origin to pass", w.Code, dispatched.Load()) + } + }) +} + +func TestProxyHandlerWebsockets(t *testing.T) { + t.Run("disabled by default, whatever the origin", func(t *testing.T) { + for _, origin := range []string{"https://evil.com", "null", "file://", "http://127.0.0.1:3030", ""} { + handler, dispatched := newTestProxy(t, newOriginPolicy("", ""), false) + w := httptest.NewRecorder() + + handler(w, newWebsocketRequest(proxyHost, origin)) + + if w.Code != http.StatusForbidden { + t.Errorf("origin %q: status = %d, want %d", origin, w.Code, http.StatusForbidden) + } + if dispatched.Load() { + t.Errorf("origin %q: the rpc must not reach the handler", origin) + } + } + }) + + t.Run("when enabled, an untrusted origin is still refused", func(t *testing.T) { + for _, origin := range []string{"https://evil.com", "null", "http://192.168.1.5:3030"} { + handler, dispatched := newTestProxy(t, newOriginPolicy("", ""), true) + w := httptest.NewRecorder() + + handler(w, newWebsocketRequest(proxyHost, origin)) + + if w.Code != http.StatusForbidden { + t.Errorf("origin %q: status = %d, want %d", origin, w.Code, http.StatusForbidden) + } + if dispatched.Load() { + t.Errorf("origin %q: the rpc must not reach the handler", origin) + } + } + }) +} + +func TestWebsocketsEnabledReadsEnv(t *testing.T) { + t.Setenv(envEnableWebsockets, "") + if websocketsEnabled() { + t.Error("websockets must be off by default") + } + t.Setenv(envEnableWebsockets, "1") + if !websocketsEnabled() { + t.Errorf("websockets must be on when %s=1", envEnableWebsockets) + } +} + +func TestOriginInterceptorCarriesOriginIntoContext(t *testing.T) { + tests := []struct { + name string + md metadata.MD + want string + }{ + {"webclipper extension origin", metadata.Pairs("origin", "chrome-extension://jbnammhjiplhpjfncnlejjjejghimdkf"), "chrome-extension://jbnammhjiplhpjfncnlejjjejghimdkf"}, + {"loopback page origin", metadata.Pairs("origin", "http://localhost:3000"), "http://localhost:3000"}, + {"native caller sends none", metadata.MD{}, ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var got string + handler := func(ctx context.Context, _ interface{}) (interface{}, error) { + got = localorigin.OriginFromContext(ctx) + return nil, nil + } + ctx := metadata.NewIncomingContext(context.Background(), tt.md) + + _, err := originInterceptor()(ctx, nil, &grpc.UnaryServerInfo{FullMethod: probedMethod}, handler) + + if err != nil { + t.Fatalf("interceptor returned error: %v", err) + } + if got != tt.want { + t.Errorf("origin = %q, want %q", got, tt.want) + } + }) + } +} diff --git a/core/grpcserver/server.go b/core/grpcserver/server.go index 0aafc65..1e0a64a 100644 --- a/core/grpcserver/server.go +++ b/core/grpcserver/server.go @@ -91,6 +91,7 @@ func (s *Server) Start(grpcAddr, grpcWebAddr string) error { unaryInterceptors = append(unaryInterceptors, grpcprocess.ProcessInfoInterceptor( "/anytype.ClientCommands/AccountLocalLinkNewChallenge", )) + unaryInterceptors = append(unaryInterceptors, originInterceptor()) s.grpcServer = grpc.NewServer( grpc.MaxRecvMsgSize(20*1024*1024), @@ -103,15 +104,12 @@ func (s *Server) Start(grpcAddr, grpcWebAddr string) error { grpc_prometheus.EnableHandlingTimeHistogram() } - webrpc := grpcweb.WrapServer( - s.grpcServer, - grpcweb.WithOriginFunc(func(origin string) bool { return true }), - grpcweb.WithWebsockets(true), - grpcweb.WithWebsocketOriginFunc(func(req *http.Request) bool { return true }), - ) + originPolicy := newOriginPolicy(os.Getenv(envAllowedOrigins), os.Getenv(envAllowedHosts)) + withWebsockets := websocketsEnabled() + webrpc := grpcweb.WrapServer(s.grpcServer, wrapOptions(originPolicy, withWebsockets)...) s.webServer = &http.Server{ - Handler: webrpc, + Handler: newProxyHandler(webrpc, originPolicy, withWebsockets), ReadHeaderTimeout: 30 * time.Second, } From eafcc5b83cf09300ba0997f6cefe84cfb2ba0189 Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Tue, 29 Sep 2026 17:13:18 +0200 Subject: [PATCH 04/14] Add API key grant building and space resolution Require an explicit space choice (--space/--all-spaces) and permission choice (--read-only/--read-write); resolve spaces to full Ids (Id wins over name, ambiguous names fail, tech space only by explicit Id); never build a nil or empty grant; validate key names like the server does. --- core/apikeygrant.go | 148 +++++++++++++++++++++++++++ core/apikeygrant_test.go | 211 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 359 insertions(+) create mode 100644 core/apikeygrant.go create mode 100644 core/apikeygrant_test.go diff --git a/core/apikeygrant.go b/core/apikeygrant.go new file mode 100644 index 0000000..be29f17 --- /dev/null +++ b/core/apikeygrant.go @@ -0,0 +1,148 @@ +package core + +import ( + "errors" + "fmt" + "strings" + + "github.com/anyproto/anytype-heart/core/domain" + "github.com/anyproto/anytype-heart/pkg/lib/pb/model" +) + +var ( + ErrSpaceChoiceRequired = errors.New("choose which spaces the key can access: --space (repeatable) or --all-spaces") + ErrPermChoiceRequired = errors.New("choose the key's permission: --read-only or --read-write") + ErrConflictingSpaceFlags = errors.New("--space and --all-spaces cannot be combined") + ErrConflictingPermFlags = errors.New("--read-only and --read-write cannot be combined") +) + +// GrantFlags is the user's access choice for an API key. Both choices are +// required: the CLI never picks spaces or a permission on the user's behalf. +type GrantFlags struct { + Spaces []string + AllSpaces bool + ReadOnly bool + ReadWrite bool +} + +// ResolvedSpace is a space argument resolved to a full space Id. +type ResolvedSpace struct { + Id string + Name string + IsTech bool +} + +// ValidateGrantFlags checks that exactly one space choice and exactly one +// permission choice were made. +func ValidateGrantFlags(flags GrantFlags) error { + hasSpaces := len(flags.Spaces) > 0 + if hasSpaces && flags.AllSpaces { + return ErrConflictingSpaceFlags + } + if !hasSpaces && !flags.AllSpaces { + return ErrSpaceChoiceRequired + } + if flags.ReadOnly && flags.ReadWrite { + return ErrConflictingPermFlags + } + if !flags.ReadOnly && !flags.ReadWrite { + return ErrPermChoiceRequired + } + return nil +} + +// ResolveSpaces resolves each argument to a full space Id. An exact Id wins over +// a name; a name must match exactly one space. The tech space is only reachable +// by its explicit Id. Duplicates are dropped, keeping first-appearance order. +func ResolveSpaces(args []string, spaces []SpaceListItem, techSpaceId string) ([]ResolvedSpace, error) { + var resolved []ResolvedSpace + seen := make(map[string]struct{}) + + for _, arg := range args { + if strings.TrimSpace(arg) == "" { + return nil, errors.New("empty space argument") + } + + space, err := resolveSpace(arg, spaces, techSpaceId) + if err != nil { + return nil, err + } + if _, ok := seen[space.Id]; ok { + continue + } + seen[space.Id] = struct{}{} + resolved = append(resolved, space) + } + + return resolved, nil +} + +func resolveSpace(arg string, spaces []SpaceListItem, techSpaceId string) (ResolvedSpace, error) { + if techSpaceId != "" && arg == techSpaceId { + return ResolvedSpace{Id: techSpaceId, IsTech: true}, nil + } + for _, space := range spaces { + if space.SpaceId == arg { + return ResolvedSpace{Id: space.SpaceId, Name: space.Name}, nil + } + } + + var matches []SpaceListItem + for _, space := range spaces { + if space.Name == arg { + matches = append(matches, space) + } + } + switch len(matches) { + case 0: + return ResolvedSpace{}, fmt.Errorf("space %q not found; run 'anytype space list' to see your spaces", arg) + case 1: + return ResolvedSpace{Id: matches[0].SpaceId, Name: matches[0].Name}, nil + default: + candidates := make([]string, len(matches)) + for i, m := range matches { + candidates[i] = fmt.Sprintf("%s (%s)", m.Name, m.SpaceId) + } + return ResolvedSpace{}, fmt.Errorf("space name %q is ambiguous, pass the space Id instead: %s", arg, strings.Join(candidates, ", ")) + } +} + +// BuildGrant turns validated flags and resolved spaces into the grant sent to +// the server. It never returns a nil or empty grant: a key without a grant would +// be unrestricted. +func BuildGrant(flags GrantFlags, resolved []ResolvedSpace) (*model.AccountAuthAppGrant, error) { + if err := ValidateGrantFlags(flags); err != nil { + return nil, err + } + + perm := model.AccountAuthAppGrant_Read + if flags.ReadWrite { + perm = model.AccountAuthAppGrant_ReadWrite + } + + if flags.AllSpaces { + return &model.AccountAuthAppGrant{AllSpaces: true, Perm: perm}, nil + } + if len(resolved) == 0 { + return nil, ErrSpaceChoiceRequired + } + + spaceIds := make([]string, len(resolved)) + for i, space := range resolved { + spaceIds[i] = space.Id + } + return &model.AccountAuthAppGrant{SpaceIds: spaceIds, Perm: perm}, nil +} + +// ValidateAPIKeyName mirrors the server's rule: the name is required and at most +// domain.MaxIntegrationNameLen bytes. It is never truncated, because on API v2 +// the name decides which objects the key may delete. +func ValidateAPIKeyName(name string) error { + if strings.TrimSpace(name) == "" { + return errors.New("API key name is required") + } + if len(name) > domain.MaxIntegrationNameLen { + return fmt.Errorf("API key name is %d bytes, the maximum is %d", len(name), domain.MaxIntegrationNameLen) + } + return nil +} diff --git a/core/apikeygrant_test.go b/core/apikeygrant_test.go new file mode 100644 index 0000000..f090bb2 --- /dev/null +++ b/core/apikeygrant_test.go @@ -0,0 +1,211 @@ +package core + +import ( + "errors" + "reflect" + "strings" + "testing" + + "github.com/anyproto/anytype-heart/pkg/lib/pb/model" +) + +const testTechSpaceId = "bafyreitech.tech" + +var testSpaces = []SpaceListItem{ + {SpaceId: "bafyreia.one", Name: "Personal"}, + {SpaceId: "bafyreib.two", Name: "Team"}, + {SpaceId: "bafyreic.three", Name: "Team"}, + {SpaceId: "bafyreid.four", Name: "Work"}, +} + +func TestValidateGrantFlags(t *testing.T) { + tests := []struct { + name string + flags GrantFlags + wantErr error + }{ + {"spaces and read-only", GrantFlags{Spaces: []string{"Work"}, ReadOnly: true}, nil}, + {"all spaces and read-write", GrantFlags{AllSpaces: true, ReadWrite: true}, nil}, + {"no space choice", GrantFlags{ReadOnly: true}, ErrSpaceChoiceRequired}, + {"no permission choice", GrantFlags{AllSpaces: true}, ErrPermChoiceRequired}, + {"nothing chosen reports spaces first", GrantFlags{}, ErrSpaceChoiceRequired}, + {"spaces and all spaces together", GrantFlags{Spaces: []string{"Work"}, AllSpaces: true, ReadOnly: true}, ErrConflictingSpaceFlags}, + {"read-only and read-write together", GrantFlags{AllSpaces: true, ReadOnly: true, ReadWrite: true}, ErrConflictingPermFlags}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidateGrantFlags(tt.flags) + if !errors.Is(err, tt.wantErr) { + t.Errorf("ValidateGrantFlags() error = %v, want %v", err, tt.wantErr) + } + }) + } +} + +func TestResolveSpaces(t *testing.T) { + tests := []struct { + name string + args []string + want []ResolvedSpace + wantErrText string + }{ + { + name: "by exact id", + args: []string{"bafyreid.four"}, + want: []ResolvedSpace{{Id: "bafyreid.four", Name: "Work"}}, + }, + { + name: "by unique name", + args: []string{"Personal"}, + want: []ResolvedSpace{{Id: "bafyreia.one", Name: "Personal"}}, + }, + { + name: "id and name of the same space are deduplicated", + args: []string{"Work", "bafyreid.four", "Work"}, + want: []ResolvedSpace{{Id: "bafyreid.four", Name: "Work"}}, + }, + { + name: "order of first appearance is kept", + args: []string{"Work", "Personal"}, + want: []ResolvedSpace{{Id: "bafyreid.four", Name: "Work"}, {Id: "bafyreia.one", Name: "Personal"}}, + }, + { + name: "tech space by explicit id", + args: []string{testTechSpaceId}, + want: []ResolvedSpace{{Id: testTechSpaceId, IsTech: true}}, + }, + { + name: "ambiguous name lists candidates", + args: []string{"Team"}, + wantErrText: "bafyreic.three", + }, + { + name: "unknown name or id", + args: []string{"Nope"}, + wantErrText: `space "Nope" not found`, + }, + { + name: "name match is exact, not case-insensitive", + args: []string{"work"}, + wantErrText: `space "work" not found`, + }, + { + name: "empty argument", + args: []string{""}, + wantErrText: "empty space", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ResolveSpaces(tt.args, testSpaces, testTechSpaceId) + if tt.wantErrText != "" { + if err == nil || !strings.Contains(err.Error(), tt.wantErrText) { + t.Fatalf("ResolveSpaces() error = %v, want it to contain %q", err, tt.wantErrText) + } + return + } + if err != nil { + t.Fatalf("ResolveSpaces() unexpected error: %v", err) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ResolveSpaces() = %+v, want %+v", got, tt.want) + } + }) + } +} + +func TestBuildGrant(t *testing.T) { + resolved := []ResolvedSpace{{Id: "bafyreia.one", Name: "Personal"}, {Id: "bafyreid.four", Name: "Work"}} + + tests := []struct { + name string + flags GrantFlags + resolved []ResolvedSpace + want *model.AccountAuthAppGrant + }{ + { + name: "listed spaces, read-only", + flags: GrantFlags{Spaces: []string{"Personal", "Work"}, ReadOnly: true}, + resolved: resolved, + want: &model.AccountAuthAppGrant{SpaceIds: []string{"bafyreia.one", "bafyreid.four"}, Perm: model.AccountAuthAppGrant_Read}, + }, + { + name: "listed spaces, read-write", + flags: GrantFlags{Spaces: []string{"Personal", "Work"}, ReadWrite: true}, + resolved: resolved, + want: &model.AccountAuthAppGrant{SpaceIds: []string{"bafyreia.one", "bafyreid.four"}, Perm: model.AccountAuthAppGrant_ReadWrite}, + }, + { + name: "all spaces, read-write", + flags: GrantFlags{AllSpaces: true, ReadWrite: true}, + want: &model.AccountAuthAppGrant{AllSpaces: true, Perm: model.AccountAuthAppGrant_ReadWrite}, + }, + { + name: "all spaces, read-only", + flags: GrantFlags{AllSpaces: true, ReadOnly: true}, + want: &model.AccountAuthAppGrant{AllSpaces: true, Perm: model.AccountAuthAppGrant_Read}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := BuildGrant(tt.flags, tt.resolved) + if err != nil { + t.Fatalf("BuildGrant() unexpected error: %v", err) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("BuildGrant() = %+v, want %+v", got, tt.want) + } + }) + } +} + +func TestBuildGrantNeverReturnsNilOrEmpty(t *testing.T) { + tests := []struct { + name string + flags GrantFlags + resolved []ResolvedSpace + }{ + {"no choices", GrantFlags{}, nil}, + {"space flag but nothing resolved", GrantFlags{Spaces: []string{"x"}, ReadOnly: true}, nil}, + {"no permission", GrantFlags{AllSpaces: true}, nil}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := BuildGrant(tt.flags, tt.resolved) + if err == nil { + t.Fatalf("BuildGrant() = %+v, want an error", got) + } + if got != nil { + t.Errorf("BuildGrant() returned a grant alongside error: %+v", got) + } + }) + } +} + +func TestValidateAPIKeyName(t *testing.T) { + tests := []struct { + name string + keyName string + wantErr bool + }{ + {"normal name", "my-integration", false}, + {"exactly 128 bytes", strings.Repeat("a", 128), false}, + {"empty", "", true}, + {"whitespace only", " ", true}, + {"129 bytes", strings.Repeat("a", 129), true}, + {"multibyte over the byte limit", strings.Repeat("é", 65), true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidateAPIKeyName(tt.keyName) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateAPIKeyName(%q) error = %v, wantErr %v", tt.keyName, err, tt.wantErr) + } + }) + } +} From ef9063bd9aa7288d6e7c56da74180c49606d7510 Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Tue, 29 Sep 2026 17:17:15 +0200 Subject: [PATCH 05/14] Create JSON API keys with an explicit space and permission grant apikey create now requires --space ... or --all-spaces, and --read-only or --read-write, and creates JsonAPI-scope keys that work with the JSON API v2. Before creating, probe the server for grant support (old servers would silently drop the grant); after creating, read the key back and revoke it if its scope or grant differ. --- cmd/auth/apikey/create/create.go | 92 ++++++++++++++- cmd/auth/apikey/create/create_test.go | 122 ++++++++++++++++++++ core/apikey.go | 144 ++++++++++++++++++----- core/apikey_test.go | 159 ++++++++++++++++++++++++++ core/apikeygrant.go | 44 +++++++ core/apikeygrant_test.go | 50 ++++++++ 6 files changed, 579 insertions(+), 32 deletions(-) create mode 100644 cmd/auth/apikey/create/create_test.go create mode 100644 core/apikey_test.go diff --git a/cmd/auth/apikey/create/create.go b/cmd/auth/apikey/create/create.go index 3e9e55a..66631e4 100644 --- a/cmd/auth/apikey/create/create.go +++ b/cmd/auth/apikey/create/create.go @@ -1,34 +1,118 @@ package create import ( + "errors" + "fmt" + "strings" + "github.com/spf13/cobra" "github.com/anyproto/anytype-cli/cmd/cmdutil" "github.com/anyproto/anytype-cli/core" + "github.com/anyproto/anytype-cli/core/config" "github.com/anyproto/anytype-cli/core/output" ) +// Server calls, replaceable in tests. +var ( + listSpaces = core.ListSpaces + techSpaceId = config.GetTechSpaceIdFromConfig + createAPIKey = core.CreateAPIKey +) + func NewCreateCmd() *cobra.Command { + var flags core.GrantFlags + cmd := &cobra.Command{ Use: "create ", Short: "Create a new API key", - Long: "Create a new API key for programmatic access to Anytype", - Args: cmdutil.ExactArgs(1, "cannot create API key: name argument required"), + Long: `Create a new API key for programmatic access to Anytype. + +You must choose which spaces the key can access and whether it can write: + --space (repeatable) or --all-spaces + --read-only or --read-write + +Keys limited to specific spaces, or read-only keys, work with the JSON API v2 only.`, + Example: ` anytype auth apikey create my-app --space "Personal" --read-only + anytype auth apikey create my-app --all-spaces --read-write`, + Args: cmdutil.ExactArgs(1, "cannot create API key: name argument required"), RunE: func(cmd *cobra.Command, args []string) error { name := args[0] - resp, err := core.CreateAPIKey(name) + if err := core.ValidateAPIKeyName(name); err != nil { + return output.Error("Failed to create API key: %w", err) + } + if err := core.ValidateGrantFlags(flags); err != nil { + if errors.Is(err, core.ErrSpaceChoiceRequired) { + return output.Error("Failed to create API key: %w%s", err, spaceChoices()) + } + return output.Error("Failed to create API key: %w", err) + } + + var resolved []core.ResolvedSpace + if len(flags.Spaces) > 0 { + spaces, err := listSpaces() + if err != nil { + return output.Error("Failed to list spaces: %w", err) + } + techId, err := techSpaceId() + if err != nil { + return output.Error("Failed to read tech space Id: %w", err) + } + resolved, err = core.ResolveSpaces(flags.Spaces, spaces, techId) + if err != nil { + return output.Error("Failed to create API key: %w", err) + } + for _, space := range resolved { + if space.IsTech { + output.Warning("The key can access the tech space, which holds account internals; writing to it can break your account") + } + } + } + + grant, err := core.BuildGrant(flags, resolved) + if err != nil { + return output.Error("Failed to create API key: %w", err) + } + + created, err := createAPIKey(name, grant) if err != nil { return output.Error("Failed to create API key: %w", err) } output.Success("API key created successfully") output.Info("Name: %s", name) - output.Info("Key: %s", resp.AppKey) + output.Info("Key: %s", created.Key) + output.Info("Access: %s", core.DescribeGrant(created.App.Grant, resolved)) + if core.GrantWorksOnV1(created.App.Grant) { + output.Info("Works with: JSON API v1 and v2") + } else { + output.Info("Works with: JSON API v2 only") + } return nil }, } + cmd.Flags().StringArrayVar(&flags.Spaces, "space", nil, "Space the key can access, by Id or exact name (repeatable)") + cmd.Flags().BoolVar(&flags.AllSpaces, "all-spaces", false, "Let the key access all spaces, including ones created later") + cmd.Flags().BoolVar(&flags.ReadOnly, "read-only", false, "Let the key read but not change data") + cmd.Flags().BoolVar(&flags.ReadWrite, "read-write", false, "Let the key read and change data") + return cmd } + +// spaceChoices lists the user's spaces to help pick --space values. It is best +// effort: without a running server the error is returned without the list. +func spaceChoices() string { + spaces, err := listSpaces() + if err != nil || len(spaces) == 0 { + return "" + } + var b strings.Builder + b.WriteString("\n\nYour spaces:") + for _, space := range spaces { + fmt.Fprintf(&b, "\n %s (%s)", space.Name, space.SpaceId) + } + return b.String() +} diff --git a/cmd/auth/apikey/create/create_test.go b/cmd/auth/apikey/create/create_test.go new file mode 100644 index 0000000..db51c3d --- /dev/null +++ b/cmd/auth/apikey/create/create_test.go @@ -0,0 +1,122 @@ +package create + +import ( + "errors" + "io" + "strings" + "testing" + + "github.com/anyproto/anytype-cli/core" + "github.com/anyproto/anytype-heart/pkg/lib/pb/model" +) + +// stubServer replaces the server calls and records whether a key was created. +func stubServer(t *testing.T, spaces []core.SpaceListItem) *bool { + t.Helper() + created := false + origList, origTech, origCreate := listSpaces, techSpaceId, createAPIKey + listSpaces = func() ([]core.SpaceListItem, error) { return spaces, nil } + techSpaceId = func() (string, error) { return "bafyreitech.tech", nil } + createAPIKey = func(name string, grant *model.AccountAuthAppGrant) (*core.CreatedAPIKey, error) { + created = true + return &core.CreatedAPIKey{Key: "secret", App: &model.AccountAuthAppInfo{AppName: name, Scope: model.AccountAuth_JsonAPI, Grant: grant}}, nil + } + t.Cleanup(func() { listSpaces, techSpaceId, createAPIKey = origList, origTech, origCreate }) + return &created +} + +func runCreate(args ...string) error { + cmd := NewCreateCmd() + cmd.SetArgs(args) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + return cmd.Execute() +} + +func TestCreateCommandFlags(t *testing.T) { + cmd := NewCreateCmd() + for _, name := range []string{"space", "all-spaces", "read-only", "read-write"} { + if cmd.Flag(name) == nil { + t.Errorf("flag --%s not found", name) + } + } +} + +func TestCreateRequiresExplicitChoices(t *testing.T) { + spaces := []core.SpaceListItem{{SpaceId: "bafyreia.one", Name: "Personal"}} + + tests := []struct { + name string + args []string + wantErr error + wantMsg string + }{ + {"no space choice lists the spaces", []string{"my-app", "--read-only"}, core.ErrSpaceChoiceRequired, "Personal (bafyreia.one)"}, + {"no permission choice", []string{"my-app", "--all-spaces"}, core.ErrPermChoiceRequired, ""}, + {"no choices at all", []string{"my-app"}, core.ErrSpaceChoiceRequired, ""}, + {"conflicting space flags", []string{"my-app", "--all-spaces", "--space", "Personal", "--read-only"}, core.ErrConflictingSpaceFlags, ""}, + {"conflicting permission flags", []string{"my-app", "--all-spaces", "--read-only", "--read-write"}, core.ErrConflictingPermFlags, ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + created := stubServer(t, spaces) + + err := runCreate(tt.args...) + + if !errors.Is(err, tt.wantErr) { + t.Fatalf("error = %v, want %v", err, tt.wantErr) + } + if tt.wantMsg != "" && !strings.Contains(err.Error(), tt.wantMsg) { + t.Errorf("error = %q, want it to contain %q", err, tt.wantMsg) + } + if *created { + t.Error("no key may be created without both choices") + } + }) + } +} + +func TestCreateRejectsInvalidName(t *testing.T) { + created := stubServer(t, nil) + + err := runCreate(strings.Repeat("a", 129), "--all-spaces", "--read-only") + + if err == nil { + t.Fatal("expected an error for a name over 128 bytes") + } + if *created { + t.Error("no key may be created with an invalid name") + } +} + +func TestCreateRejectsUnknownSpace(t *testing.T) { + created := stubServer(t, []core.SpaceListItem{{SpaceId: "bafyreia.one", Name: "Personal"}}) + + err := runCreate("my-app", "--space", "Nope", "--read-only") + + if err == nil || !strings.Contains(err.Error(), `"Nope" not found`) { + t.Fatalf("error = %v, want unknown space error", err) + } + if *created { + t.Error("no key may be created for an unknown space") + } +} + +func TestCreateSendsResolvedGrant(t *testing.T) { + stubServer(t, []core.SpaceListItem{{SpaceId: "bafyreia.one", Name: "Personal"}}) + var sent *model.AccountAuthAppGrant + createAPIKey = func(name string, grant *model.AccountAuthAppGrant) (*core.CreatedAPIKey, error) { + sent = grant + return &core.CreatedAPIKey{Key: "secret", App: &model.AccountAuthAppInfo{AppName: name, Grant: grant}}, nil + } + + err := runCreate("my-app", "--space", "Personal", "--read-write") + + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if sent == nil || len(sent.SpaceIds) != 1 || sent.SpaceIds[0] != "bafyreia.one" || sent.Perm != model.AccountAuthAppGrant_ReadWrite { + t.Errorf("sent grant = %+v, want Personal read-write", sent) + } +} diff --git a/core/apikey.go b/core/apikey.go index c52cc2c..a10062d 100644 --- a/core/apikey.go +++ b/core/apikey.go @@ -2,36 +2,120 @@ package core import ( "context" + "errors" "fmt" - "github.com/anyproto/anytype-heart/pkg/lib/pb/model" + "slices" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "github.com/anyproto/anytype-heart/pb" "github.com/anyproto/anytype-heart/pb/service" + "github.com/anyproto/anytype-heart/pkg/lib/pb/model" ) -// CreateAPIKey creates a new API key for local app access -func CreateAPIKey(name string) (*pb.RpcAccountLocalLinkCreateAppResponse, error) { - var resp *pb.RpcAccountLocalLinkCreateAppResponse +// ErrServerTooOld means the running server cannot store API key grants, so a +// key created on it would silently get unrestricted access. +var ErrServerTooOld = errors.New("the running Anytype service is older than this CLI and cannot restrict API keys; restart it with: anytype service restart") + +// CreatedAPIKey is a newly created key: the secret and the key as the server +// stored it. +type CreatedAPIKey struct { + Key string + App *model.AccountAuthAppInfo +} +// CreateAPIKey creates a JSON API key limited to the given grant. +func CreateAPIKey(name string, grant *model.AccountAuthAppGrant) (*CreatedAPIKey, error) { + var created *CreatedAPIKey err := GRPCCall(func(ctx context.Context, client service.ClientCommandsClient) error { var err error - resp, err = client.AccountLocalLinkCreateApp(ctx, &pb.RpcAccountLocalLinkCreateAppRequest{ - App: &model.AccountAuthAppInfo{ - AppName: name, - }, - }) - if err != nil { - return fmt.Errorf("failed to create API key: %w", err) - } + created, err = createAPIKey(ctx, client, name, grant) + return err + }) + return created, err +} - if resp.Error != nil && resp.Error.Code != pb.RpcAccountLocalLinkCreateAppResponseError_NULL { - return fmt.Errorf("API error: %s", resp.Error.Description) - } +func createAPIKey(ctx context.Context, client service.ClientCommandsClient, name string, grant *model.AccountAuthAppGrant) (*CreatedAPIKey, error) { + if grant == nil { + return nil, errors.New("an API key must be limited to a grant") + } + if err := ensureGrantSupport(ctx, client); err != nil { + return nil, err + } - return nil + resp, err := client.AccountLocalLinkCreateApp(ctx, &pb.RpcAccountLocalLinkCreateAppRequest{ + App: &model.AccountAuthAppInfo{ + AppName: name, + Scope: model.AccountAuth_JsonAPI, + Grant: grant, + }, }) + if err != nil { + return nil, fmt.Errorf("failed to create API key: %w", err) + } + if resp.Error != nil && resp.Error.Code != pb.RpcAccountLocalLinkCreateAppResponseError_NULL { + return nil, fmt.Errorf("API error: %s", resp.Error.Description) + } - return resp, err + // Never trust the server to have applied what was asked: read the key back + // and revoke it if its access differs from the request. + stored, err := findAppByKey(ctx, client, resp.AppKey) + if err != nil { + return nil, fmt.Errorf("API key created but could not be verified, check 'anytype auth apikey list': %w", err) + } + if stored.Scope != model.AccountAuth_JsonAPI || !grantsEqual(stored.Grant, grant) { + if revokeErr := revokeAPIKey(ctx, client, stored.AppHash); revokeErr != nil { + return nil, fmt.Errorf("the server did not store the requested access and revoking the key failed, revoke %s manually: %w", stored.AppHash, revokeErr) + } + return nil, fmt.Errorf("the server did not store the requested access, so the key was revoked: %w", ErrServerTooOld) + } + + return &CreatedAPIKey{Key: resp.AppKey, App: stored}, nil +} + +// ensureGrantSupport probes for AccountLocalLinkUpdateApp, which arrived with +// grants. An empty app hash makes a capable server answer BAD_INPUT without +// changing anything; an older server does not know the method. +func ensureGrantSupport(ctx context.Context, client service.ClientCommandsClient) error { + _, err := client.AccountLocalLinkUpdateApp(ctx, &pb.RpcAccountLocalLinkUpdateAppRequest{}) + if status.Code(err) == codes.Unimplemented { + return ErrServerTooOld + } + if err != nil { + return fmt.Errorf("failed to check server capabilities: %w", err) + } + return nil +} + +func findAppByKey(ctx context.Context, client service.ClientCommandsClient, key string) (*model.AccountAuthAppInfo, error) { + resp, err := client.AccountLocalLinkListApps(ctx, &pb.RpcAccountLocalLinkListAppsRequest{}) + if err != nil { + return nil, err + } + if resp.Error != nil && resp.Error.Code != pb.RpcAccountLocalLinkListAppsResponseError_NULL { + return nil, fmt.Errorf("API error: %s", resp.Error.Description) + } + for _, app := range resp.App { + if app.AppKey == key { + return app, nil + } + } + return nil, errors.New("the new key is not in the server's key list") +} + +// grantsEqual compares grants by meaning: space order is irrelevant. +func grantsEqual(a, b *model.AccountAuthAppGrant) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + if a.AllSpaces != b.AllSpaces || a.Perm != b.Perm { + return false + } + as, bs := slices.Clone(a.SpaceIds), slices.Clone(b.SpaceIds) + slices.Sort(as) + slices.Sort(bs) + return slices.Equal(as, bs) } // ListAPIKeys lists all API keys @@ -58,17 +142,21 @@ func ListAPIKeys() (*pb.RpcAccountLocalLinkListAppsResponse, error) { // RevokeAPIKey revokes an API key by appId func RevokeAPIKey(appId string) error { return GRPCCall(func(ctx context.Context, client service.ClientCommandsClient) error { - resp, err := client.AccountLocalLinkRevokeApp(ctx, &pb.RpcAccountLocalLinkRevokeAppRequest{ - AppHash: appId, - }) - if err != nil { - return fmt.Errorf("failed to revoke API key: %w", err) - } - - if resp.Error != nil && resp.Error.Code != pb.RpcAccountLocalLinkRevokeAppResponseError_NULL { - return fmt.Errorf("API error: %s", resp.Error.Description) - } + return revokeAPIKey(ctx, client, appId) + }) +} - return nil +func revokeAPIKey(ctx context.Context, client service.ClientCommandsClient, appId string) error { + resp, err := client.AccountLocalLinkRevokeApp(ctx, &pb.RpcAccountLocalLinkRevokeAppRequest{ + AppHash: appId, }) + if err != nil { + return fmt.Errorf("failed to revoke API key: %w", err) + } + + if resp.Error != nil && resp.Error.Code != pb.RpcAccountLocalLinkRevokeAppResponseError_NULL { + return fmt.Errorf("API error: %s", resp.Error.Description) + } + + return nil } diff --git a/core/apikey_test.go b/core/apikey_test.go new file mode 100644 index 0000000..8728960 --- /dev/null +++ b/core/apikey_test.go @@ -0,0 +1,159 @@ +package core + +import ( + "context" + "errors" + "testing" + + "github.com/anyproto/anytype-heart/pb" + "github.com/anyproto/anytype-heart/pb/service" + "github.com/anyproto/anytype-heart/pkg/lib/pb/model" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// fakeAppLinkClient is an in-memory app link store. It embeds the client +// interface so only the methods under test need implementing. +type fakeAppLinkClient struct { + service.ClientCommandsClient + + // oldServer makes UpdateApp unknown, like anytype-heart before v0.51.3. + oldServer bool + // dropGrant makes CreateApp ignore the grant, like an old server would. + dropGrant bool + + apps []*model.AccountAuthAppInfo + createCalls []*pb.RpcAccountLocalLinkCreateAppRequest + revoked []string +} + +func (f *fakeAppLinkClient) AccountLocalLinkUpdateApp(_ context.Context, in *pb.RpcAccountLocalLinkUpdateAppRequest, _ ...grpc.CallOption) (*pb.RpcAccountLocalLinkUpdateAppResponse, error) { + if f.oldServer { + return nil, status.Error(codes.Unimplemented, "unknown method AccountLocalLinkUpdateApp") + } + if in.AppHash == "" { + return &pb.RpcAccountLocalLinkUpdateAppResponse{Error: &pb.RpcAccountLocalLinkUpdateAppResponseError{ + Code: pb.RpcAccountLocalLinkUpdateAppResponseError_BAD_INPUT, Description: "app hash is required", + }}, nil + } + return &pb.RpcAccountLocalLinkUpdateAppResponse{Error: &pb.RpcAccountLocalLinkUpdateAppResponseError{}}, nil +} + +func (f *fakeAppLinkClient) AccountLocalLinkCreateApp(_ context.Context, in *pb.RpcAccountLocalLinkCreateAppRequest, _ ...grpc.CallOption) (*pb.RpcAccountLocalLinkCreateAppResponse, error) { + f.createCalls = append(f.createCalls, in) + key := "key-" + in.App.AppName + stored := &model.AccountAuthAppInfo{ + AppHash: "hash-" + in.App.AppName, + AppName: in.App.AppName, + AppKey: key, + Scope: in.App.Scope, + ExpireAt: in.App.ExpireAt, + Grant: in.App.Grant, + } + if f.dropGrant { + stored.Grant = nil + } + f.apps = append(f.apps, stored) + return &pb.RpcAccountLocalLinkCreateAppResponse{Error: &pb.RpcAccountLocalLinkCreateAppResponseError{}, AppKey: key}, nil +} + +func (f *fakeAppLinkClient) AccountLocalLinkListApps(_ context.Context, _ *pb.RpcAccountLocalLinkListAppsRequest, _ ...grpc.CallOption) (*pb.RpcAccountLocalLinkListAppsResponse, error) { + return &pb.RpcAccountLocalLinkListAppsResponse{Error: &pb.RpcAccountLocalLinkListAppsResponseError{}, App: f.apps}, nil +} + +func (f *fakeAppLinkClient) AccountLocalLinkRevokeApp(_ context.Context, in *pb.RpcAccountLocalLinkRevokeAppRequest, _ ...grpc.CallOption) (*pb.RpcAccountLocalLinkRevokeAppResponse, error) { + f.revoked = append(f.revoked, in.AppHash) + return &pb.RpcAccountLocalLinkRevokeAppResponse{Error: &pb.RpcAccountLocalLinkRevokeAppResponseError{}}, nil +} + +var testGrant = &model.AccountAuthAppGrant{SpaceIds: []string{"bafyreia.one"}, Perm: model.AccountAuthAppGrant_Read} + +func TestCreateAPIKeySendsJsonAPIScopeAndGrant(t *testing.T) { + client := &fakeAppLinkClient{} + + created, err := createAPIKey(context.Background(), client, "my-app", testGrant) + + if err != nil { + t.Fatalf("createAPIKey() unexpected error: %v", err) + } + if len(client.createCalls) != 1 { + t.Fatalf("CreateApp called %d times, want 1", len(client.createCalls)) + } + sent := client.createCalls[0].App + if sent.Scope != model.AccountAuth_JsonAPI { + t.Errorf("scope = %v, want JsonAPI", sent.Scope) + } + if sent.Grant != testGrant { + t.Errorf("grant = %+v, want %+v", sent.Grant, testGrant) + } + if created.Key != "key-my-app" || created.App.AppHash != "hash-my-app" { + t.Errorf("created = %+v, want key and stored app", created) + } + if len(client.revoked) != 0 { + t.Errorf("revoked %v, want nothing revoked", client.revoked) + } +} + +func TestCreateAPIKeyRejectsNilGrant(t *testing.T) { + client := &fakeAppLinkClient{} + + _, err := createAPIKey(context.Background(), client, "my-app", nil) + + if err == nil { + t.Fatal("createAPIKey() with nil grant succeeded, want an error") + } + if len(client.createCalls) != 0 { + t.Error("CreateApp must not be called without a grant") + } +} + +func TestCreateAPIKeyRefusesOldServer(t *testing.T) { + client := &fakeAppLinkClient{oldServer: true} + + _, err := createAPIKey(context.Background(), client, "my-app", testGrant) + + if !errors.Is(err, ErrServerTooOld) { + t.Fatalf("createAPIKey() error = %v, want ErrServerTooOld", err) + } + if len(client.createCalls) != 0 { + t.Error("CreateApp must not be called on a server that cannot store grants") + } +} + +func TestCreateAPIKeyRevokesKeyWhenServerDropsGrant(t *testing.T) { + client := &fakeAppLinkClient{dropGrant: true} + + _, err := createAPIKey(context.Background(), client, "my-app", testGrant) + + if err == nil { + t.Fatal("createAPIKey() succeeded although the server dropped the grant") + } + if len(client.revoked) != 1 || client.revoked[0] != "hash-my-app" { + t.Errorf("revoked = %v, want the new key revoked", client.revoked) + } +} + +func TestGrantsEqual(t *testing.T) { + tests := []struct { + name string + a, b *model.AccountAuthAppGrant + want bool + }{ + {"both nil", nil, nil, true}, + {"one nil", testGrant, nil, false}, + {"same spaces and perm", testGrant, &model.AccountAuthAppGrant{SpaceIds: []string{"bafyreia.one"}, Perm: model.AccountAuthAppGrant_Read}, true}, + {"space order does not matter", &model.AccountAuthAppGrant{SpaceIds: []string{"a", "b"}}, &model.AccountAuthAppGrant{SpaceIds: []string{"b", "a"}}, true}, + {"different perm", testGrant, &model.AccountAuthAppGrant{SpaceIds: []string{"bafyreia.one"}, Perm: model.AccountAuthAppGrant_ReadWrite}, false}, + {"different spaces", testGrant, &model.AccountAuthAppGrant{SpaceIds: []string{"bafyreib.two"}}, false}, + {"all spaces vs list", &model.AccountAuthAppGrant{AllSpaces: true}, &model.AccountAuthAppGrant{SpaceIds: []string{"a"}}, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := grantsEqual(tt.a, tt.b); got != tt.want { + t.Errorf("grantsEqual() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/core/apikeygrant.go b/core/apikeygrant.go index be29f17..699f7ba 100644 --- a/core/apikeygrant.go +++ b/core/apikeygrant.go @@ -146,3 +146,47 @@ func ValidateAPIKeyName(name string) error { } return nil } + +// GrantWorksOnV1 reports whether the JSON API v1 accepts a key with this grant. +// v1 cannot enforce space grants, so it only admits keys that grant no less +// than an unrestricted key: no grant, or all spaces with read-write. +func GrantWorksOnV1(grant *model.AccountAuthAppGrant) bool { + return grant == nil || (grant.AllSpaces && grant.Perm == model.AccountAuthAppGrant_ReadWrite) +} + +// DescribeGrant renders a grant for people, naming spaces where resolved names +// are known. +func DescribeGrant(grant *model.AccountAuthAppGrant, resolved []ResolvedSpace) string { + if grant == nil { + return "unrestricted" + } + perm := "read-only" + if grant.Perm == model.AccountAuthAppGrant_ReadWrite { + perm = "read-write" + } + if grant.AllSpaces { + return perm + ", all spaces" + } + + byId := make(map[string]ResolvedSpace, len(resolved)) + for _, space := range resolved { + byId[space.Id] = space + } + names := make([]string, len(grant.SpaceIds)) + for i, id := range grant.SpaceIds { + space, ok := byId[id] + switch { + case ok && space.IsTech: + names[i] = fmt.Sprintf("tech space (%s)", id) + case ok && space.Name != "": + names[i] = fmt.Sprintf("%s (%s)", space.Name, id) + default: + names[i] = id + } + } + noun := "spaces" + if len(names) == 1 { + noun = "space" + } + return fmt.Sprintf("%s, %d %s: %s", perm, len(names), noun, strings.Join(names, ", ")) +} diff --git a/core/apikeygrant_test.go b/core/apikeygrant_test.go index f090bb2..5c16d8e 100644 --- a/core/apikeygrant_test.go +++ b/core/apikeygrant_test.go @@ -209,3 +209,53 @@ func TestValidateAPIKeyName(t *testing.T) { }) } } + +func TestGrantWorksOnV1(t *testing.T) { + tests := []struct { + name string + grant *model.AccountAuthAppGrant + want bool + }{ + {"all spaces read-write", &model.AccountAuthAppGrant{AllSpaces: true, Perm: model.AccountAuthAppGrant_ReadWrite}, true}, + {"all spaces read-only", &model.AccountAuthAppGrant{AllSpaces: true, Perm: model.AccountAuthAppGrant_Read}, false}, + {"listed spaces read-write", &model.AccountAuthAppGrant{SpaceIds: []string{"a"}, Perm: model.AccountAuthAppGrant_ReadWrite}, false}, + {"listed spaces read-only", &model.AccountAuthAppGrant{SpaceIds: []string{"a"}}, false}, + {"no grant", nil, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := GrantWorksOnV1(tt.grant); got != tt.want { + t.Errorf("GrantWorksOnV1() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDescribeGrant(t *testing.T) { + tests := []struct { + name string + grant *model.AccountAuthAppGrant + resolved []ResolvedSpace + want string + }{ + {"all spaces read-write", &model.AccountAuthAppGrant{AllSpaces: true, Perm: model.AccountAuthAppGrant_ReadWrite}, nil, "read-write, all spaces"}, + {"all spaces read-only", &model.AccountAuthAppGrant{AllSpaces: true}, nil, "read-only, all spaces"}, + { + "named spaces", + &model.AccountAuthAppGrant{SpaceIds: []string{"bafyreia.one", "bafyreitech.tech"}}, + []ResolvedSpace{{Id: "bafyreia.one", Name: "Personal"}, {Id: "bafyreitech.tech", IsTech: true}}, + "read-only, 2 spaces: Personal (bafyreia.one), tech space (bafyreitech.tech)", + }, + {"spaces without names", &model.AccountAuthAppGrant{SpaceIds: []string{"bafyreia.one"}, Perm: model.AccountAuthAppGrant_ReadWrite}, nil, "read-write, 1 space: bafyreia.one"}, + {"no grant", nil, nil, "unrestricted"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := DescribeGrant(tt.grant, tt.resolved); got != tt.want { + t.Errorf("DescribeGrant() = %q, want %q", got, tt.want) + } + }) + } +} From 9541d97523f4c68d894d78f4b58f9457fcbedee8 Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Tue, 29 Sep 2026 17:17:50 +0200 Subject: [PATCH 06/14] Document API key grants, API v2 migration and host/origin allowlists --- CLAUDE.md | 2 ++ README.md | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 5eacba9..d933677 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -210,6 +210,8 @@ func NewConfigCmd() *cobra.Command { - The CLI provides commands to create, list, and revoke API keys - Keys are generated server-side and can be used for programmatic access - Keys are stored in the system keyring alongside tokens +- Keys are created with `JsonAPI` scope and always carry a grant (spaces × read/read-write); the CLI never creates an unrestricted key. Grant logic lives in `core/apikeygrant.go` +- `CreateAPIKey` probes the server for grant support and reads the key back, revoking it if the stored access differs from the request ### Testing Strategy - **Unit Tests**: Test individual functions and logic in isolation diff --git a/README.md b/README.md index 70fbcd5..d6217e7 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ anytype space join anytype space list # Create an API key for programmatic access -anytype auth apikey create "my-bot-api-key" +anytype auth apikey create "my-bot-api-key" --all-spaces --read-write ``` Once running, the API is available at `http://127.0.0.1:31012`. Use your API key to authenticate requests to the endpoints described on the [Developer Portal](https://developers.anytype.io). See [Network Configuration](#network-configuration) for remote access options. @@ -130,6 +130,18 @@ By default, the server binds to `127.0.0.1` (localhost only) on ports 31010-3101 You can change the API listen address using `--listen-address` (e.g., `--listen-address 0.0.0.0:31012`). For remote access, you can also use a reverse proxy, SSH tunnel, or Docker port mapping to expose the local ports. +The server only accepts requests whose `Host` is `localhost` or an IP address, and browser requests from local origins. If you reach it by another hostname (for example through a reverse proxy) or from a web page on another origin, allow them explicitly in the server's environment: + +| Variable | Applies to | Value | +| --- | --- | --- | +| `ANYTYPE_API_ALLOWED_HOSTS` | HTTP API (31012) | Comma-separated hostnames, e.g. `anytype.example.com` | +| `ANYTYPE_API_ALLOWED_ORIGINS` | HTTP API (31012) | Comma-separated exact origins, e.g. `https://app.example.com` | +| `ANYTYPE_GRPCWEB_ALLOWED_HOSTS` | gRPC-Web (31011) | Comma-separated hostnames | +| `ANYTYPE_GRPCWEB_ALLOWED_ORIGINS` | gRPC-Web (31011) | Comma-separated exact origins | +| `ANYTYPE_GRPCWEB_ENABLE_WEBSOCKETS` | gRPC-Web (31011) | `1` to enable the WebSocket transport (off by default) | + +Set them where `anytype serve` runs: in your shell, your Docker/Compose environment, or the user service's definition. + **Security note**: Always keep your API keys safe. If ports are exposed externally, third parties with your API key could gain unauthorized access to the spaces your headless instance has access to. ### Authentication @@ -155,8 +167,9 @@ anytype auth logout Manage API keys for programmatic access: ```bash -# Create a new API key -anytype auth apikey create +# Create a new API key: choose its spaces and whether it can write +anytype auth apikey create --space [--space ...] --read-only +anytype auth apikey create --all-spaces --read-write # List all API keys anytype auth apikey list @@ -165,6 +178,20 @@ anytype auth apikey list anytype auth apikey revoke ``` +Every key is limited to the spaces and permission you choose; there is no default. Use `anytype space list` to find space names and Ids. A key limited to specific spaces, or a read-only key, works with the JSON API v2 only; an `--all-spaces --read-write` key works with v1 and v2. + +#### Upgrading to the JSON API v2 + +Keys created by earlier CLI versions keep working with the JSON API v1, but the v2 API rejects them. To move an integration to v2: + +1. Create a new key with the access it needs, using **the same name** as the old key. On v2, a key can only delete objects created under its name. +2. Check that the integration works with the new key, then switch it over. +3. Revoke the old key with `anytype auth apikey revoke `. + +Keep the old key if the integration calls the gRPC API directly: new keys work only with the JSON API. + +After updating the CLI, restart the service (`anytype service restart`) so it runs the new version; `apikey create` refuses to create keys on an older running server. Keys created by this version don't work if you downgrade to an earlier one. + ### Space Management Work with Anytype spaces: From 079911ba6dd151cc9c180dbebb6fbba4ca67cb9d Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Tue, 29 Sep 2026 17:34:06 +0200 Subject: [PATCH 07/14] Reset flags between shell commands and honor quotes Shell mode reused the command tree, so flag values leaked into later commands: --space values accumulated across 'apikey create' calls and widened the next key's grant. Reset every flag before each line, and split lines with quote support so space names with spaces work. --- cmd/shell/shell.go | 104 +++++++++++++++++++++++++++++++++++++--- cmd/shell/shell_test.go | 100 ++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- 3 files changed, 199 insertions(+), 7 deletions(-) create mode 100644 cmd/shell/shell_test.go diff --git a/cmd/shell/shell.go b/cmd/shell/shell.go index 27160fe..4f7035a 100644 --- a/cmd/shell/shell.go +++ b/cmd/shell/shell.go @@ -4,9 +4,11 @@ import ( "errors" "io" "strings" + "unicode" "github.com/chzyer/readline" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/anyproto/anytype-cli/core/output" "github.com/anyproto/anytype-cli/core/updatecheck" @@ -62,17 +64,107 @@ func runShell(rootCmd *cobra.Command) error { continue } - args := strings.Split(line, " ") - if args[0] == "shell" { + if err := executeLine(rootCmd, line); errors.Is(err, errAlreadyInShell) { output.Warning("Already in shell mode. Type 'exit' or 'quit' to leave.") - continue + } else if err != nil { + output.Warning("Command error: %v", err) } - rootCmd.SetArgs(args) + } +} - if err := rootCmd.Execute(); err != nil { - output.Warning("Command error: %v", err) +var errAlreadyInShell = errors.New("already in shell mode") + +// executeLine runs one shell line against the shared command tree. Flag values +// are reset first: cobra keeps them between executions, so an earlier +// command's --space or --read-only would otherwise leak into the next one. +func executeLine(rootCmd *cobra.Command, line string) error { + args, err := splitLine(line) + if err != nil { + return err + } + if len(args) == 0 { + return nil + } + if args[0] == "shell" { + return errAlreadyInShell + } + + resetFlags(rootCmd) + rootCmd.SetArgs(args) + return rootCmd.Execute() +} + +func resetFlags(cmd *cobra.Command) { + reset := func(flag *pflag.Flag) { + if slice, ok := flag.Value.(pflag.SliceValue); ok { + _ = slice.Replace(nil) + } else { + _ = flag.Value.Set(flag.DefValue) } + flag.Changed = false + } + cmd.Flags().VisitAll(reset) + cmd.PersistentFlags().VisitAll(reset) + for _, sub := range cmd.Commands() { + resetFlags(sub) + } +} + +// splitLine splits a shell line into arguments. Whitespace separates +// arguments; single quotes keep text literally; double quotes keep whitespace +// and allow \" and \\ escapes. +func splitLine(line string) ([]string, error) { + var args []string + var current strings.Builder + inArg := false + var quote rune + escaped := false + + for _, r := range line { + switch { + case escaped: + if r != '"' && r != '\\' { + current.WriteRune('\\') + } + current.WriteRune(r) + escaped = false + case quote == '\'': + if r == '\'' { + quote = 0 + } else { + current.WriteRune(r) + } + case quote == '"': + switch r { + case '"': + quote = 0 + case '\\': + escaped = true + default: + current.WriteRune(r) + } + case r == '\'' || r == '"': + quote = r + inArg = true + case unicode.IsSpace(r): + if inArg { + args = append(args, current.String()) + current.Reset() + inArg = false + } + default: + current.WriteRune(r) + inArg = true + } + } + + if quote != 0 || escaped { + return nil, errors.New("unterminated quote") + } + if inArg { + args = append(args, current.String()) } + return args, nil } func buildCompleter(rootCmd *cobra.Command) *readline.PrefixCompleter { diff --git a/cmd/shell/shell_test.go b/cmd/shell/shell_test.go new file mode 100644 index 0000000..96600a2 --- /dev/null +++ b/cmd/shell/shell_test.go @@ -0,0 +1,100 @@ +package shell + +import ( + "reflect" + "testing" + + "github.com/spf13/cobra" +) + +// newTestRoot builds root → group → leaf, where leaf records the flag values it +// ran with. +func newTestRoot(got *[]string, gotBool *bool) *cobra.Command { + root := &cobra.Command{Use: "root", SilenceErrors: true, SilenceUsage: true} + group := &cobra.Command{Use: "group"} + var spaces []string + var readOnly bool + leaf := &cobra.Command{ + Use: "leaf", + RunE: func(cmd *cobra.Command, args []string) error { + *got = append([]string(nil), spaces...) + *gotBool = readOnly + return nil + }, + } + leaf.Flags().StringArrayVar(&spaces, "space", nil, "") + leaf.Flags().BoolVar(&readOnly, "read-only", false, "") + group.AddCommand(leaf) + root.AddCommand(group) + return root +} + +func TestExecuteLineDoesNotCarryFlagsBetweenCommands(t *testing.T) { + var got []string + var gotBool bool + root := newTestRoot(&got, &gotBool) + + if err := executeLine(root, "group leaf --space A --read-only"); err != nil { + t.Fatalf("first command: %v", err) + } + if err := executeLine(root, "group leaf --space B"); err != nil { + t.Fatalf("second command: %v", err) + } + + if !reflect.DeepEqual(got, []string{"B"}) { + t.Errorf("second command saw --space %v, want [B]", got) + } + if gotBool { + t.Error("second command saw --read-only from the first command") + } +} + +func TestExecuteLineWithoutFlagsSeesDefaults(t *testing.T) { + var got []string + var gotBool bool + root := newTestRoot(&got, &gotBool) + + if err := executeLine(root, "group leaf --space A --read-only"); err != nil { + t.Fatalf("first command: %v", err) + } + if err := executeLine(root, "group leaf"); err != nil { + t.Fatalf("second command: %v", err) + } + + if len(got) != 0 || gotBool { + t.Errorf("second command saw --space %v --read-only=%v, want defaults", got, gotBool) + } +} + +func TestSplitLine(t *testing.T) { + tests := []struct { + name string + line string + want []string + wantErr bool + }{ + {"plain words", "auth apikey list", []string{"auth", "apikey", "list"}, false}, + {"repeated spaces", "space list", []string{"space", "list"}, false}, + {"double quotes keep spaces", `auth apikey create bot --space "My Team"`, []string{"auth", "apikey", "create", "bot", "--space", "My Team"}, false}, + {"single quotes keep spaces", `create 'my bot'`, []string{"create", "my bot"}, false}, + {"quotes are removed", `--space "Personal"`, []string{"--space", "Personal"}, false}, + {"escaped quote inside double quotes", `create "say \"hi\""`, []string{"create", `say "hi"`}, false}, + {"other backslashes are kept", `--path "C:\dir"`, []string{"--path", `C:\dir`}, false}, + {"quotes join with adjacent text", `--name=my" "bot`, []string{"--name=my bot"}, false}, + {"empty quoted argument", `create ""`, []string{"create", ""}, false}, + {"tabs separate", "space\tlist", []string{"space", "list"}, false}, + {"unterminated quote", `create "my bot`, nil, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := splitLine(tt.line) + if (err != nil) != tt.wantErr { + t.Fatalf("splitLine(%q) error = %v, wantErr %v", tt.line, err, tt.wantErr) + } + if !tt.wantErr && !reflect.DeepEqual(got, tt.want) { + t.Errorf("splitLine(%q) = %q, want %q", tt.line, got, tt.want) + } + }) + } +} diff --git a/go.mod b/go.mod index 56775c7..bec0e8d 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/improbable-eng/grpc-web v0.15.0 github.com/kardianos/service v1.2.4 github.com/spf13/cobra v1.10.2 + github.com/spf13/pflag v1.0.10 github.com/zalando/go-keyring v0.2.8 golang.org/x/mod v0.41.0 google.golang.org/grpc v1.81.1 @@ -202,7 +203,6 @@ require ( github.com/sashabaranov/go-openai v1.41.2 // indirect github.com/shirou/gopsutil/v4 v4.26.3 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/spf13/pflag v1.0.10 // indirect github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect github.com/stretchr/objx v0.5.3 // indirect From f9af677f7f6bc3f112e593b7bcd908af8efdc41a Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Tue, 29 Sep 2026 17:34:07 +0200 Subject: [PATCH 08/14] Revoke API keys whose access cannot be verified If reading the new key back fails, re-list and revoke it with a fresh deadline instead of leaving a live, undisclosed key. Report leftover keys by name or Id, without wrapping gRPC statuses that GRPCCall would rewrite into 'anytype is not running'. --- core/apikey.go | 32 +++++++++++++---- core/apikey_test.go | 86 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 8 deletions(-) diff --git a/core/apikey.go b/core/apikey.go index a10062d..43f1c6f 100644 --- a/core/apikey.go +++ b/core/apikey.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "slices" + "time" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -59,21 +60,40 @@ func createAPIKey(ctx context.Context, client service.ClientCommandsClient, name } // Never trust the server to have applied what was asked: read the key back - // and revoke it if its access differs from the request. + // and revoke it if its access differs from the request or can't be checked. stored, err := findAppByKey(ctx, client, resp.AppKey) if err != nil { - return nil, fmt.Errorf("API key created but could not be verified, check 'anytype auth apikey list': %w", err) + return nil, removeUnverifiedKey(ctx, client, name, resp.AppKey, fmt.Errorf("could not verify the new API key: %v", err)) } if stored.Scope != model.AccountAuth_JsonAPI || !grantsEqual(stored.Grant, grant) { - if revokeErr := revokeAPIKey(ctx, client, stored.AppHash); revokeErr != nil { - return nil, fmt.Errorf("the server did not store the requested access and revoking the key failed, revoke %s manually: %w", stored.AppHash, revokeErr) - } - return nil, fmt.Errorf("the server did not store the requested access, so the key was revoked: %w", ErrServerTooOld) + return nil, removeUnverifiedKey(ctx, client, name, resp.AppKey, fmt.Errorf("the server did not store the requested access: %w", ErrServerTooOld)) } return &CreatedAPIKey{Key: resp.AppKey, App: stored}, nil } +// cleanupTimeout bounds the revocation of a key that failed verification. It +// starts fresh because the create call may have used up the caller's deadline. +const cleanupTimeout = 10 * time.Second + +// removeUnverifiedKey revokes a key whose access could not be confirmed and +// returns the error to report. Errors from here on are formatted with %v, not +// wrapped: GRPCCall rewrites any error carrying an Unavailable status into +// "anytype is not running", which would hide that a key was left behind. +func removeUnverifiedKey(ctx context.Context, client service.ClientCommandsClient, name, key string, cause error) error { + ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), cleanupTimeout) + defer cancel() + + app, err := findAppByKey(ctx, client, key) + if err != nil { + return fmt.Errorf("%w; the key %q may still exist and could not be revoked (%v): check 'anytype auth apikey list' and revoke it", cause, name, err) + } + if err := revokeAPIKey(ctx, client, app.AppHash); err != nil { + return fmt.Errorf("%w; revoking the key failed (%v): revoke it with 'anytype auth apikey revoke %s'", cause, err, app.AppHash) + } + return fmt.Errorf("%w; the key was revoked", cause) +} + // ensureGrantSupport probes for AccountLocalLinkUpdateApp, which arrived with // grants. An empty app hash makes a capable server answer BAD_INPUT without // changing anything; an older server does not know the method. diff --git a/core/apikey_test.go b/core/apikey_test.go index 8728960..867a617 100644 --- a/core/apikey_test.go +++ b/core/apikey_test.go @@ -3,6 +3,7 @@ package core import ( "context" "errors" + "strings" "testing" "github.com/anyproto/anytype-heart/pb" @@ -23,6 +24,14 @@ type fakeAppLinkClient struct { // dropGrant makes CreateApp ignore the grant, like an old server would. dropGrant bool + // cancelOnCreate is called right after CreateApp, to expire the caller's + // context the way a slow create uses up GRPCCall's deadline. + cancelOnCreate func() + // listFailures makes that many ListApps calls fail as unavailable. + listFailures int + // revokeErr makes RevokeApp fail. + revokeErr error + apps []*model.AccountAuthAppInfo createCalls []*pb.RpcAccountLocalLinkCreateAppRequest revoked []string @@ -55,14 +64,30 @@ func (f *fakeAppLinkClient) AccountLocalLinkCreateApp(_ context.Context, in *pb. stored.Grant = nil } f.apps = append(f.apps, stored) + if f.cancelOnCreate != nil { + f.cancelOnCreate() + } return &pb.RpcAccountLocalLinkCreateAppResponse{Error: &pb.RpcAccountLocalLinkCreateAppResponseError{}, AppKey: key}, nil } -func (f *fakeAppLinkClient) AccountLocalLinkListApps(_ context.Context, _ *pb.RpcAccountLocalLinkListAppsRequest, _ ...grpc.CallOption) (*pb.RpcAccountLocalLinkListAppsResponse, error) { +func (f *fakeAppLinkClient) AccountLocalLinkListApps(ctx context.Context, _ *pb.RpcAccountLocalLinkListAppsRequest, _ ...grpc.CallOption) (*pb.RpcAccountLocalLinkListAppsResponse, error) { + if err := ctx.Err(); err != nil { + return nil, status.Error(codes.DeadlineExceeded, err.Error()) + } + if f.listFailures > 0 { + f.listFailures-- + return nil, status.Error(codes.Unavailable, "connection lost") + } return &pb.RpcAccountLocalLinkListAppsResponse{Error: &pb.RpcAccountLocalLinkListAppsResponseError{}, App: f.apps}, nil } -func (f *fakeAppLinkClient) AccountLocalLinkRevokeApp(_ context.Context, in *pb.RpcAccountLocalLinkRevokeAppRequest, _ ...grpc.CallOption) (*pb.RpcAccountLocalLinkRevokeAppResponse, error) { +func (f *fakeAppLinkClient) AccountLocalLinkRevokeApp(ctx context.Context, in *pb.RpcAccountLocalLinkRevokeAppRequest, _ ...grpc.CallOption) (*pb.RpcAccountLocalLinkRevokeAppResponse, error) { + if err := ctx.Err(); err != nil { + return nil, status.Error(codes.DeadlineExceeded, err.Error()) + } + if f.revokeErr != nil { + return nil, f.revokeErr + } f.revoked = append(f.revoked, in.AppHash) return &pb.RpcAccountLocalLinkRevokeAppResponse{Error: &pb.RpcAccountLocalLinkRevokeAppResponseError{}}, nil } @@ -134,6 +159,63 @@ func TestCreateAPIKeyRevokesKeyWhenServerDropsGrant(t *testing.T) { } } +func TestCreateAPIKeyRevokesKeyWhenVerificationFails(t *testing.T) { + client := &fakeAppLinkClient{listFailures: 1} + + _, err := createAPIKey(context.Background(), client, "my-app", testGrant) + + if err == nil { + t.Fatal("createAPIKey() succeeded although the key could not be verified") + } + if len(client.revoked) != 1 || client.revoked[0] != "hash-my-app" { + t.Errorf("revoked = %v, want the unverified key revoked", client.revoked) + } +} + +func TestCreateAPIKeyCleansUpWithFreshDeadline(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + client := &fakeAppLinkClient{cancelOnCreate: cancel} + + _, err := createAPIKey(ctx, client, "my-app", testGrant) + + if err == nil { + t.Fatal("createAPIKey() succeeded although verification ran out of time") + } + if len(client.revoked) != 1 { + t.Errorf("revoked = %v, want cleanup to run despite the expired context", client.revoked) + } +} + +func TestCreateAPIKeyReportsKeyThatCouldNotBeCleanedUp(t *testing.T) { + tests := []struct { + name string + client *fakeAppLinkClient + wantText string + }{ + {"key cannot be found again", &fakeAppLinkClient{listFailures: 2}, `"my-app"`}, + {"revoke fails", &fakeAppLinkClient{dropGrant: true, revokeErr: status.Error(codes.Unavailable, "connection lost")}, "hash-my-app"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := createAPIKey(context.Background(), tt.client, "my-app", testGrant) + + if err == nil { + t.Fatal("createAPIKey() succeeded, want an error") + } + if !strings.Contains(err.Error(), tt.wantText) || !strings.Contains(err.Error(), "revoke") { + t.Errorf("error = %q, want it to name %s and say to revoke it", err, tt.wantText) + } + // GRPCCall rewrites errors carrying an Unavailable status into + // "anytype is not running", which would hide the leftover key. + if _, isStatus := status.FromError(err); isStatus { + t.Errorf("error %q carries a gRPC status and would be rewritten by GRPCCall", err) + } + }) + } +} + func TestGrantsEqual(t *testing.T) { tests := []struct { name string From b7e105e04b59b6f86ce48149cc74356617053322 Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Wed, 30 Sep 2026 11:52:44 +0200 Subject: [PATCH 09/14] Show and remember the JSON API listen address The JSON API starts when an account logs in, on the address that login carries, so 'serve --listen-address X' followed by a plain 'auth login' used to put the API on the default address. Now an explicit --listen-address is remembered in the CLI config (kept across logout) and used by later commands; login, account creation and serve's auto-login print 'JSON API listening on ...', and 'auth status' shows it. serve saves the address only once its servers are listening, and service install only after a successful install, so a failed start changes nothing. --- README.md | 2 +- cmd/auth/create/create.go | 11 +++- cmd/auth/login/login.go | 12 ++++- cmd/auth/status/status.go | 5 ++ cmd/cmdutil/listenaddr.go | 26 +++++++++ cmd/cmdutil/listenaddr_test.go | 44 +++++++++++++++ cmd/serve/serve.go | 16 +++++- cmd/serve/serve_test.go | 4 +- cmd/service/install/install.go | 17 ++++-- cmd/service/install/install_test.go | 4 +- core/auth.go | 5 +- core/config/config.go | 28 ++++++++++ core/config/config_helper.go | 18 +++++++ core/config/config_test.go | 62 ++++++++++++++++++++++ core/config/listenaddr.go | 20 +++++++ core/config/listenaddr_test.go | 43 +++++++++++++++ core/serviceprogram/serviceprogram.go | 24 +++++++-- core/serviceprogram/serviceprogram_test.go | 34 ++++++++++++ 18 files changed, 355 insertions(+), 20 deletions(-) create mode 100644 cmd/cmdutil/listenaddr.go create mode 100644 cmd/cmdutil/listenaddr_test.go create mode 100644 core/config/listenaddr.go create mode 100644 core/config/listenaddr_test.go diff --git a/README.md b/README.md index d6217e7..d89096b 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ By default, the server binds to `127.0.0.1` (localhost only) on ports 31010-3101 | 31012 | API | HTTP API server endpoint ⭐ | -You can change the API listen address using `--listen-address` (e.g., `--listen-address 0.0.0.0:31012`). For remote access, you can also use a reverse proxy, SSH tunnel, or Docker port mapping to expose the local ports. +You can change the JSON API listen address with `--listen-address` on `serve`, `service install`, `auth login` or `auth create` (e.g., `--listen-address 0.0.0.0:31012`). The address is remembered, including across logout, so later commands use it without the flag. The JSON API starts once an account is logged in; `anytype auth status` and the login commands print its address. For remote access, you can also use a reverse proxy, SSH tunnel, or Docker port mapping to expose the local ports. The server only accepts requests whose `Host` is `localhost` or an IP address, and browser requests from local origins. If you reach it by another hostname (for example through a reverse proxy) or from a web page on another origin, allow them explicitly in the server's environment: diff --git a/cmd/auth/create/create.go b/cmd/auth/create/create.go index af9d307..32c6480 100644 --- a/cmd/auth/create/create.go +++ b/cmd/auth/create/create.go @@ -26,10 +26,16 @@ func NewCreateCmd() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { name := args[0] - accountKey, accountId, savedToKeyring, err := core.CreateWallet(name, rootPath, listenAddress, networkConfigPath) + apiAddr, explicit := cmdutil.APIListenAddr(cmd, listenAddress) + accountKey, accountId, savedToKeyring, err := core.CreateWallet(name, rootPath, apiAddr, networkConfigPath) if err != nil { return output.Error("Failed to create account: %w", err) } + if explicit { + if err := config.SetApiListenAddrToConfig(apiAddr); err != nil { + output.Warning("Failed to remember the JSON API address: %v", err) + } + } output.Success("Bot account created successfully!") @@ -70,13 +76,14 @@ func NewCreateCmd() *cobra.Command { } else { output.Success("Account key saved to config file.") } + output.Info("JSON API listening on %s", config.APIURL(apiAddr)) return nil }, } cmd.Flags().StringVar(&rootPath, "root-path", "", "Root path for account data") - cmd.Flags().StringVar(&listenAddress, "listen-address", config.DefaultAPIAddress, "API listen address in `host:port` format") + cmdutil.AddListenAddressFlag(cmd, &listenAddress) cmd.Flags().StringVar(&networkConfigPath, "network-config", "", "Path to custom network configuration YAML (for self-hosted)") return cmd diff --git a/cmd/auth/login/login.go b/cmd/auth/login/login.go index b8e69b1..4e70359 100644 --- a/cmd/auth/login/login.go +++ b/cmd/auth/login/login.go @@ -3,6 +3,7 @@ package login import ( "github.com/spf13/cobra" + "github.com/anyproto/anytype-cli/cmd/cmdutil" "github.com/anyproto/anytype-cli/core" "github.com/anyproto/anytype-cli/core/config" "github.com/anyproto/anytype-cli/core/output" @@ -19,10 +20,17 @@ func NewLoginCmd() *cobra.Command { Short: "Log in to your bot account", Long: "Authenticate using your account key to access your Anytype bot account and stored data. Use --network-config for self-hosted networks.", RunE: func(cmd *cobra.Command, args []string) error { - if err := core.Login(accountKey, rootPath, listenAddress, networkConfigPath); err != nil { + apiAddr, explicit := cmdutil.APIListenAddr(cmd, listenAddress) + if err := core.Login(accountKey, rootPath, apiAddr, networkConfigPath); err != nil { return output.Error("Failed to log in: %w", err) } + if explicit { + if err := config.SetApiListenAddrToConfig(apiAddr); err != nil { + output.Warning("Failed to remember the JSON API address: %v", err) + } + } output.Success("Successfully logged in") + output.Info("JSON API listening on %s", config.APIURL(apiAddr)) return nil }, @@ -30,7 +38,7 @@ func NewLoginCmd() *cobra.Command { cmd.Flags().StringVar(&accountKey, "account-key", "", "Account key for authentication") cmd.Flags().StringVar(&rootPath, "path", "", "Root path for account data") - cmd.Flags().StringVar(&listenAddress, "listen-address", config.DefaultAPIAddress, "API listen address in `host:port` format") + cmdutil.AddListenAddressFlag(cmd, &listenAddress) cmd.Flags().StringVar(&networkConfigPath, "network-config", "", "Path to custom network configuration YAML (for self-hosted)") return cmd diff --git a/cmd/auth/status/status.go b/cmd/auth/status/status.go index 45af1e2..73cb604 100644 --- a/cmd/auth/status/status.go +++ b/cmd/auth/status/status.go @@ -88,6 +88,11 @@ func NewStatusCmd() *cobra.Command { } output.Print(" - Active session: \033[1m%v\033[0m", isLoggedIn) + if isLoggedIn { + storedAddr, _ := config.GetApiListenAddrFromConfig() + apiAddr := config.ResolveAPIListenAddr("", false, storedAddr) + output.Print(" - JSON API: \033[1m%s\033[0m", config.APIURL(apiAddr)) + } if hasAccountKey { if len(accountKey) > 8 { diff --git a/cmd/cmdutil/listenaddr.go b/cmd/cmdutil/listenaddr.go new file mode 100644 index 0000000..a6119d4 --- /dev/null +++ b/cmd/cmdutil/listenaddr.go @@ -0,0 +1,26 @@ +package cmdutil + +import ( + "github.com/spf13/cobra" + + "github.com/anyproto/anytype-cli/core/config" +) + +const listenAddressFlag = "listen-address" + +// storedAPIListenAddr reads the saved JSON API address; replaceable in tests. +var storedAPIListenAddr = config.GetApiListenAddrFromConfig + +// AddListenAddressFlag registers --listen-address for the JSON API. +func AddListenAddressFlag(cmd *cobra.Command, target *string) { + cmd.Flags().StringVar(target, listenAddressFlag, config.DefaultAPIAddress, + "JSON API listen address in `host:port` format (remembered for later commands)") +} + +// APIListenAddr resolves the JSON API address for a command and reports +// whether the user passed --listen-address explicitly. +func APIListenAddr(cmd *cobra.Command, flagValue string) (string, bool) { + changed := cmd.Flags().Changed(listenAddressFlag) + stored, _ := storedAPIListenAddr() + return config.ResolveAPIListenAddr(flagValue, changed, stored), changed +} diff --git a/cmd/cmdutil/listenaddr_test.go b/cmd/cmdutil/listenaddr_test.go new file mode 100644 index 0000000..2c8a59b --- /dev/null +++ b/cmd/cmdutil/listenaddr_test.go @@ -0,0 +1,44 @@ +package cmdutil + +import ( + "testing" + + "github.com/spf13/cobra" + + "github.com/anyproto/anytype-cli/core/config" +) + +func TestAPIListenAddr(t *testing.T) { + tests := []struct { + name string + args []string + stored string + want string + changed bool + }{ + {"flag given", []string{"--listen-address", "0.0.0.0:5000"}, "127.0.0.1:4000", "0.0.0.0:5000", true}, + {"flag omitted uses stored", nil, "127.0.0.1:4000", "127.0.0.1:4000", false}, + {"flag omitted, nothing stored", nil, "", config.DefaultAPIAddress, false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + orig := storedAPIListenAddr + storedAPIListenAddr = func() (string, error) { return tt.stored, nil } + t.Cleanup(func() { storedAPIListenAddr = orig }) + + var flag string + cmd := &cobra.Command{Use: "x", RunE: func(*cobra.Command, []string) error { return nil }} + AddListenAddressFlag(cmd, &flag) + cmd.SetArgs(tt.args) + if err := cmd.Execute(); err != nil { + t.Fatalf("Execute: %v", err) + } + + got, changed := APIListenAddr(cmd, flag) + if got != tt.want || changed != tt.changed { + t.Errorf("APIListenAddr() = (%q, %v), want (%q, %v)", got, changed, tt.want, tt.changed) + } + }) + } +} diff --git a/cmd/serve/serve.go b/cmd/serve/serve.go index 79767f8..c07f538 100644 --- a/cmd/serve/serve.go +++ b/cmd/serve/serve.go @@ -6,6 +6,7 @@ import ( "github.com/kardianos/service" "github.com/spf13/cobra" + "github.com/anyproto/anytype-cli/cmd/cmdutil" "github.com/anyproto/anytype-cli/core/config" "github.com/anyproto/anytype-cli/core/output" "github.com/anyproto/anytype-cli/core/serviceprogram" @@ -26,7 +27,7 @@ func NewServeCmd() *cobra.Command { RunE: runServer, } - cmd.Flags().StringVar(&listenAddress, "listen-address", config.DefaultAPIAddress, "API listen address in `host:port` format") + cmdutil.AddListenAddressFlag(cmd, &listenAddress) cmd.Flags().BoolVarP(&quietMode, "quiet", "q", false, "Suppress most output (only errors)") cmd.Flags().BoolVarP(&verboseMode, "verbose", "v", false, "Show detailed output (debug level)") cmd.MarkFlagsMutuallyExclusive("quiet", "verbose") @@ -50,7 +51,18 @@ func runServer(cmd *cobra.Command, args []string) error { Description: "Anytype", } - prg := serviceprogram.New(listenAddress) + apiAddr, explicit := cmdutil.APIListenAddr(cmd, listenAddress) + + prg := serviceprogram.New(apiAddr) + if explicit { + // Remember the address only once this server is actually up, so a + // failed start (e.g. ports taken by another server) changes nothing. + prg.OnStarted = func() { + if err := config.SetApiListenAddrToConfig(apiAddr); err != nil { + output.Warning("Failed to remember the JSON API address: %v", err) + } + } + } s, err := service.New(prg, svcConfig) if err != nil { diff --git a/cmd/serve/serve_test.go b/cmd/serve/serve_test.go index b9eb457..e314090 100644 --- a/cmd/serve/serve_test.go +++ b/cmd/serve/serve_test.go @@ -32,8 +32,8 @@ func TestServeCmd_ListenAddressFlag(t *testing.T) { t.Errorf("listen-address default = %v, want %v", flag.DefValue, config.DefaultAPIAddress) } - if flag.Usage != "API listen address in `host:port` format" { - t.Errorf("listen-address usage = %v, want 'API listen address in `host:port` format'", flag.Usage) + if flag.Usage != "JSON API listen address in `host:port` format (remembered for later commands)" { + t.Errorf("listen-address usage = %v, want %q", flag.Usage, "JSON API listen address in `host:port` format (remembered for later commands)") } } diff --git a/cmd/service/install/install.go b/cmd/service/install/install.go index 8a5b8f4..398df35 100644 --- a/cmd/service/install/install.go +++ b/cmd/service/install/install.go @@ -3,6 +3,7 @@ package install import ( "github.com/spf13/cobra" + "github.com/anyproto/anytype-cli/cmd/cmdutil" "github.com/anyproto/anytype-cli/core/config" "github.com/anyproto/anytype-cli/core/output" "github.com/anyproto/anytype-cli/core/serviceprogram" @@ -15,7 +16,9 @@ func NewInstallCmd() *cobra.Command { Use: "install", Short: "Install as a user service", RunE: func(cmd *cobra.Command, args []string) error { - s, err := serviceprogram.GetServiceWithAddress(listenAddress) + apiAddr, explicit := cmdutil.APIListenAddr(cmd, listenAddress) + + s, err := serviceprogram.GetServiceWithAddress(apiAddr) if err != nil { return output.Error("Failed to create service: %w", err) } @@ -25,10 +28,14 @@ func NewInstallCmd() *cobra.Command { return output.Error("Failed to install service: %w", err) } - output.Success("anytype service installed successfully") - if listenAddress != config.DefaultAPIAddress { - output.Info("API will listen on %s", listenAddress) + if explicit { + if err := config.SetApiListenAddrToConfig(apiAddr); err != nil { + output.Warning("Failed to remember the JSON API address: %v", err) + } } + + output.Success("anytype service installed successfully") + output.Info("JSON API will listen on %s once an account is logged in", config.APIURL(apiAddr)) output.Print("\nTo manage the service:") output.Print(" Start: anytype service start") output.Print(" Stop: anytype service stop") @@ -39,7 +46,7 @@ func NewInstallCmd() *cobra.Command { }, } - cmd.Flags().StringVar(&listenAddress, "listen-address", config.DefaultAPIAddress, "API listen address in `host:port` format") + cmdutil.AddListenAddressFlag(cmd, &listenAddress) return cmd } diff --git a/cmd/service/install/install_test.go b/cmd/service/install/install_test.go index 5239133..6449152 100644 --- a/cmd/service/install/install_test.go +++ b/cmd/service/install/install_test.go @@ -31,8 +31,8 @@ func TestInstallCmd_ListenAddressFlag(t *testing.T) { t.Errorf("listen-address default = %v, want %v", flag.DefValue, config.DefaultAPIAddress) } - if flag.Usage != "API listen address in `host:port` format" { - t.Errorf("listen-address usage = %v, want 'API listen address in `host:port` format'", flag.Usage) + if flag.Usage != "JSON API listen address in `host:port` format (remembered for later commands)" { + t.Errorf("listen-address usage = %v, want %q", flag.Usage, "JSON API listen address in `host:port` format (remembered for later commands)") } } diff --git a/core/auth.go b/core/auth.go index e0c19ea..9e50a39 100644 --- a/core/auth.go +++ b/core/auth.go @@ -223,7 +223,10 @@ func Logout() error { } configMgr := config.GetConfigManager() - if err := configMgr.Delete(); err != nil { + if err := configMgr.Load(); err != nil { + output.Warning("Failed to read config: %v", err) + } + if err := configMgr.ClearAccount(); err != nil { output.Warning("Failed to clear config: %v", err) } diff --git a/core/config/config.go b/core/config/config.go index 2db19e1..bf23fc5 100644 --- a/core/config/config.go +++ b/core/config/config.go @@ -17,6 +17,9 @@ type Config struct { // WARNING: This is insecure and should only be used on headless servers AccountKey string `json:"accountKey,omitempty"` SessionToken string `json:"sessionToken,omitempty"` + // ApiListenAddr is the JSON API address last chosen with --listen-address. + // It is a server setting, so it survives logout. + ApiListenAddr string `json:"apiListenAddr,omitempty"` } var ( @@ -152,6 +155,31 @@ func (cm *ConfigManager) SetNetworkId(networkId string) error { return cm.Save() } +func (cm *ConfigManager) SetApiListenAddr(addr string) error { + cm.mu.Lock() + cm.config.ApiListenAddr = addr + cm.mu.Unlock() + + return cm.Save() +} + +// ClearAccount removes everything tied to the logged-in account and keeps +// server settings. The file is deleted when no settings remain. +func (cm *ConfigManager) ClearAccount() error { + cm.mu.Lock() + keep := &Config{ApiListenAddr: cm.config.ApiListenAddr} + cm.mu.Unlock() + + if keep.ApiListenAddr == "" { + return cm.Delete() + } + + cm.mu.Lock() + cm.config = keep + cm.mu.Unlock() + return cm.Save() +} + func (cm *ConfigManager) Reset() error { cm.mu.Lock() cm.config = &Config{} diff --git a/core/config/config_helper.go b/core/config/config_helper.go index ff093e6..6c3758a 100644 --- a/core/config/config_helper.go +++ b/core/config/config_helper.go @@ -162,3 +162,21 @@ func ReadNetworkIdFromYAML(path string) (string, error) { return cfg.NetworkId, nil } + +func GetApiListenAddrFromConfig() (string, error) { + configMgr := GetConfigManager() + if err := configMgr.Load(); err != nil { + return "", fmt.Errorf("failed to load config: %w", err) + } + + return configMgr.Get().ApiListenAddr, nil +} + +func SetApiListenAddrToConfig(addr string) error { + configMgr := GetConfigManager() + if err := configMgr.Load(); err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + + return configMgr.SetApiListenAddr(addr) +} diff --git a/core/config/config_test.go b/core/config/config_test.go index 5fbaea6..3223091 100644 --- a/core/config/config_test.go +++ b/core/config/config_test.go @@ -94,3 +94,65 @@ func TestGetConfigManager(t *testing.T) { t.Error("GetConfigManager should initialize with a valid file path") } } + +func newTestConfigManager(t *testing.T, cfg *Config) *ConfigManager { + t.Helper() + return &ConfigManager{config: cfg, filePath: filepath.Join(t.TempDir(), "config.json")} +} + +func TestApiListenAddrPersists(t *testing.T) { + cm := newTestConfigManager(t, &Config{}) + + if err := cm.SetApiListenAddr("0.0.0.0:4000"); err != nil { + t.Fatalf("SetApiListenAddr: %v", err) + } + + cm2 := &ConfigManager{config: &Config{}, filePath: cm.filePath} + if err := cm2.Load(); err != nil { + t.Fatalf("Load: %v", err) + } + if got := cm2.Get().ApiListenAddr; got != "0.0.0.0:4000" { + t.Errorf("ApiListenAddr = %q, want %q", got, "0.0.0.0:4000") + } +} + +func TestClearAccountKeepsApiListenAddr(t *testing.T) { + cm := newTestConfigManager(t, &Config{ + AccountId: "acc", + TechSpaceId: "tech", + AccountKey: "key", + SessionToken: "token", + ApiListenAddr: "0.0.0.0:4000", + }) + if err := cm.Save(); err != nil { + t.Fatalf("Save: %v", err) + } + + if err := cm.ClearAccount(); err != nil { + t.Fatalf("ClearAccount: %v", err) + } + + cm2 := &ConfigManager{config: &Config{}, filePath: cm.filePath} + if err := cm2.Load(); err != nil { + t.Fatalf("Load: %v", err) + } + want := Config{ApiListenAddr: "0.0.0.0:4000"} + if got := *cm2.Get(); got != want { + t.Errorf("config after ClearAccount = %+v, want %+v", got, want) + } +} + +func TestClearAccountRemovesFileWithoutSettings(t *testing.T) { + cm := newTestConfigManager(t, &Config{AccountId: "acc", SessionToken: "token"}) + if err := cm.Save(); err != nil { + t.Fatalf("Save: %v", err) + } + + if err := cm.ClearAccount(); err != nil { + t.Fatalf("ClearAccount: %v", err) + } + + if _, err := os.Stat(cm.filePath); !os.IsNotExist(err) { + t.Errorf("config file still exists after clearing an account with no settings to keep (err = %v)", err) + } +} diff --git a/core/config/listenaddr.go b/core/config/listenaddr.go new file mode 100644 index 0000000..0cc1127 --- /dev/null +++ b/core/config/listenaddr.go @@ -0,0 +1,20 @@ +package config + +// ResolveAPIListenAddr picks the JSON API address: an explicit --listen-address +// wins, then the address saved from an earlier explicit choice, then the +// default. The JSON API starts when an account logs in, on the address that +// login carries, so every command that logs in must agree on it. +func ResolveAPIListenAddr(flag string, flagSet bool, stored string) string { + if flagSet { + return flag + } + if stored != "" { + return stored + } + return DefaultAPIAddress +} + +// APIURL is the base URL of the JSON API listening on addr. +func APIURL(addr string) string { + return "http://" + addr +} diff --git a/core/config/listenaddr_test.go b/core/config/listenaddr_test.go new file mode 100644 index 0000000..8346235 --- /dev/null +++ b/core/config/listenaddr_test.go @@ -0,0 +1,43 @@ +package config + +import "testing" + +func TestResolveAPIListenAddr(t *testing.T) { + tests := []struct { + name string + flag string + flagSet bool + stored string + want string + }{ + {"explicit flag wins over stored", "0.0.0.0:5000", true, "127.0.0.1:4000", "0.0.0.0:5000"}, + {"explicit flag equal to default still wins", DefaultAPIAddress, true, "127.0.0.1:4000", DefaultAPIAddress}, + {"stored used when flag not set", DefaultAPIAddress, false, "127.0.0.1:4000", "127.0.0.1:4000"}, + {"default when nothing stored", DefaultAPIAddress, false, "", DefaultAPIAddress}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ResolveAPIListenAddr(tt.flag, tt.flagSet, tt.stored); got != tt.want { + t.Errorf("ResolveAPIListenAddr() = %q, want %q", got, tt.want) + } + }) + } +} + +func TestAPIURL(t *testing.T) { + tests := []struct { + addr string + want string + }{ + {"127.0.0.1:31012", "http://127.0.0.1:31012"}, + {"0.0.0.0:31012", "http://0.0.0.0:31012"}, + {"[::1]:31012", "http://[::1]:31012"}, + } + + for _, tt := range tests { + if got := APIURL(tt.addr); got != tt.want { + t.Errorf("APIURL(%q) = %q, want %q", tt.addr, got, tt.want) + } + } +} diff --git a/core/serviceprogram/serviceprogram.go b/core/serviceprogram/serviceprogram.go index 4aba1cd..f538151 100644 --- a/core/serviceprogram/serviceprogram.go +++ b/core/serviceprogram/serviceprogram.go @@ -63,6 +63,13 @@ type Program struct { startErr error startCh chan struct{} apiListenAddr string + + // OnStarted, if set, runs once the gRPC servers are listening, before + // Start returns. It does not run when the server fails to start. + OnStarted func() + + // startServer starts the gRPC servers; replaceable in tests. + startServer func(grpcAddr, grpcWebAddr string) error } func New(apiListenAddr string) *Program { @@ -75,6 +82,9 @@ func New(apiListenAddr string) *Program { func (p *Program) Start(s service.Service) error { p.ctx, p.cancel = context.WithCancel(context.Background()) p.server = grpcserver.NewServer() + if p.startServer == nil { + p.startServer = p.server.Start + } p.wg.Add(1) go p.run() @@ -93,6 +103,9 @@ func (p *Program) Start(s service.Service) error { return fmt.Errorf("timeout waiting for server to start") } + if p.OnStarted != nil { + p.OnStarted() + } return nil } @@ -115,7 +128,7 @@ func (p *Program) run() { defer p.wg.Done() defer close(p.startCh) - if err := p.server.Start(config.DefaultGRPCAddress, config.DefaultGRPCWebAddress); err != nil { + if err := p.startServer(config.DefaultGRPCAddress, config.DefaultGRPCWebAddress); err != nil { p.startErr = err return } @@ -123,8 +136,12 @@ func (p *Program) run() { // Signal successful start p.startCh <- struct{}{} - // Wait a moment for server to be ready - time.Sleep(2 * time.Second) + // Wait a moment for server to be ready; skip auto-login if stopped meanwhile + select { + case <-time.After(2 * time.Second): + case <-p.ctx.Done(): + return + } go p.attemptAutoLogin() @@ -152,6 +169,7 @@ func (p *Program) attemptAutoLogin() { output.Info("Failed to auto-login with account key after %d attempts: %v", maxRetries, err) } else { output.Success("Successfully logged in using stored account key") + output.Info("JSON API listening on %s", config.APIURL(p.apiListenAddr)) return } } diff --git a/core/serviceprogram/serviceprogram_test.go b/core/serviceprogram/serviceprogram_test.go index 1d7f317..0abb138 100644 --- a/core/serviceprogram/serviceprogram_test.go +++ b/core/serviceprogram/serviceprogram_test.go @@ -1,6 +1,7 @@ package serviceprogram import ( + "errors" "testing" "github.com/anyproto/anytype-cli/core/config" @@ -92,3 +93,36 @@ func TestGetServiceWithAddress(t *testing.T) { }) } } + +func TestStartCallsOnStartedOnlyAfterServerStarts(t *testing.T) { + tests := []struct { + name string + startErr error + wantStarted bool + }{ + {"server starts", nil, true}, + {"server fails to listen", errors.New("bind: address already in use"), false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := New(config.DefaultAPIAddress) + p.startServer = func(grpcAddr, grpcWebAddr string) error { return tt.startErr } + started := false + p.OnStarted = func() { started = true } + + err := p.Start(nil) + if p.cancel != nil { + p.cancel() + } + p.wg.Wait() + + if (err != nil) != (tt.startErr != nil) { + t.Fatalf("Start() error = %v, want error %v", err, tt.startErr != nil) + } + if started != tt.wantStarted { + t.Errorf("OnStarted called = %v, want %v", started, tt.wantStarted) + } + }) + } +} From 27516bf670e83b434661e6bc4110528bc1a6363a Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Wed, 30 Sep 2026 12:01:14 +0200 Subject: [PATCH 10/14] Print the JSON API address when the server starts serve (and the user service) now prints where the JSON API will listen as soon as the gRPC servers are up. Previously it only appeared after a successful auto-login, so a server started without a stored account key never showed it. --- README.md | 2 +- core/serviceprogram/serviceprogram.go | 3 ++ core/serviceprogram/serviceprogram_test.go | 51 ++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d89096b..52f63ff 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ By default, the server binds to `127.0.0.1` (localhost only) on ports 31010-3101 | 31012 | API | HTTP API server endpoint ⭐ | -You can change the JSON API listen address with `--listen-address` on `serve`, `service install`, `auth login` or `auth create` (e.g., `--listen-address 0.0.0.0:31012`). The address is remembered, including across logout, so later commands use it without the flag. The JSON API starts once an account is logged in; `anytype auth status` and the login commands print its address. For remote access, you can also use a reverse proxy, SSH tunnel, or Docker port mapping to expose the local ports. +You can change the JSON API listen address with `--listen-address` on `serve`, `service install`, `auth login` or `auth create` (e.g., `--listen-address 0.0.0.0:31012`). The address is remembered, including across logout, so later commands use it without the flag. The JSON API starts once an account is logged in. `serve` prints the address it will use at startup, and `anytype auth status` and the login commands print it too. For remote access, you can also use a reverse proxy, SSH tunnel, or Docker port mapping to expose the local ports. The server only accepts requests whose `Host` is `localhost` or an IP address, and browser requests from local origins. If you reach it by another hostname (for example through a reverse proxy) or from a web page on another origin, allow them explicitly in the server's environment: diff --git a/core/serviceprogram/serviceprogram.go b/core/serviceprogram/serviceprogram.go index f538151..baf0cc1 100644 --- a/core/serviceprogram/serviceprogram.go +++ b/core/serviceprogram/serviceprogram.go @@ -103,6 +103,9 @@ func (p *Program) Start(s service.Service) error { return fmt.Errorf("timeout waiting for server to start") } + // The JSON API starts later, when an account logs in; say where it will be. + output.Info("JSON API will listen on %s once an account is logged in", config.APIURL(p.apiListenAddr)) + if p.OnStarted != nil { p.OnStarted() } diff --git a/core/serviceprogram/serviceprogram_test.go b/core/serviceprogram/serviceprogram_test.go index 0abb138..cf1a5be 100644 --- a/core/serviceprogram/serviceprogram_test.go +++ b/core/serviceprogram/serviceprogram_test.go @@ -2,6 +2,9 @@ package serviceprogram import ( "errors" + "io" + "os" + "strings" "testing" "github.com/anyproto/anytype-cli/core/config" @@ -126,3 +129,51 @@ func TestStartCallsOnStartedOnlyAfterServerStarts(t *testing.T) { }) } } + +// captureStdout returns what fn wrote to stdout. +func captureStdout(t *testing.T, fn func()) string { + t.Helper() + old := os.Stdout + r, w, err := os.Pipe() + if err != nil { + t.Fatalf("pipe: %v", err) + } + os.Stdout = w + fn() + w.Close() + os.Stdout = old + out, _ := io.ReadAll(r) + return string(out) +} + +func TestStartPrintsJSONAPIAddress(t *testing.T) { + const want = "JSON API will listen on http://127.0.0.1:4000 once an account is logged in" + + tests := []struct { + name string + startErr error + wantLine bool + }{ + {"server starts", nil, true}, + {"server fails to listen", errors.New("bind: address already in use"), false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := New("127.0.0.1:4000") + p.startServer = func(grpcAddr, grpcWebAddr string) error { return tt.startErr } + + out := captureStdout(t, func() { + _ = p.Start(nil) + if p.cancel != nil { + p.cancel() + } + p.wg.Wait() + }) + + if got := strings.Contains(out, want); got != tt.wantLine { + t.Errorf("output %q contains %q = %v, want %v", out, want, got, tt.wantLine) + } + }) + } +} From c1e59c0cb338bb3e34af1751d6a414af68a4ccbe Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Wed, 30 Sep 2026 12:15:17 +0200 Subject: [PATCH 11/14] Apply the log level at server start heart applies ANYTYPE_LOG_LEVEL only when an account logs in, so everything logged before that (including our own startup lines) used the logger's built-in DEBUG default. Apply the level (default ERROR) as soon as the server starts. --- cmd/auth/create/create.go | 2 +- cmd/auth/login/login.go | 2 +- cmd/service/install/install.go | 2 +- core/grpcserver/loglevel_test.go | 63 ++++++++++++++++++++++++++++++++ core/grpcserver/server.go | 18 +++++++-- core/output/output.go | 26 +++++++++++++ core/output/output_test.go | 24 ++++++++++++ 7 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 core/grpcserver/loglevel_test.go diff --git a/cmd/auth/create/create.go b/cmd/auth/create/create.go index 32c6480..39e5433 100644 --- a/cmd/auth/create/create.go +++ b/cmd/auth/create/create.go @@ -76,7 +76,7 @@ func NewCreateCmd() *cobra.Command { } else { output.Success("Account key saved to config file.") } - output.Info("JSON API listening on %s", config.APIURL(apiAddr)) + output.Banner("JSON API listening on " + config.APIURL(apiAddr)) return nil }, diff --git a/cmd/auth/login/login.go b/cmd/auth/login/login.go index 4e70359..8443902 100644 --- a/cmd/auth/login/login.go +++ b/cmd/auth/login/login.go @@ -30,7 +30,7 @@ func NewLoginCmd() *cobra.Command { } } output.Success("Successfully logged in") - output.Info("JSON API listening on %s", config.APIURL(apiAddr)) + output.Banner("JSON API listening on " + config.APIURL(apiAddr)) return nil }, diff --git a/cmd/service/install/install.go b/cmd/service/install/install.go index 398df35..1c2c04c 100644 --- a/cmd/service/install/install.go +++ b/cmd/service/install/install.go @@ -35,7 +35,7 @@ func NewInstallCmd() *cobra.Command { } output.Success("anytype service installed successfully") - output.Info("JSON API will listen on %s once an account is logged in", config.APIURL(apiAddr)) + output.Banner("JSON API: "+config.APIURL(apiAddr), "starts when an account is logged in") output.Print("\nTo manage the service:") output.Print(" Start: anytype service start") output.Print(" Stop: anytype service stop") diff --git a/core/grpcserver/loglevel_test.go b/core/grpcserver/loglevel_test.go new file mode 100644 index 0000000..63b921d --- /dev/null +++ b/core/grpcserver/loglevel_test.go @@ -0,0 +1,63 @@ +//go:build !nogrpcserver + +package grpcserver + +import ( + "io" + "os" + "strings" + "testing" + + "github.com/anyproto/anytype-heart/pkg/lib/logging" +) + +// captureStderr returns what fn wrote to stderr. zap opens its "stderr" sink +// when the config is applied, so fn must apply it after the swap. +func captureStderr(t *testing.T, fn func()) string { + t.Helper() + old := os.Stderr + r, w, err := os.Pipe() + if err != nil { + t.Fatalf("pipe: %v", err) + } + os.Stderr = w + fn() + w.Close() + os.Stderr = old + out, _ := io.ReadAll(r) + return string(out) +} + +func TestApplyLogLevelFiltersBeforeLogin(t *testing.T) { + tests := []struct { + name string + env string + wantInfo bool + wantError bool + }{ + {"default is ERROR", "", false, true}, + {"quiet mode", "*=FATAL", false, false}, + {"verbose mode", "*=DEBUG", true, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Setenv("ANYTYPE_LOG_LEVEL", tt.env) + log := logging.Logger("anytype-cli-loglevel-test") + + out := captureStderr(t, func() { + applyLogLevel() + log.Info("INFO-LINE") + log.Error("ERROR-LINE") + _ = log.Sync() + }) + + if got := strings.Contains(out, "INFO-LINE"); got != tt.wantInfo { + t.Errorf("info shown = %v, want %v (output %q)", got, tt.wantInfo, out) + } + if got := strings.Contains(out, "ERROR-LINE"); got != tt.wantError { + t.Errorf("error shown = %v, want %v (output %q)", got, tt.wantError, out) + } + }) + } +} diff --git a/core/grpcserver/server.go b/core/grpcserver/server.go index 1e0a64a..1d58242 100644 --- a/core/grpcserver/server.go +++ b/core/grpcserver/server.go @@ -47,9 +47,7 @@ func NewServer() *Server { func (s *Server) Start(grpcAddr, grpcWebAddr string) error { app.StartWarningAfter = time.Second * 5 - if os.Getenv("ANYTYPE_LOG_LEVEL") == "" { - os.Setenv("ANYTYPE_LOG_LEVEL", "ERROR") - } + applyLogLevel() metrics.Service.InitWithKeys(metrics.DefaultInHouseKey) @@ -156,3 +154,17 @@ func (s *Server) Stop() error { log.Info("Servers stopped") return nil } + +// defaultLogLevel applies when ANYTYPE_LOG_LEVEL is unset. +const defaultLogLevel = "ERROR" + +// applyLogLevel applies ANYTYPE_LOG_LEVEL to heart's loggers right away. +// heart applies it itself only when an account logs in (InitialSetParameters), +// so without this everything logged before login uses the logger's built-in +// DEBUG default. +func applyLogLevel() { + if os.Getenv("ANYTYPE_LOG_LEVEL") == "" { + os.Setenv("ANYTYPE_LOG_LEVEL", defaultLogLevel) + } + logging.SetLogLevels(os.Getenv("ANYTYPE_LOG_LEVEL")) +} diff --git a/core/output/output.go b/core/output/output.go index de9b394..a950f6d 100644 --- a/core/output/output.go +++ b/core/output/output.go @@ -3,6 +3,8 @@ package output import ( "fmt" "os" + "strings" + "unicode/utf8" ) func Success(format string, args ...interface{}) { @@ -28,3 +30,27 @@ func Debug(format string, args ...interface{}) { func Print(format string, args ...interface{}) { fmt.Fprintf(os.Stdout, format+"\n", args...) } + +// Banner prints lines inside a box, for information that must stand out in +// busy output, such as where the JSON API listens. +func Banner(lines ...string) { + fmt.Fprint(os.Stdout, FormatBanner(lines...)) +} + +// FormatBanner draws lines inside a rounded box. +func FormatBanner(lines ...string) string { + width := 0 + for _, line := range lines { + width = max(width, utf8.RuneCountInString(line)) + } + inner := width + 3 // two spaces before the text, one after + + var b strings.Builder + b.WriteString("╭" + strings.Repeat("─", inner) + "╮\n") + for _, line := range lines { + pad := width - utf8.RuneCountInString(line) + b.WriteString("│ " + line + strings.Repeat(" ", pad) + " │\n") + } + b.WriteString("╰" + strings.Repeat("─", inner) + "╯\n") + return b.String() +} diff --git a/core/output/output_test.go b/core/output/output_test.go index c70f8c5..1749de8 100644 --- a/core/output/output_test.go +++ b/core/output/output_test.go @@ -87,3 +87,27 @@ func TestPrint(t *testing.T) { t.Errorf("Print() output = %v, want 'test 123 message'", output) } } + +func TestFormatBanner(t *testing.T) { + got := FormatBanner("JSON API: http://127.0.0.1:31012", "starts when an account is logged in") + want := strings.Join([]string{ + "╭──────────────────────────────────────╮", + "│ JSON API: http://127.0.0.1:31012 │", + "│ starts when an account is logged in │", + "╰──────────────────────────────────────╯", + }, "\n") + "\n" + if got != want { + t.Errorf("FormatBanner() =\n%s\nwant\n%s", got, want) + } +} + +func TestFormatBannerCountsRunesNotBytes(t *testing.T) { + got := FormatBanner("café") + lines := strings.Split(strings.TrimSuffix(got, "\n"), "\n") + width := len([]rune(lines[0])) + for i, line := range lines { + if n := len([]rune(line)); n != width { + t.Errorf("line %d has %d runes, want %d: %q", i, n, width, line) + } + } +} From 2e1376f472c050b0f33f30992c69910a1031db03 Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Wed, 30 Sep 2026 12:15:18 +0200 Subject: [PATCH 12/14] Show the JSON API address in a box The address was easy to miss among server logs. serve, service install, auth login and auth create now print it in a framed banner. --- core/serviceprogram/serviceprogram.go | 4 ++-- core/serviceprogram/serviceprogram_test.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/serviceprogram/serviceprogram.go b/core/serviceprogram/serviceprogram.go index baf0cc1..f53dea7 100644 --- a/core/serviceprogram/serviceprogram.go +++ b/core/serviceprogram/serviceprogram.go @@ -104,7 +104,7 @@ func (p *Program) Start(s service.Service) error { } // The JSON API starts later, when an account logs in; say where it will be. - output.Info("JSON API will listen on %s once an account is logged in", config.APIURL(p.apiListenAddr)) + output.Banner("JSON API: "+config.APIURL(p.apiListenAddr), "starts when an account is logged in") if p.OnStarted != nil { p.OnStarted() @@ -172,7 +172,7 @@ func (p *Program) attemptAutoLogin() { output.Info("Failed to auto-login with account key after %d attempts: %v", maxRetries, err) } else { output.Success("Successfully logged in using stored account key") - output.Info("JSON API listening on %s", config.APIURL(p.apiListenAddr)) + output.Banner("JSON API listening on " + config.APIURL(p.apiListenAddr)) return } } diff --git a/core/serviceprogram/serviceprogram_test.go b/core/serviceprogram/serviceprogram_test.go index cf1a5be..e37e82c 100644 --- a/core/serviceprogram/serviceprogram_test.go +++ b/core/serviceprogram/serviceprogram_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/anyproto/anytype-cli/core/config" + "github.com/anyproto/anytype-cli/core/output" ) func TestNew(t *testing.T) { @@ -147,7 +148,7 @@ func captureStdout(t *testing.T, fn func()) string { } func TestStartPrintsJSONAPIAddress(t *testing.T) { - const want = "JSON API will listen on http://127.0.0.1:4000 once an account is logged in" + want := output.FormatBanner("JSON API: http://127.0.0.1:4000", "starts when an account is logged in") tests := []struct { name string From f315e6c2bae7d4fc7e618b0a44ca67aa613050cf Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Wed, 30 Sep 2026 12:19:35 +0200 Subject: [PATCH 13/14] Tell users how to log in when serve can't auto-login The startup banner now shows just the JSON API address when a stored account key will be used for auto-login. Without one, it adds the commands to log in or create a bot account; if auto-login fails, a second banner says the JSON API isn't running and how to log in. --- core/serviceprogram/serviceprogram.go | 39 +++++++++++++++-- core/serviceprogram/serviceprogram_test.go | 51 ++++++++++++++++++---- 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/core/serviceprogram/serviceprogram.go b/core/serviceprogram/serviceprogram.go index f53dea7..276f3bb 100644 --- a/core/serviceprogram/serviceprogram.go +++ b/core/serviceprogram/serviceprogram.go @@ -70,6 +70,9 @@ type Program struct { // startServer starts the gRPC servers; replaceable in tests. startServer func(grpcAddr, grpcWebAddr string) error + // hasStoredAccount reports whether auto-login has a key to use; + // replaceable in tests. + hasStoredAccount func() bool } func New(apiListenAddr string) *Program { @@ -85,6 +88,12 @@ func (p *Program) Start(s service.Service) error { if p.startServer == nil { p.startServer = p.server.Start } + if p.hasStoredAccount == nil { + p.hasStoredAccount = func() bool { + key, _, err := core.GetStoredAccountKey() + return err == nil && key != "" + } + } p.wg.Add(1) go p.run() @@ -103,8 +112,9 @@ func (p *Program) Start(s service.Service) error { return fmt.Errorf("timeout waiting for server to start") } - // The JSON API starts later, when an account logs in; say where it will be. - output.Banner("JSON API: "+config.APIURL(p.apiListenAddr), "starts when an account is logged in") + // The JSON API starts when an account logs in: show where it will be and, + // if there is nothing to auto-login with, how to log in. + output.Banner(startupBanner(config.APIURL(p.apiListenAddr), p.hasStoredAccount())...) if p.OnStarted != nil { p.OnStarted() @@ -170,10 +180,33 @@ func (p *Program) attemptAutoLogin() { continue } output.Info("Failed to auto-login with account key after %d attempts: %v", maxRetries, err) + output.Banner(autoLoginFailedBanner()...) } else { output.Success("Successfully logged in using stored account key") - output.Banner("JSON API listening on " + config.APIURL(p.apiListenAddr)) return } } } + +// startupBanner is shown once the server is up. With a stored account key the +// server logs in by itself, so the address is enough; without one, the JSON +// API won't start until someone logs in. +func startupBanner(url string, hasStoredAccount bool) []string { + if hasStoredAccount { + return []string{"JSON API: " + url} + } + return []string{ + "JSON API: " + url + " (starts after login)", + "", + "Not logged in. In another terminal, run one of:", + " anytype auth login # existing bot account", + " anytype auth create # new bot account", + } +} + +func autoLoginFailedBanner() []string { + return []string{ + "Auto-login failed, so the JSON API is not running.", + "In another terminal, run: anytype auth login", + } +} diff --git a/core/serviceprogram/serviceprogram_test.go b/core/serviceprogram/serviceprogram_test.go index e37e82c..8820b0d 100644 --- a/core/serviceprogram/serviceprogram_test.go +++ b/core/serviceprogram/serviceprogram_test.go @@ -112,6 +112,7 @@ func TestStartCallsOnStartedOnlyAfterServerStarts(t *testing.T) { t.Run(tt.name, func(t *testing.T) { p := New(config.DefaultAPIAddress) p.startServer = func(grpcAddr, grpcWebAddr string) error { return tt.startErr } + p.hasStoredAccount = func() bool { return true } started := false p.OnStarted = func() { started = true } @@ -147,22 +148,48 @@ func captureStdout(t *testing.T, fn func()) string { return string(out) } -func TestStartPrintsJSONAPIAddress(t *testing.T) { - want := output.FormatBanner("JSON API: http://127.0.0.1:4000", "starts when an account is logged in") +func TestStartupBanner(t *testing.T) { + const url = "http://127.0.0.1:4000" + withAccount := startupBanner(url, true) + if len(withAccount) != 1 || withAccount[0] != "JSON API: "+url { + t.Errorf("with stored account = %q, want just the address", withAccount) + } + + without := strings.Join(startupBanner(url, false), "\n") + for _, want := range []string{"JSON API: " + url, "anytype auth login", "anytype auth create "} { + if !strings.Contains(without, want) { + t.Errorf("without stored account = %q, want it to contain %q", without, want) + } + } +} + +func TestAutoLoginFailedBanner(t *testing.T) { + got := strings.Join(autoLoginFailedBanner(), "\n") + for _, want := range []string{"not running", "anytype auth login"} { + if !strings.Contains(got, want) { + t.Errorf("banner = %q, want it to contain %q", got, want) + } + } +} + +func TestStartPrintsStartupBanner(t *testing.T) { tests := []struct { - name string - startErr error - wantLine bool + name string + startErr error + hasAccount bool + want string }{ - {"server starts", nil, true}, - {"server fails to listen", errors.New("bind: address already in use"), false}, + {"stored account", nil, true, output.FormatBanner(startupBanner("http://127.0.0.1:4000", true)...)}, + {"no stored account", nil, false, output.FormatBanner(startupBanner("http://127.0.0.1:4000", false)...)}, + {"server fails to listen", errors.New("bind: address already in use"), true, ""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p := New("127.0.0.1:4000") p.startServer = func(grpcAddr, grpcWebAddr string) error { return tt.startErr } + p.hasStoredAccount = func() bool { return tt.hasAccount } out := captureStdout(t, func() { _ = p.Start(nil) @@ -172,8 +199,14 @@ func TestStartPrintsJSONAPIAddress(t *testing.T) { p.wg.Wait() }) - if got := strings.Contains(out, want); got != tt.wantLine { - t.Errorf("output %q contains %q = %v, want %v", out, want, got, tt.wantLine) + if tt.want == "" { + if strings.Contains(out, "JSON API") { + t.Errorf("output %q mentions the JSON API although the server failed to start", out) + } + return + } + if !strings.Contains(out, tt.want) { + t.Errorf("output %q does not contain banner %q", out, tt.want) } }) } From 2ea52e8392e98c71d25ea0e63654724d529cfd2e Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Wed, 30 Sep 2026 17:21:45 +0200 Subject: [PATCH 14/14] Bump anytype-heart to v0.51.4 Brings GO-7552: heart loggers now follow the configured log level, so 'anytype serve' no longer prints DEBUG lines at the default ERROR level. --- go.mod | 38 +++++++++++++------------- go.sum | 84 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/go.mod b/go.mod index bec0e8d..b08dbc6 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/anyproto/anytype-cli go 1.26.5 require ( - github.com/anyproto/any-sync v0.13.3 - github.com/anyproto/anytype-heart v0.51.3 + github.com/anyproto/any-sync v0.13.5 + github.com/anyproto/anytype-heart v0.51.4 github.com/cheggaaa/mb/v3 v3.0.3 github.com/chzyer/readline v1.5.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 @@ -15,7 +15,7 @@ require ( github.com/spf13/pflag v1.0.10 github.com/zalando/go-keyring v0.2.8 golang.org/x/mod v0.41.0 - google.golang.org/grpc v1.81.1 + google.golang.org/grpc v1.83.1 gopkg.in/yaml.v3 v3.0.1 ) @@ -28,7 +28,7 @@ require ( github.com/andybalholm/cascadia v1.3.3 // indirect github.com/anyproto/any-block v0.0.0-20260919082013-9906a7c36b68 // indirect github.com/anyproto/any-store v1.0.2 // indirect - github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20260407134332-83cc769fbbb8 // indirect + github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20260925080338-0fb960f00458 // indirect github.com/anyproto/anytype-push-server/pushclient v0.0.0-20260407093150-0b14187dfd27 // indirect github.com/anyproto/go-bip39 v1.0.0 // indirect github.com/anyproto/go-chash v0.1.0 // indirect @@ -68,13 +68,13 @@ require ( github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d // indirect github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect - github.com/dunglas/httpsfv v1.1.0 // indirect + github.com/dunglas/httpsfv v1.1.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/ebitengine/purego v0.10.0 // indirect github.com/ethereum/go-ethereum v1.17.2 // indirect github.com/flopp/go-findfont v0.1.0 // indirect github.com/fogleman/gg v1.3.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.13 // indirect + github.com/gabriel-vasile/mimetype v1.4.15 // indirect github.com/gammazero/chanqueue v1.1.2 // indirect github.com/gammazero/deque v1.2.1 // indirect github.com/gin-contrib/sse v1.1.1 // indirect @@ -82,7 +82,7 @@ require ( github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 // indirect github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/go-errors/errors v1.5.1 // indirect - github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-pkgz/expirable-cache/v3 v3.1.0 // indirect @@ -127,7 +127,7 @@ require ( github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/bbloom v0.1.0 // indirect - github.com/ipfs/boxo v0.42.2 // indirect + github.com/ipfs/boxo v0.43.0 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect github.com/ipfs/go-block-format v0.2.4 // indirect github.com/ipfs/go-cid v0.6.2 // indirect @@ -160,7 +160,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.42 // indirect github.com/mb0/diff v0.0.0-20131118162322-d8d9a906c24d // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect - github.com/miekg/dns v1.1.72 // indirect + github.com/miekg/dns v1.1.73 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/miolini/datacounter v1.0.3 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -188,12 +188,12 @@ require ( github.com/polydawn/refmt v0.90.0 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_golang v1.24.1 // indirect - github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/client_model v0.6.3 // indirect github.com/prometheus/common v0.70.1 // indirect github.com/prometheus/procfs v0.21.1 // indirect github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/quic-go v0.62.0 // indirect - github.com/quic-go/webtransport-go v0.12.0 // indirect + github.com/quic-go/webtransport-go v0.13.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/cors v1.11.1 // indirect github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect @@ -225,25 +225,25 @@ require ( go.mongodb.org/mongo-driver/v2 v2.5.1 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/otel v1.44.0 // indirect - go.opentelemetry.io/otel/metric v1.44.0 // indirect - go.opentelemetry.io/otel/trace v1.44.0 // indirect - go.uber.org/atomic v1.11.0 // indirect + go.opentelemetry.io/otel v1.46.0 // indirect + go.opentelemetry.io/otel/metric v1.46.0 // indirect + go.opentelemetry.io/otel/trace v1.46.0 // indirect + go.uber.org/atomic v1.12.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.28.0 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect golang.org/x/arch v0.26.0 // indirect golang.org/x/crypto v0.57.0 // indirect - golang.org/x/exp v0.0.0-20260718201538-764159d718ef // indirect + golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba // indirect golang.org/x/image v0.38.0 // indirect golang.org/x/net v0.59.0 // indirect - golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/oauth2 v0.37.0 // indirect golang.org/x/sync v0.23.0 // indirect golang.org/x/sys v0.48.0 // indirect golang.org/x/text v0.42.0 // indirect - golang.org/x/time v0.15.0 // indirect + golang.org/x/time v0.16.0 // indirect golang.org/x/tools v0.50.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 // indirect google.golang.org/protobuf v1.36.12 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index e8e55df..4b803f9 100644 --- a/go.sum +++ b/go.sum @@ -31,12 +31,12 @@ github.com/anyproto/any-block v0.0.0-20260919082013-9906a7c36b68 h1:7EAL+fDiqZs/ github.com/anyproto/any-block v0.0.0-20260919082013-9906a7c36b68/go.mod h1:ctWUBba2Nm+mHwkh4bBej57avQHaW2HDzDZDSlbVchs= github.com/anyproto/any-store v1.0.2 h1:vQvgKKDDmM0j9EheBWGq8bMVU7Oi3061DKJFG8D3sTQ= github.com/anyproto/any-store v1.0.2/go.mod h1:8cqb52gjZSaYnlybugqpSqSG1RQygY96D2vWMbSJsLo= -github.com/anyproto/any-sync v0.13.3 h1:tNsrh7HSe4+p/bbvMdh2OuRiVMzSefrYpPxu/6tDjdU= -github.com/anyproto/any-sync v0.13.3/go.mod h1:J+/XaGglDbK4o67YnmDK7GDHS5pqjByshR+7m7j5pYs= -github.com/anyproto/anytype-heart v0.51.3 h1:EvVvGKKbYLwTjwMWqEP9BT5fLeZ8gDyjGcYVkOHPM6o= -github.com/anyproto/anytype-heart v0.51.3/go.mod h1:s0+4XvNVXBLU3iZFphLt9hZY42axzQrqe0mjfNE76rk= -github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20260407134332-83cc769fbbb8 h1:Oaz1B7AUr/4U/kVDBafZ7sP8VCWSYQ51fo6G2T8smH4= -github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20260407134332-83cc769fbbb8/go.mod h1:lRppnNvn5vAw/ASBOYV6LTYPqEg+XC34AzloxK1E/Ac= +github.com/anyproto/any-sync v0.13.5 h1:wWDEcdJReNdZh1yuVcUgWA/VsPom7uP59KM25SdqSCU= +github.com/anyproto/any-sync v0.13.5/go.mod h1:c6f4LXwoji9JkJYt14dXuVbPzYBRa3Z85+sBQ4HX5+4= +github.com/anyproto/anytype-heart v0.51.4 h1:pd+oIWZaRKU9e6+NUR3B+td/tSrRKJVXwSMgJlLWY9o= +github.com/anyproto/anytype-heart v0.51.4/go.mod h1:L/IXpU2eOy79+b4rrrVvvvrqJVNQCCOaNLnyb/Sljt4= +github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20260925080338-0fb960f00458 h1:kg/BHaimoLI2suFe4Kq1MfNxFvWYlFfPPkgVehU9+FE= +github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20260925080338-0fb960f00458/go.mod h1:lRppnNvn5vAw/ASBOYV6LTYPqEg+XC34AzloxK1E/Ac= github.com/anyproto/anytype-push-server/pushclient v0.0.0-20260407093150-0b14187dfd27 h1:O/n87PsZozTtfIbKOad8lS2safL/A1CuzFNrLbin18M= github.com/anyproto/anytype-push-server/pushclient v0.0.0-20260407093150-0b14187dfd27/go.mod h1:1m8LlK1kjKKP3qt/HfOOJLlpKndQoOP4kSErjhXljsM= github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580 h1:Ba80IlCCxkZ9H1GF+7vFu/TSpPvbpDCxXJ5ogc4euYc= @@ -193,8 +193,8 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20221003142440-7a1927d49d9d/go.mod h1:LV github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU= github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw= github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8= -github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= -github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= +github.com/dunglas/httpsfv v1.1.1 h1:HoSs101zIE9I23DlqlmljJ/OIi7ILwrH347pXhRZdxI= +github.com/dunglas/httpsfv v1.1.1/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= @@ -224,8 +224,8 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= -github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI= +github.com/gabriel-vasile/mimetype v1.4.15/go.mod h1:azpTcoLcDZRNgFou5j+APrqQx9HqVPWa6ijYQIIVswQ= github.com/gammazero/chanqueue v1.1.2 h1:dZEsxlyANZMyeTRemABqZF8QM9BnE4NBI43Oh3y5fIU= github.com/gammazero/chanqueue v1.1.2/go.mod h1:XDN1X/jjAbmSceNFOQbtKToeSkxtdVdpKu90LiEdBEE= github.com/gammazero/deque v1.2.1 h1:9fnQVFCCZ9/NOc7ccTNqzoKd1tCWOqeI05/lPqFPMGQ= @@ -256,8 +256,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -441,8 +441,8 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/ipfs/bbloom v0.1.0 h1:nIWwfIE3AaG7RCDQIsrUonGCOTp7qSXzxH7ab/ss964= github.com/ipfs/bbloom v0.1.0/go.mod h1:lDy3A3i6ndgEW2z1CaRFvDi5/ZTzgM1IxA/pkL7Wgts= -github.com/ipfs/boxo v0.42.2 h1:c/lP/MQ2ChmfQ5I0JokqK53bAZuMsNjGia9sHc/RkqU= -github.com/ipfs/boxo v0.42.2/go.mod h1:Izfi844gxRpk7VYbgtMOufY811ohXciUvdgSwd+uPuo= +github.com/ipfs/boxo v0.43.0 h1:nhIbfBBxgLoAxUi8upOIO5RATy++2WigMVWniRJFjnw= +github.com/ipfs/boxo v0.43.0/go.mod h1:n9HNLPLfAGexg2DGoQ5B4BMVlmj9g4+5dIcuo7w95iI= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= github.com/ipfs/go-block-format v0.2.4 h1:pgsT9i8zB4YQkBIQRrBwqbQiXPogRCiQnfxd2bC4koI= @@ -546,8 +546,8 @@ github.com/libp2p/go-libp2p v0.49.0 h1:ibXuYPIHmMIPShob1BktQvSuFQkq/MemhQOLKfGuj github.com/libp2p/go-libp2p v0.49.0/go.mod h1:lzjVcOBk5fCn1QD2XbSOKLZesB6gEsry8SLjCsAAGT4= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= -github.com/libp2p/go-libp2p-kad-dht v0.42.1 h1:b560sbk3L2WIgkY08VgQQSqXJfHgBTr6tmymfW+GaZY= -github.com/libp2p/go-libp2p-kad-dht v0.42.1/go.mod h1:WgImeG7wsNVtUkHVBQSSVaQ4IJR2NUVlSdn5scSI49Y= +github.com/libp2p/go-libp2p-kad-dht v0.42.2 h1:5RtESYeBbjaF+KIPmU47xz2DOb2iLqvoRCZcsjxCS48= +github.com/libp2p/go-libp2p-kad-dht v0.42.2/go.mod h1:oLGZ7xq317zXmoeJe0dwgUdOeWeJ85MDJ/+fbKqFoK0= github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg= github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= @@ -586,8 +586,8 @@ github.com/mehanizm/dateparse v0.0.0-20210806203422-f82c8742c9f8/go.mod h1:cBDq2 github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= -github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= +github.com/miekg/dns v1.1.73 h1:uhT8nJxmTrPJYClxVxTCX+CVn6qnzSiybRk72Z6DgrE= +github.com/miekg/dns v1.1.73/go.mod h1:RW2Obtfd5NZHvOFe3zYG0W8koWOQtAzyHaLo8vASBuQ= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/miolini/datacounter v1.0.3 h1:tanOZPVblGXQl7/bSZWoEM8l4KK83q24qwQLMrO/HOA= @@ -709,8 +709,8 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= -github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/client_model v0.6.3 h1:O0jaTVAYNxTHYInEPFJt5I3+sN8zqBtVMPTB1qyxiEo= +github.com/prometheus/client_model v0.6.3/go.mod h1:gpN5P9S7Rr6Yr92PiQ+Ixvhf6JZEkF1dnxsYL2aPBEM= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= @@ -732,8 +732,8 @@ github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= github.com/quic-go/quic-go v0.62.0 h1:ZHDjCk5OacATwGvs8PWE97CTvX7AqZiVoW7++ZOXTf8= github.com/quic-go/quic-go v0.62.0/go.mod h1:RAro2j2yN9a9EiPACLHT9IB2NXCvGQmmo/alT0yYI0w= -github.com/quic-go/webtransport-go v0.12.0 h1:CpnKNwZvdV0LD73xoHO8QaR0NI3llqpWRwnazdZS0sE= -github.com/quic-go/webtransport-go v0.12.0/go.mod h1:GHne8aRFJ24h73pAMrcywXtuaz/ShBXCLXLvG/NPFdU= +github.com/quic-go/webtransport-go v0.13.0 h1:RJLrTUHlTj8jJaQlQJUy0z0Mf7u1fVM0I6L1b9pe2M0= +github.com/quic-go/webtransport-go v0.13.0/go.mod h1:K83X9YHbAqgSLO6ikS6BXCMdWOvqh9JTHALulvb2JVk= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -882,23 +882,23 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc= +go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE= +go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8= +go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o= +go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI= +go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= +go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c= +go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/atomic v1.12.0 h1:BvcXdFKuviU4fTL/f+SxdQ5qJX/Jix8pAkgdUcb3XOE= +go.uber.org/atomic v1.12.0/go.mod h1:I6c4cg+6HCxRjfjSsYtApoFILnpc0CGUdGkXVqbYVNk= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -947,8 +947,8 @@ golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20260718201538-764159d718ef h1:LkZ48HFgy/TvhTI0bcWkjgFkgLyKUwcTbDjS0DUjw+A= -golang.org/x/exp v0.0.0-20260718201538-764159d718ef/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q= +golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba h1:Ck8QetSgk912qxWLMCKxd0in+aiyBQyDSMae6e/xmpU= +golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba/go.mod h1:50RgIsmK7OwqzTTeqcSXQW8SswW0o8fRcDxmqGluJ8E= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1017,8 +1017,8 @@ 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/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= -golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/oauth2 v0.37.0 h1:JUlcxA8oAtauLfiH8FX2/FkAWHAdi0QtGCGc+hofE98= +golang.org/x/oauth2 v0.37.0/go.mod h1:IxwZNxUULJmpBFf9K/9NTMSIfZZuvuTy1gGxhigP/58= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1114,8 +1114,8 @@ golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= -golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE= +golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1176,8 +1176,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= -google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= +google.golang.org/grpc v1.83.1 h1:HIO0+BEtBP6soyqvqC8sNUjZ7bTs+0hFQuFF+RAy++Y= +google.golang.org/grpc v1.83.1/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=