Skip to content

feat(config): socket login now configures socket-patch — socket-cli config.json fallback + SOCKET_CLI_* aliases#125

Merged
Mikola Lysenko (mikolalysenko) merged 6 commits into
mainfrom
feat/socket-cli-config-alignment
Jul 22, 2026
Merged

feat(config): socket login now configures socket-patch — socket-cli config.json fallback + SOCKET_CLI_* aliases#125
Mikola Lysenko (mikolalysenko) merged 6 commits into
mainfrom
feat/socket-cli-config-alignment

Conversation

@mikolalysenko

Copy link
Copy Markdown
Collaborator

Summary

Aligns socket-patch's configuration with the JS Socket CLI so one socket login configures every Socket tool — without adding any new config file. Design record: docs/design/configuration.md.

Per-key resolution for the three auth settings:

--api-token / --org / --api-url
  1. CLI flag
  2. Canonical env       SOCKET_API_TOKEN / SOCKET_ORG_SLUG / SOCKET_API_URL
  3. Peer alias env      SOCKET_CLI_API_TOKEN / SOCKET_CLI_ORG_SLUG / SOCKET_CLI_API_BASE_URL
                         (silent in-process promotion; canonical wins)
  4. socket-cli config   <data dir>/socket/settings/config.json — READ-ONLY
                         (apiToken, defaultOrg [alias org], apiBaseUrl)
  5. Built-in default    no token → public proxy; org → auto-resolve; api.socket.dev

What's in here

  • New socket_patch_core::utils::socket_cli_config: mirrors socket-cli's getSocketAppDataPath (on macOS also probes the legacy ~/.local/share location older socket-cli releases wrote — real logins exist there); lenient base64→JSON decode with plain-JSON fallback; allowlist copy (unknown keys / non-string values ignored); OnceLock disk cache with the SOCKET_NO_CONFIG gate checked per call. The file is never written — apiProxy/enforcedOrgs/skipAskToPersistDefaultOrg are deliberately ignored.
  • Client integration (get_api_client_with_overrides): config layer between env and defaults; SOCKET_NO_API_TOKEN (alias SOCKET_CLI_NO_API_TOKEN) vetoes ambient tokens while an explicit --api-token still wins; --debug prints provenance (source only, never values); the no-token notice now suggests socket login.
  • Telemetry: resolve_telemetry_endpoint shares resolve_api_base_url() with client construction so a config apiBaseUrl applies to both (e2e-pinned).
  • Enabler: --api-url/--proxy-url drop their clap defaults (Option<String>); documented default URLs now apply at client construction. Observable behavior unchanged unless a socket-cli login exists.
  • Failure semantics: missing file silent; corrupt/unreadable file warns once on stderr and is ignored — never fatal, --json stdout stays clean.
  • Docs: docs/design/configuration.md (settled model, explicitly-rejected alternatives incl. .env loading and repo-level endpoint/credential sources — now a CLI_CONTRACT property — and the deferred env-cleanup list), README "Configuration sources", CLI_CONTRACT sections, CHANGELOG.

Test hermeticity (important for reviewers)

A developer's real socket login must never authenticate a test run. The workspace .cargo/config.toml now exports SOCKET_NO_CONFIG=1 for every cargo-run process; the e2e env-scrub loops deliberately skip that variable so the guard survives into spawned binaries, and targeted token scrubs also drop SOCKET_CLI_API_TOKEN. Tests exercising the layer re-enable it with SOCKET_NO_CONFIG=0 on the child.

Testing

  • Full workspace suite green — run on a machine with a real socket login on disk, doubling as the leak-proof for the hermeticity guard.
  • New tests/cli_config_fallback.rs (9 e2e cases): config token/apiBaseUrl authenticate; defaultOrg skips org auto-resolve with telemetry following the config host+token; env-beats-config per key; alias honored, canonical wins; corrupt config warns while --json stdout parses; both toggles; --api-token survives the veto; missing file silent.
  • Unit tests: path candidates per platform (incl. empty-env-is-unset), decode variants, allowlist, gates, peer-alias promotion (silent, canonical wins), client veto behavior.
  • Manual smoke against a real login: --debug provenance shows token + org from socket-cli config; SOCKET_NO_CONFIG=1 reproduces pre-PR behavior; --offline still refuses up front.

