{"version":3,"file":"architecture-snapshot.cjs","names":["EventSubscriber","fs","path"],"sources":["../src/architecture-snapshot.ts"],"sourcesContent":["/**\n * ArchitectureSnapshotSubscriber\n *\n * Captures `track()` events into an in-memory architecture snapshot, then\n * writes it to disk. The snapshot is the input to `autotel-eventcatalog`'s\n * generator and is designed to be deterministic, reviewable, and committable.\n *\n * v0 scope: capture event names, observation counts, first/last-seen, sample\n * trace IDs, and the dotted field paths present in payloads. Producer /\n * consumer / channel attribution is read from a small `_autotel.*` convention\n * inside event attributes — that convention is documented in\n * `apps/example-eventcatalog`.\n *\n * @example\n * ```typescript\n * import { init, track } from 'autotel';\n * import { ArchitectureSnapshotSubscriber } from 'autotel-subscribers/architecture';\n *\n * const snapshot = new ArchitectureSnapshotSubscriber({ service: 'orders' });\n *\n * init({\n *   service: 'orders',\n *   subscribers: [snapshot],\n * });\n *\n * // ... exercise the system (run integration tests, hit endpoints, etc.) ...\n *\n * await snapshot.writeToFile('./.autotel/snapshot.json');\n * ```\n */\n\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { EventSubscriber, type EventPayload } from './event-subscriber-base';\n\n/**\n * Public, versioned snapshot format. The generator and any downstream tooling\n * target this spec. Bumping the spec version is a breaking change for\n * downstream consumers, so add fields rather than rename existing ones.\n */\nexport const ARCHITECTURE_SNAPSHOT_SPEC = 'autotel-architecture/v0.1.0' as const;\n\nexport type ArchitectureSnapshot = {\n  spec: typeof ARCHITECTURE_SNAPSHOT_SPEC;\n  generatedAt: string;\n  service: string;\n  events: Record<string, EventObservation>;\n};\n\nexport type EventObservation = {\n  name: string;\n  observedCount: number;\n  firstSeen: string;\n  lastSeen: string;\n  /** Dotted field paths observed in any payload (e.g. `items[].sku`). */\n  fieldPaths: string[];\n  /** Up to 3 trace IDs for click-through from the catalog into the backend. */\n  sampleTraceIds: string[];\n  /** Channel the event was published on, if the caller provided `_autotel.channel`. */\n  channel?: string;\n  /** Service that produced the event, if not the snapshot's own service. */\n  producer?: string;\n  /** Services known to consume this event (optional metadata from _autotel.consumers). */\n  consumers?: string[];\n  /** Observed runtime types and sample primitive values per field path. */\n  fieldStats?: Record<string, FieldStats>;\n  /** Optional contract schema metadata carried from track() call sites. */\n  schema?: {\n    source: 'zod';\n    jsonSchema: unknown;\n    hash: string;\n  };\n};\n\nexport type FieldStats = {\n  /** Runtime types observed for this field path (e.g. string, number). */\n  types: string[];\n  /** Small set of observed primitive values (for enum/value drift checks). */\n  sampleValues: Array<string | number | boolean | null>;\n};\n\nexport interface ArchitectureSnapshotConfig {\n  /** Service identifier that appears in the snapshot header. */\n  service: string;\n  /** Maximum number of trace IDs to retain per event (default 3). */\n  maxSampleTraceIds?: number;\n}\n\nconst DEFAULT_MAX_SAMPLES = 3;\n\nexport class ArchitectureSnapshotSubscriber extends EventSubscriber {\n  readonly name = 'ArchitectureSnapshotSubscriber';\n\n  private readonly service: string;\n  private readonly maxSampleTraceIds: number;\n  private readonly observations = new Map<string, EventObservation>();\n\n  constructor(config: ArchitectureSnapshotConfig) {\n    super();\n    this.service = config.service;\n    this.maxSampleTraceIds = config.maxSampleTraceIds ?? DEFAULT_MAX_SAMPLES;\n  }\n\n  protected async sendToDestination(payload: EventPayload): Promise<void> {\n    // Only `track()` events feed the architecture snapshot. Funnels, outcomes,\n    // and value metrics belong to product analytics, not the architecture model.\n    if (payload.type !== 'event') return;\n\n    const existing = this.observations.get(payload.name);\n    const now = payload.timestamp;\n    const traceId = payload.autotel?.trace_id;\n    const attrs = payload.attributes ?? {};\n    const autotelMeta = readAutotelMeta(attrs);\n    const cleanAttrs = stripAutotelMeta(attrs);\n    const fieldPaths = extractFieldPaths(cleanAttrs);\n    const fieldStats = extractFieldStats(cleanAttrs);\n\n    if (!existing) {\n      this.observations.set(payload.name, {\n        name: payload.name,\n        observedCount: 1,\n        firstSeen: now,\n        lastSeen: now,\n        fieldPaths,\n        sampleTraceIds: traceId ? [traceId] : [],\n        channel: autotelMeta.channel,\n        producer: autotelMeta.producer,\n        consumers: autotelMeta.consumers,\n        fieldStats,\n        schema: payload.schema\n          ? {\n              source: payload.schema.source,\n              jsonSchema: payload.schema.jsonSchema,\n              hash: payload.schema.hash,\n            }\n          : undefined,\n      });\n      return;\n    }\n\n    existing.observedCount += 1;\n    existing.lastSeen = now;\n    existing.fieldPaths = mergeUnique(existing.fieldPaths, fieldPaths);\n    existing.fieldStats = mergeFieldStats(existing.fieldStats ?? {}, fieldStats);\n\n    if (\n      traceId &&\n      !existing.sampleTraceIds.includes(traceId) &&\n      existing.sampleTraceIds.length < this.maxSampleTraceIds\n    ) {\n      existing.sampleTraceIds.push(traceId);\n    }\n\n    existing.channel ??= autotelMeta.channel;\n    existing.producer ??= autotelMeta.producer;\n    existing.consumers = mergeUnique(existing.consumers ?? [], autotelMeta.consumers ?? []);\n    existing.schema ??= payload.schema\n      ? {\n          source: payload.schema.source,\n          jsonSchema: payload.schema.jsonSchema,\n          hash: payload.schema.hash,\n        }\n      : undefined;\n  }\n\n  /**\n   * Build the snapshot in memory. Use this in tests or when you want to\n   * inspect the result before writing it. Field paths and trace IDs are\n   * sorted so equal inputs always produce byte-identical snapshots.\n   *\n   * @param options.now Clock used for the snapshot's `generatedAt` field.\n   * @param options.freezeTimestamps If supplied, every timestamp in the\n   *   output (`generatedAt`, and each event's `firstSeen` / `lastSeen`)\n   *   is replaced with this value. Use when writing a snapshot intended\n   *   to be committed to a repo as a stable artifact — production code\n   *   should not pass this.\n   */\n  toSnapshot(\n    options: { now?: () => Date; freezeTimestamps?: string } = {},\n  ): ArchitectureSnapshot {\n    const { now = () => new Date(), freezeTimestamps } = options;\n\n    const events: Record<string, EventObservation> = {};\n\n    const names = [...this.observations.keys()].toSorted();\n    for (const name of names) {\n      const obs = this.observations.get(name);\n      if (!obs) continue;\n      events[name] = {\n        ...obs,\n        firstSeen: freezeTimestamps ?? obs.firstSeen,\n        lastSeen: freezeTimestamps ?? obs.lastSeen,\n        fieldPaths: obs.fieldPaths.toSorted(),\n        sampleTraceIds: obs.sampleTraceIds.toSorted(),\n        fieldStats: sortFieldStats(obs.fieldStats),\n      };\n    }\n\n    return {\n      spec: ARCHITECTURE_SNAPSHOT_SPEC,\n      generatedAt: freezeTimestamps ?? now().toISOString(),\n      service: this.service,\n      events,\n    };\n  }\n\n  /**\n   * Write the snapshot to disk. Creates parent directories as needed.\n   * Files are written with a trailing newline so they diff cleanly in git.\n   *\n   * See {@link toSnapshot} for option semantics, including `freezeTimestamps`\n   * for byte-stable committed artifacts.\n   */\n  async writeToFile(\n    filePath: string,\n    options: { now?: () => Date; freezeTimestamps?: string } = {},\n  ): Promise<void> {\n    await fs.mkdir(path.dirname(filePath), { recursive: true });\n    const json = JSON.stringify(this.toSnapshot(options), null, 2);\n    await fs.writeFile(filePath, json + '\\n', 'utf8');\n  }\n\n  /** Reset all accumulated state. Useful between test cases. */\n  reset(): void {\n    this.observations.clear();\n  }\n}\n\ntype AutotelMeta = {\n  channel?: string;\n  producer?: string;\n  consumers?: string[];\n};\n\nfunction readAutotelMeta(attrs: Record<string, unknown>): AutotelMeta {\n  const meta = attrs._autotel;\n  if (!meta || typeof meta !== 'object') return {};\n  const m = meta as Record<string, unknown>;\n  return {\n    channel: typeof m.channel === 'string' ? m.channel : undefined,\n    producer: typeof m.producer === 'string' ? m.producer : undefined,\n    consumers: Array.isArray(m.consumers)\n      ? m.consumers.filter((v): v is string => typeof v === 'string').toSorted()\n      : undefined,\n  };\n}\n\n/**\n * Top-level attribute keys that autotel injects automatically (correlation\n * context, baggage, service metadata). These describe the trace, not the\n * event payload, so they don't belong in the captured field paths.\n */\nconst AUTOTEL_INJECTED_KEYS = new Set([\n  '_autotel',\n  'traceId',\n  'trace_id',\n  'spanId',\n  'span_id',\n  'parentSpanId',\n  'parent_span_id',\n  'correlationId',\n  'correlation_id',\n  'service',\n  'service.name',\n]);\n\nfunction stripAutotelMeta(attrs: Record<string, unknown>): Record<string, unknown> {\n  const out: Record<string, unknown> = {};\n  for (const [key, value] of Object.entries(attrs)) {\n    if (AUTOTEL_INJECTED_KEYS.has(key)) continue;\n    out[key] = value;\n  }\n  return out;\n}\n\n/**\n * Walk a JSON-like value and produce a sorted list of dotted field paths.\n * Arrays collapse with `[]`, so `items: [{ sku: 'x' }]` yields `items[].sku`.\n */\nexport function extractFieldPaths(value: unknown, prefix = ''): string[] {\n  const paths = new Set<string>();\n  walk(value, prefix, paths);\n  return [...paths].toSorted();\n}\n\nfunction walk(value: unknown, prefix: string, out: Set<string>): void {\n  if (value === null || value === undefined) return;\n  if (Array.isArray(value)) {\n    const arrayPrefix = prefix + '[]';\n    for (const item of value) walk(item, arrayPrefix, out);\n    return;\n  }\n  if (typeof value === 'object') {\n    for (const [key, v] of Object.entries(value)) {\n      const path = prefix === '' ? key : `${prefix}.${key}`;\n      out.add(path);\n      walk(v, path, out);\n    }\n    return;\n  }\n  // Primitives don't add new paths beyond what their key already added.\n}\n\nfunction mergeUnique(a: string[], b: string[]): string[] {\n  if (b.length === 0) return a;\n  const set = new Set(a);\n  for (const v of b) set.add(v);\n  return [...set];\n}\n\nfunction extractFieldStats(value: unknown, prefix = ''): Record<string, FieldStats> {\n  const out = new Map<string, { types: Set<string>; sampleValues: Set<string | number | boolean | null> }>();\n  walkFieldStats(value, prefix, out);\n  const obj: Record<string, FieldStats> = {};\n  for (const [path, stats] of out) {\n    obj[path] = {\n      types: [...stats.types].toSorted(),\n      sampleValues: [...stats.sampleValues].toSorted(comparePrimitiveValues),\n    };\n  }\n  return obj;\n}\n\nfunction walkFieldStats(\n  value: unknown,\n  prefix: string,\n  out: Map<string, { types: Set<string>; sampleValues: Set<string | number | boolean | null> }>,\n): void {\n  if (value === null || value === undefined) return;\n  if (Array.isArray(value)) {\n    const arrayPrefix = prefix + '[]';\n    for (const item of value) walkFieldStats(item, arrayPrefix, out);\n    return;\n  }\n  if (typeof value === 'object') {\n    for (const [key, v] of Object.entries(value)) {\n      const path = prefix === '' ? key : `${prefix}.${key}`;\n      addPathValue(path, v, out);\n      walkFieldStats(v, path, out);\n    }\n  }\n}\n\nfunction addPathValue(\n  path: string,\n  value: unknown,\n  out: Map<string, { types: Set<string>; sampleValues: Set<string | number | boolean | null> }>,\n): void {\n  const existing = out.get(path) ?? { types: new Set<string>(), sampleValues: new Set<string | number | boolean | null>() };\n  const t = classifyValueType(value);\n  existing.types.add(t);\n  if (\n    (value === null ||\n      typeof value === 'string' ||\n      typeof value === 'number' ||\n      typeof value === 'boolean') &&\n    existing.sampleValues.size < 20\n  ) {\n    existing.sampleValues.add(value);\n  }\n  out.set(path, existing);\n}\n\nfunction classifyValueType(value: unknown): string {\n  if (value === null) return 'null';\n  if (Array.isArray(value)) return 'array';\n  return typeof value;\n}\n\nfunction mergeFieldStats(\n  a: Record<string, FieldStats>,\n  b: Record<string, FieldStats>,\n): Record<string, FieldStats> {\n  const merged: Record<string, FieldStats> = { ...a };\n  for (const [path, bs] of Object.entries(b)) {\n    const prev = merged[path];\n    if (!prev) {\n      merged[path] = bs;\n      continue;\n    }\n    const types = new Set([...prev.types, ...bs.types]);\n    const sampleValues = new Set([...prev.sampleValues, ...bs.sampleValues]);\n    merged[path] = {\n      types: [...types].toSorted(),\n      sampleValues: [...sampleValues]\n        .toSorted(comparePrimitiveValues)\n        .slice(0, 20),\n    };\n  }\n  return merged;\n}\n\nfunction sortFieldStats(\n  stats: Record<string, FieldStats> | undefined,\n): Record<string, FieldStats> | undefined {\n  if (!stats) return undefined;\n  const out: Record<string, FieldStats> = {};\n  for (const path of Object.keys(stats).toSorted()) {\n    out[path] = {\n      types: [...stats[path].types].toSorted(),\n      sampleValues: [...stats[path].sampleValues].toSorted(\n        comparePrimitiveValues,\n      ),\n    };\n  }\n  return out;\n}\n\nfunction comparePrimitiveValues(\n  a: string | number | boolean | null,\n  b: string | number | boolean | null,\n): number {\n  const sa = JSON.stringify(a);\n  const sb = JSON.stringify(b);\n  return sa.localeCompare(sb);\n}\n"],"mappings":"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"}