Skip to content

Resolve the org once per run and route every API call through it (#648) - #1041

Queued
Mikola Lysenko (mikolalysenko) wants to merge 10 commits into
mainfrom
arch-refactor/648-resolve-org-once
Queued

Mikola Lysenko (mikolalysenko) wants to merge 10 commits into
mainfrom
arch-refactor/648-resolve-org-once

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Why

The maintainer decided on #648: resolve the org once at startup and use it for every later API call. Re-resolving the org or switching endpoints mid-run is wrong. On main, a token whose org can't be resolved splits one run four ways: JSON calls go to /v0/orgs/default/…, blob/diff and vendor references re-derive the proxy from the env, telemetry decides on its own, and embedded --vex builds a second client that calls /v0/organizations again.

What changed

Core (api/client.rs)

  • New ApiRoute { Org { slug }, Proxy } replaces the use_public_proxy flag and optional org_slug. A Proxy client never carries the token.
  • get_api_client_with_overrides decides the route once:
    • no token: Proxy
    • token + slug: Org
    • token, no slug, online: one GET /v0/organizations. Org on success. On failure, Proxy for the whole run plus one warning: "Could not determine your organization (…); using the public patch API proxy (free patches only). Pass --org or set SOCKET_ORG_SLUG." The hint about a token set to its stored sha512- hash is kept.
    • token, no slug, offline: Proxy, no network call, no warning.
  • Patch view, search, batch, blob, diff and vendor package URLs all read the route.
  • Removed: the default slug fallback, the proxy re-derivation from env in binary_url / vendor_package_url, and the per-call override fetch_registry_references_for_org.

Telemetry

  • New TelemetryAuth. for_client uses the client's own route and base URL. from_credentials keeps the no-network path for list and other commands that never build a client.

CLI: one client per run

  • VexBuildParams carries the run's client. scan (JSON and human), hosted scan, the scan vendor flows, apply and vendor (including eject) pass theirs in, so embedded --vex no longer calls /v0/organizations a second time.
  • Standalone vex builds its client at most once, and its telemetry uses it.
  • Vendored repair reuses the client it builds instead of building two.

--json warning

  • scan --json, get --json (search, UUID, hosted and vendored paths, including not_found and paid_required) and standalone vex --json add api_auth_fallback to warnings[] when the run fell back to the proxy. Error envelopes stay minimal and don't carry it; the warning still prints on stderr.

Not in scope: the mid-run 401/403 proxy swap is left for #647, which can build on ApiRoute.

User-visible changes

  • A token whose org can't be resolved no longer queries /v0/orgs/default/…. The whole run uses the public proxy (free patches only), warns once, and reports api_auth_fallback in --json.
  • /v0/organizations is called at most once per run, including scan --vex.
  • Telemetry for an org client now goes to the client's API URL, so it follows --api-url.

Docs

  • crates/socket-patch-cli/CLI_CONTRACT.md: the --org / SOCKET_ORG_SLUG rows and the api_auth_fallback text.
  • docs/migrating-to-v5.md and docs/configuration.md.
  • CHANGELOG.md is unchanged.

Tests

New:

  • core route_decides_every_url: token+slug, failed resolve (500 and 401), offline, no token.
  • telemetry for_client_follows_the_clients_route.
  • CLI unresolved_org_routes_the_whole_scan_vex_run_to_the_proxy_once: scan --json --vex with a token, no org and a 500 from /v0/organizations. Checks one /v0/organizations call, nothing to /v0/orgs/, the embedded VEX fetch goes to the proxy without the token, and api_auth_fallback is in warnings[].
  • vex_sources unit test: one /v0/organizations call across two fetches and exactly one note.
  • get tests: the warning shows once on stderr and in warnings[].

Updated: failed-resolve tests now expect Proxy; the binary_url / vendor_package_url tests build through the resolver; default-slug assertions now expect /patch/view; telemetry and vex_sources tests use the new arguments. Deleted the per-call org override test.

Run: cargo build --all-targets and cargo test -p socket-patch-cli -p socket-patch-core --no-fail-fast after rebasing onto main (the build passed; the full-suite run was still in progress when this PR was opened, and CI will cover it). Before the rebase, the targeted core and CLI lib and integration tests passed. Docker e2e suites were not run locally. cargo clippy --all-targets shows no new warnings in changed code.

Review findings fixed

  • get --json missed api_auth_fallback on five outputs (UUID save, UUID paid_required, UUID not_found, search not_found, search paid_required). Fixed.
  • Standalone vex --json never reported the fallback when it built its own client. Fixed, JSON mode only, with no duplicate when a host passes its client.
  • Docs updated to match.

Left as is: commands that never build a client still send telemetry via env/config and ignore --api-url (unchanged from main); after a mid-run 401/403 swap the telemetry route still points at the org (#647).

Overlaps

PR #913 also touches client.rs. Rebased onto main after #889 landed.

Closes #648

🤖 Generated with Claude Code


Note

Medium Risk
Changes authentication routing and telemetry attribution across most network-touching commands; incorrect routing could affect patch access or event reporting, but behavior is more consistent than the prior split-endpoint model.

Overview
Resolves the org once per run and routes every patch API call, blob/vendor fetch, embedded --vex record fetch, and telemetry event through that single decision—fixing runs where a token without --org/SOCKET_ORG_SLUG previously mixed /v0/orgs/default/…, proxy URLs, a second /v0/organizations in VEX, and mismatched telemetry.

Core: ApiRoute (Org vs Proxy) replaces the use_public_proxy flag; failed online org lookup puts the whole run on the anonymous public proxy (free patches only) with one stderr warning instead of falling back to a default org slug.

CLI: Commands thread a shared ApiClient into embedded VEX via RunApiClient / to_build_params; telemetry uses TelemetryAuth instead of raw token/org pairs. --json adds api_auth_fallback to warnings[] on scan, get, apply, vendor, and related paths when org resolution failed. CLI_CONTRACT.md documents the new --org behavior and warning semantics.

Reviewed by Cursor Bugbot for commit 5082b17. Configure here.


Generated by Claude Code

The run's API client now carries one ApiRoute, Org{slug} or Proxy,
decided once in get_api_client_with_overrides. With a token and no
--org / SOCKET_ORG_SLUG / socket-cli defaultOrg, a failed
GET /v0/organizations (network error, 401/403, no orgs, bad answer)
makes the whole run an anonymous public-proxy run with one warning,
instead of querying /v0/orgs/default/... for JSON while blobs, vendor
package references and telemetry went to the proxy. Offline runs with a
token and no slug use the proxy route without a network call.

- ApiClient: route replaces use_public_proxy + org_slug; a proxy client
  never keeps the token. patches_path, the batch 404 message,
  binary_url and vendor_package_url match on the route; the
  org_slug_or_default fallback, the proxy_url_from_env re-derivation and
  fetch_registry_references_for_org are gone.
- Telemetry takes a TelemetryAuth built from the run's client
  (TelemetryAuth::for_client); list keeps a no-client constructor.
- Embedded --vex reuses the host command's client (VexBuildParams
  api_client), so scan/apply/vendor --vex no longer resolve the org a
  second time; standalone vex builds its client at most once and reports
  telemetry on it. vendored repair hands the client it builds back to
  repair.
- scan --json and get --json report the downgrade as api_auth_fallback
  in warnings[].

The mid-run 401/403 proxy swap is unchanged (#647).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CLI_CONTRACT.md: the --org / SOCKET_ORG_SLUG rows and the
api_auth_fallback warning cover the unresolved-org proxy run.
docs/configuration.md and docs/migrating-to-v5.md describe the change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n path (#648)

get <uuid> --json (agent save, paid_required, not_found) and the search
path's not_found / paid_required envelopes now carry the
api_auth_fallback warning like the other get paths. Standalone
vex --json notes it when it built the run's client itself; a host that
seeded its client reports it and adds no duplicate. Human mode still
warns once, from client construction. Tests pin the warning count and
the new JSON entries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko
Mikola Lysenko (mikolalysenko) force-pushed the arch-refactor/648-resolve-org-once branch from 428e09c to 158ed10 Compare October 7, 2026 23:07
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] CI status: rebased onto origin/main (05ecc6e) at 158ed10. The PR is MERGEABLE again. The only conflict was the api_auth_fallback / vendored_tree_out_of_sync paragraph in CLI_CONTRACT.md, merged to keep both main's Hatch note and this PR's unresolved-org text. Main added no new API call sites, so no code changes were needed. Locally: cargo check --workspace --all-targets passes, and core api/telemetry lib tests (289), core API e2e tests, CLI lib (871) and the cli/get/vex/scan covgap suites all pass.

CI on 158ed10: 8 jobs succeeded, including npm hosted/vendored, pnpm hosted and the GHA audit. Most other runs were cancelled manually at about 23:16–23:18Z as part of a bulk cancel across several branches (also #973 and ci/cut-pr-ci-waste). ci-ok fails only because its dependencies were cancelled. Nothing failed on its own merits. I did not re-run, so as not to override the throttle. Re-run with gh run rerun 37700451708 (and the sibling compat runs) once runners are free.


Generated by Claude Code

Resolve import conflicts in rollback.rs, vendor.rs and scan/vendor_flow.rs
(keep TelemetryAuth, take main's PurlKey in place of
composer_purls_equivalent), and move main's new blob_fetcher test client
onto ApiRoute::Proxy.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 8, 2026 11:16

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-cli/src/commands/apply.rs
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Merged main, CI green; ready for review.


Generated by Claude Code

apply and vendor seed their embedded --vex with the run's client, which
suppresses the VEX plan's own api_auth_fallback note on the promise that
the host reports it. scan and get copy org_unresolved() into warnings[],
but apply and vendor (including the hosted-pin eject path) never did, so a
token whose org failed to resolve was invisible to --json consumers.

Add a shared api_auth_fallback_warning() helper and push it onto the
apply and vendor envelopes under --json, plus an e2e test covering both.

Co-Authored-By: Claude <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-cli/src/commands/vendor.rs
run_eject builds its client (and may fall back to the public proxy)
before any envelope is printed, but only the wet-path envelope carried
the api_auth_fallback warning. The dry-run success envelope and the
fetch-failure / refused envelopes now carry it too, so --json consumers
see the same downgrade stderr already reported.

Co-Authored-By: Claude <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Conflicts in get.rs (imports: kept main's trimmed set plus this branch's TelemetryAuth) and remove.rs (kept main's emit_hosted_unwind_error with this branch's TelemetryAuth telemetry call).

Co-Authored-By: Claude <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-cli/src/commands/get.rs
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[final reviewer] Tanmay Singla (@Tanmay182003) Two non-merge commits landed after your approval on 1cde3710:

  • ac1d2883 Report api_auth_fallback in apply/vendor --json warnings
  • bed1b13e Report the API auth fallback on every vendor --eject JSON envelope

Please take another look at head 2ec62854 before it goes into the merge queue.


Generated by Claude Code

save_and_apply_patch folds the run's org warnings into the wet-run JSON
envelope, but its --dry-run branch called agent_dry_run with empty
warning slices. So `get <uuid> --json --dry-run --mode agent` after a
failed org resolve dropped api_auth_fallback from warnings[], even
though the client warned on stderr and the search dry-run path (which
extends narrow_warnings with org_warnings) reports it. Pass org_warnings
through so the preview envelope matches the wet run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[final reviewer] Tanmay Singla (@Tanmay182003) One non-merge commit landed after your approval on 1cde3710: 7336184 Report the API auth fallback on the get agent dry-run envelope. It fixes Bugbot's open finding: get <uuid> --json --dry-run dropped api_auth_fallback from warnings[]. One-line change in commands/get.rs plus a regression test. Please take another look at head 7336184 once CI is green; it isn't enqueued until then.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Resolve get.rs and rollback.rs conflicts with #1027: keep this PR's
shared telemetry handle and take main's {code, message} error codes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[final reviewer] Merged main at ffe27156 to clear the conflict with #1027 ({code, message} JSON errors) in get.rs and rollback.rs: kept this PR's shared telemetry handle and took main's error codes (patch_fetch_failed, manifest_invalid, manifest_unreadable, path_glob_no_match). Merge-only, no new behavior. Locally: cargo clippy -p socket-patch-cli -p socket-patch-core --all-features -D warnings clean; socket-patch-cli lib (895), json_error_shape, get, rollback tests pass.

Tanmay Singla (@Tanmay182003) the re-look request above for 7336184 still stands; once you approve at this head and CI is green it goes to the merge queue.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-cli/src/commands/repair.rs
When a token's org cannot be resolved, repair's download runs on the
public proxy and only stderr said so; scan, get, apply and vendor already
carry api_auth_fallback in the envelope's warnings[]. Copy it from the
download phase's client (not the telemetry-only client, which fetched
nothing). Bugbot finding on #1041.

Co-Authored-By: Claude <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 5082b17. Configure here.

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[final reviewer] Tanmay Singla (@Tanmay182003) One more non-merge commit landed after your approval on 1cde3710, on top of the ones listed above:

  • 5082b172 Report repair's public-proxy fallback in the --json warnings (2 files, +82/−1). When a token's org can't be resolved, repair now puts api_auth_fallback in the JSON envelope's warnings[], as scan, get, apply and vendor already do. It reads the flag from the download phase's client (crates/socket-patch-cli/src/commands/repair.rs). Adds a test in tests/repair/repair_invariants.rs. This fixes a Bugbot finding.

CI is green and the PR is mergeable at 5082b172. Re-approving sends it to the merge queue on my next pass.


Generated by Claude Code

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 9, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[burn-down agent] Labeled Ready for review at 5082b172a7.

  • CI: all 466 check runs on the head are success/skipped (ci-ok green), including the Gradle Windows jobs that were still running at the last handoff.
  • Bugbot: reviewed 5082b172 with no new findings; all 4 review threads resolved.
  • Mergeable, no CHANGELOG.md change. Needs a human approval (the final reviewer flagged a non-merge commit after the earlier approval).

Generated by Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-refactor PR opened by the scheduled architecture refactor routine Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decide: where patch API calls go when a token is set but the org slug can't be resolved

3 participants