Commit Graph
4462 Commits
Author SHA1 Message Date
github-actions[bot] 5b6c3e87e9 chore(release): 8.4.0-dev.11 2026-06-18 23:52:27 +00:00
Kai (Tam Nhu) Tran 2a14904a23 Merge pull request #1568 from kaitranntt/kai/feat/maintainability-traceability-epic
Maintainability & Traceability Epic (P1-P7)
2026-06-18 19:48:25 -04:00
Tam Nhu Tran 1462823be8 fix(logging): harden structured trace redaction
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.
2026-06-18 18:48:13 -04:00
Tam Nhu Tran 2d48488475 docs(hardening): finalize epic metrics + progress log (P1-P7) 2026-06-18 18:48:13 -04:00
Tam Nhu Tran aecc1f7217 refactor: P6 god-file splits (quota-fetcher + quota-fetcher-gemini-cli; 4 deferred)
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.
2026-06-18 18:48:13 -04:00
Tam Nhu Tran 2f94f35ec3 feat(lint): P7 enforcement gates (no-new-throw-error + max-lines) + docs
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.
2026-06-18 18:48:13 -04:00
Tam Nhu Tran 919be3c722 refactor: P5 god-file splits (test-backed, public API preserved)
Epic P5. Splits 4 test-backed god-files into focused submodules using the
Monster File Splitting methodology; each original file is now a thin barrel
re-exporting the full public surface, so consumers are unchanged.

- src/management/shared-manager.ts (1631 -> barrel 21 + 10 submodules,
  max 337 LOC): fs-helpers, symlink-helpers, plugin-metadata-normalizer,
  plugin-layout-internals, shared-dir-linker, project-context-sync,
  project-memory-sync, migrations, orchestrator, types.
- src/web-server/routes/cliproxy-stats-routes.ts (1216 -> barrel 23 + 8
  submodules, max 290 LOC): shared, quota-helpers, version-helpers,
  restart-route, quota-routes, error-log-routes, config-routes, router.
- src/commands/persist-command.ts (1071 -> barrel + 8 submodules, max 258):
  types, arg-parsing, secure-file, backup-rotation, secret-detection,
  receipt, help, handler.
- src/commands/cliproxy/quota-subcommand.ts (1130 -> barrel + 14 submodules,
  max 303): types, format-helpers, codex/claude-window-helpers, provider-runtime,
  handlers, per-provider sections.

Public API preserved verbatim (default + named exports). All P3 structured
logging and P4 typed errors preserved through the splits. Each resulting file
< 400 LOC. Existing tests (shared-manager x4, cliproxy-stats x4, persist x2,
quota-subcommand x1) green, unchanged.

Metric: files > 400 LOC 95 -> 91. validate + validate:ci-parity green.
2026-06-18 18:48:13 -04:00
Tam Nhu Tran 7234ef8fcf feat(errors): P4 typed-error taxonomy adoption (0->91% locked) + erasable-syntax fix
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).
2026-06-18 18:48:12 -04:00
Tam Nhu Tran 87aeb8f193 feat(logging): P3 hotpath console.error migration + redaction gate (928->267)
Epic P3. Migrates hotpath console.error/warn to the structured logger
(diagnostics) or process.stderr.write (user-facing), and adds a redaction
safety gate so the migration cannot leak credentials.

Redaction gate (MR1):
- log-redaction: scrub known credential token shapes (sk-ant, sk-, xoxb,
  ghp, glpat, AIza, JWT bodies, api_key=, Bearer/Basic/Token scheme) in
  string values, Error.message, AND the log message string (defense-in-depth).
- logger: message now passes through maskSecretTokens.

tool-sanitization-proxy: deleted the private file-logging subsystem
(initLogFile/writeLog/log/warn, logFilePath, debugMode); 13 call sites now
route through the existing createLogger('cliproxy:tool-sanitization-proxy').

Sweep (~120 diagnostic -> structured createLogger; ~540 user-facing -> stderr):
- diagnostics converted across proxy, web-server/routes, glmt pipeline, quota
  fetchers, executors, delegation, session-bridge, https-tunnel-proxy.
- user-facing CLI output (flows, arg-parser usage, installers, prompts, adapter
  launch errors, error display) moved to process.stderr.write (preserves stderr).
- src/utils/error-manager.ts reclassified CLI-UX-exempt (user-facing display).

Metric: hotpath console.error 928 -> 267 (71%); createLogger files 35 -> 64.
Residual 267 is user-facing CLI output (not diagnostics); documented in
docs/hardening-debt-burndown.md. Redaction gate makes further conversion safe.

