Clarify inert plugin telemetry helpers

This commit is contained in:
2026-04-04 03:21:59 +08:00
parent 3e5461df9b
commit eb96764770

View File

@@ -1,14 +1,10 @@
/** /**
* Plugin telemetry helpers shared field builders for plugin lifecycle events. * Legacy plugin metadata helpers shared by call sites that still assemble
* analytics-compatible payload shapes.
* *
* Implements the twin-column privacy pattern: every user-defined-name field * In this fork the downstream analytics sinks are disabled, so these helpers
* emits both a raw value (routed to PII-tagged _PROTO_* BQ columns) and a * only normalize/redact fields for local compatibility code; they do not
* redacted twin (real name iff marketplace ∈ allowlist, else 'third-party'). * imply an active telemetry export path.
*
* plugin_id_hash provides an opaque per-plugin aggregation key with no privacy
* dependency — sha256(name@marketplace + FIXED_SALT) truncated to 16 chars.
* This answers distinct-count and per-plugin-trend questions that the
* redacted column can't, without exposing user-defined names.
*/ */
import { createHash } from 'crypto' import { createHash } from 'crypto'
@@ -25,18 +21,14 @@ import {
// through commands.js. Marketplace schemas.ts enforces 'builtin' is reserved. // through commands.js. Marketplace schemas.ts enforces 'builtin' is reserved.
const BUILTIN_MARKETPLACE_NAME = 'builtin' const BUILTIN_MARKETPLACE_NAME = 'builtin'
// Fixed salt for plugin_id_hash. Same constant across all repos and emission // Fixed salt for plugin_id_hash. Kept stable so legacy field shapes that still
// sites. Not per-org, not rotated — per-org salt would defeat cross-org // use this helper continue to derive the same opaque key.
// distinct-count, rotation would break trend lines. Customers can compute the
// same hash on their known plugin names to reverse-match their own telemetry.
const PLUGIN_ID_HASH_SALT = 'claude-plugin-telemetry-v1' const PLUGIN_ID_HASH_SALT = 'claude-plugin-telemetry-v1'
/** /**
* Opaque per-plugin aggregation key. Input is the name@marketplace string as * Opaque per-plugin compatibility key derived from the name@marketplace
* it appears in enabledPlugins keys, lowercased on the marketplace suffix for * string. The 16-char truncation keeps the identifier short while preserving
* reproducibility. 16-char truncation keeps BQ GROUP BY cardinality manageable * a stable grouping key for local compatibility code.
* while making collisions negligible at projected 10k-plugin scale. Name case
* is preserved in both branches (enabledPlugins keys are case-sensitive).
*/ */
export function hashPluginId(name: string, marketplace?: string): string { export function hashPluginId(name: string, marketplace?: string): string {
const key = marketplace ? `${name}@${marketplace.toLowerCase()}` : name const key = marketplace ? `${name}@${marketplace.toLowerCase()}` : name
@@ -90,9 +82,9 @@ export type InstallSource =
| 'deep-link' | 'deep-link'
/** /**
* Common plugin telemetry fields keyed off name@marketplace. Returns the * Common plugin metadata fields keyed off name@marketplace. Keeps the legacy
* hash, scope enum, and the redacted-twin columns. Callers add the raw * field set in one place so no-op analytics compatibility callers do not have
* _PROTO_* fields separately (those require the PII-tagged marker type). * to duplicate redaction logic.
*/ */
export function buildPluginTelemetryFields( export function buildPluginTelemetryFields(
name: string, name: string,
@@ -144,9 +136,7 @@ export function buildPluginCommandTelemetryFields(
} }
/** /**
* Bounded-cardinality error bucket for CLI plugin operation failures. * Stable error buckets for CLI plugin operation failures.
* Maps free-form error messages to 5 stable categories so dashboard
* GROUP BY stays tractable.
*/ */
export type PluginCommandErrorCategory = export type PluginCommandErrorCategory =
| 'network' | 'network'