Redact StageOptions error payloads and summarize debug launch args.
Propagate request IDs through Cursor daemon and dashboard completion logs.
Mark remaining P2/P3 maintainability targets as partial instead of overclaiming.
Epic P6 (partial: 2 of 6 targets). These two files have strong existing
per-provider test coverage, so the characterization-first requirement is met
by the safety net; both are split test-backed.
- src/cliproxy/quota/quota-fetcher.ts (1106 -> barrel 29 + 9 submodules, max
254 LOC): status-classifier (the clean extract), http-client, auth-file-reader,
project-lookup, available-models-fetcher, account-quota-fetcher,
all-accounts-fetcher, types, constants.
- src/cliproxy/quota/quota-fetcher-gemini-cli.ts (1179 -> barrel 27 + 11
submodules, max 334 LOC): token-parsing, auth-file-discovery,
supplementary-metadata, error-parsing, bucket-building, managed-request,
shared-utils, types, constants, index.
Public API preserved verbatim (incl. __testExports). All P3 structured logging
preserved through the splits. Regenerated eslint-rules/throw-error-baseline.json
(throws moved to new module paths).
Remaining P6 targets (characterization-first, deferred): oauth-handler.ts,
cursor-executor.ts, tool-sanitization-proxy.ts, + 1. Each needs dedicated
characterization-test work before splitting; tracked in the epic plan.
Metric: files > 400 LOC 91 -> 89. validate + validate:ci-parity green.
Epic P7. Locks in the epic's gains with ESLint gates so the adoption work
does not regress.
- ccs/no-new-throw-error (error): custom flat-config rule that flags NEW
throw new Error(...) outside a generated baseline allowlist. Forces the
typed-error taxonomy (src/errors/error-types.ts). Existing 338 sites are
grandfathered in eslint-rules/throw-error-baseline.json; only NEW violations
error. Rule normalizes the filename to repo-root-relative to match baseline
keys regardless of how ESLint reports paths.
- max-lines (warn, 400, skipBlankLines/skipComments): warns on files over
400 LOC (goal of P5/P6 god-file splits). Currently 51 warnings on the
not-yet-split god-files (P6 territory).
- scripts/generate-throw-error-baseline.js: emits the allowlist from raw
source (superset of real throws; never undercounts). Run after intentionally
grandfathering a site, or quarterly to prune.
- tests/unit/eslint-rules/no-throw-new-error.test.ts: rule logic (flags
off-allowlist, passes on-allowlist/typed/rethrow, line-sensitivity).
- docs/code-standards.md: Lint Enforcement Gates section.
- docs/logging-contract.md: error.code -> ExitCode table (from P4).
validate + validate:ci-parity green.
Epic P4. Migrates plain throw new Error to the typed-error classes in the four
locked subdomains, and makes the taxonomy erasable-syntax-compatible so it can
be adopted across UI-reachable code.
Migration (cliproxy/auth, web-server/routes, auth):
- 21 of 23 throws in the locked subdomains now use typed subclasses
(ProfileError, AuthError, ConfigError, ValidationError, ProviderError).
- Typed adoption in locked subdomains: 0/23 -> 21/23 (91.3%), > 40% target.
- Overall typed adoption: 0.9% -> 8.6%.
- Messages preserved exactly (message-based tests stable). Exit codes now
differentiate via handleError (ProfileError=7, AuthError=4, ConfigError=2,
ProviderError=6). ccs doctor 0/1 contract untouched (outside scope).
Erasable-syntax fix (unblocks the migration in the UI build graph):
- exit-codes.ts: enum ExitCode -> const object + union type (value and type
usage both preserved; no Object.values(ExitCode) consumers).
- error-types.ts: constructor parameter properties -> explicit readonly field
declarations + body assignment.
- The web UI build enforces erasableSyntaxOnly (ui/tsconfig.app.json) and
reaches src/errors via the @shared -> src/auth graph; pre-erasable
error-types blocked the build once profile-registry adopted typed errors.
Compat audit: docs/reports/typed-error-exit-code-compat-audit.md (Q1 resolved:
migrate freely; only documented contract is ccs doctor, which is untouched).
Behavior-lock: src/errors/__tests__/typed-error-migration-exit-codes.test.ts
(taxonomy -> exit-code mapping, instanceof chains, context fields).
validate + validate:ci-parity green (incl. UI build).
Epic P2. Closes the three real traceability gaps so every diagnostic log can
carry a requestId from origin (ccs.ts main) through HTTP edges and spawned
daemons.
- log-context: add REQUEST_ID_HEADER/ENV/PATTERN, resolveRequestIdFromEnv,
forwardRequestIdEnv. runWithRequestId now reuses a forwarded CCS_REQUEST_ID
when well-formed (child re-anchor), else mints fresh.
- request-logging-middleware: wrap the Express dashboard handler chain in
withRequestContext so downstream route-handler logs carry requestId (mirrors
src/proxy/server/proxy-server.ts, which is untouched prior art).
- forward CCS_REQUEST_ID at the 4 child-daemon spawn sites: delegation
headless-executor, cursor-daemon, cursor-profile-executor, copilot-executor.
- cursor-daemon-entry: re-anchor via runWithRequestId so daemon startup logs
correlate with the spawning CLI invocation (ALS does not cross spawn).
- logger adoption toe-hold: delegation/session-manager (load/save failures) and
docker/supervisord-lifecycle (restart failure) now use createLogger.
api/channels/shared have no touchable diagnostic console.error (CLI-UX only or
pure data); dispatcher's only diagnostic is in pre-dispatch.ts, owned by plan
#1165. Those defer to P3's full per-site sweep.
Tests: request-context-middleware (handler log requestId === header),
request-id-forwarding (env resolve/reject, re-anchor, forwardRequestIdEnv).
validate + validate:ci-parity green.
Built-in Claude provider now uses the CLIProxy root URL instead of /api/provider/claude (which 404'd since base CLIProxy registers /v1/messages at root). Repairs stale local Claude settings, keeps non-Claude providers on their scoped routes, and applies the same root-URL rule to the ccs api create --cliproxy-provider claude bridge path via a shared buildCliproxyProviderPath helper. Closes#1545.
* test(bar): cover socket-level 401/403 auth detection and liveness-poll rogue rejection
Add two new describe blocks to bar-command.test.ts:
1. `defaultFindRunningServer: socket-level 401/403 classifies authRequired=true`
Drives `net.connect` via mock.module('net') to verify that status lines
401 and 403 off the wire set authRequired=true. A correct-token 200 must
not set authRequired. Prior tests bypassed the real status-line parser by
injecting authRequired via deps; these tests couple to the actual branch.
2. `defaultWaitForServerLive: rogue 200 without matching token is rejected`
Uses the same net mock pattern to verify that a 200 carrying a wrong
x-ccs-bar-token never causes the liveness poll to resolve (rogue reflector
cannot pass). Correct token resolves immediately.
Export `defaultWaitForServerLive` from launch-subcommand.ts so the direct
unit test can import it without forcing a full handleBarLaunch invocation.
Both test groups are behavior-coupled: removing the relevant branch in
production causes the tests to fail (verified under mutation).
* refactor(bar): drop dead ensureLoopbackNoProxy proxy shim
The probe now uses raw net.connect() which never consults proxy env vars
(undici was fully removed in an earlier PR). ensureLoopbackNoProxy()
permanently mutated process-wide NO_PROXY/no_proxy on every discovery call
with no effect on the actual network path.
Verified zero remaining references to ensureLoopbackNoProxy outside the
declaration and call site that are now removed.
Closes a spoofed-loopback-200 bar.json poisoning vector with a per-user 0600 capability token. The real bar server echoes its file-derived token on /bar/* responses; the launch probe verifies the echoed token against the locally-read file (fail-closed) before reusing a server, so a rogue loopback process that cannot read the token file is rejected.
Raw-socket probe detects auth-protected (401/403) bar servers, reuses them, and kills the orphaned detached server on auth timeout. Integrated with the non-blocking priority probe.
Preserves the Gatekeeper quarantine attribute on the installed CCS Bar app so the user makes the right-click to Open trust decision, instead of silently clearing it.
Hardens the macOS bar launch.json descriptor against untrusted/foreign-owned files and constrains the decoded descriptor; blocks dashboard file writes to the launch descriptor.
Adds opt-in config.runtime.outputLimits to inject MAX_MCP_OUTPUT_TOKENS/BASH_MAX_OUTPUT_LENGTH into the spawned CLI; defaults unchanged when unset. Closes#231.
Sets undici headersTimeout/bodyTimeout to request_timeout+30s so the AbortController is the single authority on upstream request lifetime, preventing premature socket closes on slow self-hosted upstreams. Verified undici v5 ProxyAgent object-signature compat.
Reflect the seamless-launch change: the app self-starts the background
server, ccs bar runs it detached, and add the serve/stop/status commands
plus the launch.json/server.pid/serve.log files.
The dropdown height defaulted to screenCap before the content was measured,
and the ScrollView frame had no alignment, so an unmeasured panel rendered at
nearly full screen height with the content centered in it (macOS then centered
the oversized window). Default to a modest height until measured and pin the
frame to .top, so the popover anchors under the menu bar and sizes to its
content, scrolling only on genuine overflow.