Tests: hotpath-redaction-regression (12 token shapes); updated delegation-handler,
arg-parser, model-warnings spies (console.error -> process.stderr.write).
validate + validate:ci-parity green.
2026-06-18 18:48:12 -04:00
Tam Nhu Tran 5e1b8640ab feat(logging): P2 traceability foundation - requestId wrap, daemon forwarding (#NNN)
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.
2026-06-18 18:48:12 -04:00
Tam Nhu Tran 95a2864ef3 feat(hardening): P1 maintainability metrics baseline + freshness gate (#1561)
Epic P1. Adds maintainability-metrics script (typed-error adoption, createLogger coverage, hotpath console.error, files>400 LOC), merges maintainability block into hardening-inventory report, adds 30-day freshness gate to ci-parity-gate.sh, re-baselines burndown 2026-06-18. Local validate + validate:ci-parity green.
2026-06-18 18:48:12 -04:00
github-actions[bot] 27f4e89ad1 chore(release): 8.4.0-dev.10 2026-06-16 14:27:50 +00:00
Kai (Tam Nhu) Tran 49a7b9dc85 fix(cliproxy): use root URL for Claude provider (#1554)
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.
2026-06-16 10:23:48 -04:00
github-actions[bot] 81e9bdea5d chore(release): 8.4.0-dev.9 2026-06-16 13:34:13 +00:00
Kai (Tam Nhu) Tran 3fa4a342f9 test(bar): harden bar-probe auth coverage; drop dead proxy shim (#1555)
* 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.
2026-06-16 09:30:01 -04:00
github-actions[bot] a649c9568a chore(release): 8.4.0-dev.8 2026-06-16 13:12:21 +00:00
Kai (Tam Nhu) Tran f25a1015ed fix(bar): authenticate reused local server probes (#1546)
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.
2026-06-16 09:08:21 -04:00
github-actions[bot] 2c812efafa chore(release): 8.4.0-dev.7 2026-06-16 12:49:43 +00:00
Kai (Tam Nhu) Tran 84ff4d57a4 fix(bar): tolerate duplicate rows in alert pruning (#1553)
Bar alert pruning tolerates duplicate rows without crashing.
2026-06-16 08:45:47 -04:00
Kai (Tam Nhu) Tran c0409862d2 fix: handle auth-protected bar launch probes (#1551)
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.
2026-06-16 08:45:41 -04:00
Kai (Tam Nhu) Tran 361328c788 fix: enforce tier lock during quota preflight (#1550)
Tier lock now fails closed in quota preflight when no healthy locked-tier account is available, instead of falling through cross-tier.
2026-06-16 08:45:35 -04:00
Kai (Tam Nhu) Tran 06e83091be fix: bound Codex rollout tail reads (#1547)
Replaces unbounded rollout-file reads with a bounded backward tail (1 MiB cap), preserving last-N-lines semantics.
2026-06-16 08:45:30 -04:00
github-actions[bot] c83d004783 chore(release): 8.4.0-dev.6 2026-06-16 12:32:50 +00:00
Kai (Tam Nhu) Tran ba7a2abb79 fix(bar): distinguish native Codex subscription rows (#1552)
Distinguishes native Codex subscription rows from pool rows in the bar menu.
2026-06-16 08:28:36 -04:00
Kai (Tam Nhu) Tran 50f136a1f0 fix(macos-bar): launch dashboard without shell (#1549)
Launches the dashboard without going through a shell, avoiding unescaped-command exposure.
2026-06-16 08:28:31 -04:00
Kai (Tam Nhu) Tran 8bd289bfae fix(bar): avoid blocking on lower-priority probes (#1548)
Bar server probing no longer blocks on lower-priority probes.
2026-06-16 08:28:15 -04:00
github-actions[bot] 639334b40b chore(release): 8.4.0-dev.5 2026-06-16 03:32:52 +00:00
Kai (Tam Nhu) Tran c776e18434 fix(bar): preserve Gatekeeper quarantine on install (#1534)
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.
2026-06-15 23:28:24 -04:00
Kai (Tam Nhu) Tran e3566ed765 fix: avoid echoing invalid channel token values (#1542)
Avoids echoing invalid channel token values in config output.
2026-06-15 23:24:42 -04:00
Kai (Tam Nhu) Tran b85a3de26e fix(cursor): redact daemon token from dashboard start (#1540)
Redacts the Cursor daemon token from dashboard start output.
2026-06-15 23:24:37 -04:00
Kai (Tam Nhu) Tran 74dd2f38cc fix: harden release issue parsing (#1536)
Hardens release issue parsing against a quadratic/ReDoS pattern while preserving parsing semantics.
2026-06-15 23:24:33 -04:00
Kai (Tam Nhu) Tran 10aff10a67 fix: harden macOS bar launch descriptor (#1533)
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.
2026-06-15 23:24:13 -04:00
github-actions[bot] 619723e9b7 chore(release): 8.4.0-dev.4 2026-06-16 03:21:39 +00:00
Kai (Tam Nhu) Tran ab6c59ba35 fix(browser): preserve profile-bound DevTools discovery (#1541)
Preserves the profile-bound DevTools port/discovery so browser launches resolve the correct per-profile endpoint.
2026-06-15 23:14:55 -04:00
Kai (Tam Nhu) Tran 473aa082f6 fix: honor default target for Claude passthrough (#1539)
Honors the configured default target in the Claude subcommand passthrough resolver.
2026-06-15 23:12:52 -04:00
Kai (Tam Nhu) Tran d2848d3931 fix(bar): verify CCS Bar release archive digest (#1532)
Verifies the GitHub release asset sha256 digest before extracting the CCS Bar archive.
2026-06-15 23:12:49 -04:00
Kai (Tam Nhu) Tran db44845857 fix(codex): sanitize config override probes (#1535)
Sanitizes ccsxp support-probe config overrides to avoid env leak; parity with the real Codex launch path.
2026-06-15 23:12:46 -04:00
github-actions[bot] c351261fe4 chore(release): 8.4.0-dev.3 2026-06-16 02:54:04 +00:00
Kai (Tam Nhu) Tran f74561fe9b fix: avoid quadratic cliproxy usage hydration (#1537)
Replaces O(n^2) usage hydration in the cliproxy merge path with a linear lookup.
2026-06-15 22:48:11 -04:00
github-actions[bot] 21e2dc1c24 chore(release): 8.4.0-dev.2 2026-06-16 02:20:52 +00:00
Kai (Tam Nhu) Tran 499aec8a9b feat(config): add opt-in output limits for spawned CLI (#1544)
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.
2026-06-15 22:16:54 -04:00
Kai (Tam Nhu) Tran a472c44015 feat(api): add Fireworks AI provider preset (#1543)
Promotes Fireworks AI to a first-class discoverable preset over the existing Anthropic-compatible Bearer path. Closes #890.
2026-06-15 22:16:50 -04:00
github-actions[bot] 5320b4f418 chore(release): 8.4.0-dev.1 2026-06-16 02:01:20 +00:00
kcfang 8f9795bce2 fix(proxy): keep undici timeouts above the upstream request timeout (#1524)
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.
2026-06-15 21:57:23 -04:00
semantic-release-bot 0d856fc0ab chore(release): 8.4.0 [skip ci]
## [8.4.0](https://github.com/kaitranntt/ccs/compare/v8.3.0...v8.4.0) (2026-06-16)

### Features

* **bar:** bundle a macOS app icon ([30ed7c4](https://github.com/kaitranntt/ccs/commit/30ed7c42b1c8a24fc10d1c788a532e1a3198a410)), closes [#1525](https://github.com/kaitranntt/ccs/issues/1525)
* **bar:** run the CCS server detached with serve/stop/status ([b5ef06a](https://github.com/kaitranntt/ccs/commit/b5ef06a4d5fe0ea2a83110947a2772b8ea87ee3f)), closes [#1526](https://github.com/kaitranntt/ccs/issues/1526)
* **bar:** self-start the server from the app and stop dropdown clipping ([64fbf2e](https://github.com/kaitranntt/ccs/commit/64fbf2e0621aca4398693de5b5ef43b9448bfecc)), closes [#1526](https://github.com/kaitranntt/ccs/issues/1526) [#1527](https://github.com/kaitranntt/ccs/issues/1527)

### Bug Fixes

* **bar:** anchor menu panel to top and stop full-screen sizing ([#1530](https://github.com/kaitranntt/ccs/issues/1530)) ([842857d](https://github.com/kaitranntt/ccs/commit/842857dec6035625b14ec81c77045b4562004575))
* **cliproxy:** resolve plus release asset variants ([#1523](https://github.com/kaitranntt/ccs/issues/1523)) ([9e9cddd](https://github.com/kaitranntt/ccs/commit/9e9cddd101dc7ae91d9e8051e6f172747a0fc1b4)), closes [#1522](https://github.com/kaitranntt/ccs/issues/1522)

### Documentation

* **bar:** document detached launch model and serve/stop/status ([#1529](https://github.com/kaitranntt/ccs/issues/1529)) ([b03e2e1](https://github.com/kaitranntt/ccs/commit/b03e2e1cb2dbc30e4a9f923ffd4bbb5bd817732c))
2026-06-16 00:12:20 +00:00
Kai (Tam Nhu) Tran d12eb3f825 Merge pull request #1531 from kaitranntt/dev
feat(bar): CCS Bar seamless launch, app icon, and panel fixes
2026-06-15 20:08:35 -04:00
github-actions[bot] dd9b469093 chore(release): 8.3.0-dev.3 2026-06-16 00:02:23 +00:00
Kai (Tam Nhu) Tran b03e2e1cb2 docs(bar): document detached launch model and serve/stop/status (#1529)
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.
2026-06-15 19:58:03 -04:00
Kai (Tam Nhu) Tran 842857dec6 fix(bar): anchor menu panel to top and stop full-screen sizing (#1530)
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.
2026-06-15 19:58:00 -04:00
github-actions[bot] 9f8517bb29 chore(release): 8.3.0-dev.2 2026-06-15 23:10:10 +00:00