🤖 Generated with Claude Code

…ve in core

api_url/proxy_url become Option<String> with no default_value so
api_client_overrides() forwards None when neither flag nor env var is
set. get_api_client_with_overrides already owns env → default
resolution, and this makes room for the socket-cli config fallback
layer between env and the built-in defaults. Parse-time contract tests
now pin None; the documented URLs stay pinned in core's resolver tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ayer

New socket_patch_core::utils::socket_cli_config reads the JS socket-cli
login state (<data dir>/socket/settings/config.json, base64 JSON,
read-only) and exposes it as the resolution layer below env vars and
above built-in defaults for apiToken/defaultOrg/apiBaseUrl. One
'socket login' now configures socket-patch too.

- get_api_client_with_overrides: flag > env > config > default per key;
  SOCKET_NO_API_TOKEN vetoes ambient tokens (env+config, explicit
  --api-token still wins); SOCKET_NO_CONFIG disables the layer.
- telemetry: resolve_telemetry_endpoint now shares
  resolve_api_base_url() with client construction so the two can't
  disagree about the API host.
- env_compat: SOCKET_CLI_API_TOKEN / SOCKET_CLI_ORG_SLUG /
  SOCKET_CLI_API_BASE_URL / SOCKET_CLI_NO_API_TOKEN accepted as silent
  peer aliases (canonical SOCKET_* names win; no deprecation warning).
- corrupt/unreadable config warns once on stderr and is ignored; missing
  file is silent; --json stdout purity unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ck layer

- .cargo/config.toml [env] exports SOCKET_NO_CONFIG=1 so a developer's
  real 'socket login' can never authenticate a test run; every env
  scrub loop in the e2e harnesses now skips SOCKET_NO_CONFIG so the
  guard survives into spawned binaries, and targeted token scrubs also
  drop SOCKET_CLI_API_TOKEN.
- new tests/cli_config_fallback.rs (9 cases): config token/apiBaseUrl
  authenticate, defaultOrg skips org auto-resolve with telemetry
  following the config host+token, per-key env-beats-config, alias
  honored + canonical wins, corrupt config warns on stderr with --json
  stdout still parseable, SOCKET_NO_CONFIG gate, SOCKET_NO_API_TOKEN
  veto incl. --api-token surviving it, missing file silent.
- client.rs unit tests for the veto (ambient suppressed, override wins).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- docs/design/configuration.md: the settled configuration model —
  per-key precedence (flag > env > SOCKET_CLI_* alias > socket-cli
  config.json > default), read-only pledge, rejected alternatives
  (.env loading, new config file, repo-level endpoints/credentials),
  and deferred items (manifest setup.defaults, the env cleanup sweep,
  token-file/keychain sourcing).
- README: 'Configuration sources' subsection under Global Options.
- CLI_CONTRACT: peer-alias paragraph, config-layer toggles table, and
  a 'Persisted configuration' section with contract properties incl.
  'repo-level files never carry endpoints/credentials/interlocks'.
- CHANGELOG: Unreleased Added + Changed entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Older socket-cli releases wrote the Linux-style data dir on every
platform — real macOS logins exist at ~/.local/share/socket/settings/
config.json (verified on a dev machine where ~/Library/Application
Support/socket/settings/ exists but is empty). With XDG_DATA_HOME unset,
macOS now probes the native Application Support path first and the
legacy path second; first existing file wins, and a corrupt preferred
file stops the probe rather than silently resurrecting older
credentials from the fallback location.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…config-alignment

