@decantr/telemetry 0.2.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@ This package is the first layer of Decantr's usage intelligence system. It defin
8
8
 
9
9
  Decantr telemetry measures Decantr usage, not customer application data.
10
10
 
11
- Allowed signals include command names, registry sources, registry content IDs, package versions, workflow modes, success/failure, duration, audit scores, aggregate counts, marketing route labels, campaign tags, and referrer domains. Do not send prompts, source code, generated files, raw file paths, environment variables, secrets, API keys, email addresses, IP addresses, raw referrer URLs, click IDs, or user agents.
11
+ Allowed signals include command names, registry sources, registry content IDs, package versions, workflow modes, success/failure, duration, audit scores, Project Health status/score/counts, aggregate counts, marketing route labels, campaign tags, and referrer domains. Do not send prompts, source code, generated files, health reports, finding evidence, raw file paths, environment variables, secrets, API keys, email addresses, IP addresses, raw referrer URLs, click IDs, or user agents.
12
12
 
13
13
  ## MVP Events
14
14
 
@@ -19,6 +19,16 @@ Allowed signals include command names, registry sources, registry content IDs, p
19
19
  - `execution_pack.selected`
20
20
  - `audit.completed`
21
21
  - `critique.completed`
22
+ - `decantr.init.completed`
23
+ - `decantr.new.completed`
24
+ - `decantr.refresh.completed`
25
+ - `decantr.check.completed`
26
+ - `decantr.health.healthy`
27
+ - `health.report.generated`
28
+ - `health.finding.prompt_requested`
29
+ - `health.ci.failed`
30
+ - `studio.started`
31
+ - `studio.health_refreshed`
22
32
  - `content.validation.completed`
23
33
  - `content.publish.completed`
24
34
  - `user.signup.completed`
package/dist/client.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/events.ts
2
- var DECANTR_TELEMETRY_SCHEMA_VERSION = "0.1.0";
2
+ var DECANTR_TELEMETRY_SCHEMA_VERSION = "0.2.0";
3
3
 
4
4
  // src/privacy.ts
