Skip to content

Commit af988db

Browse files
author
test
committed
Merge origin/master into fix/issue-885
Three textual conflicts, all resolved by keeping both sides: - docs/PRIVACY.md: master's disclosure of the launchd LaunchAgent stays, re-tensed as residue of the proxy-attach releases to match this branch's "nothing installs the CA into a system trust store any more"; the lifetime paragraph keeps master's added facts (permitted hosts, launchd variable) inside this branch's wording about detach and the grant. - src/core/commands/status.js: master's describePermittedHosts is kept verbatim; describeLaunchdEnv keeps this branch's doc comment explaining why it states rather than prescribes. - src/core/daemon/status.js: collectProxyTrust takes both master's timeout-bounded probes and this branch's `config` argument, and returns both `hosts` and `proxyModeConfigured`. One semantic conflict, from master's #817 pinning the `--json` shape of the migration pointer against `claude` while this branch stops the claude row declaring `compose.gateway_proxy_mode`. Both pins are kept by driving them through the staged picker row that still declares proxy attach, the way this branch already converted the rest of the file, plus a new pin that a `--json` claude attach on a TTY carries no pointer either. LLP 0251 gains the `Extended-by: LLP 0262` forward-ref LLP 0243 already carried, since its section 2 names the claude declarers this branch removes.
2 parents a7e8a1d + 1215492 commit af988db

46 files changed

Lines changed: 3268 additions & 95 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,25 @@ Such a client is then pointed at the gateway with `HTTPS_PROXY` and
338338
with that inbound channel off. No admin rights are needed and the
339339
machine-wide system keychain is not touched. On other platforms trust
340340
stays file-scoped to the client's own settings. `hyp status` shows the
341-
fingerprint and whether the keychain still trusts it.
342-
`hyp detach <client>` keeps the CA and the trust, so re-attaching does not
343-
ask again; `hyp detach <client> --purge` and `hyp daemon uninstall` remove
344-
both.
341+
fingerprint, every host the CA is permitted to vouch for, and whether the
342+
keychain still trusts it. `hyp detach <client>` keeps the CA and the
343+
trust, so re-attaching does not ask again; `hyp detach <client> --purge`
344+
and `hyp daemon uninstall` remove both.
345+
- **On macOS, a proxy attach also leaves a login-session variable behind.**
346+
Bun picks its trust store before any settings file is read, so a keychain
347+
root only counts if `NODE_USE_SYSTEM_CA=1` is already in the process
348+
environment. The attach that trusted the CA therefore ran `launchctl
349+
setenv NODE_USE_SYSTEM_CA 1` and installed a small LaunchAgent,
350+
`~/Library/LaunchAgents/com.hyperparam.hypaware.node-system-ca.plist`,
351+
whose only job is to re-run that command at each login. It stays a login
352+
item on your machine until it is removed, and it is a session-wide
353+
variable that other Node programs read too. `launchctl setenv` reaches
354+
processes launched after it, so a terminal app that was already running
355+
must be fully quit and reopened. `hyp detach <client>` unsets the
356+
variable and removes the agent, as do `hyp detach <client> --purge` and
357+
`hyp daemon uninstall`; `hyp attach claude` unwinds it when it migrates a
358+
previously proxied machine; and `hyp status` shows whether the variable is
359+
currently live.
345360
- **Only the hosts a registered upstream names are decrypted.** Every other
346361
host the client talks to is tunnelled through without being decrypted.
347362
- **What gets recorded does not change.** Only the recorded API paths are

docs/PRIVACY.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,27 @@ those, that trust setting is still on your account until you remove it, and
7878
`hyp status` says so. It never needed admin rights, and the machine-wide
7979
system keychain and other user accounts were never modified.
8080

81-
**Its lifetime.** `hyp status` shows the fingerprint and, on macOS, whether
82-
the login keychain still trusts it. `hyp detach claude` deliberately leaves
83-
the CA and any trust from an earlier release in place, because a detach is
84-
not a statement about the certificate and no attach re-creates the grant;
85-
`hyp detach claude --purge` and `hyp daemon uninstall` remove the CA and its
86-
keychain trust.
81+
**What an earlier macOS attach also left behind.** The keychain root only
82+
takes effect if `NODE_USE_SYSTEM_CA=1` is in the environment before Claude
83+
Code starts, so the proxy attach of those releases also ran
84+
`launchctl setenv NODE_USE_SYSTEM_CA 1` and installed a LaunchAgent at
85+
`~/Library/LaunchAgents/com.hyperparam.hypaware.node-system-ca.plist` that
86+
re-ran that one command at each login. What it runs is `/bin/launchctl`
87+
itself, once, which sets the variable and exits: there is no resident
88+
process, no HypAware code in it, and nothing is sent anywhere. It is still a
89+
login item on your machine, and a session-wide variable that other Node
90+
programs will also read. Attaching today installs neither, but if you ran one
91+
of those releases both are still there; `hyp detach claude` unsets the
92+
variable and removes the agent, as do `hyp detach claude --purge` and
93+
`hyp daemon uninstall`.
94+
95+
**Its lifetime.** `hyp status` shows the fingerprint, every host the CA is
96+
permitted to vouch for, and, on macOS, whether the login keychain still
97+
trusts it and whether the launchd variable is live. `hyp detach claude`
98+
deliberately leaves the CA and any trust from an earlier release in place,
99+
because a detach is not a statement about the certificate and no attach
100+
re-creates the grant; `hyp detach claude --purge` and `hyp daemon uninstall`
101+
remove the CA and its keychain trust.
87102

88103
## Where it goes
89104

hypaware-core/plugins-workspace/ai-gateway/src/source.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,17 +432,23 @@ async function prepareInterception(ctx, config, upstreams, liveState) {
432432
if (!config.proxyMode) {
433433
// Proxy mode is off, but a CA on disk means a client was attached in proxy
434434
// mode at some point and may still have `HTTPS_PROXY` pointing here. Serve
435-
// blind tunnels so its egress keeps working, and say so loudly: the repair
436-
// is a re-attach (or a detach), and nothing else on the machine will
437-
// volunteer that.
435+
// blind tunnels so its egress keeps working, and say so loudly: nothing
436+
// else on the machine will volunteer that this install is in the degraded
437+
// state. A plain re-attach is NOT the remedy: attach leaves the CA where
438+
// it is on purpose (the trust is offered back, never taken), so the file
439+
// that puts the install in this state survives the re-attach. The
440+
// remedies that land are removing the CA (`hyp detach claude --purge`,
441+
// then re-attach) or turning `proxy_mode` back on.
442+
// @ref LLP 0262#migration [constrained-by]: attach offers the CA back rather than removing it, so it cannot clear this state on its own
438443
const stale = await readLocalCaInfo({ stateRoot: defaultStateRoot(ctx.env) })
439444
if (stale) {
440445
liveState.interceptionError = 'proxy_mode is off but a local CA is installed'
441446
ctx.log.warn('aigw.proxy_mode_stale_ca', {
442447
[Attr.PLUGIN]: PLUGIN_NAME,
443448
ca_cert_path: stale.certPath,
444449
reason: 'serving blind tunnels so an already-attached client keeps working; ' +
445-
'run `hyp attach claude` to move it back to base-URL mode, or `hyp detach claude`',
450+
're-attaching leaves this CA on disk, so run `hyp detach claude --purge` ' +
451+
'and re-attach to clear the proxy residue, or turn proxy_mode back on',
446452
})
447453
return { tunnelOnly: true }
448454
}

0 commit comments

Comments
 (0)