@decantr/telemetry 2.2.1 → 3.0.0-next.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 +4 -0
- package/dist/client.js.map +1 -1
- package/dist/events.d.ts +15 -0
- package/dist/events.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/posthog.js.map +1 -1
- package/package.json +12 -1
package/README.md
CHANGED
|
@@ -74,6 +74,10 @@ The registry admin portal exposes `/admin/telemetry` for managing `anonymous`, `
|
|
|
74
74
|
|
|
75
75
|
The shared client redacts sensitive keys before any sink receives an event. This includes prompts, source code, file paths, repository names, raw route names, package slugs, emails, tokens, cookies, URLs, user agents, and authorization fields, while preserving aggregate product fields such as command, duration, success, counts, workflow mode, and signal bucket metadata.
|
|
76
76
|
|
|
77
|
+
## Security And Permissions
|
|
78
|
+
|
|
79
|
+
This package defines telemetry contracts, redaction, clients, and optional sinks. It does not auto-start collection. Events are emitted only when a caller constructs a client and calls `capture`. The Decantr CLI remains opt-in for telemetry; use `decantr telemetry explain` for the shareable review view. See [security permissions](https://decantr.ai/reference/security-permissions.md).
|
|
80
|
+
|
|
77
81
|
## Campaign Attribution
|
|
78
82
|
|
|
79
83
|
The marketing site and registry can attach campaign attribution fields to web events: UTM source/medium/campaign/content/term/id, first and last touch variants, landing path, referrer domain, click-id provider, and whether a supported click id was present. Raw ad click ids such as `twclid`, `gclid`, `gbraid`, `wbraid`, `fbclid`, `msclkid`, `ttclid`, and `li_fat_id` are not included in Decantr telemetry.
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/events.ts","../src/privacy.ts","../src/client.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.3.0';\nexport const DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS = [\n '0.2.0',\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n] as const;\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';\nexport type TelemetrySignalBucket =\n | 'activation'\n | 'billing_intent'\n | 'cli_adoption'\n | 'commercial_intent'\n | 'content_pipeline'\n | 'hosted_intelligence'\n | 'identity_hygiene'\n | 'paid_acquisition'\n | 'private_registry_readiness'\n | 'product_activation'\n | 'project_health'\n | 'registry_discovery';\nexport type TelemetryPrivacyClass = 'aggregate' | 'opaque_identity' | 'public_metadata';\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.analyze.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 'billing.checkout_blocked',\n 'billing.plan_clicked',\n 'private_registry.content_listed',\n 'private_registry.gate_viewed',\n 'private_registry.intent_clicked',\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 'telemetry.identity_linked',\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 DecantrAnalyzeCompletedProperties extends TelemetryProperties {\n command: 'analyze';\n success: boolean;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n componentCount?: number;\n dependencyCategoryCount?: number;\n errorCode?: string;\n pageCount?: number;\n projectScope?: ProjectScope;\n routeCount?: number;\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 interface TelemetryIdentityLinkedProperties extends TelemetryProperties {\n success: boolean;\n entrypoint?: string;\n identityType?: 'anonymous' | 'install' | 'project';\n linkCount?: number;\n orgScoped?: boolean;\n plan?: string;\n surface?: string;\n}\n\nexport interface PrivateRegistryGateViewedProperties extends TelemetryProperties {\n orgScoped: boolean;\n plan?: string;\n surface: string;\n enterpriseOrgCount?: number;\n}\n\nexport interface PrivateRegistryIntentClickedProperties extends TelemetryProperties {\n action: 'open_billing' | 'open_team' | 'open_private_registry';\n orgScoped: boolean;\n plan?: string;\n surface: string;\n}\n\nexport interface PrivateRegistryContentListedProperties extends TelemetryProperties {\n itemCount: number;\n orgScoped: true;\n plan?: string;\n queryPresent?: boolean;\n statusFilterPresent?: boolean;\n surface: string;\n typeFilterPresent?: boolean;\n visibilityFilterPresent?: boolean;\n}\n\nexport interface BillingPlanClickedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n currentPlan?: string;\n orgScoped?: boolean;\n plan: 'enterprise' | 'pro' | 'team';\n surface: string;\n}\n\nexport interface BillingCheckoutBlockedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n orgScoped?: boolean;\n plan?: 'enterprise' | 'pro' | 'team';\n reason: 'billing_coming_soon' | 'billing_not_configured' | 'not_authorized';\n surface: string;\n}\n\nexport interface TelemetryEventCatalogEntry {\n name: DecantrTelemetryEventName;\n allowedSources: readonly TelemetrySource[];\n bucket: TelemetrySignalBucket;\n privacy: TelemetryPrivacyClass;\n privacyNotes: string;\n publicIngest: boolean;\n}\n\nconst API_ONLY = ['api'] as const;\nconst CLI_ONLY = ['cli'] as const;\nconst REGISTRY_WEB_ONLY = ['registry-web'] as const;\nconst MARKETING_WEB_ONLY = ['marketing-web'] as const;\nconst CONTENT_CI_AND_API = ['content-ci', 'api'] as const;\nconst REGISTRY_RESOLUTION_SOURCES = ['api', 'cli', 'mcp'] as const;\n\nexport const DECANTR_TELEMETRY_EVENT_CATALOG: readonly TelemetryEventCatalogEntry[] = [\n eventCatalogEntry('api_key.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('audit.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('cli.command.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('content.publish.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('content.validation.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('critique.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('decantr.analyze.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.check.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.health.healthy', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('decantr.init.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.new.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.refresh.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('execution_pack.compiled', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('execution_pack.selected', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('health.ci.failed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.finding.prompt_requested', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.report.generated', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('marketing_web.command_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.cta_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.outbound_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.page_viewed', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('org.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('billing.checkout_blocked', ['api', 'registry-web'], 'billing_intent', 'aggregate', true),\n eventCatalogEntry('billing.plan_clicked', REGISTRY_WEB_ONLY, 'billing_intent', 'aggregate', true),\n eventCatalogEntry('private_registry.content_listed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.gate_viewed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.intent_clicked', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('registry_web.api_key_page_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.billing_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.content_opened', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.identity_linked', REGISTRY_WEB_ONLY, 'identity_hygiene', 'opaque_identity', true),\n eventCatalogEntry('registry_web.organization_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'aggregate', true),\n eventCatalogEntry('registry_web.page_viewed', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.search_performed', REGISTRY_WEB_ONLY, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry_web.signup_clicked', REGISTRY_WEB_ONLY, 'activation', 'public_metadata', true),\n eventCatalogEntry('registry.item.resolved', REGISTRY_RESOLUTION_SOURCES, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry.sync.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('studio.health_refreshed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('studio.started', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('telemetry.identity_linked', API_ONLY, 'identity_hygiene', 'opaque_identity', false),\n eventCatalogEntry('user.signup.completed', API_ONLY, 'activation', 'aggregate', false),\n];\n\nconst TELEMETRY_EVENT_CATALOG_BY_NAME = new Map(\n DECANTR_TELEMETRY_EVENT_CATALOG.map((entry) => [entry.name, entry]),\n);\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'billing.checkout_blocked', BillingCheckoutBlockedProperties>\n | TelemetryEventBase<'billing.plan_clicked', BillingPlanClickedProperties>\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.analyze.completed', DecantrAnalyzeCompletedProperties>\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<'private_registry.content_listed', PrivateRegistryContentListedProperties>\n | TelemetryEventBase<'private_registry.gate_viewed', PrivateRegistryGateViewedProperties>\n | TelemetryEventBase<'private_registry.intent_clicked', PrivateRegistryIntentClickedProperties>\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<'telemetry.identity_linked', TelemetryIdentityLinkedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetrySchemaVersion(\n value: unknown,\n): value is (typeof DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS)[number] {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS as readonly string[]).includes(value)\n );\n}\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n\nexport function getTelemetryEventCatalogEntry(\n name: DecantrTelemetryEventName,\n): TelemetryEventCatalogEntry {\n return TELEMETRY_EVENT_CATALOG_BY_NAME.get(name)!;\n}\n\nexport function isTelemetryEventAllowedForSource(\n name: DecantrTelemetryEventName,\n source: TelemetrySource,\n): boolean {\n return getTelemetryEventCatalogEntry(name).allowedSources.includes(source);\n}\n\nfunction eventCatalogEntry(\n name: DecantrTelemetryEventName,\n allowedSources: readonly TelemetrySource[],\n bucket: TelemetrySignalBucket,\n privacy: TelemetryPrivacyClass,\n publicIngest: boolean,\n): TelemetryEventCatalogEntry {\n return {\n name,\n allowedSources,\n bucket,\n privacy,\n publicIngest,\n privacyNotes:\n privacy === 'aggregate'\n ? 'Aggregate product metadata only; no source, prompts, raw paths, emails, or secrets.'\n : privacy === 'opaque_identity'\n ? 'Opaque Decantr identity ids only; no emails, source, prompts, raw paths, or secrets.'\n : 'Public product or acquisition metadata only; no raw referrer URLs, user agents, emails, or click ids.',\n };\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 /^package[_-]?slug$/i,\n /^password$/i,\n /^path$/i,\n /^prompt$/i,\n /^private[_-]?package[_-]?slug$/i,\n /^repo$/i,\n /^repository$/i,\n /^repository[_-]?name$/i,\n /^route[_-]?name$/i,\n /^route[_-]?names$/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.3.0';\nexport const DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS = [\n '0.2.0',\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n] as const;\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';\nexport type TelemetrySignalBucket =\n | 'activation'\n | 'billing_intent'\n | 'cli_adoption'\n | 'commercial_intent'\n | 'content_pipeline'\n | 'hosted_intelligence'\n | 'identity_hygiene'\n | 'paid_acquisition'\n | 'private_registry_readiness'\n | 'product_activation'\n | 'project_health'\n | 'registry_discovery';\nexport type TelemetryPrivacyClass = 'aggregate' | 'opaque_identity' | 'public_metadata';\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.analyze.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 'billing.checkout_blocked',\n 'billing.plan_clicked',\n 'private_registry.content_listed',\n 'private_registry.gate_viewed',\n 'private_registry.intent_clicked',\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 'telemetry.identity_linked',\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 DecantrAnalyzeCompletedProperties extends TelemetryProperties {\n command: 'analyze';\n success: boolean;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n componentCount?: number;\n dependencyCategoryCount?: number;\n errorCode?: string;\n pageCount?: number;\n projectScope?: ProjectScope;\n routeCount?: number;\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 attributionChannel?: string | null;\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstChannel?: string | null;\n attributionFirstLandingPath?: string | null;\n attributionFirstLandingIntent?: string | null;\n attributionFirstLandingPageKind?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstSource?: string | null;\n attributionFirstSourceCategory?: 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 attributionLandingIntent?: string | null;\n attributionLandingPageKind?: string | null;\n attributionLastChannel?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastLandingIntent?: string | null;\n attributionLastLandingPageKind?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastSource?: string | null;\n attributionLastSourceCategory?: 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 attributionSource?: string | null;\n attributionSourceCategory?: 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 interface TelemetryIdentityLinkedProperties extends TelemetryProperties {\n success: boolean;\n entrypoint?: string;\n identityType?: 'anonymous' | 'install' | 'project';\n linkCount?: number;\n orgScoped?: boolean;\n plan?: string;\n surface?: string;\n}\n\nexport interface PrivateRegistryGateViewedProperties extends TelemetryProperties {\n orgScoped: boolean;\n plan?: string;\n surface: string;\n enterpriseOrgCount?: number;\n}\n\nexport interface PrivateRegistryIntentClickedProperties extends TelemetryProperties {\n action: 'open_billing' | 'open_team' | 'open_private_registry';\n orgScoped: boolean;\n plan?: string;\n surface: string;\n}\n\nexport interface PrivateRegistryContentListedProperties extends TelemetryProperties {\n itemCount: number;\n orgScoped: true;\n plan?: string;\n queryPresent?: boolean;\n statusFilterPresent?: boolean;\n surface: string;\n typeFilterPresent?: boolean;\n visibilityFilterPresent?: boolean;\n}\n\nexport interface BillingPlanClickedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n currentPlan?: string;\n orgScoped?: boolean;\n plan: 'enterprise' | 'pro' | 'team';\n surface: string;\n}\n\nexport interface BillingCheckoutBlockedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n orgScoped?: boolean;\n plan?: 'enterprise' | 'pro' | 'team';\n reason: 'billing_coming_soon' | 'billing_not_configured' | 'not_authorized';\n surface: string;\n}\n\nexport interface TelemetryEventCatalogEntry {\n name: DecantrTelemetryEventName;\n allowedSources: readonly TelemetrySource[];\n bucket: TelemetrySignalBucket;\n privacy: TelemetryPrivacyClass;\n privacyNotes: string;\n publicIngest: boolean;\n}\n\nconst API_ONLY = ['api'] as const;\nconst CLI_ONLY = ['cli'] as const;\nconst REGISTRY_WEB_ONLY = ['registry-web'] as const;\nconst MARKETING_WEB_ONLY = ['marketing-web'] as const;\nconst CONTENT_CI_AND_API = ['content-ci', 'api'] as const;\nconst REGISTRY_RESOLUTION_SOURCES = ['api', 'cli', 'mcp'] as const;\n\nexport const DECANTR_TELEMETRY_EVENT_CATALOG: readonly TelemetryEventCatalogEntry[] = [\n eventCatalogEntry('api_key.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('audit.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('cli.command.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('content.publish.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('content.validation.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('critique.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('decantr.analyze.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.check.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.health.healthy', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('decantr.init.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.new.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.refresh.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('execution_pack.compiled', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('execution_pack.selected', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('health.ci.failed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.finding.prompt_requested', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.report.generated', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('marketing_web.command_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.cta_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.outbound_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.page_viewed', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('org.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('billing.checkout_blocked', ['api', 'registry-web'], 'billing_intent', 'aggregate', true),\n eventCatalogEntry('billing.plan_clicked', REGISTRY_WEB_ONLY, 'billing_intent', 'aggregate', true),\n eventCatalogEntry('private_registry.content_listed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.gate_viewed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.intent_clicked', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('registry_web.api_key_page_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.billing_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.content_opened', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.identity_linked', REGISTRY_WEB_ONLY, 'identity_hygiene', 'opaque_identity', true),\n eventCatalogEntry('registry_web.organization_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'aggregate', true),\n eventCatalogEntry('registry_web.page_viewed', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.search_performed', REGISTRY_WEB_ONLY, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry_web.signup_clicked', REGISTRY_WEB_ONLY, 'activation', 'public_metadata', true),\n eventCatalogEntry('registry.item.resolved', REGISTRY_RESOLUTION_SOURCES, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry.sync.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('studio.health_refreshed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('studio.started', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('telemetry.identity_linked', API_ONLY, 'identity_hygiene', 'opaque_identity', false),\n eventCatalogEntry('user.signup.completed', API_ONLY, 'activation', 'aggregate', false),\n];\n\nconst TELEMETRY_EVENT_CATALOG_BY_NAME = new Map(\n DECANTR_TELEMETRY_EVENT_CATALOG.map((entry) => [entry.name, entry]),\n);\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'billing.checkout_blocked', BillingCheckoutBlockedProperties>\n | TelemetryEventBase<'billing.plan_clicked', BillingPlanClickedProperties>\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.analyze.completed', DecantrAnalyzeCompletedProperties>\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<'private_registry.content_listed', PrivateRegistryContentListedProperties>\n | TelemetryEventBase<'private_registry.gate_viewed', PrivateRegistryGateViewedProperties>\n | TelemetryEventBase<'private_registry.intent_clicked', PrivateRegistryIntentClickedProperties>\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<'telemetry.identity_linked', TelemetryIdentityLinkedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetrySchemaVersion(\n value: unknown,\n): value is (typeof DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS)[number] {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS as readonly string[]).includes(value)\n );\n}\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n\nexport function getTelemetryEventCatalogEntry(\n name: DecantrTelemetryEventName,\n): TelemetryEventCatalogEntry {\n return TELEMETRY_EVENT_CATALOG_BY_NAME.get(name)!;\n}\n\nexport function isTelemetryEventAllowedForSource(\n name: DecantrTelemetryEventName,\n source: TelemetrySource,\n): boolean {\n return getTelemetryEventCatalogEntry(name).allowedSources.includes(source);\n}\n\nfunction eventCatalogEntry(\n name: DecantrTelemetryEventName,\n allowedSources: readonly TelemetrySource[],\n bucket: TelemetrySignalBucket,\n privacy: TelemetryPrivacyClass,\n publicIngest: boolean,\n): TelemetryEventCatalogEntry {\n return {\n name,\n allowedSources,\n bucket,\n privacy,\n publicIngest,\n privacyNotes:\n privacy === 'aggregate'\n ? 'Aggregate product metadata only; no source, prompts, raw paths, emails, or secrets.'\n : privacy === 'opaque_identity'\n ? 'Opaque Decantr identity ids only; no emails, source, prompts, raw paths, or secrets.'\n : 'Public product or acquisition metadata only; no raw referrer URLs, user agents, emails, or click ids.',\n };\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 /^package[_-]?slug$/i,\n /^password$/i,\n /^path$/i,\n /^prompt$/i,\n /^private[_-]?package[_-]?slug$/i,\n /^repo$/i,\n /^repository$/i,\n /^repository[_-]?name$/i,\n /^route[_-]?name$/i,\n /^route[_-]?names$/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
|
@@ -222,10 +222,16 @@ interface ProductEventProperties extends TelemetryProperties {
|
|
|
222
222
|
plan?: string;
|
|
223
223
|
}
|
|
224
224
|
interface CampaignAttributionProperties extends TelemetryProperties {
|
|
225
|
+
attributionChannel?: string | null;
|
|
225
226
|
attributionClickIdProvider?: string | null;
|
|
226
227
|
attributionClickIdPresent?: boolean;
|
|
228
|
+
attributionFirstChannel?: string | null;
|
|
227
229
|
attributionFirstLandingPath?: string | null;
|
|
230
|
+
attributionFirstLandingIntent?: string | null;
|
|
231
|
+
attributionFirstLandingPageKind?: string | null;
|
|
228
232
|
attributionFirstReferrerDomain?: string | null;
|
|
233
|
+
attributionFirstSource?: string | null;
|
|
234
|
+
attributionFirstSourceCategory?: string | null;
|
|
229
235
|
attributionFirstUtmCampaign?: string | null;
|
|
230
236
|
attributionFirstUtmContent?: string | null;
|
|
231
237
|
attributionFirstUtmId?: string | null;
|
|
@@ -233,8 +239,15 @@ interface CampaignAttributionProperties extends TelemetryProperties {
|
|
|
233
239
|
attributionFirstUtmSource?: string | null;
|
|
234
240
|
attributionFirstUtmTerm?: string | null;
|
|
235
241
|
attributionLandingPath?: string | null;
|
|
242
|
+
attributionLandingIntent?: string | null;
|
|
243
|
+
attributionLandingPageKind?: string | null;
|
|
244
|
+
attributionLastChannel?: string | null;
|
|
236
245
|
attributionLastLandingPath?: string | null;
|
|
246
|
+
attributionLastLandingIntent?: string | null;
|
|
247
|
+
attributionLastLandingPageKind?: string | null;
|
|
237
248
|
attributionLastReferrerDomain?: string | null;
|
|
249
|
+
attributionLastSource?: string | null;
|
|
250
|
+
attributionLastSourceCategory?: string | null;
|
|
238
251
|
attributionLastUtmCampaign?: string | null;
|
|
239
252
|
attributionLastUtmContent?: string | null;
|
|
240
253
|
attributionLastUtmId?: string | null;
|
|
@@ -242,6 +255,8 @@ interface CampaignAttributionProperties extends TelemetryProperties {
|
|
|
242
255
|
attributionLastUtmSource?: string | null;
|
|
243
256
|
attributionLastUtmTerm?: string | null;
|
|
244
257
|
attributionReferrerDomain?: string | null;
|
|
258
|
+
attributionSource?: string | null;
|
|
259
|
+
attributionSourceCategory?: string | null;
|
|
245
260
|
attributionUtmCampaign?: string | null;
|
|
246
261
|
attributionUtmContent?: string | null;
|
|
247
262
|
attributionUtmId?: string | null;
|
package/dist/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/events.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.3.0';\nexport const DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS = [\n '0.2.0',\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n] as const;\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';\nexport type TelemetrySignalBucket =\n | 'activation'\n | 'billing_intent'\n | 'cli_adoption'\n | 'commercial_intent'\n | 'content_pipeline'\n | 'hosted_intelligence'\n | 'identity_hygiene'\n | 'paid_acquisition'\n | 'private_registry_readiness'\n | 'product_activation'\n | 'project_health'\n | 'registry_discovery';\nexport type TelemetryPrivacyClass = 'aggregate' | 'opaque_identity' | 'public_metadata';\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.analyze.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 'billing.checkout_blocked',\n 'billing.plan_clicked',\n 'private_registry.content_listed',\n 'private_registry.gate_viewed',\n 'private_registry.intent_clicked',\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 'telemetry.identity_linked',\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 DecantrAnalyzeCompletedProperties extends TelemetryProperties {\n command: 'analyze';\n success: boolean;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n componentCount?: number;\n dependencyCategoryCount?: number;\n errorCode?: string;\n pageCount?: number;\n projectScope?: ProjectScope;\n routeCount?: number;\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 interface TelemetryIdentityLinkedProperties extends TelemetryProperties {\n success: boolean;\n entrypoint?: string;\n identityType?: 'anonymous' | 'install' | 'project';\n linkCount?: number;\n orgScoped?: boolean;\n plan?: string;\n surface?: string;\n}\n\nexport interface PrivateRegistryGateViewedProperties extends TelemetryProperties {\n orgScoped: boolean;\n plan?: string;\n surface: string;\n enterpriseOrgCount?: number;\n}\n\nexport interface PrivateRegistryIntentClickedProperties extends TelemetryProperties {\n action: 'open_billing' | 'open_team' | 'open_private_registry';\n orgScoped: boolean;\n plan?: string;\n surface: string;\n}\n\nexport interface PrivateRegistryContentListedProperties extends TelemetryProperties {\n itemCount: number;\n orgScoped: true;\n plan?: string;\n queryPresent?: boolean;\n statusFilterPresent?: boolean;\n surface: string;\n typeFilterPresent?: boolean;\n visibilityFilterPresent?: boolean;\n}\n\nexport interface BillingPlanClickedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n currentPlan?: string;\n orgScoped?: boolean;\n plan: 'enterprise' | 'pro' | 'team';\n surface: string;\n}\n\nexport interface BillingCheckoutBlockedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n orgScoped?: boolean;\n plan?: 'enterprise' | 'pro' | 'team';\n reason: 'billing_coming_soon' | 'billing_not_configured' | 'not_authorized';\n surface: string;\n}\n\nexport interface TelemetryEventCatalogEntry {\n name: DecantrTelemetryEventName;\n allowedSources: readonly TelemetrySource[];\n bucket: TelemetrySignalBucket;\n privacy: TelemetryPrivacyClass;\n privacyNotes: string;\n publicIngest: boolean;\n}\n\nconst API_ONLY = ['api'] as const;\nconst CLI_ONLY = ['cli'] as const;\nconst REGISTRY_WEB_ONLY = ['registry-web'] as const;\nconst MARKETING_WEB_ONLY = ['marketing-web'] as const;\nconst CONTENT_CI_AND_API = ['content-ci', 'api'] as const;\nconst REGISTRY_RESOLUTION_SOURCES = ['api', 'cli', 'mcp'] as const;\n\nexport const DECANTR_TELEMETRY_EVENT_CATALOG: readonly TelemetryEventCatalogEntry[] = [\n eventCatalogEntry('api_key.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('audit.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('cli.command.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('content.publish.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('content.validation.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('critique.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('decantr.analyze.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.check.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.health.healthy', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('decantr.init.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.new.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.refresh.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('execution_pack.compiled', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('execution_pack.selected', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('health.ci.failed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.finding.prompt_requested', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.report.generated', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('marketing_web.command_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.cta_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.outbound_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.page_viewed', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('org.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('billing.checkout_blocked', ['api', 'registry-web'], 'billing_intent', 'aggregate', true),\n eventCatalogEntry('billing.plan_clicked', REGISTRY_WEB_ONLY, 'billing_intent', 'aggregate', true),\n eventCatalogEntry('private_registry.content_listed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.gate_viewed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.intent_clicked', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('registry_web.api_key_page_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.billing_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.content_opened', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.identity_linked', REGISTRY_WEB_ONLY, 'identity_hygiene', 'opaque_identity', true),\n eventCatalogEntry('registry_web.organization_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'aggregate', true),\n eventCatalogEntry('registry_web.page_viewed', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.search_performed', REGISTRY_WEB_ONLY, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry_web.signup_clicked', REGISTRY_WEB_ONLY, 'activation', 'public_metadata', true),\n eventCatalogEntry('registry.item.resolved', REGISTRY_RESOLUTION_SOURCES, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry.sync.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('studio.health_refreshed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('studio.started', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('telemetry.identity_linked', API_ONLY, 'identity_hygiene', 'opaque_identity', false),\n eventCatalogEntry('user.signup.completed', API_ONLY, 'activation', 'aggregate', false),\n];\n\nconst TELEMETRY_EVENT_CATALOG_BY_NAME = new Map(\n DECANTR_TELEMETRY_EVENT_CATALOG.map((entry) => [entry.name, entry]),\n);\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'billing.checkout_blocked', BillingCheckoutBlockedProperties>\n | TelemetryEventBase<'billing.plan_clicked', BillingPlanClickedProperties>\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.analyze.completed', DecantrAnalyzeCompletedProperties>\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<'private_registry.content_listed', PrivateRegistryContentListedProperties>\n | TelemetryEventBase<'private_registry.gate_viewed', PrivateRegistryGateViewedProperties>\n | TelemetryEventBase<'private_registry.intent_clicked', PrivateRegistryIntentClickedProperties>\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<'telemetry.identity_linked', TelemetryIdentityLinkedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetrySchemaVersion(\n value: unknown,\n): value is (typeof DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS)[number] {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS as readonly string[]).includes(value)\n );\n}\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n\nexport function getTelemetryEventCatalogEntry(\n name: DecantrTelemetryEventName,\n): TelemetryEventCatalogEntry {\n return TELEMETRY_EVENT_CATALOG_BY_NAME.get(name)!;\n}\n\nexport function isTelemetryEventAllowedForSource(\n name: DecantrTelemetryEventName,\n source: TelemetrySource,\n): boolean {\n return getTelemetryEventCatalogEntry(name).allowedSources.includes(source);\n}\n\nfunction eventCatalogEntry(\n name: DecantrTelemetryEventName,\n allowedSources: readonly TelemetrySource[],\n bucket: TelemetrySignalBucket,\n privacy: TelemetryPrivacyClass,\n publicIngest: boolean,\n): TelemetryEventCatalogEntry {\n return {\n name,\n allowedSources,\n bucket,\n privacy,\n publicIngest,\n privacyNotes:\n privacy === 'aggregate'\n ? 'Aggregate product metadata only; no source, prompts, raw paths, emails, or secrets.'\n : privacy === 'opaque_identity'\n ? 'Opaque Decantr identity ids only; no emails, source, prompts, raw paths, or secrets.'\n : 'Public product or acquisition metadata only; no raw referrer URLs, user agents, emails, or click ids.',\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/events.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.3.0';\nexport const DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS = [\n '0.2.0',\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n] as const;\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';\nexport type TelemetrySignalBucket =\n | 'activation'\n | 'billing_intent'\n | 'cli_adoption'\n | 'commercial_intent'\n | 'content_pipeline'\n | 'hosted_intelligence'\n | 'identity_hygiene'\n | 'paid_acquisition'\n | 'private_registry_readiness'\n | 'product_activation'\n | 'project_health'\n | 'registry_discovery';\nexport type TelemetryPrivacyClass = 'aggregate' | 'opaque_identity' | 'public_metadata';\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.analyze.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 'billing.checkout_blocked',\n 'billing.plan_clicked',\n 'private_registry.content_listed',\n 'private_registry.gate_viewed',\n 'private_registry.intent_clicked',\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 'telemetry.identity_linked',\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 DecantrAnalyzeCompletedProperties extends TelemetryProperties {\n command: 'analyze';\n success: boolean;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n componentCount?: number;\n dependencyCategoryCount?: number;\n errorCode?: string;\n pageCount?: number;\n projectScope?: ProjectScope;\n routeCount?: number;\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 attributionChannel?: string | null;\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstChannel?: string | null;\n attributionFirstLandingPath?: string | null;\n attributionFirstLandingIntent?: string | null;\n attributionFirstLandingPageKind?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstSource?: string | null;\n attributionFirstSourceCategory?: 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 attributionLandingIntent?: string | null;\n attributionLandingPageKind?: string | null;\n attributionLastChannel?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastLandingIntent?: string | null;\n attributionLastLandingPageKind?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastSource?: string | null;\n attributionLastSourceCategory?: 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 attributionSource?: string | null;\n attributionSourceCategory?: 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 interface TelemetryIdentityLinkedProperties extends TelemetryProperties {\n success: boolean;\n entrypoint?: string;\n identityType?: 'anonymous' | 'install' | 'project';\n linkCount?: number;\n orgScoped?: boolean;\n plan?: string;\n surface?: string;\n}\n\nexport interface PrivateRegistryGateViewedProperties extends TelemetryProperties {\n orgScoped: boolean;\n plan?: string;\n surface: string;\n enterpriseOrgCount?: number;\n}\n\nexport interface PrivateRegistryIntentClickedProperties extends TelemetryProperties {\n action: 'open_billing' | 'open_team' | 'open_private_registry';\n orgScoped: boolean;\n plan?: string;\n surface: string;\n}\n\nexport interface PrivateRegistryContentListedProperties extends TelemetryProperties {\n itemCount: number;\n orgScoped: true;\n plan?: string;\n queryPresent?: boolean;\n statusFilterPresent?: boolean;\n surface: string;\n typeFilterPresent?: boolean;\n visibilityFilterPresent?: boolean;\n}\n\nexport interface BillingPlanClickedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n currentPlan?: string;\n orgScoped?: boolean;\n plan: 'enterprise' | 'pro' | 'team';\n surface: string;\n}\n\nexport interface BillingCheckoutBlockedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n orgScoped?: boolean;\n plan?: 'enterprise' | 'pro' | 'team';\n reason: 'billing_coming_soon' | 'billing_not_configured' | 'not_authorized';\n surface: string;\n}\n\nexport interface TelemetryEventCatalogEntry {\n name: DecantrTelemetryEventName;\n allowedSources: readonly TelemetrySource[];\n bucket: TelemetrySignalBucket;\n privacy: TelemetryPrivacyClass;\n privacyNotes: string;\n publicIngest: boolean;\n}\n\nconst API_ONLY = ['api'] as const;\nconst CLI_ONLY = ['cli'] as const;\nconst REGISTRY_WEB_ONLY = ['registry-web'] as const;\nconst MARKETING_WEB_ONLY = ['marketing-web'] as const;\nconst CONTENT_CI_AND_API = ['content-ci', 'api'] as const;\nconst REGISTRY_RESOLUTION_SOURCES = ['api', 'cli', 'mcp'] as const;\n\nexport const DECANTR_TELEMETRY_EVENT_CATALOG: readonly TelemetryEventCatalogEntry[] = [\n eventCatalogEntry('api_key.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('audit.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('cli.command.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('content.publish.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('content.validation.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('critique.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('decantr.analyze.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.check.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.health.healthy', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('decantr.init.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.new.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.refresh.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('execution_pack.compiled', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('execution_pack.selected', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('health.ci.failed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.finding.prompt_requested', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.report.generated', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('marketing_web.command_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.cta_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.outbound_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.page_viewed', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('org.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('billing.checkout_blocked', ['api', 'registry-web'], 'billing_intent', 'aggregate', true),\n eventCatalogEntry('billing.plan_clicked', REGISTRY_WEB_ONLY, 'billing_intent', 'aggregate', true),\n eventCatalogEntry('private_registry.content_listed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.gate_viewed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.intent_clicked', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('registry_web.api_key_page_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.billing_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.content_opened', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.identity_linked', REGISTRY_WEB_ONLY, 'identity_hygiene', 'opaque_identity', true),\n eventCatalogEntry('registry_web.organization_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'aggregate', true),\n eventCatalogEntry('registry_web.page_viewed', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.search_performed', REGISTRY_WEB_ONLY, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry_web.signup_clicked', REGISTRY_WEB_ONLY, 'activation', 'public_metadata', true),\n eventCatalogEntry('registry.item.resolved', REGISTRY_RESOLUTION_SOURCES, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry.sync.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('studio.health_refreshed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('studio.started', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('telemetry.identity_linked', API_ONLY, 'identity_hygiene', 'opaque_identity', false),\n eventCatalogEntry('user.signup.completed', API_ONLY, 'activation', 'aggregate', false),\n];\n\nconst TELEMETRY_EVENT_CATALOG_BY_NAME = new Map(\n DECANTR_TELEMETRY_EVENT_CATALOG.map((entry) => [entry.name, entry]),\n);\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'billing.checkout_blocked', BillingCheckoutBlockedProperties>\n | TelemetryEventBase<'billing.plan_clicked', BillingPlanClickedProperties>\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.analyze.completed', DecantrAnalyzeCompletedProperties>\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<'private_registry.content_listed', PrivateRegistryContentListedProperties>\n | TelemetryEventBase<'private_registry.gate_viewed', PrivateRegistryGateViewedProperties>\n | TelemetryEventBase<'private_registry.intent_clicked', PrivateRegistryIntentClickedProperties>\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<'telemetry.identity_linked', TelemetryIdentityLinkedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetrySchemaVersion(\n value: unknown,\n): value is (typeof DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS)[number] {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS as readonly string[]).includes(value)\n );\n}\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n\nexport function getTelemetryEventCatalogEntry(\n name: DecantrTelemetryEventName,\n): TelemetryEventCatalogEntry {\n return TELEMETRY_EVENT_CATALOG_BY_NAME.get(name)!;\n}\n\nexport function isTelemetryEventAllowedForSource(\n name: DecantrTelemetryEventName,\n source: TelemetrySource,\n): boolean {\n return getTelemetryEventCatalogEntry(name).allowedSources.includes(source);\n}\n\nfunction eventCatalogEntry(\n name: DecantrTelemetryEventName,\n allowedSources: readonly TelemetrySource[],\n bucket: TelemetrySignalBucket,\n privacy: TelemetryPrivacyClass,\n publicIngest: boolean,\n): TelemetryEventCatalogEntry {\n return {\n name,\n allowedSources,\n bucket,\n privacy,\n publicIngest,\n privacyNotes:\n privacy === 'aggregate'\n ? 'Aggregate product metadata only; no source, prompts, raw paths, emails, or secrets.'\n : privacy === 'opaque_identity'\n ? 'Opaque Decantr identity ids only; no emails, source, prompts, raw paths, or secrets.'\n : 'Public product or acquisition metadata only; no raw referrer URLs, user agents, emails, or click ids.',\n };\n}\n"],"mappings":"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","names":[]}
|
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.3.0';\nexport const DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS = [\n '0.2.0',\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n] as const;\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';\nexport type TelemetrySignalBucket =\n | 'activation'\n | 'billing_intent'\n | 'cli_adoption'\n | 'commercial_intent'\n | 'content_pipeline'\n | 'hosted_intelligence'\n | 'identity_hygiene'\n | 'paid_acquisition'\n | 'private_registry_readiness'\n | 'product_activation'\n | 'project_health'\n | 'registry_discovery';\nexport type TelemetryPrivacyClass = 'aggregate' | 'opaque_identity' | 'public_metadata';\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.analyze.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 'billing.checkout_blocked',\n 'billing.plan_clicked',\n 'private_registry.content_listed',\n 'private_registry.gate_viewed',\n 'private_registry.intent_clicked',\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 'telemetry.identity_linked',\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 DecantrAnalyzeCompletedProperties extends TelemetryProperties {\n command: 'analyze';\n success: boolean;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n componentCount?: number;\n dependencyCategoryCount?: number;\n errorCode?: string;\n pageCount?: number;\n projectScope?: ProjectScope;\n routeCount?: number;\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 interface TelemetryIdentityLinkedProperties extends TelemetryProperties {\n success: boolean;\n entrypoint?: string;\n identityType?: 'anonymous' | 'install' | 'project';\n linkCount?: number;\n orgScoped?: boolean;\n plan?: string;\n surface?: string;\n}\n\nexport interface PrivateRegistryGateViewedProperties extends TelemetryProperties {\n orgScoped: boolean;\n plan?: string;\n surface: string;\n enterpriseOrgCount?: number;\n}\n\nexport interface PrivateRegistryIntentClickedProperties extends TelemetryProperties {\n action: 'open_billing' | 'open_team' | 'open_private_registry';\n orgScoped: boolean;\n plan?: string;\n surface: string;\n}\n\nexport interface PrivateRegistryContentListedProperties extends TelemetryProperties {\n itemCount: number;\n orgScoped: true;\n plan?: string;\n queryPresent?: boolean;\n statusFilterPresent?: boolean;\n surface: string;\n typeFilterPresent?: boolean;\n visibilityFilterPresent?: boolean;\n}\n\nexport interface BillingPlanClickedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n currentPlan?: string;\n orgScoped?: boolean;\n plan: 'enterprise' | 'pro' | 'team';\n surface: string;\n}\n\nexport interface BillingCheckoutBlockedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n orgScoped?: boolean;\n plan?: 'enterprise' | 'pro' | 'team';\n reason: 'billing_coming_soon' | 'billing_not_configured' | 'not_authorized';\n surface: string;\n}\n\nexport interface TelemetryEventCatalogEntry {\n name: DecantrTelemetryEventName;\n allowedSources: readonly TelemetrySource[];\n bucket: TelemetrySignalBucket;\n privacy: TelemetryPrivacyClass;\n privacyNotes: string;\n publicIngest: boolean;\n}\n\nconst API_ONLY = ['api'] as const;\nconst CLI_ONLY = ['cli'] as const;\nconst REGISTRY_WEB_ONLY = ['registry-web'] as const;\nconst MARKETING_WEB_ONLY = ['marketing-web'] as const;\nconst CONTENT_CI_AND_API = ['content-ci', 'api'] as const;\nconst REGISTRY_RESOLUTION_SOURCES = ['api', 'cli', 'mcp'] as const;\n\nexport const DECANTR_TELEMETRY_EVENT_CATALOG: readonly TelemetryEventCatalogEntry[] = [\n eventCatalogEntry('api_key.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('audit.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('cli.command.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('content.publish.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('content.validation.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('critique.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('decantr.analyze.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.check.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.health.healthy', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('decantr.init.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.new.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.refresh.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('execution_pack.compiled', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('execution_pack.selected', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('health.ci.failed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.finding.prompt_requested', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.report.generated', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('marketing_web.command_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.cta_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.outbound_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.page_viewed', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('org.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('billing.checkout_blocked', ['api', 'registry-web'], 'billing_intent', 'aggregate', true),\n eventCatalogEntry('billing.plan_clicked', REGISTRY_WEB_ONLY, 'billing_intent', 'aggregate', true),\n eventCatalogEntry('private_registry.content_listed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.gate_viewed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.intent_clicked', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('registry_web.api_key_page_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.billing_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.content_opened', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.identity_linked', REGISTRY_WEB_ONLY, 'identity_hygiene', 'opaque_identity', true),\n eventCatalogEntry('registry_web.organization_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'aggregate', true),\n eventCatalogEntry('registry_web.page_viewed', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.search_performed', REGISTRY_WEB_ONLY, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry_web.signup_clicked', REGISTRY_WEB_ONLY, 'activation', 'public_metadata', true),\n eventCatalogEntry('registry.item.resolved', REGISTRY_RESOLUTION_SOURCES, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry.sync.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('studio.health_refreshed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('studio.started', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('telemetry.identity_linked', API_ONLY, 'identity_hygiene', 'opaque_identity', false),\n eventCatalogEntry('user.signup.completed', API_ONLY, 'activation', 'aggregate', false),\n];\n\nconst TELEMETRY_EVENT_CATALOG_BY_NAME = new Map(\n DECANTR_TELEMETRY_EVENT_CATALOG.map((entry) => [entry.name, entry]),\n);\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'billing.checkout_blocked', BillingCheckoutBlockedProperties>\n | TelemetryEventBase<'billing.plan_clicked', BillingPlanClickedProperties>\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.analyze.completed', DecantrAnalyzeCompletedProperties>\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<'private_registry.content_listed', PrivateRegistryContentListedProperties>\n | TelemetryEventBase<'private_registry.gate_viewed', PrivateRegistryGateViewedProperties>\n | TelemetryEventBase<'private_registry.intent_clicked', PrivateRegistryIntentClickedProperties>\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<'telemetry.identity_linked', TelemetryIdentityLinkedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetrySchemaVersion(\n value: unknown,\n): value is (typeof DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS)[number] {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS as readonly string[]).includes(value)\n );\n}\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n\nexport function getTelemetryEventCatalogEntry(\n name: DecantrTelemetryEventName,\n): TelemetryEventCatalogEntry {\n return TELEMETRY_EVENT_CATALOG_BY_NAME.get(name)!;\n}\n\nexport function isTelemetryEventAllowedForSource(\n name: DecantrTelemetryEventName,\n source: TelemetrySource,\n): boolean {\n return getTelemetryEventCatalogEntry(name).allowedSources.includes(source);\n}\n\nfunction eventCatalogEntry(\n name: DecantrTelemetryEventName,\n allowedSources: readonly TelemetrySource[],\n bucket: TelemetrySignalBucket,\n privacy: TelemetryPrivacyClass,\n publicIngest: boolean,\n): TelemetryEventCatalogEntry {\n return {\n name,\n allowedSources,\n bucket,\n privacy,\n publicIngest,\n privacyNotes:\n privacy === 'aggregate'\n ? 'Aggregate product metadata only; no source, prompts, raw paths, emails, or secrets.'\n : privacy === 'opaque_identity'\n ? 'Opaque Decantr identity ids only; no emails, source, prompts, raw paths, or secrets.'\n : 'Public product or acquisition metadata only; no raw referrer URLs, user agents, emails, or click ids.',\n };\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 /^package[_-]?slug$/i,\n /^password$/i,\n /^path$/i,\n /^prompt$/i,\n /^private[_-]?package[_-]?slug$/i,\n /^repo$/i,\n /^repository$/i,\n /^repository[_-]?name$/i,\n /^route[_-]?name$/i,\n /^route[_-]?names$/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.3.0';\nexport const DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS = [\n '0.2.0',\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n] as const;\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';\nexport type TelemetrySignalBucket =\n | 'activation'\n | 'billing_intent'\n | 'cli_adoption'\n | 'commercial_intent'\n | 'content_pipeline'\n | 'hosted_intelligence'\n | 'identity_hygiene'\n | 'paid_acquisition'\n | 'private_registry_readiness'\n | 'product_activation'\n | 'project_health'\n | 'registry_discovery';\nexport type TelemetryPrivacyClass = 'aggregate' | 'opaque_identity' | 'public_metadata';\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.analyze.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 'billing.checkout_blocked',\n 'billing.plan_clicked',\n 'private_registry.content_listed',\n 'private_registry.gate_viewed',\n 'private_registry.intent_clicked',\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 'telemetry.identity_linked',\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 DecantrAnalyzeCompletedProperties extends TelemetryProperties {\n command: 'analyze';\n success: boolean;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n componentCount?: number;\n dependencyCategoryCount?: number;\n errorCode?: string;\n pageCount?: number;\n projectScope?: ProjectScope;\n routeCount?: number;\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 attributionChannel?: string | null;\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstChannel?: string | null;\n attributionFirstLandingPath?: string | null;\n attributionFirstLandingIntent?: string | null;\n attributionFirstLandingPageKind?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstSource?: string | null;\n attributionFirstSourceCategory?: 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 attributionLandingIntent?: string | null;\n attributionLandingPageKind?: string | null;\n attributionLastChannel?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastLandingIntent?: string | null;\n attributionLastLandingPageKind?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastSource?: string | null;\n attributionLastSourceCategory?: 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 attributionSource?: string | null;\n attributionSourceCategory?: 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 interface TelemetryIdentityLinkedProperties extends TelemetryProperties {\n success: boolean;\n entrypoint?: string;\n identityType?: 'anonymous' | 'install' | 'project';\n linkCount?: number;\n orgScoped?: boolean;\n plan?: string;\n surface?: string;\n}\n\nexport interface PrivateRegistryGateViewedProperties extends TelemetryProperties {\n orgScoped: boolean;\n plan?: string;\n surface: string;\n enterpriseOrgCount?: number;\n}\n\nexport interface PrivateRegistryIntentClickedProperties extends TelemetryProperties {\n action: 'open_billing' | 'open_team' | 'open_private_registry';\n orgScoped: boolean;\n plan?: string;\n surface: string;\n}\n\nexport interface PrivateRegistryContentListedProperties extends TelemetryProperties {\n itemCount: number;\n orgScoped: true;\n plan?: string;\n queryPresent?: boolean;\n statusFilterPresent?: boolean;\n surface: string;\n typeFilterPresent?: boolean;\n visibilityFilterPresent?: boolean;\n}\n\nexport interface BillingPlanClickedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n currentPlan?: string;\n orgScoped?: boolean;\n plan: 'enterprise' | 'pro' | 'team';\n surface: string;\n}\n\nexport interface BillingCheckoutBlockedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n orgScoped?: boolean;\n plan?: 'enterprise' | 'pro' | 'team';\n reason: 'billing_coming_soon' | 'billing_not_configured' | 'not_authorized';\n surface: string;\n}\n\nexport interface TelemetryEventCatalogEntry {\n name: DecantrTelemetryEventName;\n allowedSources: readonly TelemetrySource[];\n bucket: TelemetrySignalBucket;\n privacy: TelemetryPrivacyClass;\n privacyNotes: string;\n publicIngest: boolean;\n}\n\nconst API_ONLY = ['api'] as const;\nconst CLI_ONLY = ['cli'] as const;\nconst REGISTRY_WEB_ONLY = ['registry-web'] as const;\nconst MARKETING_WEB_ONLY = ['marketing-web'] as const;\nconst CONTENT_CI_AND_API = ['content-ci', 'api'] as const;\nconst REGISTRY_RESOLUTION_SOURCES = ['api', 'cli', 'mcp'] as const;\n\nexport const DECANTR_TELEMETRY_EVENT_CATALOG: readonly TelemetryEventCatalogEntry[] = [\n eventCatalogEntry('api_key.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('audit.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('cli.command.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('content.publish.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('content.validation.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('critique.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('decantr.analyze.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.check.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.health.healthy', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('decantr.init.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.new.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.refresh.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('execution_pack.compiled', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('execution_pack.selected', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('health.ci.failed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.finding.prompt_requested', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.report.generated', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('marketing_web.command_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.cta_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.outbound_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.page_viewed', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('org.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('billing.checkout_blocked', ['api', 'registry-web'], 'billing_intent', 'aggregate', true),\n eventCatalogEntry('billing.plan_clicked', REGISTRY_WEB_ONLY, 'billing_intent', 'aggregate', true),\n eventCatalogEntry('private_registry.content_listed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.gate_viewed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.intent_clicked', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('registry_web.api_key_page_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.billing_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.content_opened', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.identity_linked', REGISTRY_WEB_ONLY, 'identity_hygiene', 'opaque_identity', true),\n eventCatalogEntry('registry_web.organization_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'aggregate', true),\n eventCatalogEntry('registry_web.page_viewed', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.search_performed', REGISTRY_WEB_ONLY, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry_web.signup_clicked', REGISTRY_WEB_ONLY, 'activation', 'public_metadata', true),\n eventCatalogEntry('registry.item.resolved', REGISTRY_RESOLUTION_SOURCES, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry.sync.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('studio.health_refreshed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('studio.started', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('telemetry.identity_linked', API_ONLY, 'identity_hygiene', 'opaque_identity', false),\n eventCatalogEntry('user.signup.completed', API_ONLY, 'activation', 'aggregate', false),\n];\n\nconst TELEMETRY_EVENT_CATALOG_BY_NAME = new Map(\n DECANTR_TELEMETRY_EVENT_CATALOG.map((entry) => [entry.name, entry]),\n);\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'billing.checkout_blocked', BillingCheckoutBlockedProperties>\n | TelemetryEventBase<'billing.plan_clicked', BillingPlanClickedProperties>\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.analyze.completed', DecantrAnalyzeCompletedProperties>\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<'private_registry.content_listed', PrivateRegistryContentListedProperties>\n | TelemetryEventBase<'private_registry.gate_viewed', PrivateRegistryGateViewedProperties>\n | TelemetryEventBase<'private_registry.intent_clicked', PrivateRegistryIntentClickedProperties>\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<'telemetry.identity_linked', TelemetryIdentityLinkedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetrySchemaVersion(\n value: unknown,\n): value is (typeof DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS)[number] {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS as readonly string[]).includes(value)\n );\n}\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n\nexport function getTelemetryEventCatalogEntry(\n name: DecantrTelemetryEventName,\n): TelemetryEventCatalogEntry {\n return TELEMETRY_EVENT_CATALOG_BY_NAME.get(name)!;\n}\n\nexport function isTelemetryEventAllowedForSource(\n name: DecantrTelemetryEventName,\n source: TelemetrySource,\n): boolean {\n return getTelemetryEventCatalogEntry(name).allowedSources.includes(source);\n}\n\nfunction eventCatalogEntry(\n name: DecantrTelemetryEventName,\n allowedSources: readonly TelemetrySource[],\n bucket: TelemetrySignalBucket,\n privacy: TelemetryPrivacyClass,\n publicIngest: boolean,\n): TelemetryEventCatalogEntry {\n return {\n name,\n allowedSources,\n bucket,\n privacy,\n publicIngest,\n privacyNotes:\n privacy === 'aggregate'\n ? 'Aggregate product metadata only; no source, prompts, raw paths, emails, or secrets.'\n : privacy === 'opaque_identity'\n ? 'Opaque Decantr identity ids only; no emails, source, prompts, raw paths, or secrets.'\n : 'Public product or acquisition metadata only; no raw referrer URLs, user agents, emails, or click ids.',\n };\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 /^package[_-]?slug$/i,\n /^password$/i,\n /^path$/i,\n /^prompt$/i,\n /^private[_-]?package[_-]?slug$/i,\n /^repo$/i,\n /^repository$/i,\n /^repository[_-]?name$/i,\n /^route[_-]?name$/i,\n /^route[_-]?names$/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.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/events.ts","../src/posthog.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.3.0';\nexport const DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS = [\n '0.2.0',\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n] as const;\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';\nexport type TelemetrySignalBucket =\n | 'activation'\n | 'billing_intent'\n | 'cli_adoption'\n | 'commercial_intent'\n | 'content_pipeline'\n | 'hosted_intelligence'\n | 'identity_hygiene'\n | 'paid_acquisition'\n | 'private_registry_readiness'\n | 'product_activation'\n | 'project_health'\n | 'registry_discovery';\nexport type TelemetryPrivacyClass = 'aggregate' | 'opaque_identity' | 'public_metadata';\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.analyze.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 'billing.checkout_blocked',\n 'billing.plan_clicked',\n 'private_registry.content_listed',\n 'private_registry.gate_viewed',\n 'private_registry.intent_clicked',\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 'telemetry.identity_linked',\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 DecantrAnalyzeCompletedProperties extends TelemetryProperties {\n command: 'analyze';\n success: boolean;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n componentCount?: number;\n dependencyCategoryCount?: number;\n errorCode?: string;\n pageCount?: number;\n projectScope?: ProjectScope;\n routeCount?: number;\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 interface TelemetryIdentityLinkedProperties extends TelemetryProperties {\n success: boolean;\n entrypoint?: string;\n identityType?: 'anonymous' | 'install' | 'project';\n linkCount?: number;\n orgScoped?: boolean;\n plan?: string;\n surface?: string;\n}\n\nexport interface PrivateRegistryGateViewedProperties extends TelemetryProperties {\n orgScoped: boolean;\n plan?: string;\n surface: string;\n enterpriseOrgCount?: number;\n}\n\nexport interface PrivateRegistryIntentClickedProperties extends TelemetryProperties {\n action: 'open_billing' | 'open_team' | 'open_private_registry';\n orgScoped: boolean;\n plan?: string;\n surface: string;\n}\n\nexport interface PrivateRegistryContentListedProperties extends TelemetryProperties {\n itemCount: number;\n orgScoped: true;\n plan?: string;\n queryPresent?: boolean;\n statusFilterPresent?: boolean;\n surface: string;\n typeFilterPresent?: boolean;\n visibilityFilterPresent?: boolean;\n}\n\nexport interface BillingPlanClickedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n currentPlan?: string;\n orgScoped?: boolean;\n plan: 'enterprise' | 'pro' | 'team';\n surface: string;\n}\n\nexport interface BillingCheckoutBlockedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n orgScoped?: boolean;\n plan?: 'enterprise' | 'pro' | 'team';\n reason: 'billing_coming_soon' | 'billing_not_configured' | 'not_authorized';\n surface: string;\n}\n\nexport interface TelemetryEventCatalogEntry {\n name: DecantrTelemetryEventName;\n allowedSources: readonly TelemetrySource[];\n bucket: TelemetrySignalBucket;\n privacy: TelemetryPrivacyClass;\n privacyNotes: string;\n publicIngest: boolean;\n}\n\nconst API_ONLY = ['api'] as const;\nconst CLI_ONLY = ['cli'] as const;\nconst REGISTRY_WEB_ONLY = ['registry-web'] as const;\nconst MARKETING_WEB_ONLY = ['marketing-web'] as const;\nconst CONTENT_CI_AND_API = ['content-ci', 'api'] as const;\nconst REGISTRY_RESOLUTION_SOURCES = ['api', 'cli', 'mcp'] as const;\n\nexport const DECANTR_TELEMETRY_EVENT_CATALOG: readonly TelemetryEventCatalogEntry[] = [\n eventCatalogEntry('api_key.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('audit.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('cli.command.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('content.publish.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('content.validation.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('critique.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('decantr.analyze.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.check.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.health.healthy', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('decantr.init.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.new.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.refresh.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('execution_pack.compiled', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('execution_pack.selected', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('health.ci.failed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.finding.prompt_requested', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.report.generated', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('marketing_web.command_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.cta_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.outbound_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.page_viewed', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('org.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('billing.checkout_blocked', ['api', 'registry-web'], 'billing_intent', 'aggregate', true),\n eventCatalogEntry('billing.plan_clicked', REGISTRY_WEB_ONLY, 'billing_intent', 'aggregate', true),\n eventCatalogEntry('private_registry.content_listed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.gate_viewed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.intent_clicked', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('registry_web.api_key_page_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.billing_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.content_opened', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.identity_linked', REGISTRY_WEB_ONLY, 'identity_hygiene', 'opaque_identity', true),\n eventCatalogEntry('registry_web.organization_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'aggregate', true),\n eventCatalogEntry('registry_web.page_viewed', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.search_performed', REGISTRY_WEB_ONLY, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry_web.signup_clicked', REGISTRY_WEB_ONLY, 'activation', 'public_metadata', true),\n eventCatalogEntry('registry.item.resolved', REGISTRY_RESOLUTION_SOURCES, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry.sync.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('studio.health_refreshed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('studio.started', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('telemetry.identity_linked', API_ONLY, 'identity_hygiene', 'opaque_identity', false),\n eventCatalogEntry('user.signup.completed', API_ONLY, 'activation', 'aggregate', false),\n];\n\nconst TELEMETRY_EVENT_CATALOG_BY_NAME = new Map(\n DECANTR_TELEMETRY_EVENT_CATALOG.map((entry) => [entry.name, entry]),\n);\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'billing.checkout_blocked', BillingCheckoutBlockedProperties>\n | TelemetryEventBase<'billing.plan_clicked', BillingPlanClickedProperties>\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.analyze.completed', DecantrAnalyzeCompletedProperties>\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<'private_registry.content_listed', PrivateRegistryContentListedProperties>\n | TelemetryEventBase<'private_registry.gate_viewed', PrivateRegistryGateViewedProperties>\n | TelemetryEventBase<'private_registry.intent_clicked', PrivateRegistryIntentClickedProperties>\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<'telemetry.identity_linked', TelemetryIdentityLinkedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetrySchemaVersion(\n value: unknown,\n): value is (typeof DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS)[number] {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS as readonly string[]).includes(value)\n );\n}\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n\nexport function getTelemetryEventCatalogEntry(\n name: DecantrTelemetryEventName,\n): TelemetryEventCatalogEntry {\n return TELEMETRY_EVENT_CATALOG_BY_NAME.get(name)!;\n}\n\nexport function isTelemetryEventAllowedForSource(\n name: DecantrTelemetryEventName,\n source: TelemetrySource,\n): boolean {\n return getTelemetryEventCatalogEntry(name).allowedSources.includes(source);\n}\n\nfunction eventCatalogEntry(\n name: DecantrTelemetryEventName,\n allowedSources: readonly TelemetrySource[],\n bucket: TelemetrySignalBucket,\n privacy: TelemetryPrivacyClass,\n publicIngest: boolean,\n): TelemetryEventCatalogEntry {\n return {\n name,\n allowedSources,\n bucket,\n privacy,\n publicIngest,\n privacyNotes:\n privacy === 'aggregate'\n ? 'Aggregate product metadata only; no source, prompts, raw paths, emails, or secrets.'\n : privacy === 'opaque_identity'\n ? 'Opaque Decantr identity ids only; no emails, source, prompts, raw paths, or secrets.'\n : 'Public product or acquisition metadata only; no raw referrer URLs, user agents, emails, or click ids.',\n };\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":";AAAO,IAAM,mCAAmC;AAmJzC,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;AAqVA,IAAM,WAAW,CAAC,KAAK;AACvB,IAAM,WAAW,CAAC,KAAK;AACvB,IAAM,oBAAoB,CAAC,cAAc;AACzC,IAAM,qBAAqB,CAAC,eAAe;AAC3C,IAAM,qBAAqB,CAAC,cAAc,KAAK;AAC/C,IAAM,8BAA8B,CAAC,OAAO,OAAO,KAAK;AAEjD,IAAM,kCAAyE;AAAA,EACpF,kBAAkB,mBAAmB,UAAU,cAAc,aAAa,KAAK;AAAA,EAC/E,kBAAkB,mBAAmB,UAAU,uBAAuB,aAAa,KAAK;AAAA,EACxF,kBAAkB,yBAAyB,UAAU,gBAAgB,aAAa,IAAI;AAAA,EACtF,kBAAkB,6BAA6B,oBAAoB,oBAAoB,aAAa,IAAI;AAAA,EACxG,kBAAkB,gCAAgC,oBAAoB,oBAAoB,aAAa,IAAI;AAAA,EAC3G,kBAAkB,sBAAsB,UAAU,uBAAuB,aAAa,KAAK;AAAA,EAC3F,kBAAkB,6BAA6B,UAAU,sBAAsB,aAAa,IAAI;AAAA,EAChG,kBAAkB,2BAA2B,UAAU,sBAAsB,aAAa,IAAI;AAAA,EAC9F,kBAAkB,0BAA0B,UAAU,kBAAkB,aAAa,IAAI;AAAA,EACzF,kBAAkB,0BAA0B,UAAU,sBAAsB,aAAa,IAAI;AAAA,EAC7F,kBAAkB,yBAAyB,UAAU,sBAAsB,aAAa,IAAI;AAAA,EAC5F,kBAAkB,6BAA6B,UAAU,sBAAsB,aAAa,IAAI;AAAA,EAChG,kBAAkB,2BAA2B,UAAU,uBAAuB,aAAa,KAAK;AAAA,EAChG,kBAAkB,2BAA2B,UAAU,uBAAuB,aAAa,KAAK;AAAA,EAChG,kBAAkB,oBAAoB,UAAU,kBAAkB,aAAa,IAAI;AAAA,EACnF,kBAAkB,mCAAmC,UAAU,kBAAkB,aAAa,IAAI;AAAA,EAClG,kBAAkB,2BAA2B,UAAU,kBAAkB,aAAa,IAAI;AAAA,EAC1F,kBAAkB,iCAAiC,oBAAoB,oBAAoB,mBAAmB,IAAI;AAAA,EAClH,kBAAkB,6BAA6B,oBAAoB,oBAAoB,mBAAmB,IAAI;AAAA,EAC9G,kBAAkB,kCAAkC,oBAAoB,oBAAoB,mBAAmB,IAAI;AAAA,EACnH,kBAAkB,6BAA6B,oBAAoB,oBAAoB,mBAAmB,IAAI;AAAA,EAC9G,kBAAkB,eAAe,UAAU,cAAc,aAAa,KAAK;AAAA,EAC3E,kBAAkB,4BAA4B,CAAC,OAAO,cAAc,GAAG,kBAAkB,aAAa,IAAI;AAAA,EAC1G,kBAAkB,wBAAwB,mBAAmB,kBAAkB,aAAa,IAAI;AAAA,EAChG,kBAAkB,mCAAmC,mBAAmB,8BAA8B,aAAa,IAAI;AAAA,EACvH,kBAAkB,gCAAgC,mBAAmB,8BAA8B,aAAa,IAAI;AAAA,EACpH,kBAAkB,mCAAmC,mBAAmB,8BAA8B,aAAa,IAAI;AAAA,EACvH,kBAAkB,oCAAoC,mBAAmB,qBAAqB,mBAAmB,IAAI;AAAA,EACrH,kBAAkB,+BAA+B,mBAAmB,qBAAqB,mBAAmB,IAAI;AAAA,EAChH,kBAAkB,+BAA+B,mBAAmB,sBAAsB,mBAAmB,IAAI;AAAA,EACjH,kBAAkB,gCAAgC,mBAAmB,oBAAoB,mBAAmB,IAAI;AAAA,EAChH,kBAAkB,oCAAoC,mBAAmB,qBAAqB,aAAa,IAAI;AAAA,EAC/G,kBAAkB,4BAA4B,mBAAmB,sBAAsB,mBAAmB,IAAI;AAAA,EAC9G,kBAAkB,iCAAiC,mBAAmB,sBAAsB,aAAa,IAAI;AAAA,EAC7G,kBAAkB,+BAA+B,mBAAmB,cAAc,mBAAmB,IAAI;AAAA,EACzG,kBAAkB,0BAA0B,6BAA6B,sBAAsB,aAAa,IAAI;AAAA,EAChH,kBAAkB,2BAA2B,UAAU,gBAAgB,aAAa,IAAI;AAAA,EACxF,kBAAkB,2BAA2B,UAAU,kBAAkB,aAAa,IAAI;AAAA,EAC1F,kBAAkB,kBAAkB,UAAU,kBAAkB,aAAa,IAAI;AAAA,EACjF,kBAAkB,6BAA6B,UAAU,oBAAoB,mBAAmB,KAAK;AAAA,EACrG,kBAAkB,yBAAyB,UAAU,cAAc,aAAa,KAAK;AACvF;AAEA,IAAM,kCAAkC,IAAI;AAAA,EAC1C,gCAAgC,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,KAAK,CAAC;AACpE;AAuEA,SAAS,kBACP,MACA,gBACA,QACA,SACA,cAC4B;AAC5B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cACE,YAAY,cACR,wFACA,YAAY,oBACV,yFACA;AAAA,EACV;AACF;;;ACvpBO,SAAS,2BAA2B,SAAqD;AAC9F,QAAM,OAAO,oBAAoB,QAAQ,QAAQ,0BAA0B;AAC3E,QAAM,YAAY,QAAQ,SAAS,WAAW;AAE9C,SAAO;AAAA,IACL,MAAM,QAAQ,OAAO;AACnB,YAAM,aAAa,kBAAkB,KAAK;AAC1C,UAAI,CAAC,YAAY;AACf,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,YAAM,aAAa,IAAI,gBAAgB;AACvC,YAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,QAAQ,aAAa,GAAI;AAE9E,UAAI;AACF,cAAM,WAAW,MAAM,UAAU,GAAG,IAAI,YAAY;AAAA,UAClD,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU;AAAA,YACnB,SAAS,QAAQ;AAAA,YACjB,OAAO,MAAM;AAAA,YACb,aAAa;AAAA,YACb,YAAY,oBAAoB,OAAO,OAAO;AAAA,YAC9C,WAAW,MAAM;AAAA,UACnB,CAAC;AAAA,UACD,QAAQ,WAAW;AAAA,QACrB,CAAC;AAED,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,IAAI,MAAM,iCAAiC,SAAS,MAAM,GAAG;AAAA,QACrE;AAAA,MACF,UAAE;AACA,qBAAa,OAAO;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,OAAuB;AAClD,MAAI,MAAM,MAAM;AAChB,SAAO,MAAM,KAAK,MAAM,WAAW,MAAM,CAAC,MAAM,IAAI;AAClD,WAAO;AAAA,EACT;AACA,SAAO,MAAM,MAAM,GAAG,GAAG;AAC3B;AAEA,SAAS,kBAAkB,OAAkD;AAC3E,SACE,MAAM,QAAQ,UACd,MAAM,QAAQ,aACd,MAAM,QAAQ,aACd,MAAM,QAAQ;AAElB;AAEA,SAAS,oBACP,OACA,SACqB;AACrB,QAAM,SAAiC,CAAC;AACxC,MAAI,MAAM,QAAQ,MAAO,QAAO,eAAe,MAAM,QAAQ;AAC7D,MAAI,MAAM,QAAQ,UAAW,QAAO,UAAU,MAAM,QAAQ;AAE5D,SAAO;AAAA,IACL,GAAG,MAAM;AAAA,IACT,SAAS;AAAA,IACT,yBAAyB,QAAQ,wBAAwB;AAAA,IACzD,sBAAsB,MAAM,QAAQ,eAAe;AAAA,IACnD,oBAAoB,0BAA0B,MAAM,OAAO;AAAA,IAC3D,oBAAoB,MAAM,QAAQ,aAAa;AAAA,IAC/C,gBAAgB,MAAM,QAAQ,SAAS;AAAA,IACvC,oBAAoB,MAAM,QAAQ,aAAa;AAAA,IAC/C,oBAAoB,MAAM,QAAQ,aAAa;AAAA,IAC/C,wBAAwB;AAAA,IACxB,gBAAgB,MAAM,QAAQ;AAAA,IAC9B,qBAAqB,MAAM,QAAQ,eAAe;AAAA,IAClD,iBAAiB,MAAM,QAAQ,kBAAkB;AAAA,IACjD,iBAAiB,MAAM,QAAQ,kBAAkB;AAAA,IACjD,cAAc,MAAM,QAAQ,eAAe;AAAA,IAC3C,iBAAiB,MAAM,QAAQ,kBAAkB;AAAA,EACnD;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/events.ts","../src/posthog.ts"],"sourcesContent":["export const DECANTR_TELEMETRY_SCHEMA_VERSION = '0.3.0';\nexport const DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS = [\n '0.2.0',\n DECANTR_TELEMETRY_SCHEMA_VERSION,\n] as const;\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';\nexport type TelemetrySignalBucket =\n | 'activation'\n | 'billing_intent'\n | 'cli_adoption'\n | 'commercial_intent'\n | 'content_pipeline'\n | 'hosted_intelligence'\n | 'identity_hygiene'\n | 'paid_acquisition'\n | 'private_registry_readiness'\n | 'product_activation'\n | 'project_health'\n | 'registry_discovery';\nexport type TelemetryPrivacyClass = 'aggregate' | 'opaque_identity' | 'public_metadata';\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.analyze.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 'billing.checkout_blocked',\n 'billing.plan_clicked',\n 'private_registry.content_listed',\n 'private_registry.gate_viewed',\n 'private_registry.intent_clicked',\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 'telemetry.identity_linked',\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 DecantrAnalyzeCompletedProperties extends TelemetryProperties {\n command: 'analyze';\n success: boolean;\n durationMs?: number;\n adoptionMode?: AdoptionMode;\n componentCount?: number;\n dependencyCategoryCount?: number;\n errorCode?: string;\n pageCount?: number;\n projectScope?: ProjectScope;\n routeCount?: number;\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 attributionChannel?: string | null;\n attributionClickIdProvider?: string | null;\n attributionClickIdPresent?: boolean;\n attributionFirstChannel?: string | null;\n attributionFirstLandingPath?: string | null;\n attributionFirstLandingIntent?: string | null;\n attributionFirstLandingPageKind?: string | null;\n attributionFirstReferrerDomain?: string | null;\n attributionFirstSource?: string | null;\n attributionFirstSourceCategory?: 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 attributionLandingIntent?: string | null;\n attributionLandingPageKind?: string | null;\n attributionLastChannel?: string | null;\n attributionLastLandingPath?: string | null;\n attributionLastLandingIntent?: string | null;\n attributionLastLandingPageKind?: string | null;\n attributionLastReferrerDomain?: string | null;\n attributionLastSource?: string | null;\n attributionLastSourceCategory?: 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 attributionSource?: string | null;\n attributionSourceCategory?: 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 interface TelemetryIdentityLinkedProperties extends TelemetryProperties {\n success: boolean;\n entrypoint?: string;\n identityType?: 'anonymous' | 'install' | 'project';\n linkCount?: number;\n orgScoped?: boolean;\n plan?: string;\n surface?: string;\n}\n\nexport interface PrivateRegistryGateViewedProperties extends TelemetryProperties {\n orgScoped: boolean;\n plan?: string;\n surface: string;\n enterpriseOrgCount?: number;\n}\n\nexport interface PrivateRegistryIntentClickedProperties extends TelemetryProperties {\n action: 'open_billing' | 'open_team' | 'open_private_registry';\n orgScoped: boolean;\n plan?: string;\n surface: string;\n}\n\nexport interface PrivateRegistryContentListedProperties extends TelemetryProperties {\n itemCount: number;\n orgScoped: true;\n plan?: string;\n queryPresent?: boolean;\n statusFilterPresent?: boolean;\n surface: string;\n typeFilterPresent?: boolean;\n visibilityFilterPresent?: boolean;\n}\n\nexport interface BillingPlanClickedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n currentPlan?: string;\n orgScoped?: boolean;\n plan: 'enterprise' | 'pro' | 'team';\n surface: string;\n}\n\nexport interface BillingCheckoutBlockedProperties extends TelemetryProperties {\n billingEnabled: boolean;\n orgScoped?: boolean;\n plan?: 'enterprise' | 'pro' | 'team';\n reason: 'billing_coming_soon' | 'billing_not_configured' | 'not_authorized';\n surface: string;\n}\n\nexport interface TelemetryEventCatalogEntry {\n name: DecantrTelemetryEventName;\n allowedSources: readonly TelemetrySource[];\n bucket: TelemetrySignalBucket;\n privacy: TelemetryPrivacyClass;\n privacyNotes: string;\n publicIngest: boolean;\n}\n\nconst API_ONLY = ['api'] as const;\nconst CLI_ONLY = ['cli'] as const;\nconst REGISTRY_WEB_ONLY = ['registry-web'] as const;\nconst MARKETING_WEB_ONLY = ['marketing-web'] as const;\nconst CONTENT_CI_AND_API = ['content-ci', 'api'] as const;\nconst REGISTRY_RESOLUTION_SOURCES = ['api', 'cli', 'mcp'] as const;\n\nexport const DECANTR_TELEMETRY_EVENT_CATALOG: readonly TelemetryEventCatalogEntry[] = [\n eventCatalogEntry('api_key.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('audit.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('cli.command.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('content.publish.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('content.validation.completed', CONTENT_CI_AND_API, 'content_pipeline', 'aggregate', true),\n eventCatalogEntry('critique.completed', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('decantr.analyze.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.check.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.health.healthy', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('decantr.init.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.new.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('decantr.refresh.completed', CLI_ONLY, 'product_activation', 'aggregate', true),\n eventCatalogEntry('execution_pack.compiled', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('execution_pack.selected', API_ONLY, 'hosted_intelligence', 'aggregate', false),\n eventCatalogEntry('health.ci.failed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.finding.prompt_requested', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('health.report.generated', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('marketing_web.command_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.cta_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.outbound_clicked', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('marketing_web.page_viewed', MARKETING_WEB_ONLY, 'paid_acquisition', 'public_metadata', true),\n eventCatalogEntry('org.created', API_ONLY, 'activation', 'aggregate', false),\n eventCatalogEntry('billing.checkout_blocked', ['api', 'registry-web'], 'billing_intent', 'aggregate', true),\n eventCatalogEntry('billing.plan_clicked', REGISTRY_WEB_ONLY, 'billing_intent', 'aggregate', true),\n eventCatalogEntry('private_registry.content_listed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.gate_viewed', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('private_registry.intent_clicked', REGISTRY_WEB_ONLY, 'private_registry_readiness', 'aggregate', true),\n eventCatalogEntry('registry_web.api_key_page_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.billing_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'public_metadata', true),\n eventCatalogEntry('registry_web.content_opened', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.identity_linked', REGISTRY_WEB_ONLY, 'identity_hygiene', 'opaque_identity', true),\n eventCatalogEntry('registry_web.organization_viewed', REGISTRY_WEB_ONLY, 'commercial_intent', 'aggregate', true),\n eventCatalogEntry('registry_web.page_viewed', REGISTRY_WEB_ONLY, 'registry_discovery', 'public_metadata', true),\n eventCatalogEntry('registry_web.search_performed', REGISTRY_WEB_ONLY, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry_web.signup_clicked', REGISTRY_WEB_ONLY, 'activation', 'public_metadata', true),\n eventCatalogEntry('registry.item.resolved', REGISTRY_RESOLUTION_SOURCES, 'registry_discovery', 'aggregate', true),\n eventCatalogEntry('registry.sync.completed', CLI_ONLY, 'cli_adoption', 'aggregate', true),\n eventCatalogEntry('studio.health_refreshed', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('studio.started', CLI_ONLY, 'project_health', 'aggregate', true),\n eventCatalogEntry('telemetry.identity_linked', API_ONLY, 'identity_hygiene', 'opaque_identity', false),\n eventCatalogEntry('user.signup.completed', API_ONLY, 'activation', 'aggregate', false),\n];\n\nconst TELEMETRY_EVENT_CATALOG_BY_NAME = new Map(\n DECANTR_TELEMETRY_EVENT_CATALOG.map((entry) => [entry.name, entry]),\n);\n\nexport type DecantrTelemetryEvent =\n | TelemetryEventBase<'api_key.created', ProductEventProperties>\n | TelemetryEventBase<'audit.completed', AuditCompletedProperties>\n | TelemetryEventBase<'billing.checkout_blocked', BillingCheckoutBlockedProperties>\n | TelemetryEventBase<'billing.plan_clicked', BillingPlanClickedProperties>\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.analyze.completed', DecantrAnalyzeCompletedProperties>\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<'private_registry.content_listed', PrivateRegistryContentListedProperties>\n | TelemetryEventBase<'private_registry.gate_viewed', PrivateRegistryGateViewedProperties>\n | TelemetryEventBase<'private_registry.intent_clicked', PrivateRegistryIntentClickedProperties>\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<'telemetry.identity_linked', TelemetryIdentityLinkedProperties>\n | TelemetryEventBase<'user.signup.completed', ProductEventProperties>;\n\nexport function isDecantrTelemetrySchemaVersion(\n value: unknown,\n): value is (typeof DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS)[number] {\n return (\n typeof value === 'string' &&\n (DECANTR_TELEMETRY_ACCEPTED_SCHEMA_VERSIONS as readonly string[]).includes(value)\n );\n}\n\nexport function isDecantrTelemetryEventName(value: string): value is DecantrTelemetryEventName {\n return (DECANTR_TELEMETRY_EVENT_NAMES as readonly string[]).includes(value);\n}\n\nexport function getTelemetryEventCatalogEntry(\n name: DecantrTelemetryEventName,\n): TelemetryEventCatalogEntry {\n return TELEMETRY_EVENT_CATALOG_BY_NAME.get(name)!;\n}\n\nexport function isTelemetryEventAllowedForSource(\n name: DecantrTelemetryEventName,\n source: TelemetrySource,\n): boolean {\n return getTelemetryEventCatalogEntry(name).allowedSources.includes(source);\n}\n\nfunction eventCatalogEntry(\n name: DecantrTelemetryEventName,\n allowedSources: readonly TelemetrySource[],\n bucket: TelemetrySignalBucket,\n privacy: TelemetryPrivacyClass,\n publicIngest: boolean,\n): TelemetryEventCatalogEntry {\n return {\n name,\n allowedSources,\n bucket,\n privacy,\n publicIngest,\n privacyNotes:\n privacy === 'aggregate'\n ? 'Aggregate product metadata only; no source, prompts, raw paths, emails, or secrets.'\n : privacy === 'opaque_identity'\n ? 'Opaque Decantr identity ids only; no emails, source, prompts, raw paths, or secrets.'\n : 'Public product or acquisition metadata only; no raw referrer URLs, user agents, emails, or click ids.',\n };\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,7 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decantr/telemetry",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-next.0",
|
|
4
4
|
"description": "Privacy-preserving telemetry contracts, clients, and analytics sinks for Decantr",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"decantr",
|
|
7
|
+
"decantr-ai",
|
|
8
|
+
"telemetry",
|
|
9
|
+
"privacy",
|
|
10
|
+
"product-analytics",
|
|
11
|
+
"product-activation",
|
|
12
|
+
"attribution",
|
|
13
|
+
"ai-coding",
|
|
14
|
+
"developer-tools"
|
|
15
|
+
],
|
|
5
16
|
"author": "Decantr AI",
|
|
6
17
|
"license": "MIT",
|
|
7
18
|
"bugs": {
|