Conflict: cli_parse_apply.rs defaults comment — kept main's --yes example
(--break-lock is gone) and this branch's api_url/proxy_url None pins.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mikolalysenko
Mikola Lysenko (mikolalysenko) merged commit 34fc4c0 into main Jul 22, 2026
40 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the feat/socket-cli-config-alignment branch July 22, 2026 15:26
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Jul 22, 2026
…h/config alignment (#127)

* feat!: remove unlock + --break-lock, fold lock cleanup into repair, reorder --help

v4 breaking CLI cleanup, part 1:

- Remove the `unlock` subcommand. A leftover apply.lock from a crashed
  run never blocks acquisition (the kernel releases a dead holder's
  advisory lock), so unlock's inspect path had no recovery scenario and
  its --release file deletion is now automatic in repair. The
  patch_unlocked/patch_unlock_failed telemetry events, Command::Unlock
  envelope variant, and SOCKET_UNLOCK_RELEASE are retired with it.

- Remove the global --break-lock flag and SOCKET_BREAK_LOCK. It never
  stole a live holder's lock (deliberately), and stale files never
  contend, so all it did was emit a lock_broken audit event for a
  reclaim plain acquisition performs anyway. acquire_or_emit now
  returns the LockGuard directly; the lock_held hint advises waiting /
  --lock-timeout. rollback's warnings[] stays present, now always
  empty. The never-unlink-while-live invariant survives, pinned by
  acquire_or_emit_preserves_mutual_exclusion.

- repair deletes the leftover apply.lock as its final housekeeping step
  on every completion path (after releasing its own guard; skipped on
  --dry-run; live holders still refused with lock_held exit 1).

- Reorder --help to workflow-first: scan, apply, vex, vendor, setup,
  rollback, get, list, remove, repair.

CHANGELOG carries migration notes under [Unreleased]; the 4.0.0
version-sync is deferred to batch with the remaining breaking changes.

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

* docs: README overhaul on the Divio model + docs/ecosystems.md split

README rewritten as pitch → install → five-minute tutorial → explanation →
how-to recipes → full command reference. Ecosystem/mode support matrix,
Maven/NuGet/Rush/Go/Cargo caveats, and platform table move to the new
docs/ecosystems.md. 83 defects fixed across a 5-round adversarial review
(stale claims, inverted --strict default, .socket/blobs/ path, unimplemented
--one-off stubs labeled, live-tested flatted@3.3.1 tutorial). CLI_CONTRACT.md
maven service-coverage passage synced to SERVICE_ECOSYSTEMS.

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

* docs: port PR #125 auth/config model into the rewritten README

Configuration sources subsection under Global options (per-key precedence:
flag > SOCKET_* env > SOCKET_CLI_* alias > socket-cli config.json > default,
config-file locations, SOCKET_NO_API_TOKEN / SOCKET_NO_CONFIG toggles,
read-only + no-.env pledge), socket-login-first --api-token row, anonymous
public-proxy path kept prominent in the tutorial intro, configuration.md
linked from Further reading.

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

* docs: round-6 review fixes — auth section structure + CI auth guidance

Re-nest Configuration sources as an H4 inside Global options after the flags
table (the insert had stranded the table inside the wrong section); fold the
SOCKET_CLI_* aliases into the env-var rung so the ladder matches the
contract's one-extra-layer model; XDG-first config paths on Linux+macOS;
labeled url default; CI authentication paragraph (SOCKET_API_TOKEN secret,
paidRequired fallback behavior, SOCKET_NO_API_TOKEN pin); slimmer --api-token
row; Maven/NuGet experimental-discovery breadcrumb in the tutorial;
socket-patch vs Socket CLI disambiguation and wrap fixes.

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

* docs: fix repair --offline example comment — warn-and-skip, not per-entry failure

Verified against repair.rs: offline mode prints a summary warning for
missing artifacts, records no download events, and exits success.

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants