Compare commits
2 Commits
1b4603ed3b
...
3e5461df9b
| Author | SHA1 | Date | |
|---|---|---|---|
| 3e5461df9b | |||
| ce8f0dfd2b |
@@ -48,6 +48,7 @@ Removed in this repository:
|
||||
- Datadog analytics and Anthropic 1P event-logging egress.
|
||||
- GrowthBook remote evaluation/network fetches; local env/config overrides and cached values remain available for compatibility.
|
||||
- OpenTelemetry initialization and event export paths.
|
||||
- Perfetto local trace-file output paths that could persist request/tool metadata to disk.
|
||||
- Extra dead telemetry scaffolding tied to the removed egress paths, including startup/session analytics fanout, logout telemetry flush, and remote GrowthBook metadata collectors.
|
||||
|
||||
Still present:
|
||||
|
||||
@@ -23,16 +23,6 @@ type BridgeApiDeps = {
|
||||
* tokens don't refresh, so 401 goes straight to BridgeFatalError.
|
||||
*/
|
||||
onAuth401?: (staleAccessToken: string) => Promise<boolean>
|
||||
/**
|
||||
* Returns the trusted device token to send as X-Trusted-Device-Token on
|
||||
* bridge API calls. Bridge sessions have SecurityTier=ELEVATED on the
|
||||
* server (CCR v2); when the server's enforcement flag is on,
|
||||
* ConnectBridgeWorker requires a trusted device at JWT-issuance.
|
||||
* Optional — when absent or returning undefined, the header is omitted
|
||||
* and the server falls through to its flag-off/no-op path. The CLI-side
|
||||
* gate is tengu_sessions_elevated_auth_enforcement (see trustedDevice.ts).
|
||||
*/
|
||||
getTrustedDeviceToken?: () => string | undefined
|
||||
}
|
||||
|
||||
const BETA_HEADER = 'environments-2025-11-01'
|
||||
@@ -74,18 +64,13 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
const EMPTY_POLL_LOG_INTERVAL = 100
|
||||
|
||||
function getHeaders(accessToken: string): Record<string, string> {
|
||||
const headers: Record<string, string> = {
|
||||
return {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'anthropic-version': '2023-06-01',
|
||||
'anthropic-beta': BETA_HEADER,
|
||||
'x-environment-runner-version': deps.runnerVersion,
|
||||
}
|
||||
const deviceToken = deps.getTrustedDeviceToken?.()
|
||||
if (deviceToken) {
|
||||
headers['X-Trusted-Device-Token'] = deviceToken
|
||||
}
|
||||
return headers
|
||||
}
|
||||
|
||||
function resolveAuth(): string {
|
||||
|
||||
@@ -35,7 +35,6 @@ import { createTokenRefreshScheduler } from './jwtUtils.js'
|
||||
import { getPollIntervalConfig } from './pollConfig.js'
|
||||
import { toCompatSessionId, toInfraSessionId } from './sessionIdCompat.js'
|
||||
import { createSessionSpawner, safeFilenameId } from './sessionRunner.js'
|
||||
import { getTrustedDeviceToken } from './trustedDevice.js'
|
||||
import {
|
||||
BRIDGE_LOGIN_ERROR,
|
||||
type BridgeApiClient,
|
||||
@@ -2344,7 +2343,6 @@ export async function bridgeMain(args: string[]): Promise<void> {
|
||||
runnerVersion: MACRO.VERSION,
|
||||
onDebug: logForDebugging,
|
||||
onAuth401: handleOAuth401Error,
|
||||
getTrustedDeviceToken,
|
||||
})
|
||||
|
||||
// When resuming a session via --session-id, fetch it to learn its
|
||||
@@ -2877,7 +2875,6 @@ export async function runBridgeHeadless(
|
||||
runnerVersion: MACRO.VERSION,
|
||||
onDebug: log,
|
||||
onAuth401: opts.onAuth401,
|
||||
getTrustedDeviceToken,
|
||||
})
|
||||
|
||||
let environmentId: string
|
||||
|
||||
@@ -95,20 +95,15 @@ export async function fetchRemoteCredentials(
|
||||
baseUrl: string,
|
||||
accessToken: string,
|
||||
timeoutMs: number,
|
||||
trustedDeviceToken?: string,
|
||||
): Promise<RemoteCredentials | null> {
|
||||
const url = `${baseUrl}/v1/code/sessions/${sessionId}/bridge`
|
||||
const headers = oauthHeaders(accessToken)
|
||||
if (trustedDeviceToken) {
|
||||
headers['X-Trusted-Device-Token'] = trustedDeviceToken
|
||||
}
|
||||
let response
|
||||
try {
|
||||
response = await axios.post(
|
||||
url,
|
||||
{},
|
||||
{
|
||||
headers,
|
||||
headers: oauthHeaders(accessToken),
|
||||
timeout: timeoutMs,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
|
||||
@@ -38,7 +38,6 @@ import { buildCCRv2SdkUrl } from './workSecret.js'
|
||||
import { toCompatSessionId } from './sessionIdCompat.js'
|
||||
import { FlushGate } from './flushGate.js'
|
||||
import { createTokenRefreshScheduler } from './jwtUtils.js'
|
||||
import { getTrustedDeviceToken } from './trustedDevice.js'
|
||||
import {
|
||||
getEnvLessBridgeConfig,
|
||||
type EnvLessBridgeConfig,
|
||||
@@ -925,9 +924,8 @@ import {
|
||||
} from './codeSessionApi.js'
|
||||
import { getBridgeBaseUrlOverride } from './bridgeConfig.js'
|
||||
|
||||
// CLI-side wrapper that applies the CLAUDE_BRIDGE_BASE_URL dev override and
|
||||
// injects the trusted-device token (both are env/GrowthBook reads that the
|
||||
// SDK-facing codeSessionApi.ts export must stay free of).
|
||||
// CLI-side wrapper that applies the CLAUDE_BRIDGE_BASE_URL dev override while
|
||||
// keeping the SDK-facing codeSessionApi.ts export free of CLI config reads.
|
||||
export async function fetchRemoteCredentials(
|
||||
sessionId: string,
|
||||
baseUrl: string,
|
||||
@@ -939,7 +937,6 @@ export async function fetchRemoteCredentials(
|
||||
baseUrl,
|
||||
accessToken,
|
||||
timeoutMs,
|
||||
getTrustedDeviceToken(),
|
||||
)
|
||||
if (!creds) return null
|
||||
return getBridgeBaseUrlOverride()
|
||||
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
} from './workSecret.js'
|
||||
import { toCompatSessionId, toInfraSessionId } from './sessionIdCompat.js'
|
||||
import { updateSessionBridgeId } from '../utils/concurrentSessions.js'
|
||||
import { getTrustedDeviceToken } from './trustedDevice.js'
|
||||
import { HybridTransport } from '../cli/transports/HybridTransport.js'
|
||||
import {
|
||||
type ReplBridgeTransport,
|
||||
@@ -314,7 +313,6 @@ export async function initBridgeCore(
|
||||
runnerVersion: MACRO.VERSION,
|
||||
onDebug: logForDebugging,
|
||||
onAuth401,
|
||||
getTrustedDeviceToken,
|
||||
})
|
||||
// Ant-only: interpose so /bridge-kick can inject poll/register/heartbeat
|
||||
// failures. Zero cost in external builds (rawApi passes through unchanged).
|
||||
|
||||
@@ -54,8 +54,6 @@ export type ReplBridgeTransport = {
|
||||
* (user watches the REPL locally); multi-session worker callers do.
|
||||
*/
|
||||
reportState(state: SessionState): void
|
||||
/** PUT /worker external_metadata (v2 only; v1 is a no-op). */
|
||||
reportMetadata(metadata: Record<string, unknown>): void
|
||||
/**
|
||||
* POST /worker/events/{id}/delivery (v2 only; v1 is a no-op). Populates
|
||||
* CCR's processing_at/processed_at columns. `received` is auto-fired by
|
||||
@@ -96,7 +94,6 @@ export function createV1ReplTransport(
|
||||
return hybrid.droppedBatchCount
|
||||
},
|
||||
reportState: () => {},
|
||||
reportMetadata: () => {},
|
||||
reportDelivery: () => {},
|
||||
flush: () => Promise.resolve(),
|
||||
}
|
||||
@@ -324,9 +321,6 @@ export async function createV2ReplTransport(opts: {
|
||||
reportState(state) {
|
||||
ccr.reportState(state)
|
||||
},
|
||||
reportMetadata(metadata) {
|
||||
ccr.reportMetadata(metadata)
|
||||
},
|
||||
reportDelivery(eventId, status) {
|
||||
ccr.reportDelivery(eventId, status)
|
||||
},
|
||||
|
||||
@@ -2,35 +2,19 @@ import { logForDebugging } from '../utils/debug.js'
|
||||
import { getSecureStorage } from '../utils/secureStorage/index.js'
|
||||
|
||||
/**
|
||||
* Trusted device token source for bridge (remote-control) sessions.
|
||||
* Trusted-device compatibility helpers for bridge (remote-control) sessions.
|
||||
*
|
||||
* Bridge sessions have SecurityTier=ELEVATED on the server (CCR v2).
|
||||
* The server gates ConnectBridgeWorker on its own flag
|
||||
* (sessions_elevated_auth_enforcement in Anthropic Main); this CLI-side
|
||||
* flag controls whether the CLI sends X-Trusted-Device-Token at all.
|
||||
* Two flags so rollout can be staged: flip CLI-side first (headers
|
||||
* start flowing, server still no-ops), then flip server-side.
|
||||
*
|
||||
* Enrollment (POST /auth/trusted_devices) is gated server-side by
|
||||
* account_session.created_at < 10min, so it must happen during /login.
|
||||
* Token is persistent (90d rolling expiry) and stored in keychain.
|
||||
*
|
||||
* See anthropics/anthropic#274559 (spec), #310375 (B1b tenant RPCs),
|
||||
* #295987 (B2 Python routes), #307150 (C1' CCR v2 gate).
|
||||
* This fork disables trusted-device enrollment and header emission. The
|
||||
* remaining helpers only clear any previously stored token during login/logout
|
||||
* so old state is not carried forward.
|
||||
*/
|
||||
|
||||
export function getTrustedDeviceToken(): string | undefined {
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function clearTrustedDeviceTokenCache(): void {
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the stored trusted device token from secure storage and the memo cache.
|
||||
* Called during /login so a stale token from the previous account isn't sent
|
||||
* as X-Trusted-Device-Token after account switches.
|
||||
* Clear any stored trusted-device token from secure storage.
|
||||
*/
|
||||
export function clearTrustedDeviceToken(): void {
|
||||
const secureStorage = getSecureStorage()
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2226,11 +2226,8 @@ async function run(): Promise<CommanderCommand> {
|
||||
resetUserCache();
|
||||
// Refresh GrowthBook after login to get updated feature flags (e.g., for claude.ai MCPs)
|
||||
refreshGrowthBookAfterAuthChange();
|
||||
// Clear any stale trusted device token then enroll for Remote Control.
|
||||
// Both self-gate on tengu_sessions_elevated_auth_enforcement internally
|
||||
// — enrollTrustedDevice() via checkGate_CACHED_OR_BLOCKING (awaits
|
||||
// the GrowthBook reinit above), clearTrustedDeviceToken() via the
|
||||
// sync cached check (acceptable since clear is idempotent).
|
||||
// Clear any stale trusted-device token, then run the no-op enrollment
|
||||
// stub so the disabled bridge path stays consistent after login.
|
||||
void import('./bridge/trustedDevice.js').then(m => {
|
||||
m.clearTrustedDeviceToken();
|
||||
return m.enrollTrustedDevice();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user