5
5
  var REDACTED_VALUE = "[redacted]";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/events.ts","../src/privacy.ts","../src/client.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.1.0';\n\nexport type TelemetrySource =\n | 'api'\n | 'cli'\n | 'content-ci'\n | 'marketing-web'\n | 'mcp'\n | 'registry-web';\nexport type TelemetryEnvironment = 'development' | 'preview' | 'production' | 'test';\nexport const DECANTR_TELEMETRY_ACTOR_TYPES = [\n 'anonymous',\n 'customer',\n 'internal',\n 'official_pipeline',\n 'service',\n] as const;\nexport type TelemetryActorType = (typeof DECANTR_TELEMETRY_ACTOR_TYPES)[number];\nexport type RegistrySource = 'cache' | 'custom' | 'none' | 'official' | 'private';\nexport type WorkflowMode =\n | 'brownfield-attach'\n | 'greenfield-contract-only'\n | 'greenfield-scaffold'\n | 'hybrid-compose';\nexport type AdoptionMode = 'contract-only' | 'decantr-css' | 'style-bridge';\nexport type ProjectScope = 'single-app' | 'workspace-app';\nexport type TelemetryContentType = 'archetype' | 'blueprint' | 'pattern' | 'shell' | 'theme';\nexport type TelemetryVisibility = 'private' | 'public' | 'team';\nexport type TelemetryAnalysisScope = 'hosted' | 'local';\n\nexport const DECANTR_TELEMETRY_EVENT_NAMES = [\n 'api_key.created',\n 'audit.completed',\n 'cli.command.completed',\n 'content.publish.completed',\n 'content.validation.completed',\n 'critique.completed',\n 'execution_pack.compiled',\n 'execution_pack.selected',\n 'marketing_web.command_clicked',\n 'marketing_web.cta_clicked',\n 'marketing_web.outbound_clicked',\n 'marketing_web.page_viewed',\n 'org.created',\n 'registry_web.api_key_page_viewed',\n 'registry_web.billing_viewed',\n 'registry_web.content_opened',\n 'registry_web.identity_linked',\n 'registry_web.organization_viewed',\n 'registry_web.page_viewed',\n 'registry_web.search_performed',\n 'registry_web.signup_clicked',\n 'registry.item.resolved',\n 'registry.sync.completed',\n 'user.signup.completed',\n] as const;\n\nexport type DecantrTelemetryEventName = (typeof DECANTR_TELEMETRY_EVENT_NAMES)[number];\n\nexport type TelemetryPropertyValue =\n | TelemetryPropertyValue[]\n | boolean\n | null\n | number\n | string\n | undefined\n | { [key: string]: TelemetryPropertyValue };\n\nexport type TelemetryProperties = Record<string, TelemetryPropertyValue>;\n\nexport interface TelemetryContext {\n source: TelemetrySource;\n actorType?: TelemetryActorType;\n environment?: TelemetryEnvironment;\n serviceName?: string;\n serviceVersion?: string;\n decantrVersion?: string;\n registrySource?: RegistrySource;\n anonymousId?: string;\n installId?: string;\n projectId?: string;\n sessionId?: string;\n userId?: string;\n orgId?: string;\n}\n\nexport interface TelemetryActorResolutionOptions {\n internalAnonymousIds?: readonly string[] | ReadonlySet<string>;\n internalInstallIds?: readonly string[] | ReadonlySet<string>;\n internalOrgIds?: readonly string[] | ReadonlySet<string>;\n internalProjectIds?: readonly string[] | ReadonlySet<string>;\n internalUserIds?: readonly string[] | ReadonlySet<string>;\n}\n\nexport function isTelemetryActorType(value: unknown): value is TelemetryActorType {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACTOR_TYPES as readonly string[]).includes(value)\n );\n}\n\nexport function resolveTelemetryActorType(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions = {},\n): TelemetryActorType {\n if (context.actorType) return context.actorType;\n\n if (context.source === 'content-ci') {\n return 'official_pipeline';\n }\n\n if (matchesInternalActor(context, options)) {\n return 'internal';\n }\n\n if (context.userId || context.orgId || context.projectId || context.installId) {\n return 'customer';\n }\n\n if (context.anonymousId) {\n return 'anonymous';\n }\n\n return 'service';\n}\n\nfunction matchesInternalActor(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions,\n): boolean {\n return (\n idListHas(options.internalAnonymousIds, context.anonymousId) ||\n idListHas(options.internalInstallIds, context.installId) ||\n idListHas(options.internalOrgIds, context.orgId) ||\n idListHas(options.internalProjectIds, context.projectId) ||\n idListHas(options.internalUserIds, context.userId)\n );\n}\n\nfunction idListHas(\n values: readonly string[] | ReadonlySet<string> | undefined,\n value: string | undefined,\n): boolean {\n if (!values || !value) return false;\n if (typeof (values as ReadonlySet<string>).has === 'function') {\n return (values as ReadonlySet<string>).has(value);\n }\n return (values as readonly string[]).includes(value);\n}\n\nexport interface TelemetryEventBase<\n Name extends DecantrTelemetryEventName = DecantrTelemetryEventName,\n Properties extends TelemetryProperties = TelemetryProperties,\n> {\n name: Name;\n context: TelemetryContext;\n properties: Properties;\n timestamp?: Date | string;\n}\n\nexport interface CliCommandCompletedProperties extends TelemetryProperties {\n command: string;\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface RegistryItemResolvedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n cacheHit?: boolean;\n durationMs?: number;\n errorCode?: string;\n itemId?: string;\n namespace?: string;\n registrySource?: RegistrySource;\n version?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface RegistrySyncCompletedProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n registrySource?: RegistrySource;\n totalItems?: number;\n}\n\nexport interface ExecutionPackCompiledProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n pageCount?: number;\n patternCount?: number;\n sectionCount?: number;\n targetFramework?: string;\n}\n\nexport interface ExecutionPackSelectedProperties extends TelemetryProperties {\n packType: 'mutation' | 'page' | 'review' | 'scaffold' | 'section';\n success: boolean;\n durationMs?: number;\n errorCode?: string;\n id?: string;\n}\n\nexport interface AuditCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n pageCount?: number;\n runtimePassed?: boolean;\n score?: number;\n warnCount?: number;\n}\n\nexport interface CritiqueCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n infoCount?: number;\n overall?: number;\n warnCount?: number;\n}\n\nexport interface ContentValidationCompletedProperties extends TelemetryProperties {\n valid: boolean;\n contentType?: TelemetryContentType;\n durationMs?: number;\n errorCount?: number;\n itemCount?: number;\n warningCount?: number;\n}\n\nexport interface ContentPublishCompletedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n namespace?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface ProductEventProperties extends TelemetryProperties {\n success?: boolean;\n channel?: string;\n entrypoint?: string;\n plan?: string;\n}\n\nexport interface CampaignAttributionProperties extends TelemetryProperties {\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstLandingPath?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstUtmCampaign?: string | null;\n attributionFirstUtmContent?: string | null;\n attributionFirstUtmId?: string | null;\n attributionFirstUtmMedium?: string | null;\n attributionFirstUtmSource?: string | null;\n attributionFirstUtmTerm?: string | null;\n attributionLandingPath?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastUtmCampaign?: string | null;\n attributionLastUtmContent?: string | null;\n attributionLastUtmId?: string | null;\n attributionLastUtmMedium?: string | null;\n attributionLastUtmSource?: string | null;\n attributionLastUtmTerm?: string | null;\n attributionReferrerDomain?: string | null;\n attributionUtmCampaign?: string | null;\n attributionUtmContent?: string | null;\n attributionUtmId?: string | null;\n attributionUtmMedium?: string | null;\n attributionUtmSource?: string | null;\n attributionUtmTerm?: string | null;\n}\n\nexport interface MarketingWebPageViewedProperties extends CampaignAttributionProperties {\n routePath: string;\n surface: string;\n}\n\nexport interface MarketingWebCtaClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebOutboundClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebCommandClickedProperties extends CampaignAttributionProperties {\n commandKind: 'cli' | 'mcp' | 'other';\n commandLabel?: string | null;\n surface: string;\n}\n\nexport interface RegistryWebPageViewedProperties extends CampaignAttributionProperties {\n authenticated: boolean;\n orgScoped?: boolean;\n plan?: string;\n queryPresent?: boolean;\n route: string;\n routePath: string;\n surface: string;\n}\n\nexport interface RegistryWebSearchPerformedProperties extends CampaignAttributionProperties {\n contentType?: string;\n queryLength: number;\n resultCount?: number;\n sort?: string;\n sourceFilter?: string;\n surface: string;\n}\n\nexport interface RegistryWebContentOpenedProperties extends CampaignAttributionProperties {\n contentSource?: string;\n contentType: string;\n namespace?: string;\n slug?: string;\n surface: string;\n}\n\nexport interface RegistryWebCommercialPageViewedProperties extends CampaignAttributionProperties {\n orgScoped?: boolean;\n plan?: string;\n surface: string;\n}\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties>\n | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties>\n | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties>\n | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties>\n | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties>\n | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties>\n | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties>\n | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties>\n | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties>\n | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties>\n | TelemetryEventBase<'org.created', ProductEventProperties>\n | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties>\n | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties>\n | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties>\n | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties>\n | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n","import type { DecantrTelemetryEvent, TelemetryPropertyValue } from './events.js';\n\nexport const REDACTED_VALUE = '[redacted]';\n\nconst DEFAULT_MAX_STRING_LENGTH = 240;\nconst DEFAULT_MAX_ARRAY_LENGTH = 25;\nconst DEFAULT_MAX_OBJECT_KEYS = 80;\nconst DEFAULT_MAX_DEPTH = 4;\n\nconst SENSITIVE_KEY_PATTERNS = [\n /^api[_-]?key$/i,\n /^authorization$/i,\n /^code$/i,\n /^content$/i,\n /^contents$/i,\n /^cookie$/i,\n /^cwd$/i,\n /^email$/i,\n /^env$/i,\n /^file[_-]?contents$/i,\n /^file[_-]?path$/i,\n /^home$/i,\n /^ip[_-]?address$/i,\n /^password$/i,\n /^path$/i,\n /^prompt$/i,\n /^raw[_-]?prompt$/i,\n /^secret$/i,\n /^source$/i,\n /^source[_-]?code$/i,\n /^token$/i,\n /^url$/i,\n /^user[_-]?agent$/i,\n];\n\nexport interface TelemetryRedactionOptions {\n maxArrayLength?: number;\n maxDepth?: number;\n maxObjectKeys?: number;\n maxStringLength?: number;\n redactedValue?: string;\n sensitiveKeyPatterns?: RegExp[];\n}\n\nexport function isSensitiveTelemetryKey(key: string, patterns = SENSITIVE_KEY_PATTERNS): boolean {\n return patterns.some((pattern) => pattern.test(key));\n}\n\nexport function sanitizeTelemetryValue(\n value: TelemetryPropertyValue,\n options: TelemetryRedactionOptions = {},\n depth = 0,\n): TelemetryPropertyValue {\n const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;\n if (depth > maxDepth) {\n return options.redactedValue ?? REDACTED_VALUE;\n }\n\n if (typeof value === 'string') {\n const maxStringLength = options.maxStringLength ?? DEFAULT_MAX_STRING_LENGTH;\n return value.length > maxStringLength ? `${value.slice(0, maxStringLength)}...` : value;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean' || value === null) {\n return value;\n }\n\n if (value === undefined) {\n return null;\n }\n\n if (Array.isArray(value)) {\n const maxArrayLength = options.maxArrayLength ?? DEFAULT_MAX_ARRAY_LENGTH;\n return value\n .slice(0, maxArrayLength)\n .map((entry) => sanitizeTelemetryValue(entry, options, depth + 1));\n }\n\n const redactedValue = options.redactedValue ?? REDACTED_VALUE;\n const sensitiveKeyPatterns = options.sensitiveKeyPatterns ?? SENSITIVE_KEY_PATTERNS;\n const maxObjectKeys = options.maxObjectKeys ?? DEFAULT_MAX_OBJECT_KEYS;\n const entries = Object.entries(value).slice(0, maxObjectKeys);\n const sanitized: Record<string, TelemetryPropertyValue> = {};\n\n for (const [key, entryValue] of entries) {\n sanitized[key] = isSensitiveTelemetryKey(key, sensitiveKeyPatterns)\n ? redactedValue\n : sanitizeTelemetryValue(entryValue, options, depth + 1);\n }\n\n return sanitized;\n}\n\nexport function sanitizeTelemetryEvent(\n event: DecantrTelemetryEvent,\n options: TelemetryRedactionOptions = {},\n): DecantrTelemetryEvent {\n return {\n ...event,\n properties: sanitizeTelemetryValue(\n event.properties,\n options,\n ) as DecantrTelemetryEvent['properties'],\n } as DecantrTelemetryEvent;\n}\n","import {\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n type DecantrTelemetryEvent,\n type TelemetryContext,\n} from './events.js';\nimport { sanitizeTelemetryEvent, type TelemetryRedactionOptions } from './privacy.js';\n\nexport interface TelemetrySink {\n capture(event: DecantrTelemetryEvent): Promise<void> | void;\n flush?(): Promise<void> | void;\n}\n\nexport interface TelemetryClient {\n capture(event: DecantrTelemetryEvent): Promise<void>;\n flush(): Promise<void>;\n}\n\nexport interface TelemetryClientOptions {\n context?: Partial<TelemetryContext>;\n enabled?: boolean;\n onError?: (error: unknown, event: DecantrTelemetryEvent) => void;\n redaction?: TelemetryRedactionOptions;\n sink?: TelemetrySink;\n}\n\nexport interface FetchTelemetrySinkOptions {\n endpoint: string;\n fetch?: typeof fetch;\n headers?: HeadersInit | (() => HeadersInit);\n timeoutMs?: number;\n}\n\nexport function createNoopTelemetrySink(): TelemetrySink {\n return {\n capture() {\n return undefined;\n },\n };\n}\n\nexport function createTelemetryClient(options: TelemetryClientOptions = {}): TelemetryClient {\n const enabled = options.enabled ?? true;\n const sink = options.sink ?? createNoopTelemetrySink();\n const pending = new Set<Promise<void>>();\n\n async function capture(event: DecantrTelemetryEvent): Promise<void> {\n if (!enabled) return;\n\n const enriched = sanitizeTelemetryEvent(\n {\n ...event,\n context: {\n ...options.context,\n ...event.context,\n },\n timestamp: normalizeTimestamp(event.timestamp),\n } as DecantrTelemetryEvent,\n options.redaction,\n );\n\n const promise = Promise.resolve()\n .then(() => sink.capture(enriched))\n .catch((error) => {\n options.onError?.(error, enriched);\n })\n .then(() => undefined);\n\n pending.add(promise);\n promise.finally(() => pending.delete(promise));\n await promise;\n }\n\n async function flush(): Promise<void> {\n await Promise.allSettled([...pending]);\n await sink.flush?.();\n }\n\n return { capture, flush };\n}\n\nexport function createFetchTelemetrySink(options: FetchTelemetrySinkOptions): TelemetrySink {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async capture(event) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 3000);\n\n try {\n const response = await fetchImpl(options.endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...normalizeHeaders(\n typeof options.headers === 'function' ? options.headers() : options.headers,\n ),\n },\n body: JSON.stringify({\n schemaVersion: DECANTR_TELEMETRY_SCHEMA_VERSION,\n event,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`Telemetry endpoint returned HTTP ${response.status}.`);\n }\n } finally {\n clearTimeout(timeout);\n }\n },\n };\n}\n\nfunction normalizeTimestamp(timestamp: Date | string | undefined): string {\n if (timestamp instanceof Date) {\n return timestamp.toISOString();\n }\n return timestamp ?? new Date().toISOString();\n}\n\nfunction normalizeHeaders(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n\n if (headers instanceof Headers) {\n return Object.fromEntries(headers.entries());\n }\n\n if (Array.isArray(headers)) {\n return Object.fromEntries(headers);\n }\n\n return headers as Record<string, string>;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/events.ts","../src/privacy.ts","../src/client.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.2.0';\n\nexport type TelemetrySource =\n | 'api'\n | 'cli'\n | 'content-ci'\n | 'marketing-web'\n | 'mcp'\n | 'registry-web';\nexport type TelemetryEnvironment = 'development' | 'preview' | 'production' | 'test';\nexport const DECANTR_TELEMETRY_ACTOR_TYPES = [\n 'anonymous',\n 'customer',\n 'internal',\n 'official_pipeline',\n 'service',\n] as const;\nexport type TelemetryActorType = (typeof DECANTR_TELEMETRY_ACTOR_TYPES)[number];\nexport type RegistrySource = 'cache' | 'custom' | 'none' | 'official' | 'private';\nexport type WorkflowMode =\n | 'brownfield-attach'\n | 'greenfield-contract-only'\n | 'greenfield-scaffold'\n | 'hybrid-compose';\nexport type AdoptionMode = 'contract-only' | 'decantr-css' | 'style-bridge';\nexport type ProjectScope = 'single-app' | 'workspace-app';\nexport type TelemetryContentType = 'archetype' | 'blueprint' | 'pattern' | 'shell' | 'theme';\nexport type TelemetryVisibility = 'private' | 'public' | 'team';\nexport type TelemetryAnalysisScope = 'hosted' | 'local';\nexport type ProjectHealthTelemetryStatus = 'error' | 'healthy' | 'warning';\nexport type ProjectHealthFindingSeverity = 'error' | 'info' | 'warn';\nexport type ProjectHealthFindingSource =\n | 'audit'\n | 'brownfield'\n | 'check'\n | 'interaction'\n | 'pack'\n | 'runtime';\nexport type ProjectHealthOutputFormat = 'json' | 'markdown' | 'text';\nexport type ProjectHealthFailOn = 'error' | 'none' | 'warn';\n\nexport const DECANTR_TELEMETRY_EVENT_NAMES = [\n 'api_key.created',\n 'audit.completed',\n 'cli.command.completed',\n 'content.publish.completed',\n 'content.validation.completed',\n 'critique.completed',\n 'decantr.check.completed',\n 'decantr.health.healthy',\n 'decantr.init.completed',\n 'decantr.new.completed',\n 'decantr.refresh.completed',\n 'execution_pack.compiled',\n 'execution_pack.selected',\n 'health.ci.failed',\n 'health.finding.prompt_requested',\n 'health.report.generated',\n 'marketing_web.command_clicked',\n 'marketing_web.cta_clicked',\n 'marketing_web.outbound_clicked',\n 'marketing_web.page_viewed',\n 'org.created',\n 'registry_web.api_key_page_viewed',\n 'registry_web.billing_viewed',\n 'registry_web.content_opened',\n 'registry_web.identity_linked',\n 'registry_web.organization_viewed',\n 'registry_web.page_viewed',\n 'registry_web.search_performed',\n 'registry_web.signup_clicked',\n 'registry.item.resolved',\n 'registry.sync.completed',\n 'studio.health_refreshed',\n 'studio.started',\n 'user.signup.completed',\n] as const;\n\nexport type DecantrTelemetryEventName = (typeof DECANTR_TELEMETRY_EVENT_NAMES)[number];\n\nexport type TelemetryPropertyValue =\n | TelemetryPropertyValue[]\n | boolean\n | null\n | number\n | string\n | undefined\n | { [key: string]: TelemetryPropertyValue };\n\nexport type TelemetryProperties = Record<string, TelemetryPropertyValue>;\n\nexport interface TelemetryContext {\n source: TelemetrySource;\n actorType?: TelemetryActorType;\n environment?: TelemetryEnvironment;\n serviceName?: string;\n serviceVersion?: string;\n decantrVersion?: string;\n registrySource?: RegistrySource;\n anonymousId?: string;\n installId?: string;\n projectId?: string;\n sessionId?: string;\n userId?: string;\n orgId?: string;\n}\n\nexport interface TelemetryActorResolutionOptions {\n internalAnonymousIds?: readonly string[] | ReadonlySet<string>;\n internalInstallIds?: readonly string[] | ReadonlySet<string>;\n internalOrgIds?: readonly string[] | ReadonlySet<string>;\n internalProjectIds?: readonly string[] | ReadonlySet<string>;\n internalUserIds?: readonly string[] | ReadonlySet<string>;\n}\n\nexport function isTelemetryActorType(value: unknown): value is TelemetryActorType {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACTOR_TYPES as readonly string[]).includes(value)\n );\n}\n\nexport function resolveTelemetryActorType(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions = {},\n): TelemetryActorType {\n if (context.actorType) return context.actorType;\n\n if (context.source === 'content-ci') {\n return 'official_pipeline';\n }\n\n if (matchesInternalActor(context, options)) {\n return 'internal';\n }\n\n if (context.userId || context.orgId || context.projectId || context.installId) {\n return 'customer';\n }\n\n if (context.anonymousId) {\n return 'anonymous';\n }\n\n return 'service';\n}\n\nfunction matchesInternalActor(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions,\n): boolean {\n return (\n idListHas(options.internalAnonymousIds, context.anonymousId) ||\n idListHas(options.internalInstallIds, context.installId) ||\n idListHas(options.internalOrgIds, context.orgId) ||\n idListHas(options.internalProjectIds, context.projectId) ||\n idListHas(options.internalUserIds, context.userId)\n );\n}\n\nfunction idListHas(\n values: readonly string[] | ReadonlySet<string> | undefined,\n value: string | undefined,\n): boolean {\n if (!values || !value) return false;\n if (typeof (values as ReadonlySet<string>).has === 'function') {\n return (values as ReadonlySet<string>).has(value);\n }\n return (values as readonly string[]).includes(value);\n}\n\nexport interface TelemetryEventBase<\n Name extends DecantrTelemetryEventName = DecantrTelemetryEventName,\n Properties extends TelemetryProperties = TelemetryProperties,\n> {\n name: Name;\n context: TelemetryContext;\n properties: Properties;\n timestamp?: Date | string;\n}\n\nexport interface CliCommandCompletedProperties extends TelemetryProperties {\n command: string;\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface DecantrLifecycleCompletedProperties extends TelemetryProperties {\n command: 'check' | 'init' | 'new' | 'refresh';\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface ProjectHealthTelemetryProperties extends TelemetryProperties {\n success: boolean;\n status: ProjectHealthTelemetryStatus;\n score: number;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n ci?: boolean;\n errorCode?: string;\n errorCount: number;\n failOn?: ProjectHealthFailOn;\n findingCount: number;\n format?: ProjectHealthOutputFormat;\n infoCount: number;\n outputWritten?: boolean;\n packManifestPresent?: boolean;\n pageCount?: number;\n projectScope?: ProjectScope;\n reviewPackPresent?: boolean;\n routeCount?: number;\n runtimeAuditChecked?: boolean;\n runtimeMatchedCount?: number;\n runtimePassed?: boolean | null;\n runtimeRouteCheckedCount?: number;\n warnCount: number;\n workflowMode?: WorkflowMode;\n}\n\nexport interface HealthFindingPromptRequestedProperties extends TelemetryProperties {\n success: boolean;\n findingFound: boolean;\n adoptionMode?: AdoptionMode;\n ci?: boolean;\n findingSeverity?: ProjectHealthFindingSeverity;\n findingSource?: ProjectHealthFindingSource;\n projectScope?: ProjectScope;\n workflowMode?: WorkflowMode;\n}\n\nexport interface HealthCiFailedProperties extends ProjectHealthTelemetryProperties {\n failOn: 'error' | 'warn';\n}\n\nexport interface StudioStartedProperties extends TelemetryProperties {\n success: boolean;\n hostMode: 'custom' | 'loopback';\n port: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n projectScope?: ProjectScope;\n workflowMode?: WorkflowMode;\n}\n\nexport interface StudioHealthRefreshedProperties extends ProjectHealthTelemetryProperties {\n trigger: 'api-refresh';\n}\n\nexport interface RegistryItemResolvedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n cacheHit?: boolean;\n durationMs?: number;\n errorCode?: string;\n itemId?: string;\n namespace?: string;\n registrySource?: RegistrySource;\n version?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface RegistrySyncCompletedProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n registrySource?: RegistrySource;\n totalItems?: number;\n}\n\nexport interface ExecutionPackCompiledProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n pageCount?: number;\n patternCount?: number;\n sectionCount?: number;\n targetFramework?: string;\n}\n\nexport interface ExecutionPackSelectedProperties extends TelemetryProperties {\n packType: 'mutation' | 'page' | 'review' | 'scaffold' | 'section';\n success: boolean;\n durationMs?: number;\n errorCode?: string;\n id?: string;\n}\n\nexport interface AuditCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n pageCount?: number;\n runtimePassed?: boolean;\n score?: number;\n warnCount?: number;\n}\n\nexport interface CritiqueCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n infoCount?: number;\n overall?: number;\n warnCount?: number;\n}\n\nexport interface ContentValidationCompletedProperties extends TelemetryProperties {\n valid: boolean;\n contentType?: TelemetryContentType;\n durationMs?: number;\n errorCount?: number;\n itemCount?: number;\n warningCount?: number;\n}\n\nexport interface ContentPublishCompletedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n namespace?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface ProductEventProperties extends TelemetryProperties {\n success?: boolean;\n channel?: string;\n entrypoint?: string;\n plan?: string;\n}\n\nexport interface CampaignAttributionProperties extends TelemetryProperties {\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstLandingPath?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstUtmCampaign?: string | null;\n attributionFirstUtmContent?: string | null;\n attributionFirstUtmId?: string | null;\n attributionFirstUtmMedium?: string | null;\n attributionFirstUtmSource?: string | null;\n attributionFirstUtmTerm?: string | null;\n attributionLandingPath?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastUtmCampaign?: string | null;\n attributionLastUtmContent?: string | null;\n attributionLastUtmId?: string | null;\n attributionLastUtmMedium?: string | null;\n attributionLastUtmSource?: string | null;\n attributionLastUtmTerm?: string | null;\n attributionReferrerDomain?: string | null;\n attributionUtmCampaign?: string | null;\n attributionUtmContent?: string | null;\n attributionUtmId?: string | null;\n attributionUtmMedium?: string | null;\n attributionUtmSource?: string | null;\n attributionUtmTerm?: string | null;\n}\n\nexport interface MarketingWebPageViewedProperties extends CampaignAttributionProperties {\n routePath: string;\n surface: string;\n}\n\nexport interface MarketingWebCtaClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebOutboundClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebCommandClickedProperties extends CampaignAttributionProperties {\n commandKind: 'cli' | 'mcp' | 'other';\n commandLabel?: string | null;\n surface: string;\n}\n\nexport interface RegistryWebPageViewedProperties extends CampaignAttributionProperties {\n authenticated: boolean;\n orgScoped?: boolean;\n plan?: string;\n queryPresent?: boolean;\n route: string;\n routePath: string;\n surface: string;\n}\n\nexport interface RegistryWebSearchPerformedProperties extends CampaignAttributionProperties {\n contentType?: string;\n queryLength: number;\n resultCount?: number;\n sort?: string;\n sourceFilter?: string;\n surface: string;\n}\n\nexport interface RegistryWebContentOpenedProperties extends CampaignAttributionProperties {\n contentSource?: string;\n contentType: string;\n namespace?: string;\n slug?: string;\n surface: string;\n}\n\nexport interface RegistryWebCommercialPageViewedProperties extends CampaignAttributionProperties {\n orgScoped?: boolean;\n plan?: string;\n surface: string;\n}\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties>\n | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties>\n | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties>\n | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties>\n | TelemetryEventBase<'decantr.check.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.health.healthy', ProjectHealthTelemetryProperties>\n | TelemetryEventBase<'decantr.init.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.new.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.refresh.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties>\n | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties>\n | TelemetryEventBase<'health.ci.failed', HealthCiFailedProperties>\n | TelemetryEventBase<'health.finding.prompt_requested', HealthFindingPromptRequestedProperties>\n | TelemetryEventBase<'health.report.generated', ProjectHealthTelemetryProperties>\n | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties>\n | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties>\n | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties>\n | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties>\n | TelemetryEventBase<'org.created', ProductEventProperties>\n | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties>\n | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties>\n | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties>\n | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties>\n | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties>\n | TelemetryEventBase<'studio.health_refreshed', StudioHealthRefreshedProperties>\n | TelemetryEventBase<'studio.started', StudioStartedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n","import type { DecantrTelemetryEvent, TelemetryPropertyValue } from './events.js';\n\nexport const REDACTED_VALUE = '[redacted]';\n\nconst DEFAULT_MAX_STRING_LENGTH = 240;\nconst DEFAULT_MAX_ARRAY_LENGTH = 25;\nconst DEFAULT_MAX_OBJECT_KEYS = 80;\nconst DEFAULT_MAX_DEPTH = 4;\n\nconst SENSITIVE_KEY_PATTERNS = [\n /^api[_-]?key$/i,\n /^authorization$/i,\n /^code$/i,\n /^content$/i,\n /^contents$/i,\n /^cookie$/i,\n /^cwd$/i,\n /^email$/i,\n /^env$/i,\n /^file[_-]?contents$/i,\n /^file[_-]?path$/i,\n /^home$/i,\n /^ip[_-]?address$/i,\n /^password$/i,\n /^path$/i,\n /^prompt$/i,\n /^raw[_-]?prompt$/i,\n /^secret$/i,\n /^source$/i,\n /^source[_-]?code$/i,\n /^token$/i,\n /^url$/i,\n /^user[_-]?agent$/i,\n];\n\nexport interface TelemetryRedactionOptions {\n maxArrayLength?: number;\n maxDepth?: number;\n maxObjectKeys?: number;\n maxStringLength?: number;\n redactedValue?: string;\n sensitiveKeyPatterns?: RegExp[];\n}\n\nexport function isSensitiveTelemetryKey(key: string, patterns = SENSITIVE_KEY_PATTERNS): boolean {\n return patterns.some((pattern) => pattern.test(key));\n}\n\nexport function sanitizeTelemetryValue(\n value: TelemetryPropertyValue,\n options: TelemetryRedactionOptions = {},\n depth = 0,\n): TelemetryPropertyValue {\n const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;\n if (depth > maxDepth) {\n return options.redactedValue ?? REDACTED_VALUE;\n }\n\n if (typeof value === 'string') {\n const maxStringLength = options.maxStringLength ?? DEFAULT_MAX_STRING_LENGTH;\n return value.length > maxStringLength ? `${value.slice(0, maxStringLength)}...` : value;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean' || value === null) {\n return value;\n }\n\n if (value === undefined) {\n return null;\n }\n\n if (Array.isArray(value)) {\n const maxArrayLength = options.maxArrayLength ?? DEFAULT_MAX_ARRAY_LENGTH;\n return value\n .slice(0, maxArrayLength)\n .map((entry) => sanitizeTelemetryValue(entry, options, depth + 1));\n }\n\n const redactedValue = options.redactedValue ?? REDACTED_VALUE;\n const sensitiveKeyPatterns = options.sensitiveKeyPatterns ?? SENSITIVE_KEY_PATTERNS;\n const maxObjectKeys = options.maxObjectKeys ?? DEFAULT_MAX_OBJECT_KEYS;\n const entries = Object.entries(value).slice(0, maxObjectKeys);\n const sanitized: Record<string, TelemetryPropertyValue> = {};\n\n for (const [key, entryValue] of entries) {\n sanitized[key] = isSensitiveTelemetryKey(key, sensitiveKeyPatterns)\n ? redactedValue\n : sanitizeTelemetryValue(entryValue, options, depth + 1);\n }\n\n return sanitized;\n}\n\nexport function sanitizeTelemetryEvent(\n event: DecantrTelemetryEvent,\n options: TelemetryRedactionOptions = {},\n): DecantrTelemetryEvent {\n return {\n ...event,\n properties: sanitizeTelemetryValue(\n event.properties,\n options,\n ) as DecantrTelemetryEvent['properties'],\n } as DecantrTelemetryEvent;\n}\n","import {\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n type DecantrTelemetryEvent,\n type TelemetryContext,\n} from './events.js';\nimport { sanitizeTelemetryEvent, type TelemetryRedactionOptions } from './privacy.js';\n\nexport interface TelemetrySink {\n capture(event: DecantrTelemetryEvent): Promise<void> | void;\n flush?(): Promise<void> | void;\n}\n\nexport interface TelemetryClient {\n capture(event: DecantrTelemetryEvent): Promise<void>;\n flush(): Promise<void>;\n}\n\nexport interface TelemetryClientOptions {\n context?: Partial<TelemetryContext>;\n enabled?: boolean;\n onError?: (error: unknown, event: DecantrTelemetryEvent) => void;\n redaction?: TelemetryRedactionOptions;\n sink?: TelemetrySink;\n}\n\nexport interface FetchTelemetrySinkOptions {\n endpoint: string;\n fetch?: typeof fetch;\n headers?: HeadersInit | (() => HeadersInit);\n timeoutMs?: number;\n}\n\nexport function createNoopTelemetrySink(): TelemetrySink {\n return {\n capture() {\n return undefined;\n },\n };\n}\n\nexport function createTelemetryClient(options: TelemetryClientOptions = {}): TelemetryClient {\n const enabled = options.enabled ?? true;\n const sink = options.sink ?? createNoopTelemetrySink();\n const pending = new Set<Promise<void>>();\n\n async function capture(event: DecantrTelemetryEvent): Promise<void> {\n if (!enabled) return;\n\n const enriched = sanitizeTelemetryEvent(\n {\n ...event,\n context: {\n ...options.context,\n ...event.context,\n },\n timestamp: normalizeTimestamp(event.timestamp),\n } as DecantrTelemetryEvent,\n options.redaction,\n );\n\n const promise = Promise.resolve()\n .then(() => sink.capture(enriched))\n .catch((error) => {\n options.onError?.(error, enriched);\n })\n .then(() => undefined);\n\n pending.add(promise);\n promise.finally(() => pending.delete(promise));\n await promise;\n }\n\n async function flush(): Promise<void> {\n await Promise.allSettled([...pending]);\n await sink.flush?.();\n }\n\n return { capture, flush };\n}\n\nexport function createFetchTelemetrySink(options: FetchTelemetrySinkOptions): TelemetrySink {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async capture(event) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 3000);\n\n try {\n const response = await fetchImpl(options.endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...normalizeHeaders(\n typeof options.headers === 'function' ? options.headers() : options.headers,\n ),\n },\n body: JSON.stringify({\n schemaVersion: DECANTR_TELEMETRY_SCHEMA_VERSION,\n event,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`Telemetry endpoint returned HTTP ${response.status}.`);\n }\n } finally {\n clearTimeout(timeout);\n }\n },\n };\n}\n\nfunction normalizeTimestamp(timestamp: Date | string | undefined): string {\n if (timestamp instanceof Date) {\n return timestamp.toISOString();\n }\n return timestamp ?? new Date().toISOString();\n}\n\nfunction normalizeHeaders(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n\n if (headers instanceof Headers) {\n return Object.fromEntries(headers.entries());\n }\n\n if (Array.isArray(headers)) {\n return Object.fromEntries(headers);\n }\n\n return headers as Record<string, string>;\n}\n"],"mappings":"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","names":[]}
package/dist/events.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- declare const DECANTR_TELEMETRY_SCHEMA_VERSION = "0.1.0";
1
+ declare const DECANTR_TELEMETRY_SCHEMA_VERSION = "0.2.0";
2
2
  type TelemetrySource = 'api' | 'cli' | 'content-ci' | 'marketing-web' | 'mcp' | 'registry-web';
3
3
  type TelemetryEnvironment = 'development' | 'preview' | 'production' | 'test';
4
4
  declare const DECANTR_TELEMETRY_ACTOR_TYPES: readonly ["anonymous", "customer", "internal", "official_pipeline", "service"];
@@ -10,7 +10,12 @@ type ProjectScope = 'single-app' | 'workspace-app';
10
10
  type TelemetryContentType = 'archetype' | 'blueprint' | 'pattern' | 'shell' | 'theme';
11
11
  type TelemetryVisibility = 'private' | 'public' | 'team';
12
12
  type TelemetryAnalysisScope = 'hosted' | 'local';
13
- declare const DECANTR_TELEMETRY_EVENT_NAMES: readonly ["api_key.created", "audit.completed", "cli.command.completed", "content.publish.completed", "content.validation.completed", "critique.completed", "execution_pack.compiled", "execution_pack.selected", "marketing_web.command_clicked", "marketing_web.cta_clicked", "marketing_web.outbound_clicked", "marketing_web.page_viewed", "org.created", "registry_web.api_key_page_viewed", "registry_web.billing_viewed", "registry_web.content_opened", "registry_web.identity_linked", "registry_web.organization_viewed", "registry_web.page_viewed", "registry_web.search_performed", "registry_web.signup_clicked", "registry.item.resolved", "registry.sync.completed", "user.signup.completed"];
13
+ type ProjectHealthTelemetryStatus = 'error' | 'healthy' | 'warning';
14
+ type ProjectHealthFindingSeverity = 'error' | 'info' | 'warn';
15
+ type ProjectHealthFindingSource = 'audit' | 'brownfield' | 'check' | 'interaction' | 'pack' | 'runtime';
16
+ type ProjectHealthOutputFormat = 'json' | 'markdown' | 'text';
17
+ type ProjectHealthFailOn = 'error' | 'none' | 'warn';
18
+ declare const DECANTR_TELEMETRY_EVENT_NAMES: readonly ["api_key.created", "audit.completed", "cli.command.completed", "content.publish.completed", "content.validation.completed", "critique.completed", "decantr.check.completed", "decantr.health.healthy", "decantr.init.completed", "decantr.new.completed", "decantr.refresh.completed", "execution_pack.compiled", "execution_pack.selected", "health.ci.failed", "health.finding.prompt_requested", "health.report.generated", "marketing_web.command_clicked", "marketing_web.cta_clicked", "marketing_web.outbound_clicked", "marketing_web.page_viewed", "org.created", "registry_web.api_key_page_viewed", "registry_web.billing_viewed", "registry_web.content_opened", "registry_web.identity_linked", "registry_web.organization_viewed", "registry_web.page_viewed", "registry_web.search_performed", "registry_web.signup_clicked", "registry.item.resolved", "registry.sync.completed", "studio.health_refreshed", "studio.started", "user.signup.completed"];
14
19
  type DecantrTelemetryEventName = (typeof DECANTR_TELEMETRY_EVENT_NAMES)[number];
15
20
  type TelemetryPropertyValue = TelemetryPropertyValue[] | boolean | null | number | string | undefined | {
16
21
  [key: string]: TelemetryPropertyValue;
@@ -58,6 +63,69 @@ interface CliCommandCompletedProperties extends TelemetryProperties {
58
63
  targetFramework?: string;
59
64
  workflowMode?: WorkflowMode;
60
65
  }
66
+ interface DecantrLifecycleCompletedProperties extends TelemetryProperties {
67
+ command: 'check' | 'init' | 'new' | 'refresh';
68
+ success: boolean;
69
+ durationMs: number;
70
+ adoptionMode?: AdoptionMode;
71
+ errorCode?: string;
72
+ offline?: boolean;
73
+ projectScope?: ProjectScope;
74
+ registrySource?: RegistrySource;
75
+ targetFramework?: string;
76
+ workflowMode?: WorkflowMode;
77
+ }
78
+ interface ProjectHealthTelemetryProperties extends TelemetryProperties {
79
+ success: boolean;
80
+ status: ProjectHealthTelemetryStatus;
81
+ score: number;
82
+ durationMs?: number;
83
+ adoptionMode?: AdoptionMode;
84
+ ci?: boolean;
85
+ errorCode?: string;
86
+ errorCount: number;
87
+ failOn?: ProjectHealthFailOn;
88
+ findingCount: number;
89
+ format?: ProjectHealthOutputFormat;
90
+ infoCount: number;
91
+ outputWritten?: boolean;
92
+ packManifestPresent?: boolean;
93
+ pageCount?: number;
94
+ projectScope?: ProjectScope;
95
+ reviewPackPresent?: boolean;
96
+ routeCount?: number;
97
+ runtimeAuditChecked?: boolean;
98
+ runtimeMatchedCount?: number;
99
+ runtimePassed?: boolean | null;
100
+ runtimeRouteCheckedCount?: number;
101
+ warnCount: number;
102
+ workflowMode?: WorkflowMode;
103
+ }
104
+ interface HealthFindingPromptRequestedProperties extends TelemetryProperties {
105
+ success: boolean;
106
+ findingFound: boolean;
107
+ adoptionMode?: AdoptionMode;
108
+ ci?: boolean;
109
+ findingSeverity?: ProjectHealthFindingSeverity;
110
+ findingSource?: ProjectHealthFindingSource;
111
+ projectScope?: ProjectScope;
112
+ workflowMode?: WorkflowMode;
113
+ }
114
+ interface HealthCiFailedProperties extends ProjectHealthTelemetryProperties {
115
+ failOn: 'error' | 'warn';
116
+ }
117
+ interface StudioStartedProperties extends TelemetryProperties {
118
+ success: boolean;
119
+ hostMode: 'custom' | 'loopback';
120
+ port: number;
121
+ adoptionMode?: AdoptionMode;
122
+ errorCode?: string;
123
+ projectScope?: ProjectScope;
124
+ workflowMode?: WorkflowMode;
125
+ }
126
+ interface StudioHealthRefreshedProperties extends ProjectHealthTelemetryProperties {
127
+ trigger: 'api-refresh';
128
+ }
61
129
  interface RegistryItemResolvedProperties extends TelemetryProperties {
62
130
  contentType: TelemetryContentType;
63
131
  success: boolean;
@@ -212,7 +280,7 @@ interface RegistryWebCommercialPageViewedProperties extends CampaignAttributionP
212
280
  plan?: string;
213
281
  surface: string;
214
282
  }
215
- type DecantrTelemetryEvent = TelemetryEventBase<'api_key.created', ProductEventProperties> | TelemetryEventBase<'audit.completed', AuditCompletedProperties> | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties> | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties> | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties> | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties> | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties> | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties> | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties> | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties> | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties> | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties> | TelemetryEventBase<'org.created', ProductEventProperties> | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties> | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties> | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties> | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties> | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties> | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;
283
+ type DecantrTelemetryEvent = TelemetryEventBase<'api_key.created', ProductEventProperties> | TelemetryEventBase<'audit.completed', AuditCompletedProperties> | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties> | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties> | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties> | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties> | TelemetryEventBase<'decantr.check.completed', DecantrLifecycleCompletedProperties> | TelemetryEventBase<'decantr.health.healthy', ProjectHealthTelemetryProperties> | TelemetryEventBase<'decantr.init.completed', DecantrLifecycleCompletedProperties> | TelemetryEventBase<'decantr.new.completed', DecantrLifecycleCompletedProperties> | TelemetryEventBase<'decantr.refresh.completed', DecantrLifecycleCompletedProperties> | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties> | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties> | TelemetryEventBase<'health.ci.failed', HealthCiFailedProperties> | TelemetryEventBase<'health.finding.prompt_requested', HealthFindingPromptRequestedProperties> | TelemetryEventBase<'health.report.generated', ProjectHealthTelemetryProperties> | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties> | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties> | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties> | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties> | TelemetryEventBase<'org.created', ProductEventProperties> | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties> | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties> | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties> | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties> | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties> | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties> | TelemetryEventBase<'studio.health_refreshed', StudioHealthRefreshedProperties> | TelemetryEventBase<'studio.started', StudioStartedProperties> | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;
216
284
  declare function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName;
217
285
 
218
- export { type AdoptionMode, type AuditCompletedProperties, type CampaignAttributionProperties, type CliCommandCompletedProperties, type ContentPublishCompletedProperties, type ContentValidationCompletedProperties, type CritiqueCompletedProperties, DECANTR_TELEMETRY_ACTOR_TYPES, DECANTR_TELEMETRY_EVENT_NAMES, DECANTR_TELEMETRY_SCHEMA_VERSION, type DecantrTelemetryEvent, type DecantrTelemetryEventName, type ExecutionPackCompiledProperties, type ExecutionPackSelectedProperties, type MarketingWebCommandClickedProperties, type MarketingWebCtaClickedProperties, type MarketingWebOutboundClickedProperties, type MarketingWebPageViewedProperties, type ProductEventProperties, type ProjectScope, type RegistryItemResolvedProperties, type RegistrySource, type RegistrySyncCompletedProperties, type RegistryWebCommercialPageViewedProperties, type RegistryWebContentOpenedProperties, type RegistryWebPageViewedProperties, type RegistryWebSearchPerformedProperties, type TelemetryActorResolutionOptions, type TelemetryActorType, type TelemetryAnalysisScope, type TelemetryContentType, type TelemetryContext, type TelemetryEnvironment, type TelemetryEventBase, type TelemetryProperties, type TelemetryPropertyValue, type TelemetrySource, type TelemetryVisibility, type WorkflowMode, isDecantrTelemetryEventName, isTelemetryActorType, resolveTelemetryActorType };
286
+ export { type AdoptionMode, type AuditCompletedProperties, type CampaignAttributionProperties, type CliCommandCompletedProperties, type ContentPublishCompletedProperties, type ContentValidationCompletedProperties, type CritiqueCompletedProperties, DECANTR_TELEMETRY_ACTOR_TYPES, DECANTR_TELEMETRY_EVENT_NAMES, DECANTR_TELEMETRY_SCHEMA_VERSION, type DecantrLifecycleCompletedProperties, type DecantrTelemetryEvent, type DecantrTelemetryEventName, type ExecutionPackCompiledProperties, type ExecutionPackSelectedProperties, type HealthCiFailedProperties, type HealthFindingPromptRequestedProperties, type MarketingWebCommandClickedProperties, type MarketingWebCtaClickedProperties, type MarketingWebOutboundClickedProperties, type MarketingWebPageViewedProperties, type ProductEventProperties, type ProjectHealthFailOn, type ProjectHealthFindingSeverity, type ProjectHealthFindingSource, type ProjectHealthOutputFormat, type ProjectHealthTelemetryProperties, type ProjectHealthTelemetryStatus, type ProjectScope, type RegistryItemResolvedProperties, type RegistrySource, type RegistrySyncCompletedProperties, type RegistryWebCommercialPageViewedProperties, type RegistryWebContentOpenedProperties, type RegistryWebPageViewedProperties, type RegistryWebSearchPerformedProperties, type StudioHealthRefreshedProperties, type StudioStartedProperties, type TelemetryActorResolutionOptions, type TelemetryActorType, type TelemetryAnalysisScope, type TelemetryContentType, type TelemetryContext, type TelemetryEnvironment, type TelemetryEventBase, type TelemetryProperties, type TelemetryPropertyValue, type TelemetrySource, type TelemetryVisibility, type WorkflowMode, isDecantrTelemetryEventName, isTelemetryActorType, resolveTelemetryActorType };
package/dist/events.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/events.ts
2
- var DECANTR_TELEMETRY_SCHEMA_VERSION = "0.1.0";
2
+ var DECANTR_TELEMETRY_SCHEMA_VERSION = "0.2.0";
3
3
  var DECANTR_TELEMETRY_ACTOR_TYPES = [
4
4
  "anonymous",
5
5
  "customer",
@@ -14,8 +14,16 @@ var DECANTR_TELEMETRY_EVENT_NAMES = [
14
14
  "content.publish.completed",
15
15
  "content.validation.completed",
16
16
  "critique.completed",
17
+ "decantr.check.completed",
18
+ "decantr.health.healthy",
19
+ "decantr.init.completed",
20
+ "decantr.new.completed",
21
+ "decantr.refresh.completed",
17
22
  "execution_pack.compiled",
18
23
  "execution_pack.selected",
24
+ "health.ci.failed",
25
+ "health.finding.prompt_requested",
26
+ "health.report.generated",
19
27
  "marketing_web.command_clicked",
20
28
  "marketing_web.cta_clicked",
21
29
  "marketing_web.outbound_clicked",
@@ -31,6 +39,8 @@ var DECANTR_TELEMETRY_EVENT_NAMES = [
31
39
  "registry_web.signup_clicked",
32
40
  "registry.item.resolved",
33
41
  "registry.sync.completed",
42
+ "studio.health_refreshed",
43
+ "studio.started",
34
44
  "user.signup.completed"
35
45
  ];
36
46
  function isTelemetryActorType(value) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/events.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.1.0';\n\nexport type TelemetrySource =\n | 'api'\n | 'cli'\n | 'content-ci'\n | 'marketing-web'\n | 'mcp'\n | 'registry-web';\nexport type TelemetryEnvironment = 'development' | 'preview' | 'production' | 'test';\nexport const DECANTR_TELEMETRY_ACTOR_TYPES = [\n 'anonymous',\n 'customer',\n 'internal',\n 'official_pipeline',\n 'service',\n] as const;\nexport type TelemetryActorType = (typeof DECANTR_TELEMETRY_ACTOR_TYPES)[number];\nexport type RegistrySource = 'cache' | 'custom' | 'none' | 'official' | 'private';\nexport type WorkflowMode =\n | 'brownfield-attach'\n | 'greenfield-contract-only'\n | 'greenfield-scaffold'\n | 'hybrid-compose';\nexport type AdoptionMode = 'contract-only' | 'decantr-css' | 'style-bridge';\nexport type ProjectScope = 'single-app' | 'workspace-app';\nexport type TelemetryContentType = 'archetype' | 'blueprint' | 'pattern' | 'shell' | 'theme';\nexport type TelemetryVisibility = 'private' | 'public' | 'team';\nexport type TelemetryAnalysisScope = 'hosted' | 'local';\n\nexport const DECANTR_TELEMETRY_EVENT_NAMES = [\n 'api_key.created',\n 'audit.completed',\n 'cli.command.completed',\n 'content.publish.completed',\n 'content.validation.completed',\n 'critique.completed',\n 'execution_pack.compiled',\n 'execution_pack.selected',\n 'marketing_web.command_clicked',\n 'marketing_web.cta_clicked',\n 'marketing_web.outbound_clicked',\n 'marketing_web.page_viewed',\n 'org.created',\n 'registry_web.api_key_page_viewed',\n 'registry_web.billing_viewed',\n 'registry_web.content_opened',\n 'registry_web.identity_linked',\n 'registry_web.organization_viewed',\n 'registry_web.page_viewed',\n 'registry_web.search_performed',\n 'registry_web.signup_clicked',\n 'registry.item.resolved',\n 'registry.sync.completed',\n 'user.signup.completed',\n] as const;\n\nexport type DecantrTelemetryEventName = (typeof DECANTR_TELEMETRY_EVENT_NAMES)[number];\n\nexport type TelemetryPropertyValue =\n | TelemetryPropertyValue[]\n | boolean\n | null\n | number\n | string\n | undefined\n | { [key: string]: TelemetryPropertyValue };\n\nexport type TelemetryProperties = Record<string, TelemetryPropertyValue>;\n\nexport interface TelemetryContext {\n source: TelemetrySource;\n actorType?: TelemetryActorType;\n environment?: TelemetryEnvironment;\n serviceName?: string;\n serviceVersion?: string;\n decantrVersion?: string;\n registrySource?: RegistrySource;\n anonymousId?: string;\n installId?: string;\n projectId?: string;\n sessionId?: string;\n userId?: string;\n orgId?: string;\n}\n\nexport interface TelemetryActorResolutionOptions {\n internalAnonymousIds?: readonly string[] | ReadonlySet<string>;\n internalInstallIds?: readonly string[] | ReadonlySet<string>;\n internalOrgIds?: readonly string[] | ReadonlySet<string>;\n internalProjectIds?: readonly string[] | ReadonlySet<string>;\n internalUserIds?: readonly string[] | ReadonlySet<string>;\n}\n\nexport function isTelemetryActorType(value: unknown): value is TelemetryActorType {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACTOR_TYPES as readonly string[]).includes(value)\n );\n}\n\nexport function resolveTelemetryActorType(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions = {},\n): TelemetryActorType {\n if (context.actorType) return context.actorType;\n\n if (context.source === 'content-ci') {\n return 'official_pipeline';\n }\n\n if (matchesInternalActor(context, options)) {\n return 'internal';\n }\n\n if (context.userId || context.orgId || context.projectId || context.installId) {\n return 'customer';\n }\n\n if (context.anonymousId) {\n return 'anonymous';\n }\n\n return 'service';\n}\n\nfunction matchesInternalActor(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions,\n): boolean {\n return (\n idListHas(options.internalAnonymousIds, context.anonymousId) ||\n idListHas(options.internalInstallIds, context.installId) ||\n idListHas(options.internalOrgIds, context.orgId) ||\n idListHas(options.internalProjectIds, context.projectId) ||\n idListHas(options.internalUserIds, context.userId)\n );\n}\n\nfunction idListHas(\n values: readonly string[] | ReadonlySet<string> | undefined,\n value: string | undefined,\n): boolean {\n if (!values || !value) return false;\n if (typeof (values as ReadonlySet<string>).has === 'function') {\n return (values as ReadonlySet<string>).has(value);\n }\n return (values as readonly string[]).includes(value);\n}\n\nexport interface TelemetryEventBase<\n Name extends DecantrTelemetryEventName = DecantrTelemetryEventName,\n Properties extends TelemetryProperties = TelemetryProperties,\n> {\n name: Name;\n context: TelemetryContext;\n properties: Properties;\n timestamp?: Date | string;\n}\n\nexport interface CliCommandCompletedProperties extends TelemetryProperties {\n command: string;\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface RegistryItemResolvedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n cacheHit?: boolean;\n durationMs?: number;\n errorCode?: string;\n itemId?: string;\n namespace?: string;\n registrySource?: RegistrySource;\n version?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface RegistrySyncCompletedProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n registrySource?: RegistrySource;\n totalItems?: number;\n}\n\nexport interface ExecutionPackCompiledProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n pageCount?: number;\n patternCount?: number;\n sectionCount?: number;\n targetFramework?: string;\n}\n\nexport interface ExecutionPackSelectedProperties extends TelemetryProperties {\n packType: 'mutation' | 'page' | 'review' | 'scaffold' | 'section';\n success: boolean;\n durationMs?: number;\n errorCode?: string;\n id?: string;\n}\n\nexport interface AuditCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n pageCount?: number;\n runtimePassed?: boolean;\n score?: number;\n warnCount?: number;\n}\n\nexport interface CritiqueCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n infoCount?: number;\n overall?: number;\n warnCount?: number;\n}\n\nexport interface ContentValidationCompletedProperties extends TelemetryProperties {\n valid: boolean;\n contentType?: TelemetryContentType;\n durationMs?: number;\n errorCount?: number;\n itemCount?: number;\n warningCount?: number;\n}\n\nexport interface ContentPublishCompletedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n namespace?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface ProductEventProperties extends TelemetryProperties {\n success?: boolean;\n channel?: string;\n entrypoint?: string;\n plan?: string;\n}\n\nexport interface CampaignAttributionProperties extends TelemetryProperties {\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstLandingPath?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstUtmCampaign?: string | null;\n attributionFirstUtmContent?: string | null;\n attributionFirstUtmId?: string | null;\n attributionFirstUtmMedium?: string | null;\n attributionFirstUtmSource?: string | null;\n attributionFirstUtmTerm?: string | null;\n attributionLandingPath?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastUtmCampaign?: string | null;\n attributionLastUtmContent?: string | null;\n attributionLastUtmId?: string | null;\n attributionLastUtmMedium?: string | null;\n attributionLastUtmSource?: string | null;\n attributionLastUtmTerm?: string | null;\n attributionReferrerDomain?: string | null;\n attributionUtmCampaign?: string | null;\n attributionUtmContent?: string | null;\n attributionUtmId?: string | null;\n attributionUtmMedium?: string | null;\n attributionUtmSource?: string | null;\n attributionUtmTerm?: string | null;\n}\n\nexport interface MarketingWebPageViewedProperties extends CampaignAttributionProperties {\n routePath: string;\n surface: string;\n}\n\nexport interface MarketingWebCtaClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebOutboundClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebCommandClickedProperties extends CampaignAttributionProperties {\n commandKind: 'cli' | 'mcp' | 'other';\n commandLabel?: string | null;\n surface: string;\n}\n\nexport interface RegistryWebPageViewedProperties extends CampaignAttributionProperties {\n authenticated: boolean;\n orgScoped?: boolean;\n plan?: string;\n queryPresent?: boolean;\n route: string;\n routePath: string;\n surface: string;\n}\n\nexport interface RegistryWebSearchPerformedProperties extends CampaignAttributionProperties {\n contentType?: string;\n queryLength: number;\n resultCount?: number;\n sort?: string;\n sourceFilter?: string;\n surface: string;\n}\n\nexport interface RegistryWebContentOpenedProperties extends CampaignAttributionProperties {\n contentSource?: string;\n contentType: string;\n namespace?: string;\n slug?: string;\n surface: string;\n}\n\nexport interface RegistryWebCommercialPageViewedProperties extends CampaignAttributionProperties {\n orgScoped?: boolean;\n plan?: string;\n surface: string;\n}\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties>\n | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties>\n | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties>\n | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties>\n | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties>\n | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties>\n | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties>\n | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties>\n | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties>\n | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties>\n | TelemetryEventBase<'org.created', ProductEventProperties>\n | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties>\n | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties>\n | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties>\n | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties>\n | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n"],"mappings":";AAAO,IAAM,mCAAmC;AAUzC,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAcO,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAuCO,SAAS,qBAAqB,OAA6C;AAChF,SACE,OAAO,UAAU,YAChB,8BAAoD,SAAS,KAAK;AAEvE;AAEO,SAAS,0BACd,SACA,UAA2C,CAAC,GACxB;AACpB,MAAI,QAAQ,UAAW,QAAO,QAAQ;AAEtC,MAAI,QAAQ,WAAW,cAAc;AACnC,WAAO;AAAA,EACT;AAEA,MAAI,qBAAqB,SAAS,OAAO,GAAG;AAC1C,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,UAAU,QAAQ,SAAS,QAAQ,aAAa,QAAQ,WAAW;AAC7E,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,aAAa;AACvB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,qBACP,SACA,SACS;AACT,SACE,UAAU,QAAQ,sBAAsB,QAAQ,WAAW,KAC3D,UAAU,QAAQ,oBAAoB,QAAQ,SAAS,KACvD,UAAU,QAAQ,gBAAgB,QAAQ,KAAK,KAC/C,UAAU,QAAQ,oBAAoB,QAAQ,SAAS,KACvD,UAAU,QAAQ,iBAAiB,QAAQ,MAAM;AAErD;AAEA,SAAS,UACP,QACA,OACS;AACT,MAAI,CAAC,UAAU,CAAC,MAAO,QAAO;AAC9B,MAAI,OAAQ,OAA+B,QAAQ,YAAY;AAC7D,WAAQ,OAA+B,IAAI,KAAK;AAAA,EAClD;AACA,SAAQ,OAA6B,SAAS,KAAK;AACrD;AA+NO,SAAS,4BAA4B,OAAmD;AAC7F,SAAQ,8BAAoD,SAAS,KAAK;AAC5E;","names":[]}
1
+ {"version":3,"sources":["../src/events.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.2.0';\n\nexport type TelemetrySource =\n | 'api'\n | 'cli'\n | 'content-ci'\n | 'marketing-web'\n | 'mcp'\n | 'registry-web';\nexport type TelemetryEnvironment = 'development' | 'preview' | 'production' | 'test';\nexport const DECANTR_TELEMETRY_ACTOR_TYPES = [\n 'anonymous',\n 'customer',\n 'internal',\n 'official_pipeline',\n 'service',\n] as const;\nexport type TelemetryActorType = (typeof DECANTR_TELEMETRY_ACTOR_TYPES)[number];\nexport type RegistrySource = 'cache' | 'custom' | 'none' | 'official' | 'private';\nexport type WorkflowMode =\n | 'brownfield-attach'\n | 'greenfield-contract-only'\n | 'greenfield-scaffold'\n | 'hybrid-compose';\nexport type AdoptionMode = 'contract-only' | 'decantr-css' | 'style-bridge';\nexport type ProjectScope = 'single-app' | 'workspace-app';\nexport type TelemetryContentType = 'archetype' | 'blueprint' | 'pattern' | 'shell' | 'theme';\nexport type TelemetryVisibility = 'private' | 'public' | 'team';\nexport type TelemetryAnalysisScope = 'hosted' | 'local';\nexport type ProjectHealthTelemetryStatus = 'error' | 'healthy' | 'warning';\nexport type ProjectHealthFindingSeverity = 'error' | 'info' | 'warn';\nexport type ProjectHealthFindingSource =\n | 'audit'\n | 'brownfield'\n | 'check'\n | 'interaction'\n | 'pack'\n | 'runtime';\nexport type ProjectHealthOutputFormat = 'json' | 'markdown' | 'text';\nexport type ProjectHealthFailOn = 'error' | 'none' | 'warn';\n\nexport const DECANTR_TELEMETRY_EVENT_NAMES = [\n 'api_key.created',\n 'audit.completed',\n 'cli.command.completed',\n 'content.publish.completed',\n 'content.validation.completed',\n 'critique.completed',\n 'decantr.check.completed',\n 'decantr.health.healthy',\n 'decantr.init.completed',\n 'decantr.new.completed',\n 'decantr.refresh.completed',\n 'execution_pack.compiled',\n 'execution_pack.selected',\n 'health.ci.failed',\n 'health.finding.prompt_requested',\n 'health.report.generated',\n 'marketing_web.command_clicked',\n 'marketing_web.cta_clicked',\n 'marketing_web.outbound_clicked',\n 'marketing_web.page_viewed',\n 'org.created',\n 'registry_web.api_key_page_viewed',\n 'registry_web.billing_viewed',\n 'registry_web.content_opened',\n 'registry_web.identity_linked',\n 'registry_web.organization_viewed',\n 'registry_web.page_viewed',\n 'registry_web.search_performed',\n 'registry_web.signup_clicked',\n 'registry.item.resolved',\n 'registry.sync.completed',\n 'studio.health_refreshed',\n 'studio.started',\n 'user.signup.completed',\n] as const;\n\nexport type DecantrTelemetryEventName = (typeof DECANTR_TELEMETRY_EVENT_NAMES)[number];\n\nexport type TelemetryPropertyValue =\n | TelemetryPropertyValue[]\n | boolean\n | null\n | number\n | string\n | undefined\n | { [key: string]: TelemetryPropertyValue };\n\nexport type TelemetryProperties = Record<string, TelemetryPropertyValue>;\n\nexport interface TelemetryContext {\n source: TelemetrySource;\n actorType?: TelemetryActorType;\n environment?: TelemetryEnvironment;\n serviceName?: string;\n serviceVersion?: string;\n decantrVersion?: string;\n registrySource?: RegistrySource;\n anonymousId?: string;\n installId?: string;\n projectId?: string;\n sessionId?: string;\n userId?: string;\n orgId?: string;\n}\n\nexport interface TelemetryActorResolutionOptions {\n internalAnonymousIds?: readonly string[] | ReadonlySet<string>;\n internalInstallIds?: readonly string[] | ReadonlySet<string>;\n internalOrgIds?: readonly string[] | ReadonlySet<string>;\n internalProjectIds?: readonly string[] | ReadonlySet<string>;\n internalUserIds?: readonly string[] | ReadonlySet<string>;\n}\n\nexport function isTelemetryActorType(value: unknown): value is TelemetryActorType {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACTOR_TYPES as readonly string[]).includes(value)\n );\n}\n\nexport function resolveTelemetryActorType(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions = {},\n): TelemetryActorType {\n if (context.actorType) return context.actorType;\n\n if (context.source === 'content-ci') {\n return 'official_pipeline';\n }\n\n if (matchesInternalActor(context, options)) {\n return 'internal';\n }\n\n if (context.userId || context.orgId || context.projectId || context.installId) {\n return 'customer';\n }\n\n if (context.anonymousId) {\n return 'anonymous';\n }\n\n return 'service';\n}\n\nfunction matchesInternalActor(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions,\n): boolean {\n return (\n idListHas(options.internalAnonymousIds, context.anonymousId) ||\n idListHas(options.internalInstallIds, context.installId) ||\n idListHas(options.internalOrgIds, context.orgId) ||\n idListHas(options.internalProjectIds, context.projectId) ||\n idListHas(options.internalUserIds, context.userId)\n );\n}\n\nfunction idListHas(\n values: readonly string[] | ReadonlySet<string> | undefined,\n value: string | undefined,\n): boolean {\n if (!values || !value) return false;\n if (typeof (values as ReadonlySet<string>).has === 'function') {\n return (values as ReadonlySet<string>).has(value);\n }\n return (values as readonly string[]).includes(value);\n}\n\nexport interface TelemetryEventBase<\n Name extends DecantrTelemetryEventName = DecantrTelemetryEventName,\n Properties extends TelemetryProperties = TelemetryProperties,\n> {\n name: Name;\n context: TelemetryContext;\n properties: Properties;\n timestamp?: Date | string;\n}\n\nexport interface CliCommandCompletedProperties extends TelemetryProperties {\n command: string;\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface DecantrLifecycleCompletedProperties extends TelemetryProperties {\n command: 'check' | 'init' | 'new' | 'refresh';\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface ProjectHealthTelemetryProperties extends TelemetryProperties {\n success: boolean;\n status: ProjectHealthTelemetryStatus;\n score: number;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n ci?: boolean;\n errorCode?: string;\n errorCount: number;\n failOn?: ProjectHealthFailOn;\n findingCount: number;\n format?: ProjectHealthOutputFormat;\n infoCount: number;\n outputWritten?: boolean;\n packManifestPresent?: boolean;\n pageCount?: number;\n projectScope?: ProjectScope;\n reviewPackPresent?: boolean;\n routeCount?: number;\n runtimeAuditChecked?: boolean;\n runtimeMatchedCount?: number;\n runtimePassed?: boolean | null;\n runtimeRouteCheckedCount?: number;\n warnCount: number;\n workflowMode?: WorkflowMode;\n}\n\nexport interface HealthFindingPromptRequestedProperties extends TelemetryProperties {\n success: boolean;\n findingFound: boolean;\n adoptionMode?: AdoptionMode;\n ci?: boolean;\n findingSeverity?: ProjectHealthFindingSeverity;\n findingSource?: ProjectHealthFindingSource;\n projectScope?: ProjectScope;\n workflowMode?: WorkflowMode;\n}\n\nexport interface HealthCiFailedProperties extends ProjectHealthTelemetryProperties {\n failOn: 'error' | 'warn';\n}\n\nexport interface StudioStartedProperties extends TelemetryProperties {\n success: boolean;\n hostMode: 'custom' | 'loopback';\n port: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n projectScope?: ProjectScope;\n workflowMode?: WorkflowMode;\n}\n\nexport interface StudioHealthRefreshedProperties extends ProjectHealthTelemetryProperties {\n trigger: 'api-refresh';\n}\n\nexport interface RegistryItemResolvedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n cacheHit?: boolean;\n durationMs?: number;\n errorCode?: string;\n itemId?: string;\n namespace?: string;\n registrySource?: RegistrySource;\n version?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface RegistrySyncCompletedProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n registrySource?: RegistrySource;\n totalItems?: number;\n}\n\nexport interface ExecutionPackCompiledProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n pageCount?: number;\n patternCount?: number;\n sectionCount?: number;\n targetFramework?: string;\n}\n\nexport interface ExecutionPackSelectedProperties extends TelemetryProperties {\n packType: 'mutation' | 'page' | 'review' | 'scaffold' | 'section';\n success: boolean;\n durationMs?: number;\n errorCode?: string;\n id?: string;\n}\n\nexport interface AuditCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n pageCount?: number;\n runtimePassed?: boolean;\n score?: number;\n warnCount?: number;\n}\n\nexport interface CritiqueCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n infoCount?: number;\n overall?: number;\n warnCount?: number;\n}\n\nexport interface ContentValidationCompletedProperties extends TelemetryProperties {\n valid: boolean;\n contentType?: TelemetryContentType;\n durationMs?: number;\n errorCount?: number;\n itemCount?: number;\n warningCount?: number;\n}\n\nexport interface ContentPublishCompletedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n namespace?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface ProductEventProperties extends TelemetryProperties {\n success?: boolean;\n channel?: string;\n entrypoint?: string;\n plan?: string;\n}\n\nexport interface CampaignAttributionProperties extends TelemetryProperties {\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstLandingPath?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstUtmCampaign?: string | null;\n attributionFirstUtmContent?: string | null;\n attributionFirstUtmId?: string | null;\n attributionFirstUtmMedium?: string | null;\n attributionFirstUtmSource?: string | null;\n attributionFirstUtmTerm?: string | null;\n attributionLandingPath?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastUtmCampaign?: string | null;\n attributionLastUtmContent?: string | null;\n attributionLastUtmId?: string | null;\n attributionLastUtmMedium?: string | null;\n attributionLastUtmSource?: string | null;\n attributionLastUtmTerm?: string | null;\n attributionReferrerDomain?: string | null;\n attributionUtmCampaign?: string | null;\n attributionUtmContent?: string | null;\n attributionUtmId?: string | null;\n attributionUtmMedium?: string | null;\n attributionUtmSource?: string | null;\n attributionUtmTerm?: string | null;\n}\n\nexport interface MarketingWebPageViewedProperties extends CampaignAttributionProperties {\n routePath: string;\n surface: string;\n}\n\nexport interface MarketingWebCtaClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebOutboundClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebCommandClickedProperties extends CampaignAttributionProperties {\n commandKind: 'cli' | 'mcp' | 'other';\n commandLabel?: string | null;\n surface: string;\n}\n\nexport interface RegistryWebPageViewedProperties extends CampaignAttributionProperties {\n authenticated: boolean;\n orgScoped?: boolean;\n plan?: string;\n queryPresent?: boolean;\n route: string;\n routePath: string;\n surface: string;\n}\n\nexport interface RegistryWebSearchPerformedProperties extends CampaignAttributionProperties {\n contentType?: string;\n queryLength: number;\n resultCount?: number;\n sort?: string;\n sourceFilter?: string;\n surface: string;\n}\n\nexport interface RegistryWebContentOpenedProperties extends CampaignAttributionProperties {\n contentSource?: string;\n contentType: string;\n namespace?: string;\n slug?: string;\n surface: string;\n}\n\nexport interface RegistryWebCommercialPageViewedProperties extends CampaignAttributionProperties {\n orgScoped?: boolean;\n plan?: string;\n surface: string;\n}\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties>\n | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties>\n | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties>\n | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties>\n | TelemetryEventBase<'decantr.check.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.health.healthy', ProjectHealthTelemetryProperties>\n | TelemetryEventBase<'decantr.init.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.new.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.refresh.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties>\n | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties>\n | TelemetryEventBase<'health.ci.failed', HealthCiFailedProperties>\n | TelemetryEventBase<'health.finding.prompt_requested', HealthFindingPromptRequestedProperties>\n | TelemetryEventBase<'health.report.generated', ProjectHealthTelemetryProperties>\n | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties>\n | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties>\n | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties>\n | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties>\n | TelemetryEventBase<'org.created', ProductEventProperties>\n | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties>\n | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties>\n | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties>\n | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties>\n | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties>\n | TelemetryEventBase<'studio.health_refreshed', StudioHealthRefreshedProperties>\n | TelemetryEventBase<'studio.started', StudioStartedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n"],"mappings":";AAAO,IAAM,mCAAmC;AAUzC,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAyBO,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAuCO,SAAS,qBAAqB,OAA6C;AAChF,SACE,OAAO,UAAU,YAChB,8BAAoD,SAAS,KAAK;AAEvE;AAEO,SAAS,0BACd,SACA,UAA2C,CAAC,GACxB;AACpB,MAAI,QAAQ,UAAW,QAAO,QAAQ;AAEtC,MAAI,QAAQ,WAAW,cAAc;AACnC,WAAO;AAAA,EACT;AAEA,MAAI,qBAAqB,SAAS,OAAO,GAAG;AAC1C,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,UAAU,QAAQ,SAAS,QAAQ,aAAa,QAAQ,WAAW;AAC7E,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,aAAa;AACvB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,qBACP,SACA,SACS;AACT,SACE,UAAU,QAAQ,sBAAsB,QAAQ,WAAW,KAC3D,UAAU,QAAQ,oBAAoB,QAAQ,SAAS,KACvD,UAAU,QAAQ,gBAAgB,QAAQ,KAAK,KAC/C,UAAU,QAAQ,oBAAoB,QAAQ,SAAS,KACvD,UAAU,QAAQ,iBAAiB,QAAQ,MAAM;AAErD;AAEA,SAAS,UACP,QACA,OACS;AACT,MAAI,CAAC,UAAU,CAAC,MAAO,QAAO;AAC9B,MAAI,OAAQ,OAA+B,QAAQ,YAAY;AAC7D,WAAQ,OAA+B,IAAI,KAAK;AAAA,EAClD;AACA,SAAQ,OAA6B,SAAS,KAAK;AACrD;AA8SO,SAAS,4BAA4B,OAAmD;AAC7F,SAAQ,8BAAoD,SAAS,KAAK;AAC5E;","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { FetchTelemetrySinkOptions, TelemetryClient, TelemetryClientOptions, TelemetrySink, createFetchTelemetrySink, createNoopTelemetrySink, createTelemetryClient } from './client.js';
2
- export { AdoptionMode, AuditCompletedProperties, CampaignAttributionProperties, CliCommandCompletedProperties, ContentPublishCompletedProperties, ContentValidationCompletedProperties, CritiqueCompletedProperties, DECANTR_TELEMETRY_ACTOR_TYPES, DECANTR_TELEMETRY_EVENT_NAMES, DECANTR_TELEMETRY_SCHEMA_VERSION, DecantrTelemetryEvent, DecantrTelemetryEventName, ExecutionPackCompiledProperties, ExecutionPackSelectedProperties, MarketingWebCommandClickedProperties, MarketingWebCtaClickedProperties, MarketingWebOutboundClickedProperties, MarketingWebPageViewedProperties, ProductEventProperties, ProjectScope, RegistryItemResolvedProperties, RegistrySource, RegistrySyncCompletedProperties, RegistryWebCommercialPageViewedProperties, RegistryWebContentOpenedProperties, RegistryWebPageViewedProperties, RegistryWebSearchPerformedProperties, TelemetryActorResolutionOptions, TelemetryActorType, TelemetryAnalysisScope, TelemetryContentType, TelemetryContext, TelemetryEnvironment, TelemetryProperties, TelemetryPropertyValue, TelemetrySource, TelemetryVisibility, WorkflowMode, isDecantrTelemetryEventName, isTelemetryActorType, resolveTelemetryActorType } from './events.js';
2
+ export { AdoptionMode, AuditCompletedProperties, CampaignAttributionProperties, CliCommandCompletedProperties, ContentPublishCompletedProperties, ContentValidationCompletedProperties, CritiqueCompletedProperties, DECANTR_TELEMETRY_ACTOR_TYPES, DECANTR_TELEMETRY_EVENT_NAMES, DECANTR_TELEMETRY_SCHEMA_VERSION, DecantrLifecycleCompletedProperties, DecantrTelemetryEvent, DecantrTelemetryEventName, ExecutionPackCompiledProperties, ExecutionPackSelectedProperties, HealthCiFailedProperties, HealthFindingPromptRequestedProperties, MarketingWebCommandClickedProperties, MarketingWebCtaClickedProperties, MarketingWebOutboundClickedProperties, MarketingWebPageViewedProperties, ProductEventProperties, ProjectHealthFailOn, ProjectHealthFindingSeverity, ProjectHealthFindingSource, ProjectHealthOutputFormat, ProjectHealthTelemetryProperties, ProjectHealthTelemetryStatus, ProjectScope, RegistryItemResolvedProperties, RegistrySource, RegistrySyncCompletedProperties, RegistryWebCommercialPageViewedProperties, RegistryWebContentOpenedProperties, RegistryWebPageViewedProperties, RegistryWebSearchPerformedProperties, StudioHealthRefreshedProperties, StudioStartedProperties, TelemetryActorResolutionOptions, TelemetryActorType, TelemetryAnalysisScope, TelemetryContentType, TelemetryContext, TelemetryEnvironment, TelemetryProperties, TelemetryPropertyValue, TelemetrySource, TelemetryVisibility, WorkflowMode, isDecantrTelemetryEventName, isTelemetryActorType, resolveTelemetryActorType } from './events.js';
3
3
  export { PostHogTelemetrySinkOptions, createPostHogTelemetrySink } from './posthog.js';
4
4
  export { REDACTED_VALUE, TelemetryRedactionOptions, isSensitiveTelemetryKey, sanitizeTelemetryEvent, sanitizeTelemetryValue } from './privacy.js';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/events.ts
2
- var DECANTR_TELEMETRY_SCHEMA_VERSION = "0.1.0";
2
+ var DECANTR_TELEMETRY_SCHEMA_VERSION = "0.2.0";
3
3
  var DECANTR_TELEMETRY_ACTOR_TYPES = [
4
4
  "anonymous",
5
5
  "customer",
@@ -14,8 +14,16 @@ var DECANTR_TELEMETRY_EVENT_NAMES = [
14
14
  "content.publish.completed",
15
15
  "content.validation.completed",
16
16
  "critique.completed",
17
+ "decantr.check.completed",
18
+ "decantr.health.healthy",
19
+ "decantr.init.completed",
20
+ "decantr.new.completed",
21
+ "decantr.refresh.completed",
17
22
  "execution_pack.compiled",
18
23
  "execution_pack.selected",
24
+ "health.ci.failed",
25
+ "health.finding.prompt_requested",
26
+ "health.report.generated",
19
27
  "marketing_web.command_clicked",
20
28
  "marketing_web.cta_clicked",
21
29
  "marketing_web.outbound_clicked",
@@ -31,6 +39,8 @@ var DECANTR_TELEMETRY_EVENT_NAMES = [
31
39
  "registry_web.signup_clicked",
32
40
  "registry.item.resolved",
33
41
  "registry.sync.completed",
42
+ "studio.health_refreshed",
43
+ "studio.started",
34
44
  "user.signup.completed"
35
45
  ];
36
46
  function isTelemetryActorType(value) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/events.ts","../src/privacy.ts","../src/client.ts","../src/posthog.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.1.0';\n\nexport type TelemetrySource =\n | 'api'\n | 'cli'\n | 'content-ci'\n | 'marketing-web'\n | 'mcp'\n | 'registry-web';\nexport type TelemetryEnvironment = 'development' | 'preview' | 'production' | 'test';\nexport const DECANTR_TELEMETRY_ACTOR_TYPES = [\n 'anonymous',\n 'customer',\n 'internal',\n 'official_pipeline',\n 'service',\n] as const;\nexport type TelemetryActorType = (typeof DECANTR_TELEMETRY_ACTOR_TYPES)[number];\nexport type RegistrySource = 'cache' | 'custom' | 'none' | 'official' | 'private';\nexport type WorkflowMode =\n | 'brownfield-attach'\n | 'greenfield-contract-only'\n | 'greenfield-scaffold'\n | 'hybrid-compose';\nexport type AdoptionMode = 'contract-only' | 'decantr-css' | 'style-bridge';\nexport type ProjectScope = 'single-app' | 'workspace-app';\nexport type TelemetryContentType = 'archetype' | 'blueprint' | 'pattern' | 'shell' | 'theme';\nexport type TelemetryVisibility = 'private' | 'public' | 'team';\nexport type TelemetryAnalysisScope = 'hosted' | 'local';\n\nexport const DECANTR_TELEMETRY_EVENT_NAMES = [\n 'api_key.created',\n 'audit.completed',\n 'cli.command.completed',\n 'content.publish.completed',\n 'content.validation.completed',\n 'critique.completed',\n 'execution_pack.compiled',\n 'execution_pack.selected',\n 'marketing_web.command_clicked',\n 'marketing_web.cta_clicked',\n 'marketing_web.outbound_clicked',\n 'marketing_web.page_viewed',\n 'org.created',\n 'registry_web.api_key_page_viewed',\n 'registry_web.billing_viewed',\n 'registry_web.content_opened',\n 'registry_web.identity_linked',\n 'registry_web.organization_viewed',\n 'registry_web.page_viewed',\n 'registry_web.search_performed',\n 'registry_web.signup_clicked',\n 'registry.item.resolved',\n 'registry.sync.completed',\n 'user.signup.completed',\n] as const;\n\nexport type DecantrTelemetryEventName = (typeof DECANTR_TELEMETRY_EVENT_NAMES)[number];\n\nexport type TelemetryPropertyValue =\n | TelemetryPropertyValue[]\n | boolean\n | null\n | number\n | string\n | undefined\n | { [key: string]: TelemetryPropertyValue };\n\nexport type TelemetryProperties = Record<string, TelemetryPropertyValue>;\n\nexport interface TelemetryContext {\n source: TelemetrySource;\n actorType?: TelemetryActorType;\n environment?: TelemetryEnvironment;\n serviceName?: string;\n serviceVersion?: string;\n decantrVersion?: string;\n registrySource?: RegistrySource;\n anonymousId?: string;\n installId?: string;\n projectId?: string;\n sessionId?: string;\n userId?: string;\n orgId?: string;\n}\n\nexport interface TelemetryActorResolutionOptions {\n internalAnonymousIds?: readonly string[] | ReadonlySet<string>;\n internalInstallIds?: readonly string[] | ReadonlySet<string>;\n internalOrgIds?: readonly string[] | ReadonlySet<string>;\n internalProjectIds?: readonly string[] | ReadonlySet<string>;\n internalUserIds?: readonly string[] | ReadonlySet<string>;\n}\n\nexport function isTelemetryActorType(value: unknown): value is TelemetryActorType {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACTOR_TYPES as readonly string[]).includes(value)\n );\n}\n\nexport function resolveTelemetryActorType(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions = {},\n): TelemetryActorType {\n if (context.actorType) return context.actorType;\n\n if (context.source === 'content-ci') {\n return 'official_pipeline';\n }\n\n if (matchesInternalActor(context, options)) {\n return 'internal';\n }\n\n if (context.userId || context.orgId || context.projectId || context.installId) {\n return 'customer';\n }\n\n if (context.anonymousId) {\n return 'anonymous';\n }\n\n return 'service';\n}\n\nfunction matchesInternalActor(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions,\n): boolean {\n return (\n idListHas(options.internalAnonymousIds, context.anonymousId) ||\n idListHas(options.internalInstallIds, context.installId) ||\n idListHas(options.internalOrgIds, context.orgId) ||\n idListHas(options.internalProjectIds, context.projectId) ||\n idListHas(options.internalUserIds, context.userId)\n );\n}\n\nfunction idListHas(\n values: readonly string[] | ReadonlySet<string> | undefined,\n value: string | undefined,\n): boolean {\n if (!values || !value) return false;\n if (typeof (values as ReadonlySet<string>).has === 'function') {\n return (values as ReadonlySet<string>).has(value);\n }\n return (values as readonly string[]).includes(value);\n}\n\nexport interface TelemetryEventBase<\n Name extends DecantrTelemetryEventName = DecantrTelemetryEventName,\n Properties extends TelemetryProperties = TelemetryProperties,\n> {\n name: Name;\n context: TelemetryContext;\n properties: Properties;\n timestamp?: Date | string;\n}\n\nexport interface CliCommandCompletedProperties extends TelemetryProperties {\n command: string;\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface RegistryItemResolvedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n cacheHit?: boolean;\n durationMs?: number;\n errorCode?: string;\n itemId?: string;\n namespace?: string;\n registrySource?: RegistrySource;\n version?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface RegistrySyncCompletedProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n registrySource?: RegistrySource;\n totalItems?: number;\n}\n\nexport interface ExecutionPackCompiledProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n pageCount?: number;\n patternCount?: number;\n sectionCount?: number;\n targetFramework?: string;\n}\n\nexport interface ExecutionPackSelectedProperties extends TelemetryProperties {\n packType: 'mutation' | 'page' | 'review' | 'scaffold' | 'section';\n success: boolean;\n durationMs?: number;\n errorCode?: string;\n id?: string;\n}\n\nexport interface AuditCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n pageCount?: number;\n runtimePassed?: boolean;\n score?: number;\n warnCount?: number;\n}\n\nexport interface CritiqueCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n infoCount?: number;\n overall?: number;\n warnCount?: number;\n}\n\nexport interface ContentValidationCompletedProperties extends TelemetryProperties {\n valid: boolean;\n contentType?: TelemetryContentType;\n durationMs?: number;\n errorCount?: number;\n itemCount?: number;\n warningCount?: number;\n}\n\nexport interface ContentPublishCompletedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n namespace?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface ProductEventProperties extends TelemetryProperties {\n success?: boolean;\n channel?: string;\n entrypoint?: string;\n plan?: string;\n}\n\nexport interface CampaignAttributionProperties extends TelemetryProperties {\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstLandingPath?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstUtmCampaign?: string | null;\n attributionFirstUtmContent?: string | null;\n attributionFirstUtmId?: string | null;\n attributionFirstUtmMedium?: string | null;\n attributionFirstUtmSource?: string | null;\n attributionFirstUtmTerm?: string | null;\n attributionLandingPath?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastUtmCampaign?: string | null;\n attributionLastUtmContent?: string | null;\n attributionLastUtmId?: string | null;\n attributionLastUtmMedium?: string | null;\n attributionLastUtmSource?: string | null;\n attributionLastUtmTerm?: string | null;\n attributionReferrerDomain?: string | null;\n attributionUtmCampaign?: string | null;\n attributionUtmContent?: string | null;\n attributionUtmId?: string | null;\n attributionUtmMedium?: string | null;\n attributionUtmSource?: string | null;\n attributionUtmTerm?: string | null;\n}\n\nexport interface MarketingWebPageViewedProperties extends CampaignAttributionProperties {\n routePath: string;\n surface: string;\n}\n\nexport interface MarketingWebCtaClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebOutboundClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebCommandClickedProperties extends CampaignAttributionProperties {\n commandKind: 'cli' | 'mcp' | 'other';\n commandLabel?: string | null;\n surface: string;\n}\n\nexport interface RegistryWebPageViewedProperties extends CampaignAttributionProperties {\n authenticated: boolean;\n orgScoped?: boolean;\n plan?: string;\n queryPresent?: boolean;\n route: string;\n routePath: string;\n surface: string;\n}\n\nexport interface RegistryWebSearchPerformedProperties extends CampaignAttributionProperties {\n contentType?: string;\n queryLength: number;\n resultCount?: number;\n sort?: string;\n sourceFilter?: string;\n surface: string;\n}\n\nexport interface RegistryWebContentOpenedProperties extends CampaignAttributionProperties {\n contentSource?: string;\n contentType: string;\n namespace?: string;\n slug?: string;\n surface: string;\n}\n\nexport interface RegistryWebCommercialPageViewedProperties extends CampaignAttributionProperties {\n orgScoped?: boolean;\n plan?: string;\n surface: string;\n}\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties>\n | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties>\n | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties>\n | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties>\n | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties>\n | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties>\n | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties>\n | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties>\n | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties>\n | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties>\n | TelemetryEventBase<'org.created', ProductEventProperties>\n | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties>\n | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties>\n | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties>\n | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties>\n | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n","import type { DecantrTelemetryEvent, TelemetryPropertyValue } from './events.js';\n\nexport const REDACTED_VALUE = '[redacted]';\n\nconst DEFAULT_MAX_STRING_LENGTH = 240;\nconst DEFAULT_MAX_ARRAY_LENGTH = 25;\nconst DEFAULT_MAX_OBJECT_KEYS = 80;\nconst DEFAULT_MAX_DEPTH = 4;\n\nconst SENSITIVE_KEY_PATTERNS = [\n /^api[_-]?key$/i,\n /^authorization$/i,\n /^code$/i,\n /^content$/i,\n /^contents$/i,\n /^cookie$/i,\n /^cwd$/i,\n /^email$/i,\n /^env$/i,\n /^file[_-]?contents$/i,\n /^file[_-]?path$/i,\n /^home$/i,\n /^ip[_-]?address$/i,\n /^password$/i,\n /^path$/i,\n /^prompt$/i,\n /^raw[_-]?prompt$/i,\n /^secret$/i,\n /^source$/i,\n /^source[_-]?code$/i,\n /^token$/i,\n /^url$/i,\n /^user[_-]?agent$/i,\n];\n\nexport interface TelemetryRedactionOptions {\n maxArrayLength?: number;\n maxDepth?: number;\n maxObjectKeys?: number;\n maxStringLength?: number;\n redactedValue?: string;\n sensitiveKeyPatterns?: RegExp[];\n}\n\nexport function isSensitiveTelemetryKey(key: string, patterns = SENSITIVE_KEY_PATTERNS): boolean {\n return patterns.some((pattern) => pattern.test(key));\n}\n\nexport function sanitizeTelemetryValue(\n value: TelemetryPropertyValue,\n options: TelemetryRedactionOptions = {},\n depth = 0,\n): TelemetryPropertyValue {\n const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;\n if (depth > maxDepth) {\n return options.redactedValue ?? REDACTED_VALUE;\n }\n\n if (typeof value === 'string') {\n const maxStringLength = options.maxStringLength ?? DEFAULT_MAX_STRING_LENGTH;\n return value.length > maxStringLength ? `${value.slice(0, maxStringLength)}...` : value;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean' || value === null) {\n return value;\n }\n\n if (value === undefined) {\n return null;\n }\n\n if (Array.isArray(value)) {\n const maxArrayLength = options.maxArrayLength ?? DEFAULT_MAX_ARRAY_LENGTH;\n return value\n .slice(0, maxArrayLength)\n .map((entry) => sanitizeTelemetryValue(entry, options, depth + 1));\n }\n\n const redactedValue = options.redactedValue ?? REDACTED_VALUE;\n const sensitiveKeyPatterns = options.sensitiveKeyPatterns ?? SENSITIVE_KEY_PATTERNS;\n const maxObjectKeys = options.maxObjectKeys ?? DEFAULT_MAX_OBJECT_KEYS;\n const entries = Object.entries(value).slice(0, maxObjectKeys);\n const sanitized: Record<string, TelemetryPropertyValue> = {};\n\n for (const [key, entryValue] of entries) {\n sanitized[key] = isSensitiveTelemetryKey(key, sensitiveKeyPatterns)\n ? redactedValue\n : sanitizeTelemetryValue(entryValue, options, depth + 1);\n }\n\n return sanitized;\n}\n\nexport function sanitizeTelemetryEvent(\n event: DecantrTelemetryEvent,\n options: TelemetryRedactionOptions = {},\n): DecantrTelemetryEvent {\n return {\n ...event,\n properties: sanitizeTelemetryValue(\n event.properties,\n options,\n ) as DecantrTelemetryEvent['properties'],\n } as DecantrTelemetryEvent;\n}\n","import {\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n type DecantrTelemetryEvent,\n type TelemetryContext,\n} from './events.js';\nimport { sanitizeTelemetryEvent, type TelemetryRedactionOptions } from './privacy.js';\n\nexport interface TelemetrySink {\n capture(event: DecantrTelemetryEvent): Promise<void> | void;\n flush?(): Promise<void> | void;\n}\n\nexport interface TelemetryClient {\n capture(event: DecantrTelemetryEvent): Promise<void>;\n flush(): Promise<void>;\n}\n\nexport interface TelemetryClientOptions {\n context?: Partial<TelemetryContext>;\n enabled?: boolean;\n onError?: (error: unknown, event: DecantrTelemetryEvent) => void;\n redaction?: TelemetryRedactionOptions;\n sink?: TelemetrySink;\n}\n\nexport interface FetchTelemetrySinkOptions {\n endpoint: string;\n fetch?: typeof fetch;\n headers?: HeadersInit | (() => HeadersInit);\n timeoutMs?: number;\n}\n\nexport function createNoopTelemetrySink(): TelemetrySink {\n return {\n capture() {\n return undefined;\n },\n };\n}\n\nexport function createTelemetryClient(options: TelemetryClientOptions = {}): TelemetryClient {\n const enabled = options.enabled ?? true;\n const sink = options.sink ?? createNoopTelemetrySink();\n const pending = new Set<Promise<void>>();\n\n async function capture(event: DecantrTelemetryEvent): Promise<void> {\n if (!enabled) return;\n\n const enriched = sanitizeTelemetryEvent(\n {\n ...event,\n context: {\n ...options.context,\n ...event.context,\n },\n timestamp: normalizeTimestamp(event.timestamp),\n } as DecantrTelemetryEvent,\n options.redaction,\n );\n\n const promise = Promise.resolve()\n .then(() => sink.capture(enriched))\n .catch((error) => {\n options.onError?.(error, enriched);\n })\n .then(() => undefined);\n\n pending.add(promise);\n promise.finally(() => pending.delete(promise));\n await promise;\n }\n\n async function flush(): Promise<void> {\n await Promise.allSettled([...pending]);\n await sink.flush?.();\n }\n\n return { capture, flush };\n}\n\nexport function createFetchTelemetrySink(options: FetchTelemetrySinkOptions): TelemetrySink {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async capture(event) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 3000);\n\n try {\n const response = await fetchImpl(options.endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...normalizeHeaders(\n typeof options.headers === 'function' ? options.headers() : options.headers,\n ),\n },\n body: JSON.stringify({\n schemaVersion: DECANTR_TELEMETRY_SCHEMA_VERSION,\n event,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`Telemetry endpoint returned HTTP ${response.status}.`);\n }\n } finally {\n clearTimeout(timeout);\n }\n },\n };\n}\n\nfunction normalizeTimestamp(timestamp: Date | string | undefined): string {\n if (timestamp instanceof Date) {\n return timestamp.toISOString();\n }\n return timestamp ?? new Date().toISOString();\n}\n\nfunction normalizeHeaders(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n\n if (headers instanceof Headers) {\n return Object.fromEntries(headers.entries());\n }\n\n if (Array.isArray(headers)) {\n return Object.fromEntries(headers);\n }\n\n return headers as Record<string, string>;\n}\n","import type { TelemetrySink } from './client.js';\nimport {\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n resolveTelemetryActorType,\n type DecantrTelemetryEvent,\n type TelemetryProperties,\n} from './events.js';\n\nexport interface PostHogTelemetrySinkOptions {\n apiKey: string;\n fetch?: typeof fetch;\n host?: string;\n processPersonProfile?: boolean;\n timeoutMs?: number;\n}\n\nexport function createPostHogTelemetrySink(options: PostHogTelemetrySinkOptions): TelemetrySink {\n const host = trimTrailingSlashes(options.host ?? 'https://us.i.posthog.com');\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async capture(event) {\n const distinctId = resolveDistinctId(event);\n if (!distinctId) {\n throw new Error(\n 'PostHog telemetry requires an opaque user, install, project, or anonymous id.',\n );\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 3000);\n\n try {\n const response = await fetchImpl(`${host}/i/v0/e/`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n api_key: options.apiKey,\n event: event.name,\n distinct_id: distinctId,\n properties: toPostHogProperties(event, options),\n timestamp: event.timestamp,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`PostHog capture returned HTTP ${response.status}.`);\n }\n } finally {\n clearTimeout(timeout);\n }\n },\n };\n}\n\nfunction trimTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) {\n end -= 1;\n }\n return value.slice(0, end);\n}\n\nfunction resolveDistinctId(event: DecantrTelemetryEvent): string | undefined {\n return (\n event.context.userId ??\n event.context.installId ??\n event.context.projectId ??\n event.context.anonymousId\n );\n}\n\nfunction toPostHogProperties(\n event: DecantrTelemetryEvent,\n options: PostHogTelemetrySinkOptions,\n): TelemetryProperties {\n const groups: Record<string, string> = {};\n if (event.context.orgId) groups.organization = event.context.orgId;\n if (event.context.projectId) groups.project = event.context.projectId;\n\n return {\n ...event.properties,\n $groups: groups,\n $process_person_profile: options.processPersonProfile ?? false,\n decantr_anonymous_id: event.context.anonymousId ?? null,\n decantr_actor_type: resolveTelemetryActorType(event.context),\n decantr_install_id: event.context.installId ?? null,\n decantr_org_id: event.context.orgId ?? null,\n decantr_project_id: event.context.projectId ?? null,\n decantr_session_id: event.context.sessionId ?? null,\n decantr_schema_version: DECANTR_TELEMETRY_SCHEMA_VERSION,\n decantr_source: event.context.source,\n decantr_environment: event.context.environment ?? 'production',\n decantr_version: event.context.decantrVersion ?? null,\n registry_source: event.context.registrySource ?? null,\n service_name: event.context.serviceName ?? null,\n service_version: event.context.serviceVersion ?? null,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/events.ts","../src/privacy.ts","../src/client.ts","../src/posthog.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.2.0';\n\nexport type TelemetrySource =\n | 'api'\n | 'cli'\n | 'content-ci'\n | 'marketing-web'\n | 'mcp'\n | 'registry-web';\nexport type TelemetryEnvironment = 'development' | 'preview' | 'production' | 'test';\nexport const DECANTR_TELEMETRY_ACTOR_TYPES = [\n 'anonymous',\n 'customer',\n 'internal',\n 'official_pipeline',\n 'service',\n] as const;\nexport type TelemetryActorType = (typeof DECANTR_TELEMETRY_ACTOR_TYPES)[number];\nexport type RegistrySource = 'cache' | 'custom' | 'none' | 'official' | 'private';\nexport type WorkflowMode =\n | 'brownfield-attach'\n | 'greenfield-contract-only'\n | 'greenfield-scaffold'\n | 'hybrid-compose';\nexport type AdoptionMode = 'contract-only' | 'decantr-css' | 'style-bridge';\nexport type ProjectScope = 'single-app' | 'workspace-app';\nexport type TelemetryContentType = 'archetype' | 'blueprint' | 'pattern' | 'shell' | 'theme';\nexport type TelemetryVisibility = 'private' | 'public' | 'team';\nexport type TelemetryAnalysisScope = 'hosted' | 'local';\nexport type ProjectHealthTelemetryStatus = 'error' | 'healthy' | 'warning';\nexport type ProjectHealthFindingSeverity = 'error' | 'info' | 'warn';\nexport type ProjectHealthFindingSource =\n | 'audit'\n | 'brownfield'\n | 'check'\n | 'interaction'\n | 'pack'\n | 'runtime';\nexport type ProjectHealthOutputFormat = 'json' | 'markdown' | 'text';\nexport type ProjectHealthFailOn = 'error' | 'none' | 'warn';\n\nexport const DECANTR_TELEMETRY_EVENT_NAMES = [\n 'api_key.created',\n 'audit.completed',\n 'cli.command.completed',\n 'content.publish.completed',\n 'content.validation.completed',\n 'critique.completed',\n 'decantr.check.completed',\n 'decantr.health.healthy',\n 'decantr.init.completed',\n 'decantr.new.completed',\n 'decantr.refresh.completed',\n 'execution_pack.compiled',\n 'execution_pack.selected',\n 'health.ci.failed',\n 'health.finding.prompt_requested',\n 'health.report.generated',\n 'marketing_web.command_clicked',\n 'marketing_web.cta_clicked',\n 'marketing_web.outbound_clicked',\n 'marketing_web.page_viewed',\n 'org.created',\n 'registry_web.api_key_page_viewed',\n 'registry_web.billing_viewed',\n 'registry_web.content_opened',\n 'registry_web.identity_linked',\n 'registry_web.organization_viewed',\n 'registry_web.page_viewed',\n 'registry_web.search_performed',\n 'registry_web.signup_clicked',\n 'registry.item.resolved',\n 'registry.sync.completed',\n 'studio.health_refreshed',\n 'studio.started',\n 'user.signup.completed',\n] as const;\n\nexport type DecantrTelemetryEventName = (typeof DECANTR_TELEMETRY_EVENT_NAMES)[number];\n\nexport type TelemetryPropertyValue =\n | TelemetryPropertyValue[]\n | boolean\n | null\n | number\n | string\n | undefined\n | { [key: string]: TelemetryPropertyValue };\n\nexport type TelemetryProperties = Record<string, TelemetryPropertyValue>;\n\nexport interface TelemetryContext {\n source: TelemetrySource;\n actorType?: TelemetryActorType;\n environment?: TelemetryEnvironment;\n serviceName?: string;\n serviceVersion?: string;\n decantrVersion?: string;\n registrySource?: RegistrySource;\n anonymousId?: string;\n installId?: string;\n projectId?: string;\n sessionId?: string;\n userId?: string;\n orgId?: string;\n}\n\nexport interface TelemetryActorResolutionOptions {\n internalAnonymousIds?: readonly string[] | ReadonlySet<string>;\n internalInstallIds?: readonly string[] | ReadonlySet<string>;\n internalOrgIds?: readonly string[] | ReadonlySet<string>;\n internalProjectIds?: readonly string[] | ReadonlySet<string>;\n internalUserIds?: readonly string[] | ReadonlySet<string>;\n}\n\nexport function isTelemetryActorType(value: unknown): value is TelemetryActorType {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACTOR_TYPES as readonly string[]).includes(value)\n );\n}\n\nexport function resolveTelemetryActorType(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions = {},\n): TelemetryActorType {\n if (context.actorType) return context.actorType;\n\n if (context.source === 'content-ci') {\n return 'official_pipeline';\n }\n\n if (matchesInternalActor(context, options)) {\n return 'internal';\n }\n\n if (context.userId || context.orgId || context.projectId || context.installId) {\n return 'customer';\n }\n\n if (context.anonymousId) {\n return 'anonymous';\n }\n\n return 'service';\n}\n\nfunction matchesInternalActor(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions,\n): boolean {\n return (\n idListHas(options.internalAnonymousIds, context.anonymousId) ||\n idListHas(options.internalInstallIds, context.installId) ||\n idListHas(options.internalOrgIds, context.orgId) ||\n idListHas(options.internalProjectIds, context.projectId) ||\n idListHas(options.internalUserIds, context.userId)\n );\n}\n\nfunction idListHas(\n values: readonly string[] | ReadonlySet<string> | undefined,\n value: string | undefined,\n): boolean {\n if (!values || !value) return false;\n if (typeof (values as ReadonlySet<string>).has === 'function') {\n return (values as ReadonlySet<string>).has(value);\n }\n return (values as readonly string[]).includes(value);\n}\n\nexport interface TelemetryEventBase<\n Name extends DecantrTelemetryEventName = DecantrTelemetryEventName,\n Properties extends TelemetryProperties = TelemetryProperties,\n> {\n name: Name;\n context: TelemetryContext;\n properties: Properties;\n timestamp?: Date | string;\n}\n\nexport interface CliCommandCompletedProperties extends TelemetryProperties {\n command: string;\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface DecantrLifecycleCompletedProperties extends TelemetryProperties {\n command: 'check' | 'init' | 'new' | 'refresh';\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface ProjectHealthTelemetryProperties extends TelemetryProperties {\n success: boolean;\n status: ProjectHealthTelemetryStatus;\n score: number;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n ci?: boolean;\n errorCode?: string;\n errorCount: number;\n failOn?: ProjectHealthFailOn;\n findingCount: number;\n format?: ProjectHealthOutputFormat;\n infoCount: number;\n outputWritten?: boolean;\n packManifestPresent?: boolean;\n pageCount?: number;\n projectScope?: ProjectScope;\n reviewPackPresent?: boolean;\n routeCount?: number;\n runtimeAuditChecked?: boolean;\n runtimeMatchedCount?: number;\n runtimePassed?: boolean | null;\n runtimeRouteCheckedCount?: number;\n warnCount: number;\n workflowMode?: WorkflowMode;\n}\n\nexport interface HealthFindingPromptRequestedProperties extends TelemetryProperties {\n success: boolean;\n findingFound: boolean;\n adoptionMode?: AdoptionMode;\n ci?: boolean;\n findingSeverity?: ProjectHealthFindingSeverity;\n findingSource?: ProjectHealthFindingSource;\n projectScope?: ProjectScope;\n workflowMode?: WorkflowMode;\n}\n\nexport interface HealthCiFailedProperties extends ProjectHealthTelemetryProperties {\n failOn: 'error' | 'warn';\n}\n\nexport interface StudioStartedProperties extends TelemetryProperties {\n success: boolean;\n hostMode: 'custom' | 'loopback';\n port: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n projectScope?: ProjectScope;\n workflowMode?: WorkflowMode;\n}\n\nexport interface StudioHealthRefreshedProperties extends ProjectHealthTelemetryProperties {\n trigger: 'api-refresh';\n}\n\nexport interface RegistryItemResolvedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n cacheHit?: boolean;\n durationMs?: number;\n errorCode?: string;\n itemId?: string;\n namespace?: string;\n registrySource?: RegistrySource;\n version?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface RegistrySyncCompletedProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n registrySource?: RegistrySource;\n totalItems?: number;\n}\n\nexport interface ExecutionPackCompiledProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n pageCount?: number;\n patternCount?: number;\n sectionCount?: number;\n targetFramework?: string;\n}\n\nexport interface ExecutionPackSelectedProperties extends TelemetryProperties {\n packType: 'mutation' | 'page' | 'review' | 'scaffold' | 'section';\n success: boolean;\n durationMs?: number;\n errorCode?: string;\n id?: string;\n}\n\nexport interface AuditCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n pageCount?: number;\n runtimePassed?: boolean;\n score?: number;\n warnCount?: number;\n}\n\nexport interface CritiqueCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n infoCount?: number;\n overall?: number;\n warnCount?: number;\n}\n\nexport interface ContentValidationCompletedProperties extends TelemetryProperties {\n valid: boolean;\n contentType?: TelemetryContentType;\n durationMs?: number;\n errorCount?: number;\n itemCount?: number;\n warningCount?: number;\n}\n\nexport interface ContentPublishCompletedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n namespace?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface ProductEventProperties extends TelemetryProperties {\n success?: boolean;\n channel?: string;\n entrypoint?: string;\n plan?: string;\n}\n\nexport interface CampaignAttributionProperties extends TelemetryProperties {\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstLandingPath?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstUtmCampaign?: string | null;\n attributionFirstUtmContent?: string | null;\n attributionFirstUtmId?: string | null;\n attributionFirstUtmMedium?: string | null;\n attributionFirstUtmSource?: string | null;\n attributionFirstUtmTerm?: string | null;\n attributionLandingPath?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastUtmCampaign?: string | null;\n attributionLastUtmContent?: string | null;\n attributionLastUtmId?: string | null;\n attributionLastUtmMedium?: string | null;\n attributionLastUtmSource?: string | null;\n attributionLastUtmTerm?: string | null;\n attributionReferrerDomain?: string | null;\n attributionUtmCampaign?: string | null;\n attributionUtmContent?: string | null;\n attributionUtmId?: string | null;\n attributionUtmMedium?: string | null;\n attributionUtmSource?: string | null;\n attributionUtmTerm?: string | null;\n}\n\nexport interface MarketingWebPageViewedProperties extends CampaignAttributionProperties {\n routePath: string;\n surface: string;\n}\n\nexport interface MarketingWebCtaClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebOutboundClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebCommandClickedProperties extends CampaignAttributionProperties {\n commandKind: 'cli' | 'mcp' | 'other';\n commandLabel?: string | null;\n surface: string;\n}\n\nexport interface RegistryWebPageViewedProperties extends CampaignAttributionProperties {\n authenticated: boolean;\n orgScoped?: boolean;\n plan?: string;\n queryPresent?: boolean;\n route: string;\n routePath: string;\n surface: string;\n}\n\nexport interface RegistryWebSearchPerformedProperties extends CampaignAttributionProperties {\n contentType?: string;\n queryLength: number;\n resultCount?: number;\n sort?: string;\n sourceFilter?: string;\n surface: string;\n}\n\nexport interface RegistryWebContentOpenedProperties extends CampaignAttributionProperties {\n contentSource?: string;\n contentType: string;\n namespace?: string;\n slug?: string;\n surface: string;\n}\n\nexport interface RegistryWebCommercialPageViewedProperties extends CampaignAttributionProperties {\n orgScoped?: boolean;\n plan?: string;\n surface: string;\n}\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties>\n | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties>\n | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties>\n | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties>\n | TelemetryEventBase<'decantr.check.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.health.healthy', ProjectHealthTelemetryProperties>\n | TelemetryEventBase<'decantr.init.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.new.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.refresh.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties>\n | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties>\n | TelemetryEventBase<'health.ci.failed', HealthCiFailedProperties>\n | TelemetryEventBase<'health.finding.prompt_requested', HealthFindingPromptRequestedProperties>\n | TelemetryEventBase<'health.report.generated', ProjectHealthTelemetryProperties>\n | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties>\n | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties>\n | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties>\n | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties>\n | TelemetryEventBase<'org.created', ProductEventProperties>\n | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties>\n | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties>\n | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties>\n | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties>\n | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties>\n | TelemetryEventBase<'studio.health_refreshed', StudioHealthRefreshedProperties>\n | TelemetryEventBase<'studio.started', StudioStartedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n","import type { DecantrTelemetryEvent, TelemetryPropertyValue } from './events.js';\n\nexport const REDACTED_VALUE = '[redacted]';\n\nconst DEFAULT_MAX_STRING_LENGTH = 240;\nconst DEFAULT_MAX_ARRAY_LENGTH = 25;\nconst DEFAULT_MAX_OBJECT_KEYS = 80;\nconst DEFAULT_MAX_DEPTH = 4;\n\nconst SENSITIVE_KEY_PATTERNS = [\n /^api[_-]?key$/i,\n /^authorization$/i,\n /^code$/i,\n /^content$/i,\n /^contents$/i,\n /^cookie$/i,\n /^cwd$/i,\n /^email$/i,\n /^env$/i,\n /^file[_-]?contents$/i,\n /^file[_-]?path$/i,\n /^home$/i,\n /^ip[_-]?address$/i,\n /^password$/i,\n /^path$/i,\n /^prompt$/i,\n /^raw[_-]?prompt$/i,\n /^secret$/i,\n /^source$/i,\n /^source[_-]?code$/i,\n /^token$/i,\n /^url$/i,\n /^user[_-]?agent$/i,\n];\n\nexport interface TelemetryRedactionOptions {\n maxArrayLength?: number;\n maxDepth?: number;\n maxObjectKeys?: number;\n maxStringLength?: number;\n redactedValue?: string;\n sensitiveKeyPatterns?: RegExp[];\n}\n\nexport function isSensitiveTelemetryKey(key: string, patterns = SENSITIVE_KEY_PATTERNS): boolean {\n return patterns.some((pattern) => pattern.test(key));\n}\n\nexport function sanitizeTelemetryValue(\n value: TelemetryPropertyValue,\n options: TelemetryRedactionOptions = {},\n depth = 0,\n): TelemetryPropertyValue {\n const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;\n if (depth > maxDepth) {\n return options.redactedValue ?? REDACTED_VALUE;\n }\n\n if (typeof value === 'string') {\n const maxStringLength = options.maxStringLength ?? DEFAULT_MAX_STRING_LENGTH;\n return value.length > maxStringLength ? `${value.slice(0, maxStringLength)}...` : value;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean' || value === null) {\n return value;\n }\n\n if (value === undefined) {\n return null;\n }\n\n if (Array.isArray(value)) {\n const maxArrayLength = options.maxArrayLength ?? DEFAULT_MAX_ARRAY_LENGTH;\n return value\n .slice(0, maxArrayLength)\n .map((entry) => sanitizeTelemetryValue(entry, options, depth + 1));\n }\n\n const redactedValue = options.redactedValue ?? REDACTED_VALUE;\n const sensitiveKeyPatterns = options.sensitiveKeyPatterns ?? SENSITIVE_KEY_PATTERNS;\n const maxObjectKeys = options.maxObjectKeys ?? DEFAULT_MAX_OBJECT_KEYS;\n const entries = Object.entries(value).slice(0, maxObjectKeys);\n const sanitized: Record<string, TelemetryPropertyValue> = {};\n\n for (const [key, entryValue] of entries) {\n sanitized[key] = isSensitiveTelemetryKey(key, sensitiveKeyPatterns)\n ? redactedValue\n : sanitizeTelemetryValue(entryValue, options, depth + 1);\n }\n\n return sanitized;\n}\n\nexport function sanitizeTelemetryEvent(\n event: DecantrTelemetryEvent,\n options: TelemetryRedactionOptions = {},\n): DecantrTelemetryEvent {\n return {\n ...event,\n properties: sanitizeTelemetryValue(\n event.properties,\n options,\n ) as DecantrTelemetryEvent['properties'],\n } as DecantrTelemetryEvent;\n}\n","import {\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n type DecantrTelemetryEvent,\n type TelemetryContext,\n} from './events.js';\nimport { sanitizeTelemetryEvent, type TelemetryRedactionOptions } from './privacy.js';\n\nexport interface TelemetrySink {\n capture(event: DecantrTelemetryEvent): Promise<void> | void;\n flush?(): Promise<void> | void;\n}\n\nexport interface TelemetryClient {\n capture(event: DecantrTelemetryEvent): Promise<void>;\n flush(): Promise<void>;\n}\n\nexport interface TelemetryClientOptions {\n context?: Partial<TelemetryContext>;\n enabled?: boolean;\n onError?: (error: unknown, event: DecantrTelemetryEvent) => void;\n redaction?: TelemetryRedactionOptions;\n sink?: TelemetrySink;\n}\n\nexport interface FetchTelemetrySinkOptions {\n endpoint: string;\n fetch?: typeof fetch;\n headers?: HeadersInit | (() => HeadersInit);\n timeoutMs?: number;\n}\n\nexport function createNoopTelemetrySink(): TelemetrySink {\n return {\n capture() {\n return undefined;\n },\n };\n}\n\nexport function createTelemetryClient(options: TelemetryClientOptions = {}): TelemetryClient {\n const enabled = options.enabled ?? true;\n const sink = options.sink ?? createNoopTelemetrySink();\n const pending = new Set<Promise<void>>();\n\n async function capture(event: DecantrTelemetryEvent): Promise<void> {\n if (!enabled) return;\n\n const enriched = sanitizeTelemetryEvent(\n {\n ...event,\n context: {\n ...options.context,\n ...event.context,\n },\n timestamp: normalizeTimestamp(event.timestamp),\n } as DecantrTelemetryEvent,\n options.redaction,\n );\n\n const promise = Promise.resolve()\n .then(() => sink.capture(enriched))\n .catch((error) => {\n options.onError?.(error, enriched);\n })\n .then(() => undefined);\n\n pending.add(promise);\n promise.finally(() => pending.delete(promise));\n await promise;\n }\n\n async function flush(): Promise<void> {\n await Promise.allSettled([...pending]);\n await sink.flush?.();\n }\n\n return { capture, flush };\n}\n\nexport function createFetchTelemetrySink(options: FetchTelemetrySinkOptions): TelemetrySink {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async capture(event) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 3000);\n\n try {\n const response = await fetchImpl(options.endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...normalizeHeaders(\n typeof options.headers === 'function' ? options.headers() : options.headers,\n ),\n },\n body: JSON.stringify({\n schemaVersion: DECANTR_TELEMETRY_SCHEMA_VERSION,\n event,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`Telemetry endpoint returned HTTP ${response.status}.`);\n }\n } finally {\n clearTimeout(timeout);\n }\n },\n };\n}\n\nfunction normalizeTimestamp(timestamp: Date | string | undefined): string {\n if (timestamp instanceof Date) {\n return timestamp.toISOString();\n }\n return timestamp ?? new Date().toISOString();\n}\n\nfunction normalizeHeaders(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n\n if (headers instanceof Headers) {\n return Object.fromEntries(headers.entries());\n }\n\n if (Array.isArray(headers)) {\n return Object.fromEntries(headers);\n }\n\n return headers as Record<string, string>;\n}\n","import type { TelemetrySink } from './client.js';\nimport {\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n resolveTelemetryActorType,\n type DecantrTelemetryEvent,\n type TelemetryProperties,\n} from './events.js';\n\nexport interface PostHogTelemetrySinkOptions {\n apiKey: string;\n fetch?: typeof fetch;\n host?: string;\n processPersonProfile?: boolean;\n timeoutMs?: number;\n}\n\nexport function createPostHogTelemetrySink(options: PostHogTelemetrySinkOptions): TelemetrySink {\n const host = trimTrailingSlashes(options.host ?? 'https://us.i.posthog.com');\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async capture(event) {\n const distinctId = resolveDistinctId(event);\n if (!distinctId) {\n throw new Error(\n 'PostHog telemetry requires an opaque user, install, project, or anonymous id.',\n );\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 3000);\n\n try {\n const response = await fetchImpl(`${host}/i/v0/e/`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n api_key: options.apiKey,\n event: event.name,\n distinct_id: distinctId,\n properties: toPostHogProperties(event, options),\n timestamp: event.timestamp,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`PostHog capture returned HTTP ${response.status}.`);\n }\n } finally {\n clearTimeout(timeout);\n }\n },\n };\n}\n\nfunction trimTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) {\n end -= 1;\n }\n return value.slice(0, end);\n}\n\nfunction resolveDistinctId(event: DecantrTelemetryEvent): string | undefined {\n return (\n event.context.userId ??\n event.context.installId ??\n event.context.projectId ??\n event.context.anonymousId\n );\n}\n\nfunction toPostHogProperties(\n event: DecantrTelemetryEvent,\n options: PostHogTelemetrySinkOptions,\n): TelemetryProperties {\n const groups: Record<string, string> = {};\n if (event.context.orgId) groups.organization = event.context.orgId;\n if (event.context.projectId) groups.project = event.context.projectId;\n\n return {\n ...event.properties,\n $groups: groups,\n $process_person_profile: options.processPersonProfile ?? false,\n decantr_anonymous_id: event.context.anonymousId ?? null,\n decantr_actor_type: resolveTelemetryActorType(event.context),\n decantr_install_id: event.context.installId ?? null,\n decantr_org_id: event.context.orgId ?? null,\n decantr_project_id: event.context.projectId ?? null,\n decantr_session_id: event.context.sessionId ?? null,\n decantr_schema_version: DECANTR_TELEMETRY_SCHEMA_VERSION,\n decantr_source: event.context.source,\n decantr_environment: event.context.environment ?? 'production',\n decantr_version: event.context.decantrVersion ?? null,\n registry_source: event.context.registrySource ?? null,\n service_name: event.context.serviceName ?? null,\n service_version: event.context.serviceVersion ?? null,\n };\n}\n"],"mappings":"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","names":[]}
package/dist/posthog.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/events.ts
2
- var DECANTR_TELEMETRY_SCHEMA_VERSION = "0.1.0";
2
+ var DECANTR_TELEMETRY_SCHEMA_VERSION = "0.2.0";
3
3
  function resolveTelemetryActorType(context, options = {}) {
4
4
  if (context.actorType) return context.actorType;
5
5
  if (context.source === "content-ci") {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/events.ts","../src/posthog.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.1.0';\n\nexport type TelemetrySource =\n | 'api'\n | 'cli'\n | 'content-ci'\n | 'marketing-web'\n | 'mcp'\n | 'registry-web';\nexport type TelemetryEnvironment = 'development' | 'preview' | 'production' | 'test';\nexport const DECANTR_TELEMETRY_ACTOR_TYPES = [\n 'anonymous',\n 'customer',\n 'internal',\n 'official_pipeline',\n 'service',\n] as const;\nexport type TelemetryActorType = (typeof DECANTR_TELEMETRY_ACTOR_TYPES)[number];\nexport type RegistrySource = 'cache' | 'custom' | 'none' | 'official' | 'private';\nexport type WorkflowMode =\n | 'brownfield-attach'\n | 'greenfield-contract-only'\n | 'greenfield-scaffold'\n | 'hybrid-compose';\nexport type AdoptionMode = 'contract-only' | 'decantr-css' | 'style-bridge';\nexport type ProjectScope = 'single-app' | 'workspace-app';\nexport type TelemetryContentType = 'archetype' | 'blueprint' | 'pattern' | 'shell' | 'theme';\nexport type TelemetryVisibility = 'private' | 'public' | 'team';\nexport type TelemetryAnalysisScope = 'hosted' | 'local';\n\nexport const DECANTR_TELEMETRY_EVENT_NAMES = [\n 'api_key.created',\n 'audit.completed',\n 'cli.command.completed',\n 'content.publish.completed',\n 'content.validation.completed',\n 'critique.completed',\n 'execution_pack.compiled',\n 'execution_pack.selected',\n 'marketing_web.command_clicked',\n 'marketing_web.cta_clicked',\n 'marketing_web.outbound_clicked',\n 'marketing_web.page_viewed',\n 'org.created',\n 'registry_web.api_key_page_viewed',\n 'registry_web.billing_viewed',\n 'registry_web.content_opened',\n 'registry_web.identity_linked',\n 'registry_web.organization_viewed',\n 'registry_web.page_viewed',\n 'registry_web.search_performed',\n 'registry_web.signup_clicked',\n 'registry.item.resolved',\n 'registry.sync.completed',\n 'user.signup.completed',\n] as const;\n\nexport type DecantrTelemetryEventName = (typeof DECANTR_TELEMETRY_EVENT_NAMES)[number];\n\nexport type TelemetryPropertyValue =\n | TelemetryPropertyValue[]\n | boolean\n | null\n | number\n | string\n | undefined\n | { [key: string]: TelemetryPropertyValue };\n\nexport type TelemetryProperties = Record<string, TelemetryPropertyValue>;\n\nexport interface TelemetryContext {\n source: TelemetrySource;\n actorType?: TelemetryActorType;\n environment?: TelemetryEnvironment;\n serviceName?: string;\n serviceVersion?: string;\n decantrVersion?: string;\n registrySource?: RegistrySource;\n anonymousId?: string;\n installId?: string;\n projectId?: string;\n sessionId?: string;\n userId?: string;\n orgId?: string;\n}\n\nexport interface TelemetryActorResolutionOptions {\n internalAnonymousIds?: readonly string[] | ReadonlySet<string>;\n internalInstallIds?: readonly string[] | ReadonlySet<string>;\n internalOrgIds?: readonly string[] | ReadonlySet<string>;\n internalProjectIds?: readonly string[] | ReadonlySet<string>;\n internalUserIds?: readonly string[] | ReadonlySet<string>;\n}\n\nexport function isTelemetryActorType(value: unknown): value is TelemetryActorType {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACTOR_TYPES as readonly string[]).includes(value)\n );\n}\n\nexport function resolveTelemetryActorType(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions = {},\n): TelemetryActorType {\n if (context.actorType) return context.actorType;\n\n if (context.source === 'content-ci') {\n return 'official_pipeline';\n }\n\n if (matchesInternalActor(context, options)) {\n return 'internal';\n }\n\n if (context.userId || context.orgId || context.projectId || context.installId) {\n return 'customer';\n }\n\n if (context.anonymousId) {\n return 'anonymous';\n }\n\n return 'service';\n}\n\nfunction matchesInternalActor(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions,\n): boolean {\n return (\n idListHas(options.internalAnonymousIds, context.anonymousId) ||\n idListHas(options.internalInstallIds, context.installId) ||\n idListHas(options.internalOrgIds, context.orgId) ||\n idListHas(options.internalProjectIds, context.projectId) ||\n idListHas(options.internalUserIds, context.userId)\n );\n}\n\nfunction idListHas(\n values: readonly string[] | ReadonlySet<string> | undefined,\n value: string | undefined,\n): boolean {\n if (!values || !value) return false;\n if (typeof (values as ReadonlySet<string>).has === 'function') {\n return (values as ReadonlySet<string>).has(value);\n }\n return (values as readonly string[]).includes(value);\n}\n\nexport interface TelemetryEventBase<\n Name extends DecantrTelemetryEventName = DecantrTelemetryEventName,\n Properties extends TelemetryProperties = TelemetryProperties,\n> {\n name: Name;\n context: TelemetryContext;\n properties: Properties;\n timestamp?: Date | string;\n}\n\nexport interface CliCommandCompletedProperties extends TelemetryProperties {\n command: string;\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface RegistryItemResolvedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n cacheHit?: boolean;\n durationMs?: number;\n errorCode?: string;\n itemId?: string;\n namespace?: string;\n registrySource?: RegistrySource;\n version?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface RegistrySyncCompletedProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n registrySource?: RegistrySource;\n totalItems?: number;\n}\n\nexport interface ExecutionPackCompiledProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n pageCount?: number;\n patternCount?: number;\n sectionCount?: number;\n targetFramework?: string;\n}\n\nexport interface ExecutionPackSelectedProperties extends TelemetryProperties {\n packType: 'mutation' | 'page' | 'review' | 'scaffold' | 'section';\n success: boolean;\n durationMs?: number;\n errorCode?: string;\n id?: string;\n}\n\nexport interface AuditCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n pageCount?: number;\n runtimePassed?: boolean;\n score?: number;\n warnCount?: number;\n}\n\nexport interface CritiqueCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n infoCount?: number;\n overall?: number;\n warnCount?: number;\n}\n\nexport interface ContentValidationCompletedProperties extends TelemetryProperties {\n valid: boolean;\n contentType?: TelemetryContentType;\n durationMs?: number;\n errorCount?: number;\n itemCount?: number;\n warningCount?: number;\n}\n\nexport interface ContentPublishCompletedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n namespace?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface ProductEventProperties extends TelemetryProperties {\n success?: boolean;\n channel?: string;\n entrypoint?: string;\n plan?: string;\n}\n\nexport interface CampaignAttributionProperties extends TelemetryProperties {\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstLandingPath?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstUtmCampaign?: string | null;\n attributionFirstUtmContent?: string | null;\n attributionFirstUtmId?: string | null;\n attributionFirstUtmMedium?: string | null;\n attributionFirstUtmSource?: string | null;\n attributionFirstUtmTerm?: string | null;\n attributionLandingPath?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastUtmCampaign?: string | null;\n attributionLastUtmContent?: string | null;\n attributionLastUtmId?: string | null;\n attributionLastUtmMedium?: string | null;\n attributionLastUtmSource?: string | null;\n attributionLastUtmTerm?: string | null;\n attributionReferrerDomain?: string | null;\n attributionUtmCampaign?: string | null;\n attributionUtmContent?: string | null;\n attributionUtmId?: string | null;\n attributionUtmMedium?: string | null;\n attributionUtmSource?: string | null;\n attributionUtmTerm?: string | null;\n}\n\nexport interface MarketingWebPageViewedProperties extends CampaignAttributionProperties {\n routePath: string;\n surface: string;\n}\n\nexport interface MarketingWebCtaClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebOutboundClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebCommandClickedProperties extends CampaignAttributionProperties {\n commandKind: 'cli' | 'mcp' | 'other';\n commandLabel?: string | null;\n surface: string;\n}\n\nexport interface RegistryWebPageViewedProperties extends CampaignAttributionProperties {\n authenticated: boolean;\n orgScoped?: boolean;\n plan?: string;\n queryPresent?: boolean;\n route: string;\n routePath: string;\n surface: string;\n}\n\nexport interface RegistryWebSearchPerformedProperties extends CampaignAttributionProperties {\n contentType?: string;\n queryLength: number;\n resultCount?: number;\n sort?: string;\n sourceFilter?: string;\n surface: string;\n}\n\nexport interface RegistryWebContentOpenedProperties extends CampaignAttributionProperties {\n contentSource?: string;\n contentType: string;\n namespace?: string;\n slug?: string;\n surface: string;\n}\n\nexport interface RegistryWebCommercialPageViewedProperties extends CampaignAttributionProperties {\n orgScoped?: boolean;\n plan?: string;\n surface: string;\n}\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties>\n | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties>\n | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties>\n | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties>\n | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties>\n | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties>\n | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties>\n | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties>\n | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties>\n | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties>\n | TelemetryEventBase<'org.created', ProductEventProperties>\n | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties>\n | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties>\n | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties>\n | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties>\n | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n","import type { TelemetrySink } from './client.js';\nimport {\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n resolveTelemetryActorType,\n type DecantrTelemetryEvent,\n type TelemetryProperties,\n} from './events.js';\n\nexport interface PostHogTelemetrySinkOptions {\n apiKey: string;\n fetch?: typeof fetch;\n host?: string;\n processPersonProfile?: boolean;\n timeoutMs?: number;\n}\n\nexport function createPostHogTelemetrySink(options: PostHogTelemetrySinkOptions): TelemetrySink {\n const host = trimTrailingSlashes(options.host ?? 'https://us.i.posthog.com');\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async capture(event) {\n const distinctId = resolveDistinctId(event);\n if (!distinctId) {\n throw new Error(\n 'PostHog telemetry requires an opaque user, install, project, or anonymous id.',\n );\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 3000);\n\n try {\n const response = await fetchImpl(`${host}/i/v0/e/`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n api_key: options.apiKey,\n event: event.name,\n distinct_id: distinctId,\n properties: toPostHogProperties(event, options),\n timestamp: event.timestamp,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`PostHog capture returned HTTP ${response.status}.`);\n }\n } finally {\n clearTimeout(timeout);\n }\n },\n };\n}\n\nfunction trimTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) {\n end -= 1;\n }\n return value.slice(0, end);\n}\n\nfunction resolveDistinctId(event: DecantrTelemetryEvent): string | undefined {\n return (\n event.context.userId ??\n event.context.installId ??\n event.context.projectId ??\n event.context.anonymousId\n );\n}\n\nfunction toPostHogProperties(\n event: DecantrTelemetryEvent,\n options: PostHogTelemetrySinkOptions,\n): TelemetryProperties {\n const groups: Record<string, string> = {};\n if (event.context.orgId) groups.organization = event.context.orgId;\n if (event.context.projectId) groups.project = event.context.projectId;\n\n return {\n ...event.properties,\n $groups: groups,\n $process_person_profile: options.processPersonProfile ?? false,\n decantr_anonymous_id: event.context.anonymousId ?? null,\n decantr_actor_type: resolveTelemetryActorType(event.context),\n decantr_install_id: event.context.installId ?? null,\n decantr_org_id: event.context.orgId ?? null,\n decantr_project_id: event.context.projectId ?? null,\n decantr_session_id: event.context.sessionId ?? null,\n decantr_schema_version: DECANTR_TELEMETRY_SCHEMA_VERSION,\n decantr_source: event.context.source,\n decantr_environment: event.context.environment ?? 'production',\n decantr_version: event.context.decantrVersion ?? null,\n registry_source: event.context.registrySource ?? null,\n service_name: event.context.serviceName ?? null,\n service_version: event.context.serviceVersion ?? null,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/events.ts","../src/posthog.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.2.0';\n\nexport type TelemetrySource =\n | 'api'\n | 'cli'\n | 'content-ci'\n | 'marketing-web'\n | 'mcp'\n | 'registry-web';\nexport type TelemetryEnvironment = 'development' | 'preview' | 'production' | 'test';\nexport const DECANTR_TELEMETRY_ACTOR_TYPES = [\n 'anonymous',\n 'customer',\n 'internal',\n 'official_pipeline',\n 'service',\n] as const;\nexport type TelemetryActorType = (typeof DECANTR_TELEMETRY_ACTOR_TYPES)[number];\nexport type RegistrySource = 'cache' | 'custom' | 'none' | 'official' | 'private';\nexport type WorkflowMode =\n | 'brownfield-attach'\n | 'greenfield-contract-only'\n | 'greenfield-scaffold'\n | 'hybrid-compose';\nexport type AdoptionMode = 'contract-only' | 'decantr-css' | 'style-bridge';\nexport type ProjectScope = 'single-app' | 'workspace-app';\nexport type TelemetryContentType = 'archetype' | 'blueprint' | 'pattern' | 'shell' | 'theme';\nexport type TelemetryVisibility = 'private' | 'public' | 'team';\nexport type TelemetryAnalysisScope = 'hosted' | 'local';\nexport type ProjectHealthTelemetryStatus = 'error' | 'healthy' | 'warning';\nexport type ProjectHealthFindingSeverity = 'error' | 'info' | 'warn';\nexport type ProjectHealthFindingSource =\n | 'audit'\n | 'brownfield'\n | 'check'\n | 'interaction'\n | 'pack'\n | 'runtime';\nexport type ProjectHealthOutputFormat = 'json' | 'markdown' | 'text';\nexport type ProjectHealthFailOn = 'error' | 'none' | 'warn';\n\nexport const DECANTR_TELEMETRY_EVENT_NAMES = [\n 'api_key.created',\n 'audit.completed',\n 'cli.command.completed',\n 'content.publish.completed',\n 'content.validation.completed',\n 'critique.completed',\n 'decantr.check.completed',\n 'decantr.health.healthy',\n 'decantr.init.completed',\n 'decantr.new.completed',\n 'decantr.refresh.completed',\n 'execution_pack.compiled',\n 'execution_pack.selected',\n 'health.ci.failed',\n 'health.finding.prompt_requested',\n 'health.report.generated',\n 'marketing_web.command_clicked',\n 'marketing_web.cta_clicked',\n 'marketing_web.outbound_clicked',\n 'marketing_web.page_viewed',\n 'org.created',\n 'registry_web.api_key_page_viewed',\n 'registry_web.billing_viewed',\n 'registry_web.content_opened',\n 'registry_web.identity_linked',\n 'registry_web.organization_viewed',\n 'registry_web.page_viewed',\n 'registry_web.search_performed',\n 'registry_web.signup_clicked',\n 'registry.item.resolved',\n 'registry.sync.completed',\n 'studio.health_refreshed',\n 'studio.started',\n 'user.signup.completed',\n] as const;\n\nexport type DecantrTelemetryEventName = (typeof DECANTR_TELEMETRY_EVENT_NAMES)[number];\n\nexport type TelemetryPropertyValue =\n | TelemetryPropertyValue[]\n | boolean\n | null\n | number\n | string\n | undefined\n | { [key: string]: TelemetryPropertyValue };\n\nexport type TelemetryProperties = Record<string, TelemetryPropertyValue>;\n\nexport interface TelemetryContext {\n source: TelemetrySource;\n actorType?: TelemetryActorType;\n environment?: TelemetryEnvironment;\n serviceName?: string;\n serviceVersion?: string;\n decantrVersion?: string;\n registrySource?: RegistrySource;\n anonymousId?: string;\n installId?: string;\n projectId?: string;\n sessionId?: string;\n userId?: string;\n orgId?: string;\n}\n\nexport interface TelemetryActorResolutionOptions {\n internalAnonymousIds?: readonly string[] | ReadonlySet<string>;\n internalInstallIds?: readonly string[] | ReadonlySet<string>;\n internalOrgIds?: readonly string[] | ReadonlySet<string>;\n internalProjectIds?: readonly string[] | ReadonlySet<string>;\n internalUserIds?: readonly string[] | ReadonlySet<string>;\n}\n\nexport function isTelemetryActorType(value: unknown): value is TelemetryActorType {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACTOR_TYPES as readonly string[]).includes(value)\n );\n}\n\nexport function resolveTelemetryActorType(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions = {},\n): TelemetryActorType {\n if (context.actorType) return context.actorType;\n\n if (context.source === 'content-ci') {\n return 'official_pipeline';\n }\n\n if (matchesInternalActor(context, options)) {\n return 'internal';\n }\n\n if (context.userId || context.orgId || context.projectId || context.installId) {\n return 'customer';\n }\n\n if (context.anonymousId) {\n return 'anonymous';\n }\n\n return 'service';\n}\n\nfunction matchesInternalActor(\n context: TelemetryContext,\n options: TelemetryActorResolutionOptions,\n): boolean {\n return (\n idListHas(options.internalAnonymousIds, context.anonymousId) ||\n idListHas(options.internalInstallIds, context.installId) ||\n idListHas(options.internalOrgIds, context.orgId) ||\n idListHas(options.internalProjectIds, context.projectId) ||\n idListHas(options.internalUserIds, context.userId)\n );\n}\n\nfunction idListHas(\n values: readonly string[] | ReadonlySet<string> | undefined,\n value: string | undefined,\n): boolean {\n if (!values || !value) return false;\n if (typeof (values as ReadonlySet<string>).has === 'function') {\n return (values as ReadonlySet<string>).has(value);\n }\n return (values as readonly string[]).includes(value);\n}\n\nexport interface TelemetryEventBase<\n Name extends DecantrTelemetryEventName = DecantrTelemetryEventName,\n Properties extends TelemetryProperties = TelemetryProperties,\n> {\n name: Name;\n context: TelemetryContext;\n properties: Properties;\n timestamp?: Date | string;\n}\n\nexport interface CliCommandCompletedProperties extends TelemetryProperties {\n command: string;\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface DecantrLifecycleCompletedProperties extends TelemetryProperties {\n command: 'check' | 'init' | 'new' | 'refresh';\n success: boolean;\n durationMs: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n offline?: boolean;\n projectScope?: ProjectScope;\n registrySource?: RegistrySource;\n targetFramework?: string;\n workflowMode?: WorkflowMode;\n}\n\nexport interface ProjectHealthTelemetryProperties extends TelemetryProperties {\n success: boolean;\n status: ProjectHealthTelemetryStatus;\n score: number;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n ci?: boolean;\n errorCode?: string;\n errorCount: number;\n failOn?: ProjectHealthFailOn;\n findingCount: number;\n format?: ProjectHealthOutputFormat;\n infoCount: number;\n outputWritten?: boolean;\n packManifestPresent?: boolean;\n pageCount?: number;\n projectScope?: ProjectScope;\n reviewPackPresent?: boolean;\n routeCount?: number;\n runtimeAuditChecked?: boolean;\n runtimeMatchedCount?: number;\n runtimePassed?: boolean | null;\n runtimeRouteCheckedCount?: number;\n warnCount: number;\n workflowMode?: WorkflowMode;\n}\n\nexport interface HealthFindingPromptRequestedProperties extends TelemetryProperties {\n success: boolean;\n findingFound: boolean;\n adoptionMode?: AdoptionMode;\n ci?: boolean;\n findingSeverity?: ProjectHealthFindingSeverity;\n findingSource?: ProjectHealthFindingSource;\n projectScope?: ProjectScope;\n workflowMode?: WorkflowMode;\n}\n\nexport interface HealthCiFailedProperties extends ProjectHealthTelemetryProperties {\n failOn: 'error' | 'warn';\n}\n\nexport interface StudioStartedProperties extends TelemetryProperties {\n success: boolean;\n hostMode: 'custom' | 'loopback';\n port: number;\n adoptionMode?: AdoptionMode;\n errorCode?: string;\n projectScope?: ProjectScope;\n workflowMode?: WorkflowMode;\n}\n\nexport interface StudioHealthRefreshedProperties extends ProjectHealthTelemetryProperties {\n trigger: 'api-refresh';\n}\n\nexport interface RegistryItemResolvedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n cacheHit?: boolean;\n durationMs?: number;\n errorCode?: string;\n itemId?: string;\n namespace?: string;\n registrySource?: RegistrySource;\n version?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface RegistrySyncCompletedProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n registrySource?: RegistrySource;\n totalItems?: number;\n}\n\nexport interface ExecutionPackCompiledProperties extends TelemetryProperties {\n success: boolean;\n durationMs: number;\n errorCode?: string;\n pageCount?: number;\n patternCount?: number;\n sectionCount?: number;\n targetFramework?: string;\n}\n\nexport interface ExecutionPackSelectedProperties extends TelemetryProperties {\n packType: 'mutation' | 'page' | 'review' | 'scaffold' | 'section';\n success: boolean;\n durationMs?: number;\n errorCode?: string;\n id?: string;\n}\n\nexport interface AuditCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n pageCount?: number;\n runtimePassed?: boolean;\n score?: number;\n warnCount?: number;\n}\n\nexport interface CritiqueCompletedProperties extends TelemetryProperties {\n scope: TelemetryAnalysisScope;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n errorCount?: number;\n infoCount?: number;\n overall?: number;\n warnCount?: number;\n}\n\nexport interface ContentValidationCompletedProperties extends TelemetryProperties {\n valid: boolean;\n contentType?: TelemetryContentType;\n durationMs?: number;\n errorCount?: number;\n itemCount?: number;\n warningCount?: number;\n}\n\nexport interface ContentPublishCompletedProperties extends TelemetryProperties {\n contentType: TelemetryContentType;\n success: boolean;\n durationMs: number;\n errorCode?: string;\n namespace?: string;\n visibility?: TelemetryVisibility;\n}\n\nexport interface ProductEventProperties extends TelemetryProperties {\n success?: boolean;\n channel?: string;\n entrypoint?: string;\n plan?: string;\n}\n\nexport interface CampaignAttributionProperties extends TelemetryProperties {\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstLandingPath?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstUtmCampaign?: string | null;\n attributionFirstUtmContent?: string | null;\n attributionFirstUtmId?: string | null;\n attributionFirstUtmMedium?: string | null;\n attributionFirstUtmSource?: string | null;\n attributionFirstUtmTerm?: string | null;\n attributionLandingPath?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastUtmCampaign?: string | null;\n attributionLastUtmContent?: string | null;\n attributionLastUtmId?: string | null;\n attributionLastUtmMedium?: string | null;\n attributionLastUtmSource?: string | null;\n attributionLastUtmTerm?: string | null;\n attributionReferrerDomain?: string | null;\n attributionUtmCampaign?: string | null;\n attributionUtmContent?: string | null;\n attributionUtmId?: string | null;\n attributionUtmMedium?: string | null;\n attributionUtmSource?: string | null;\n attributionUtmTerm?: string | null;\n}\n\nexport interface MarketingWebPageViewedProperties extends CampaignAttributionProperties {\n routePath: string;\n surface: string;\n}\n\nexport interface MarketingWebCtaClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebOutboundClickedProperties extends CampaignAttributionProperties {\n destination: string;\n label?: string | null;\n surface: string;\n}\n\nexport interface MarketingWebCommandClickedProperties extends CampaignAttributionProperties {\n commandKind: 'cli' | 'mcp' | 'other';\n commandLabel?: string | null;\n surface: string;\n}\n\nexport interface RegistryWebPageViewedProperties extends CampaignAttributionProperties {\n authenticated: boolean;\n orgScoped?: boolean;\n plan?: string;\n queryPresent?: boolean;\n route: string;\n routePath: string;\n surface: string;\n}\n\nexport interface RegistryWebSearchPerformedProperties extends CampaignAttributionProperties {\n contentType?: string;\n queryLength: number;\n resultCount?: number;\n sort?: string;\n sourceFilter?: string;\n surface: string;\n}\n\nexport interface RegistryWebContentOpenedProperties extends CampaignAttributionProperties {\n contentSource?: string;\n contentType: string;\n namespace?: string;\n slug?: string;\n surface: string;\n}\n\nexport interface RegistryWebCommercialPageViewedProperties extends CampaignAttributionProperties {\n orgScoped?: boolean;\n plan?: string;\n surface: string;\n}\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'cli.command.completed', CliCommandCompletedProperties>\n | TelemetryEventBase<'content.publish.completed', ContentPublishCompletedProperties>\n | TelemetryEventBase<'content.validation.completed', ContentValidationCompletedProperties>\n | TelemetryEventBase<'critique.completed', CritiqueCompletedProperties>\n | TelemetryEventBase<'decantr.check.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.health.healthy', ProjectHealthTelemetryProperties>\n | TelemetryEventBase<'decantr.init.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.new.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'decantr.refresh.completed', DecantrLifecycleCompletedProperties>\n | TelemetryEventBase<'execution_pack.compiled', ExecutionPackCompiledProperties>\n | TelemetryEventBase<'execution_pack.selected', ExecutionPackSelectedProperties>\n | TelemetryEventBase<'health.ci.failed', HealthCiFailedProperties>\n | TelemetryEventBase<'health.finding.prompt_requested', HealthFindingPromptRequestedProperties>\n | TelemetryEventBase<'health.report.generated', ProjectHealthTelemetryProperties>\n | TelemetryEventBase<'marketing_web.command_clicked', MarketingWebCommandClickedProperties>\n | TelemetryEventBase<'marketing_web.cta_clicked', MarketingWebCtaClickedProperties>\n | TelemetryEventBase<'marketing_web.outbound_clicked', MarketingWebOutboundClickedProperties>\n | TelemetryEventBase<'marketing_web.page_viewed', MarketingWebPageViewedProperties>\n | TelemetryEventBase<'org.created', ProductEventProperties>\n | TelemetryEventBase<'registry_web.api_key_page_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.billing_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.content_opened', RegistryWebContentOpenedProperties>\n | TelemetryEventBase<'registry_web.identity_linked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.organization_viewed', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry_web.page_viewed', RegistryWebPageViewedProperties>\n | TelemetryEventBase<'registry_web.search_performed', RegistryWebSearchPerformedProperties>\n | TelemetryEventBase<'registry_web.signup_clicked', RegistryWebCommercialPageViewedProperties>\n | TelemetryEventBase<'registry.item.resolved', RegistryItemResolvedProperties>\n | TelemetryEventBase<'registry.sync.completed', RegistrySyncCompletedProperties>\n | TelemetryEventBase<'studio.health_refreshed', StudioHealthRefreshedProperties>\n | TelemetryEventBase<'studio.started', StudioStartedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n","import type { TelemetrySink } from './client.js';\nimport {\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n resolveTelemetryActorType,\n type DecantrTelemetryEvent,\n type TelemetryProperties,\n} from './events.js';\n\nexport interface PostHogTelemetrySinkOptions {\n apiKey: string;\n fetch?: typeof fetch;\n host?: string;\n processPersonProfile?: boolean;\n timeoutMs?: number;\n}\n\nexport function createPostHogTelemetrySink(options: PostHogTelemetrySinkOptions): TelemetrySink {\n const host = trimTrailingSlashes(options.host ?? 'https://us.i.posthog.com');\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async capture(event) {\n const distinctId = resolveDistinctId(event);\n if (!distinctId) {\n throw new Error(\n 'PostHog telemetry requires an opaque user, install, project, or anonymous id.',\n );\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 3000);\n\n try {\n const response = await fetchImpl(`${host}/i/v0/e/`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n api_key: options.apiKey,\n event: event.name,\n distinct_id: distinctId,\n properties: toPostHogProperties(event, options),\n timestamp: event.timestamp,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`PostHog capture returned HTTP ${response.status}.`);\n }\n } finally {\n clearTimeout(timeout);\n }\n },\n };\n}\n\nfunction trimTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) {\n end -= 1;\n }\n return value.slice(0, end);\n}\n\nfunction resolveDistinctId(event: DecantrTelemetryEvent): string | undefined {\n return (\n event.context.userId ??\n event.context.installId ??\n event.context.projectId ??\n event.context.anonymousId\n );\n}\n\nfunction toPostHogProperties(\n event: DecantrTelemetryEvent,\n options: PostHogTelemetrySinkOptions,\n): TelemetryProperties {\n const groups: Record<string, string> = {};\n if (event.context.orgId) groups.organization = event.context.orgId;\n if (event.context.projectId) groups.project = event.context.projectId;\n\n return {\n ...event.properties,\n $groups: groups,\n $process_person_profile: options.processPersonProfile ?? false,\n decantr_anonymous_id: event.context.anonymousId ?? null,\n decantr_actor_type: resolveTelemetryActorType(event.context),\n decantr_install_id: event.context.installId ?? null,\n decantr_org_id: event.context.orgId ?? null,\n decantr_project_id: event.context.projectId ?? null,\n decantr_session_id: event.context.sessionId ?? null,\n decantr_schema_version: DECANTR_TELEMETRY_SCHEMA_VERSION,\n decantr_source: event.context.source,\n decantr_environment: event.context.environment ?? 'production',\n decantr_version: event.context.decantrVersion ?? null,\n registry_source: event.context.registrySource ?? null,\n service_name: event.context.serviceName ?? null,\n service_version: event.context.serviceVersion ?? null,\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decantr/telemetry",
3
- "version": "0.2.0",
3
+ "version": "2.1.0",
4
4
  "description": "Privacy-preserving telemetry contracts, clients, and analytics sinks for Decantr",
5
5
  "author": "Decantr AI",
6
6
  "license": "MIT",