MCP schema (6): Add : () => AnyObjectSchema type annotations to
ChannelMessageNotificationSchema, ChannelPermissionNotificationSchema,
AtMentionedSchema, LogEventNotificationSchema. Remove as any at
call sites in print.ts, useManageMCPConnections.ts, useIdeAtMentioned.ts,
vscodeSdkMcp.ts.
Core API (5): Replace as any with specific type assertions in
claude.ts (supportedModels/CachedMCEditsBlock/pinCacheEdits),
filesApi.ts (error property), client.ts (vertexArgs cast).
client.ts:297 retains as any — google-auth-library version conflict
(10.x vs 9.x) with #private nominal typing makes this unavoidable.
Docs: add community-code-issues.md cataloging all 20 community tsc
errors and 49 community as any casts.
Group A (4 as any): Add : () => AnyObjectSchema type annotations to
MCP notification schema constants, removing as any at call sites.
Group B (2 as any): Add isStructuredOutputAttachmentMessage type
guard for structured output attachment payloads.
Group C (3 as any): Add isMessageDeltaStreamEvent type guard for
message_delta stream event usage extraction.
tsc: 20 errors (no regression). Build: passes.
- Add local type assertions (AgentProgressMessage, AgentToolProgressData)
- No as any used — all specific type narrowing
- AgentTool tests: 40 pass, 0 fail
- 25 stub files: types/tools, types/utils, contextCollapse, mcpSkills, etc.
- 11 reused from chore/bridge-green, 14 created from scratch
- All stubs documented in docs/devlog/02-tsc-stubs.md
- Build passes, tests not regressed
searchSkills() called .trim() on query without null-guard. When
DiscoverSkills is invoked through ExecuteExtraTool with missing
description, query is undefined, causing 'Cannot read properties of
undefined (reading trim)'.
Fixed with optional chaining: !query.trim() → !query?.trim()
Co-Authored-By: deepseek-v4-pro <deepseek-ai@claude-code-best.win>
🔒 Security Discovery: Un-gated outbound connection bypasses privacy controls
Summary
-------
preconnectAnthropicApi() unconditionally sends a TCP+TLS handshake to
api.anthropic.com on every ccb startup — even when the user has explicitly
disabled all non-essential traffic via CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
or DISABLE_TELEMETRY=1.
This is the LAST un-gated outbound connection in the entire startup path.
Every other telemetry sink (Sentry, Langfuse, OpenTelemetry, GrowthBook,
1P Event Logger, Datadog, BigQuery, etc.) already respects the
privacyLevel module's isEssentialTrafficOnly() gate. This one did not.
Impact
------
While the preconnect is a HEAD request with no payload, the connection
itself leaks the client's IP address and session timing to Anthropic's
infrastructure. For privacy-conscious users and enterprise deployments
that have disabled telemetry, this constitutes an unexpected data leak.
Fix
---
Add isEssentialTrafficOnly() check at the function entry, consistent
with every other privacy-gated code path in the codebase. The
privacyLevel module is already imported by init.ts and 12+ other
modules — no new dependencies.
Verification
------------
Reproduced and verified via strace on Linux (aarch64):
# Before fix
$ strace -f -e connect ccb -p <<< 'hello'
connect(16, sin_addr=inet_addr("160.79.104.10"), sin_port=htons(443)) = 0
# ↑ connector to api.anthropic.com despite CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
# After fix
$ strace -f -e connect ccb -p <<< 'hello'
# ↑ zero remote TCP connections — all traffic to localhost only
Changes: 1 file, +5 lines (import + gate)
Previously only vendor/audio-capture was copied. Ripgrep was left to a
postinstall download script, but no-split builds have no postinstall step.
Now both builds get the ripgrep binary directly.
The no-split build omitted vendor/ripgrep/ and vendor/audio-capture/,
causing Glob/Grep/Bash tools to fail with ENOENT when CCP runs from
dist-nosplit/. The split build (dist/) already did this copy in step 4;
now the no-split build (dist-nosplit/) does it too.