@jeffjassky/telemetry 0.7.0 → 0.8.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/dist/index.cjs +160 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +160 -5
- package/dist/index.js.map +1 -1
- package/dist/ui/_assets/{index-BksXA5iG.js → index-GvGDQ08Z.js} +2 -2
- package/dist/ui/_assets/index-GvGDQ08Z.js.map +1 -0
- package/dist/ui/index.html +1 -1
- package/package.json +15 -5
- package/types/index.d.ts +45 -0
- package/dist/ui/_assets/index-BksXA5iG.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/types.ts","../src/server/registry.ts","../src/server/model.ts","../src/server/rollups.ts","../src/server/checkpoint.ts","../src/server/emit.ts","../src/server/forget.ts","../src/server/relink.ts","../src/server/indexes.ts","../src/server/keys.ts","../src/server/ingest.ts","../src/server/catalog.ts","../src/server/suggest.ts","../src/server/funnel.ts","../src/server/query.ts","../src/server/values.ts","../src/server/report.ts","../src/server/execute.ts","../src/server/views.ts","../src/server/dashboard.ts","../src/server/index.ts"],"names":["label","Schema","capped","newId","express","count","dim","path","rows","truncated","badRequest","dims","value","MEASURE_OP"],"mappings":"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","file":"index.js","sourcesContent":["import { uuidv7 } from 'uuidv7';\n\n/**\n * UUIDv7 — time-ordered, insertion-local. Node's crypto.randomUUID() is v4:\n * random, NOT sortable. Do not substitute it here; _ids double as insertion\n * order and traceIds are sampled on their low 32 bits (schema §2.6).\n */\nexport const newId = uuidv7;\n\nexport const TelemetryKind = {\n Event: 'event',\n Error: 'error',\n Span: 'span',\n State: 'state',\n Usage: 'usage',\n} as const;\nexport type TelemetryKind = (typeof TelemetryKind)[keyof typeof TelemetryKind];\n\nexport const TELEMETRY_KINDS: readonly TelemetryKind[] = Object.values(TelemetryKind);\n\nexport const LogLevel = {\n Debug: 'debug', Info: 'info', Warn: 'warn', Error: 'error', Fatal: 'fatal',\n} as const;\nexport type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];\n\nexport const Env = { Prod: 'prod', Staging: 'staging', Dev: 'dev' } as const;\nexport type Env = (typeof Env)[keyof typeof Env];\n\nexport const Origin = { Server: 'server', Client: 'client' } as const;\nexport type Origin = (typeof Origin)[keyof typeof Origin];\n\nexport type EntityRef = `${string}:${string}`;\n\nexport const UNKNOWN = 'unknown';\n\n/**\n * The platform read scope. A dashboard `Viewer` whose tenantId is `'*'` reads\n * ACROSS tenants — a support console, a platform-wide cost page. The package\n * never decides who is a platform admin; the host's `viewerAdapter` does. All\n * `'*'` buys is that the escape hatch is expressible and inside the boundary\n * instead of a host reaching around `scoped()`.\n *\n * Which is exactly why it is RESERVED on the write side. A tenant literally\n * named `'*'` would silently become a cross-tenant read — privilege escalation\n * via a string — so every path that can mint a tenantId from outside the\n * package refuses it: emit(), forget(), createKey() in fixed mode, and the\n * ingest handler once the tenant has resolved (key / session / claimed alike).\n */\nexport const PLATFORM_SCOPE = '*';\n\n/** true when a scope is the cross-tenant platform scope rather than a tenant */\nexport const isPlatformScope = (tenantId: unknown): boolean => tenantId === PLATFORM_SCOPE;\n\n/** one wording for the refusal, so the reservation is named wherever it bites */\nexport const RESERVED_TENANT_MESSAGE =\n `telemetry: tenantId \"${PLATFORM_SCOPE}\" is reserved for the dashboard's cross-tenant ` +\n 'platform scope and may never be written';\n\n/** null = never expires. Sized for small-SaaS volume; per-name override in EventSpec. */\nexport const RETENTION_DAYS: Record<TelemetryKind, number | null> = {\n // keep-all + 90d is cheap at this scale, and it makes p95-by-route a raw\n // query instead of a rollup design (schema §2.1)\n [TelemetryKind.Span]: 90,\n [TelemetryKind.Error]: 90,\n [TelemetryKind.Event]: 730,\n [TelemetryKind.State]: 730,\n [TelemetryKind.Usage]: null, // money is immortal\n};\n\n/**\n * Keep-all across the board — small-SaaS scale, exactness beats extrapolation.\n * The per-trace machinery stays, dormant: turn a kind down here (or one name\n * via EventSpec.sampleRate) when volume ever demands it. Rollups are exact\n * either way — they run before the verdict (schema §4.6).\n */\nexport const SAMPLE_RATE: Record<TelemetryKind, number> = {\n [TelemetryKind.Span]: 1,\n [TelemetryKind.Event]: 1,\n [TelemetryKind.Error]: 1, // raw storage burst-capped per fingerprint instead\n [TelemetryKind.State]: 1,\n [TelemetryKind.Usage]: 1, // NEVER sample. money.\n};\n\nexport const REJECT_TTL_DAYS = 30;\nexport const SCHEMA_VERSION = 2;\n\n/**\n * `body` is the only unbounded field on the envelope, and it feeds Mongo's\n * 16 MB document ceiling. Every other bound in the package is stated and\n * enforced (boundedMeta 4 KB, batch 512 KB / 100 records, index budget 24), so\n * this one is too. Override per instance with CreateTelemetryConfig.bodyMax.\n */\nexport const BODY_MAX_CHARS = 16_384;\n\n/** surfaced via t.counters so drops are never silent */\nexport interface TelemetryCounters {\n rejected: number;\n defaulted: number;\n sampled: number;\n capped: number;\n rollupSkipped: number;\n /** an insert-gated write whose dedupeKey (or usage.idempotencyKey) already existed */\n deduped: number;\n /** a `body` clipped to bodyMax — the row survives, marked */\n truncated: number;\n /**\n * `rollupSkipped`, attributed: `${family}|${dimLabel}` → count. Which family\n * dropped which dim — the difference between \"12 records went missing\" and\n * \"`screens_viewed` has no `dimDefault` for `name`\", which is a registry line\n * you can go and write. The scalar above is unchanged and still counts every\n * skip; this is additive.\n */\n rollupSkippedBy: Record<string, number>;\n /**\n * attrs keys seen on a record that its spec does not declare:\n * `${name}|${key}` → count. Under the default `validation: 'lenient'` those\n * keys are STRIPPED and the record is written (see attrsDropped below);\n * under `'strict'` the record is rejected. Either way this is the map that\n * names the registry line you are missing — suggest.ts turns it into zod.\n */\n undeclaredAttrs: Record<string, number>;\n /**\n * `${name}|${key}` → count: an attr REMOVED so the record could still be\n * written, under `validation: 'lenient'`. Two causes, one number, because\n * the fix is the same registry line either way: the key is undeclared, or\n * its value fell outside the declared schema (a client shipped a sixth\n * enum member the registry still lists five of).\n *\n * `${name}|(missing)` means stripping could not rescue the object — a\n * REQUIRED attr was absent — and the record was written without it anyway.\n * That one is an emitter bug, not registry drift.\n *\n * A non-zero value here is not an incident: it is the vocabulary drifting,\n * visible, while the events keep landing. Zero under `'strict'`.\n */\n attrsDropped: Record<string, number>;\n /** metrics keys removed for the same reasons — see attrsDropped. */\n metricsDropped: Record<string, number>;\n /**\n * Write-time subject linking (createSubjectLinking() in emit.ts). All six are\n * zero for a host with no `subjectLinker`, and they exist because linking is\n * the one part of the write path that runs HOST code: every way it can fail\n * ends in a record written unlinked, and a silently unlinked record is\n * indistinguishable from one nobody could link. The split says which.\n */\n /** subjects actually ADDED to records — two links on one record count twice */\n subjectsLinked: number;\n /** records where the linker answered `[]` — no link exists, which is an answer */\n subjectLinkMisses: number;\n /** the linker threw, rejected, or returned something that is not a list of refs */\n subjectLinkErrors: number;\n /** the linker outran subjectLinkTimeoutMs and the record was written unlinked */\n subjectLinkTimeouts: number;\n /** a linked subject whose `type` the event's EventSpec.subjects does not declare */\n subjectLinkUndeclared: number;\n /** a linked subject dropped because the record already held SUBJECT_MAX of them */\n subjectLinkCapped: number;\n}\n\nexport const newCounters = (): TelemetryCounters => ({\n rejected: 0, defaulted: 0, sampled: 0, capped: 0, rollupSkipped: 0,\n deduped: 0, truncated: 0, rollupSkippedBy: {}, undeclaredAttrs: {},\n attrsDropped: {}, metricsDropped: {},\n subjectsLinked: 0, subjectLinkMisses: 0, subjectLinkErrors: 0,\n subjectLinkTimeouts: 0, subjectLinkUndeclared: 0, subjectLinkCapped: 0,\n});\n\n/**\n * Distinct keys either attributed counter map will hold. Both are keyed on\n * data a CLIENT controls — an event name, an attr key — so an unbounded map is\n * a way to grow this process's heap from the outside. Past the cap every new\n * key folds into one `(other)` bucket: the total stays honest, only the\n * attribution stops. A host seeing `(other)` climbing has either a hostile\n * client or a registry that is very far behind.\n */\n/**\n * What a record does when its attrs or metrics do not match the registry.\n *\n * `'lenient'` (the default): strip the offending keys, count them, and WRITE\n * the record. `'strict'`: reject the whole record into the quarantine.\n *\n * The default is lenient because the strict failure mode is the expensive one\n * and it is silent. A registry is a vocabulary maintained in one repo about\n * events emitted from another; the day a client ships a sixth value for a\n * five-value enum, strict mode throws away the WHOLE record — its name, its\n * subject, its metrics, its place in a funnel — to punish one attr. And it\n * does so behind a 202, so nothing surfaces at the emitter. Losing\n * `export.completed` because `outputs` gained an option is not validation\n * working; it is a schema mismatch deleting the evidence a product decision\n * would have been made from.\n *\n * What strictness legitimately protects is unchanged: `data` is still parsed\n * strictly (it is the one free-text corner, so it is a privacy boundary, not a\n * vocabulary one), a missing REQUIRED SUBJECT is still a hard reject (that is\n * structural, not drift), and rollup dimension cardinality is still bounded —\n * a stripped attr simply resolves to the family's `dimDefault`.\n */\nexport type ValidationPolicy = 'lenient' | 'strict';\n\nexport const COUNTER_MAP_MAX = 1000;\n\n/** the fold-here bucket, shaped like a real key so readers can split it the same way */\nexport const COUNTER_OVERFLOW_KEY = '(other)|(other)';\n\n/** `map[key]++`, bounded. Names no registry entry once it folds — see COUNTER_MAP_MAX. */\nexport const bumpCounterMap = (map: Record<string, number>, key: string): void => {\n const seen = map[key];\n if (seen !== undefined) {\n map[key] = seen + 1;\n return;\n }\n // The size check is O(n) and runs only on a key never seen before; once the\n // overflow bucket exists the map is known full, so it short-circuits and a\n // storm of distinct keys stays O(1) per record.\n if (map[COUNTER_OVERFLOW_KEY] !== undefined || Object.keys(map).length >= COUNTER_MAP_MAX) {\n map[COUNTER_OVERFLOW_KEY] = (map[COUNTER_OVERFLOW_KEY] ?? 0) + 1;\n return;\n }\n map[key] = 1;\n};\n\n/**\n * Consistent probability sampling — deterministic per trace, no propagation\n * needed. A traceId with no parseable hex tail silently degrades to per-record\n * sampling, which invalidates every per-trace aggregate (schema §2.6). That is\n * a bug in the caller's id generation, so it fails loudly in dev rather than\n * skewing data in prod.\n */\nexport const traceKeep = (traceId: string | undefined, rate: number): boolean => {\n if (rate >= 1) return true;\n if (!traceId) return Math.random() < rate;\n const tail = parseInt(traceId.slice(-8), 16);\n if (!Number.isFinite(tail)) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `telemetry: traceId \"${traceId}\" has no parseable hex tail — trace-consistent ` +\n `sampling is impossible and would degrade to per-record. Use UUIDv7 or a ` +\n `32-hex OTel trace id.`,\n );\n }\n return Math.random() < rate;\n }\n return tail / 0xffffffff < rate;\n};\n\n/** Map has no toJSON — JSON.stringify(new Map()) is '{}'. Never stringify raw. */\nexport const plain = (v: unknown): unknown =>\n v instanceof Map ? Object.fromEntries([...v].map(([k, x]) => [k, plain(x)]))\n : Array.isArray(v) ? v.map(plain)\n : v instanceof Date ? v\n : v && typeof v === 'object' ? Object.fromEntries(Object.entries(v).map(([k, x]) => [k, plain(x)]))\n : v;\n\nexport interface Logger {\n info(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n}\n\nexport const noopLogger: Logger = { info() {}, warn() {}, error() {} };\n","import { z } from 'zod';\nimport { TelemetryKind, TELEMETRY_KINDS } from './types.js';\n\n/**\n * The registry is the single contract: it drives validation, TypeScript types,\n * derived rollups, and index creation. It is HOST-OWNED — the host authors it\n * in their own code and passes it to createTelemetry(); this package never\n * ships event names (schema §4.2, instrumentation §8).\n */\n\n/**\n * A dimension source. `subject` fans the rollup out over matching subject refs;\n * `attr:`/`field:` read one value off the record.\n */\nexport type DimSource = 'subject' | `attr:${string}` | `field:${string}`;\n\n/**\n * Derived aggregate maintained on write (schema §4.5). One primitive, four\n * jobs: milestones, issue grouping, windowed spend, activity/retention.\n */\nexport interface RollupSpec {\n /** rollup family — several event names may feed one. Default: the event name */\n as?: string;\n /** dimensions, in order. At most one `subject`. */\n by: readonly DimSource[];\n /** when `by` includes `subject`, restrict to these subject types */\n subjects?: readonly string[];\n /**\n * Actor TYPE allowlist — a record whose `actor` has a type not listed here\n * skips this rollup; the raw row is unaffected. Absent = all actors; a record\n * with no actor always passes. This is how \"admin support browsing never\n * moves a customer aggregate\" is declared rather than disciplined.\n */\n actors?: readonly string[];\n /** time bucket (UTC). Omit for a lifetime rollup — that is the classic milestone.\n * `hour` is for incident-grade dashboards; anything finer is the wrong store. */\n bucket?: 'hour' | 'day' | 'week' | 'month';\n /** metric keys accumulated with $add */\n sum?: readonly string[];\n /** dimension sources snapshotted at FIRST occurrence — cohort dimensions */\n capture?: readonly DimSource[];\n /**\n * Bucket name for a non-subject dim that resolves null/empty. Absent keeps\n * the default: skip the record and count it in `rollupSkipped`. Present makes\n * \"no value\" an explicit, queryable group instead of a silent drop.\n *\n * The SUBJECT dim is unaffected — see the fan-out comment in rollups.ts.\n */\n dimDefault?: string;\n /** rollup TTL. Omit or null = immortal (bucketed rollups usually want a number) */\n retentionDays?: number | null;\n}\n\nexport interface EventSpec {\n kind: TelemetryKind;\n origin: 'server' | 'client' | 'any';\n /** subject TYPES that must be present (any number of ids per type) */\n subjects: readonly string[];\n /** attrs values are STRINGS after Mongoose casting — use z.string()/z.enum()/z.coerce.* */\n attrs?: z.ZodObject<any>;\n metrics?: z.ZodObject<any>;\n /**\n * `data` is UNSTORED unless declared here. Closes the erasure hole.\n *\n * Declare an OBJECT schema (or `boundedMeta()`). The type is the looser\n * `ZodType` so `boundedMeta()`'s transform fits, but `EmitInput.data` is an\n * object — a scalar schema like `z.string()` is expressible here and\n * unreachable through emit().\n */\n data?: z.ZodType<any>;\n /** attrs keys that get a real partial compound index built at boot */\n indexedAttrs?: readonly string[];\n /** metrics keys, same machinery — enables indexed numeric range queries */\n indexedMetrics?: readonly string[];\n /** derived aggregates maintained on write — funnels, issues, spend, retention */\n rollups?: readonly RollupSpec[];\n /** overrides RETENTION_DAYS[kind]. null = immortal */\n retentionDays?: number | null;\n /** overrides SAMPLE_RATE[kind]. Dormant by default — every kind ships at 1. */\n sampleRate?: number;\n /**\n * Rate cap on RAW storage per resolved key, per minute. Rollups still see\n * every record, so counts stay exact while an error storm or a client in a\n * retry loop cannot flood the collection. Omit `key` to cap the name whole.\n */\n burst?: { key?: DimSource; maxPerMinute: number };\n /**\n * Await the write with `{w:'majority', j:true}` and rethrow on failure — the\n * contract usage has always had, now declarable. For the host whose cost\n * ledger is a span: without it the only way to await was t.flush(), which\n * drains every in-flight write globally and serializes a busy worker.\n * kind=usage is durable unconditionally, with or without this flag.\n */\n durable?: boolean;\n description: string;\n}\n\nexport type Registry = Record<string, EventSpec>;\n\n/** Identity with a `const` type parameter so literal specs keep their shapes. */\nexport function defineRegistry<const R extends Registry>(specs: R): R {\n return specs;\n}\n\n/**\n * The maxed-shaped `data` escape hatch (build-plan §0.5): scalars only, ≤12\n * keys, strings ≤200 chars, one nesting level, ≤4 KB serialized. Violation\n * drops the WHOLE object — never truncates — so a stored payload is always\n * exactly what the caller sent. Parsing never throws; out-of-bounds resolves\n * to undefined and emit() counts the drop.\n */\nexport function boundedMeta(): z.ZodType<Record<string, unknown> | undefined> {\n const scalar = (v: unknown) =>\n v === null || typeof v === 'boolean' ||\n (typeof v === 'number' && Number.isFinite(v)) ||\n (typeof v === 'string' && v.length <= 200);\n\n const flat = (v: unknown): boolean => {\n if (scalar(v)) return true;\n if (Array.isArray(v)) return v.length <= 20 && v.every(scalar);\n if (v && typeof v === 'object' && !(v instanceof Date)) {\n const entries = Object.entries(v as Record<string, unknown>);\n return entries.length <= 12 && entries.every(([, x]) => scalar(x));\n }\n return false;\n };\n\n const bounded = (v: unknown): v is Record<string, unknown> => {\n if (!v || typeof v !== 'object' || Array.isArray(v) || v instanceof Date) return false;\n const entries = Object.entries(v as Record<string, unknown>);\n if (entries.length > 12) return false;\n if (!entries.every(([, x]) => flat(x))) return false;\n try {\n return JSON.stringify(v).length <= 4096;\n } catch {\n return false; // circular\n }\n };\n\n return z.unknown().transform((v) => (bounded(v) ? (v as Record<string, unknown>) : undefined));\n}\n\nconst DIM_RE = /^(subject|attr:.+|field:.+)$/;\n\n/**\n * Boot-time registry validation — misconfiguration fails deploy, not\n * dashboards. Covers per-spec sanity AND the cross-spec family-shape rule:\n * two events feeding one `as` with different `by` shapes produce docs whose\n * dims array means different things at the same position — silently\n * unqueryable (schema §4.5).\n */\nexport function validateRegistry(registry: Registry): void {\n const shapes = new Map<string, string>();\n\n for (const [name, spec] of Object.entries(registry)) {\n const fail = (msg: string) => {\n throw new Error(`telemetry: registry \"${name}\": ${msg}`);\n };\n\n if (!TELEMETRY_KINDS.includes(spec.kind)) fail(`unknown kind \"${spec.kind}\"`);\n if (!['server', 'client', 'any'].includes(spec.origin)) fail(`unknown origin \"${spec.origin}\"`);\n if (!Array.isArray(spec.subjects)) fail('`subjects` must be an array of subject types');\n if (spec.sampleRate != null && !(spec.sampleRate > 0 && spec.sampleRate <= 1)) {\n fail(`sampleRate ${spec.sampleRate} outside (0, 1]`);\n }\n if (spec.burst && !(spec.burst.maxPerMinute > 0)) fail('burst.maxPerMinute must be positive');\n if (spec.burst?.key && !DIM_RE.test(spec.burst.key)) fail(`bad burst key \"${spec.burst.key}\"`);\n for (const k of spec.indexedAttrs ?? []) {\n if (!spec.attrs || !(k in spec.attrs.shape)) fail(`indexedAttrs \"${k}\" not declared in attrs`);\n }\n for (const k of spec.indexedMetrics ?? []) {\n if (!spec.metrics || !(k in spec.metrics.shape)) fail(`indexedMetrics \"${k}\" not declared in metrics`);\n }\n\n for (const r of spec.rollups ?? []) {\n if (!r.by?.length) fail('rollup has empty `by`');\n for (const d of r.by) if (!DIM_RE.test(d)) fail(`bad dim source \"${d}\"`);\n if (r.by.filter((d) => d === 'subject').length > 1) {\n fail('rollup has more than one subject dim');\n }\n if (r.by.includes('subject') && !r.subjects?.length) {\n fail('rollup uses subject without `subjects`');\n }\n if (r.actors && !r.actors.length) fail('rollup `actors` must be non-empty when present');\n if (r.dimDefault !== undefined) {\n // dims are `label=value` and the rollup `_id` joins them on `|`, so\n // either character in the bucket name corrupts the key itself\n if (typeof r.dimDefault !== 'string' || !r.dimDefault) {\n fail('rollup `dimDefault` must be a non-empty string');\n }\n if (/[|=]/.test(r.dimDefault)) fail(`rollup dimDefault \"${r.dimDefault}\" may not contain \"|\" or \"=\"`);\n }\n\n const as = r.as ?? name;\n // shape = dims + bucket + subject classes: any mismatch makes docs in one\n // family mean different things at the same array position (or triggers\n // the null-join inflation of schema §5.4), so all three pin per family.\n // dimDefault is NOT part of the shape — it changes which bucket a record\n // lands in, never what a position MEANS, so two names may feed one family\n // with different fallbacks.\n const shape =\n r.by.join(',') + '|' + (r.bucket ?? '') + '|' + [...(r.subjects ?? [])].sort().join(',');\n const seen = shapes.get(as);\n if (seen && seen !== shape) {\n throw new Error(`telemetry: rollup family \"${as}\" declared with two shapes: ${seen} / ${shape}`);\n }\n shapes.set(as, shape);\n }\n }\n}\n","import { Schema, type Connection, type Model } from 'mongoose';\nimport {\n TelemetryKind, LogLevel, Env, Origin,\n BODY_MAX_CHARS, RETENTION_DAYS, SCHEMA_VERSION, UNKNOWN, newId, bumpCounterMap,\n type TelemetryCounters, type ValidationPolicy,\n} from './types.js';\nimport type { Registry } from './registry.js';\n\n/** Mongoose Map keys cannot contain dots. gen_ai.request.model -> gen_ai_request_model */\nconst safeKey = (k: string) => k.replace(/\\./g, '_');\nconst sanitize = <T>(m?: Map<string, T>) =>\n m ? new Map([...m].map(([k, v]) => [safeKey(k), v] as [string, T])) : m;\n\n// ── subdocs ─────────────────────────────────────────────────────────────────\n\nconst SubjectRefSchema = new Schema(\n {\n type: { type: String, required: true }, // user | org | team | session\n id: { type: String, required: true },\n /** disambiguates same-type parties: sender | recipient | impersonated */\n role: { type: String },\n },\n { _id: false },\n);\n\n/**\n * The platforms this package ships knowing about. A host may EXTEND the list\n * (CreateTelemetryConfig.platforms) but never replace it — a host adding\n * 'watchos' must not lose 'web'.\n */\nexport const BUILTIN_PLATFORMS = ['web', 'electron', 'ios', 'android', 'server', 'cli'] as const;\n\n/**\n * A factory, not a module-level const, because the enum varies per instance.\n * Everything else in the envelope is open on purpose (`name`, `feature`,\n * `attrs`); a closed platform enum was the one place a host had to lie.\n */\nconst buildClientContextSchema = (platforms: readonly string[]) =>\n new Schema(\n {\n platform: { type: String, required: true, enum: platforms },\n appVersion: { type: String, required: true },\n userAgent: String,\n os: String,\n osVersion: String,\n browser: String,\n browserVersion: String,\n deviceType: String, // desktop | mobile | tablet\n locale: String,\n timezone: String,\n screenW: Number,\n screenH: Number,\n viewportW: Number,\n viewportH: Number,\n connection: String, // 4g | wifi | slow-2g\n online: Boolean,\n /** client clock minus server clock, ms — client timestamps lie */\n clockSkewMs: Number,\n },\n { _id: false },\n );\n\nconst StackFrameSchema = new Schema(\n {\n filename: String,\n fn: String,\n lineno: Number,\n colno: Number,\n inApp: Boolean,\n context: [String],\n },\n { _id: false },\n);\n\nconst ErrorDetailSchema = new Schema(\n {\n type: { type: String, required: true },\n message: { type: String, required: true },\n handled: { type: Boolean, required: true, default: false },\n /** grouping key */\n fingerprint: { type: String, required: true },\n frames: [StackFrameSchema],\n },\n { _id: false },\n);\n\nconst StateDetailSchema = new Schema(\n {\n key: { type: String, required: true }, // 'lifecycle' | 'onboarding_step'\n from: String,\n to: { type: String, required: true },\n /** how long the subject sat in `from` — answers \"where do they stall\" */\n previousSinceMs: Number,\n },\n { _id: false },\n);\n\nconst UsageDetailSchema = new Schema(\n {\n meter: { type: String, required: true },\n quantity: { type: Number, required: true },\n unit: { type: String, required: true },\n /**\n * Authoritative money. `metrics.cost_usd` is a BSON double — fine as a\n * measure, wrong as the thing that becomes an invoice. Money is\n * authoritative only on kind=usage; the metric is a lossy copy.\n */\n amount: Schema.Types.Decimal128,\n currency: String,\n /** at-least-once dedupe. Deterministic, e.g. `${traceId}:${spanId}` */\n idempotencyKey: { type: String, required: true },\n /** who pays — 'org:o_9'. Distinct from subject and from actor. */\n billedTo: { type: String, required: true },\n billable: { type: Boolean, required: true, default: true },\n priceVersion: String,\n /** corrections are new reversing rows; never UPDATE a billed row */\n reverses: String,\n },\n { _id: false },\n);\n\n// ── base schema ─────────────────────────────────────────────────────────────\n\nfunction buildBaseSchema(\n collection: string,\n registry: Registry,\n counters: TelemetryCounters,\n opts: { platforms: readonly string[]; bodyMax: number; validation: ValidationPolicy },\n) {\n const validation = opts.validation;\n const schema = new Schema(\n {\n /** UUIDv7 — sortable, insertion-local, replaces the ObjectId */\n _id: { type: String, required: true },\n schemaVersion: { type: Number, required: true },\n occurredAt: { type: Date, required: true },\n name: { type: String, required: true },\n severity: { type: String, required: true, enum: Object.values(LogLevel), default: LogLevel.Info },\n\n // ── identity ──\n /** tenancy root: shard key, access boundary, index prefix. The only promoted id. */\n tenantId: { type: String, required: true },\n /** multi-party capable: two users, sender/recipient, admin+impersonated */\n subjects: { type: [SubjectRefSchema], default: [] },\n /** derived: ['user:u_1','org:o_9'] */\n subjectKeys: { type: [String] },\n /** who caused it */\n actor: String,\n /** impersonation / delegation */\n onBehalfOf: String,\n /** derived: actor/onBehalfOf NOT already in subjects. Erasure completeness. */\n otherPrincipals: { type: [String] },\n\n // ── origin — required, but filled by the pre-validate hook, NEVER `default:`.\n // A schema default is applied at construction, before the hook, which would\n // silently stamp dev traffic as prod and pin counters.defaulted at zero\n // forever (schema §7 / ops rule 5).\n service: { type: String, required: true },\n release: { type: String, required: true },\n env: { type: String, required: true, enum: Object.values(Env) },\n\n origin: { type: String, enum: Object.values(Origin), default: Origin.Server },\n /** required for client-origin events (enforced by the registry hook, not the schema) */\n client: buildClientContextSchema(opts.platforms),\n\n /**\n * Caller-supplied idempotency for the four non-usage kinds — a Stripe\n * webhook redelivery, a nightly lifecycle diff, a bridge that rewinds its\n * watermark by design. Trusted server callers only; the wire dedupes on\n * the client `_id` instead.\n *\n * Deliberately NOT an `_id` passthrough: `_id` is a UUIDv7 and doubles as\n * insertion order (§2.6), so letting a caller supply an arbitrary string\n * would break that invariant for every reader that sorts on it.\n */\n dedupeKey: String,\n\n // ── correlation ──\n traceId: String,\n spanId: String,\n parentId: String,\n durationMs: Number,\n\n // ── payload — no wildcard index; registry-driven indexes instead (§4.4) ──\n /** STRING VALUES ONLY — Mongoose casts on assignment. Numbers belong in metrics. */\n attrs: { type: Map, of: String, default: {} },\n metrics: { type: Map, of: Number, default: {} },\n /** only stored when the registry declares a schema for it */\n data: { type: Schema.Types.Mixed },\n body: String,\n\n // ── ops ──\n /** 1 = kept everything. 0.05 = multiply counts by 20 when aggregating. */\n sampleRate: { type: Number, default: 1 },\n /** kept despite sampling (carried money or an error). NOT representative. */\n forced: { type: Boolean, default: false },\n expiresAt: Date,\n /** set by forget() — row survives, identifiers do not */\n redactedAt: Date,\n },\n {\n collection,\n discriminatorKey: 'kind',\n timestamps: { createdAt: 'receivedAt', updatedAt: false },\n versionKey: false,\n minimize: false,\n },\n );\n\n // every subject, tenant-scoped and time-sorted, from ONE multikey compound\n // index — explain()-verified 2026-08-10 (schema §2.5)\n schema.index({ tenantId: 1, subjectKeys: 1, occurredAt: -1 });\n schema.index({ tenantId: 1, kind: 1, name: 1, occurredAt: -1 });\n schema.index(\n { traceId: 1, occurredAt: 1 },\n { partialFilterExpression: { traceId: { $exists: true } } },\n );\n // erasure completeness — usually a tiny array, so cheap to maintain.\n // `.0 $exists` = \"array non-empty\"; `$ne: []` is illegal in a partial filter.\n schema.index(\n { tenantId: 1, otherPrincipals: 1 },\n { partialFilterExpression: { 'otherPrincipals.0': { $exists: true } } },\n );\n // partial: usage rows have no expiresAt and must not be indexed as null\n schema.index(\n { expiresAt: 1 },\n { expireAfterSeconds: 0, partialFilterExpression: { expiresAt: { $exists: true } } },\n );\n // caller idempotency, tenant-scoped. The partial filter is load-bearing for\n // exactly the reason it is on usage.idempotencyKey (ops rule 4): without it\n // every record WITHOUT a dedupeKey indexes null and the second one collides.\n schema.index(\n { tenantId: 1, dedupeKey: 1 },\n { unique: true, partialFilterExpression: { dedupeKey: { $exists: true } } },\n );\n\n schema.pre('validate', function (this: any) {\n this._id ??= newId();\n this.schemaVersion ??= SCHEMA_VERSION;\n this.occurredAt ??= new Date();\n\n this.attrs = sanitize(this.attrs);\n this.metrics = sanitize(this.metrics);\n\n // `body` is the sole unbounded field feeding the 16 MB document limit.\n // Enforced HERE rather than in emit() so every write path is covered —\n // emit, ingest, and direct model use alike.\n //\n // This deliberately DIVERGES from boundedMeta's drop-never-truncate\n // doctrine, and the difference is the data, not the mood: `data` is\n // structured evidence where a partial object is a lie about what the caller\n // sent, whereas `body` is prose/log text where a marked prefix is strictly\n // more useful than nothing. The marker is visible so no reader mistakes the\n // prefix for the whole.\n if (typeof this.body === 'string' && this.body.length > opts.bodyMax) {\n const dropped = this.body.length - opts.bodyMax;\n this.body = `${this.body.slice(0, opts.bodyMax)}… [truncated ${dropped} chars]`;\n counters.truncated++;\n }\n\n // ── derived identity arrays ──\n const refs: string[] = (this.subjects ?? []).map((s: any) => `${s.type}:${s.id}`);\n this.subjectKeys = [...new Set(refs)];\n this.otherPrincipals = [\n ...new Set(\n [this.actor, this.onBehalfOf].filter((r): r is string => !!r && !refs.includes(r)),\n ),\n ];\n\n // Never fail on missing origin metadata — default and COUNT.\n for (const f of ['service', 'release'] as const) {\n if (!this[f]) {\n this[f] = UNKNOWN;\n counters.defaulted++;\n }\n }\n if (!this.env) {\n this.env = process.env.NODE_ENV === 'production' ? Env.Prod : Env.Dev;\n }\n\n const spec = registry[this.name];\n if (!spec) throw new Error(`telemetry: unregistered event \"${this.name}\"`);\n if (spec.kind !== this.kind) throw new Error(`telemetry: \"${this.name}\" is kind=${spec.kind}`);\n\n // retention: per-event override, else per-kind. `in` rather than `??` so an\n // explicit `retentionDays: null` means immortal.\n const days = 'retentionDays' in spec ? spec.retentionDays : RETENTION_DAYS[this.kind as TelemetryKind];\n if (days != null && !this.expiresAt) {\n this.expiresAt = new Date(this.occurredAt.getTime() + days * 864e5);\n }\n\n const haveTypes = new Set((this.subjects ?? []).map((s: any) => s.type));\n for (const t of spec.subjects) {\n if (!haveTypes.has(t)) throw new Error(`telemetry: \"${this.name}\" requires subject \"${t}\"`);\n }\n if (spec.origin === Origin.Client && !this.client) {\n throw new Error(`telemetry: \"${this.name}\" is client-origin and requires client context`);\n }\n\n // per-kind requiredness lives HERE so the guarantee never depends on how a\n // particular mongoose version merges discriminator schema requiredness\n if (this.kind === TelemetryKind.Span) {\n for (const f of ['traceId', 'spanId'] as const) {\n if (!this[f]) throw new Error(`telemetry: span requires ${f}`);\n }\n if (typeof this.durationMs !== 'number') throw new Error('telemetry: span requires durationMs');\n }\n if (this.kind === TelemetryKind.State && !this.state?.to) {\n throw new Error('telemetry: state requires state.to');\n }\n\n /**\n * Validate attrs/metrics against the spec.\n *\n * Under `validation: 'strict'` this throws and the whole record is\n * quarantined — the behaviour every version before 0.7.0 had, and the one\n * that quietly deletes an `export.completed` because its `outputs` enum\n * grew a sixth member in another repo.\n *\n * Under `'lenient'` (the default) the offending KEYS are removed, counted\n * by name, and the record is written with whatever survived. The record is\n * the valuable part: its name, its subject, its timestamp, its metrics and\n * its place in a funnel do not become wrong because one attr drifted.\n *\n * The Map is mutated rather than the parsed object returned, because the\n * Map is what mongoose persists — the success path here has never written\n * `r.data` back, and this must not start coercing values that used to pass\n * through untouched.\n */\n const check = (\n label: 'attrs' | 'metrics',\n m: Map<string, unknown> | undefined,\n zschema?: any,\n ) => {\n const obj = Object.fromEntries(m ?? []);\n const dropped = label === 'attrs' ? counters.attrsDropped : counters.metricsDropped;\n const note = (key: string) => bumpCounterMap(dropped, `${this.name}|${key}`);\n\n if (!zschema) {\n if (!Object.keys(obj).length) return;\n if (validation === 'strict') throw new Error(`telemetry: \"${this.name}\" declares no ${label}`);\n for (const key of Object.keys(obj)) {\n note(key);\n m?.delete(key);\n }\n return;\n }\n\n const s = zschema.strict?.() ?? zschema;\n const r = s.safeParse(obj);\n if (r.success) return;\n if (validation === 'strict') {\n throw new Error(`telemetry: ${label} invalid for \"${this.name}\": ${r.error.message}`);\n }\n\n // Which keys did zod object to? `unrecognized_keys` names them directly;\n // every other issue is attributed to the head of its path.\n const bad = new Set<string>();\n for (const issue of r.error.issues as any[]) {\n if (issue.code === 'unrecognized_keys' && Array.isArray(issue.keys)) {\n for (const k of issue.keys) bad.add(String(k));\n } else if (Array.isArray(issue.path) && issue.path.length) {\n bad.add(String(issue.path[0]));\n }\n }\n\n for (const key of bad) {\n // A key zod named but the record does not carry is a REQUIRED attr the\n // emitter omitted. Nothing to strip; count it under its own label so it\n // reads as the emitter bug it is rather than as registry drift.\n if (m?.has(key)) {\n note(key);\n m.delete(key);\n } else {\n note('(missing)');\n }\n }\n };\n check('attrs', this.attrs, spec.attrs);\n check('metrics', this.metrics, spec.metrics);\n\n // `data` is dropped unless the registry declares a schema for it. This is\n // what makes delete-by-subject a guarantee rather than best-effort.\n if (this.data != null) {\n const s: any = spec.data;\n if (!s) {\n this.data = undefined;\n counters.rejected++;\n } else {\n const strict = s.strict?.() ?? s;\n const r = strict.safeParse(this.data);\n if (!r.success) throw new Error(`telemetry: data invalid for \"${this.name}\": ${r.error.message}`);\n if (r.data === undefined) counters.rejected++; // boundedMeta out-of-bounds: drop whole, never truncate\n this.data = r.data;\n }\n }\n });\n\n return schema;\n}\n\n// ── discriminators ──────────────────────────────────────────────────────────\n\nexport interface TelemetryModels {\n /** the base model — query across every kind */\n TelemetryModel: Model<any>;\n /** per-kind discriminator models */\n byKind: Record<TelemetryKind, Model<any>>;\n}\n\n/**\n * Model factory. Mongoose keeps compiled models in a per-connection registry,\n * so a name collision throws OverwriteModelError. Reuse an already-compiled\n * model when the name is taken (standards/traps.md #2) — but note the caveat:\n * the reused model closed over the FIRST instance's registry and counters.\n * Hosts running two registries on one connection must set distinct modelNames.\n */\nexport function buildTelemetryModels(opts: {\n connection: Connection;\n registry: Registry;\n counters: TelemetryCounters;\n modelName: string;\n collection: string;\n /** host additions to the builtin platform enum — union, never replacement */\n platforms?: readonly string[];\n bodyMax?: number;\n /** what a vocabulary mismatch costs — see ValidationPolicy. Default 'lenient'. */\n validation?: ValidationPolicy;\n}): TelemetryModels {\n const { connection, registry, counters, modelName, collection } = opts;\n const platforms = [...new Set([...BUILTIN_PLATFORMS, ...(opts.platforms ?? [])])];\n const bodyMax = opts.bodyMax ?? BODY_MAX_CHARS;\n\n const existing = connection.models?.[modelName];\n if (existing) {\n return {\n TelemetryModel: existing,\n byKind: Object.fromEntries(\n Object.values(TelemetryKind).map((k) => [k, (existing.discriminators ?? {})[`${modelName}_${k}`] ?? existing]),\n ) as Record<TelemetryKind, Model<any>>,\n };\n }\n\n const base = buildBaseSchema(collection, registry, counters, {\n platforms,\n bodyMax,\n validation: opts.validation ?? 'lenient',\n });\n const TelemetryModel = connection.model(modelName, base);\n\n const disc = (kind: TelemetryKind, build: () => Schema) =>\n TelemetryModel.discriminator(`${modelName}_${kind}`, build(), kind);\n\n const byKind: Record<TelemetryKind, Model<any>> = {\n [TelemetryKind.Event]: disc(TelemetryKind.Event, () => new Schema({})), // envelope suffices\n\n [TelemetryKind.Error]: disc(TelemetryKind.Error, () => {\n const s = new Schema({ error: { type: ErrorDetailSchema, required: true } });\n s.index(\n { tenantId: 1, 'error.fingerprint': 1, occurredAt: -1 },\n { partialFilterExpression: { kind: TelemetryKind.Error } },\n );\n return s;\n }),\n\n [TelemetryKind.Span]: disc(TelemetryKind.Span, () => {\n // traceId/spanId/durationMs requiredness enforced in the pre-validate hook\n const s = new Schema({});\n s.index(\n { traceId: 1, parentId: 1 },\n { partialFilterExpression: { kind: TelemetryKind.Span } },\n );\n return s;\n }),\n\n [TelemetryKind.State]: disc(TelemetryKind.State, () => {\n const s = new Schema({ state: { type: StateDetailSchema, required: true } });\n s.index(\n { tenantId: 1, 'state.key': 1, 'state.to': 1, occurredAt: -1 },\n { partialFilterExpression: { kind: TelemetryKind.State } },\n );\n return s;\n }),\n\n [TelemetryKind.Usage]: disc(TelemetryKind.Usage, () => {\n const s = new Schema({ usage: { type: UsageDetailSchema, required: true } });\n // partialFilterExpression is load-bearing: discriminator indexes apply to\n // the WHOLE collection, so without it every non-usage doc indexes\n // idempotencyKey as null and the second one collides (ops rule 4)\n s.index(\n { 'usage.idempotencyKey': 1 },\n { unique: true, partialFilterExpression: { kind: TelemetryKind.Usage } },\n );\n s.index(\n { tenantId: 1, 'usage.meter': 1, occurredAt: 1 },\n { partialFilterExpression: { kind: TelemetryKind.Usage } },\n );\n return s;\n }),\n };\n\n return { TelemetryModel, byKind };\n}\n","import { Schema, type Connection, type Model } from 'mongoose';\nimport type { DimSource, Registry, RollupSpec } from './registry.js';\nimport { bumpCounterMap, type TelemetryCounters } from './types.js';\n\n/**\n * One derived-aggregate primitive (schema §4.5). Group a stream of records by\n * a declared tuple and keep first / last / count / sums. The registry declares\n * the tuple; this file is agnostic — the same operation is a milestone, an\n * issue group, windowed spend, and an activity/retention stream.\n */\n\nexport function buildRollupModel(connection: Connection, modelName: string, collection: string): Model<any> {\n const existing = connection.models?.[modelName];\n if (existing) return existing;\n\n const schema = new Schema(\n {\n /** `${tenantId}|${as}|${dims.join('|')}|${bucketKey}` — deterministic, upsert-safe */\n _id: { type: String, required: true },\n tenantId: { type: String, required: true },\n /** rollup family. Several event names may feed one. */\n as: { type: String, required: true },\n /**\n * Dimension values in spec order. Subject dims keep their native\n * `type:id` form ('user:u_1') so erasure can match them directly;\n * everything else is `key=value`. Flattened strings for the same reason\n * subjectKeys is — never compound-index two fields of one subdoc array.\n */\n dims: { type: [String], required: true },\n /** denormalized prefix of the subject dim, when there is one — §5.4 hazard */\n subjectType: String,\n /** UTC-truncated bucket start; absent on lifetime rollups */\n bucketAt: Date,\n\n firstAt: { type: Date, required: true },\n lastAt: { type: Date, required: true },\n count: { type: Number, required: true, default: 0 },\n /** registry `sum` keys accumulated across every contributing record */\n sums: { type: Map, of: Number, default: {} },\n /** registry `capture` snapshot at FIRST occurrence — cohort dimensions */\n firstCapture: { type: Map, of: String, default: {} },\n firstTraceId: String,\n expiresAt: Date,\n },\n { collection, versionKey: false },\n );\n\n // cohort scan within one family, ordered by first occurrence\n schema.index({ tenantId: 1, as: 1, subjectType: 1, firstAt: 1 });\n // slice a family by dimension value, newest bucket first\n schema.index({ tenantId: 1, as: 1, dims: 1, bucketAt: -1 });\n // erasure + per-subject journey across ALL families — no `as` prefix on purpose\n schema.index({ tenantId: 1, dims: 1 });\n schema.index(\n { expiresAt: 1 },\n { expireAfterSeconds: 0, partialFilterExpression: { expiresAt: { $exists: true } } },\n );\n\n return connection.model(modelName, schema);\n}\n\n// ── dimension resolution ────────────────────────────────────────────────────\n\nconst path = (o: any, p: string): unknown =>\n typeof o?.get === 'function' ? o.get(p) : p.split('.').reduce((a: any, k) => a?.[k], o);\n\n/** `subject` is handled by fan-out, so it resolves to undefined here.\n * Exported: emit()'s burst cap keys on the same sources. */\nexport const resolveDim = (src: DimSource, doc: any): unknown =>\n src.startsWith('attr:') ? doc.attrs?.get(src.slice(5))\n : src.startsWith('field:') ? path(doc, src.slice(6))\n : undefined;\n\nconst label = (src: DimSource) => src.slice(src.indexOf(':') + 1);\n\n/** UTC. Weeks start Monday. */\nexport const truncate = (d: Date, b?: RollupSpec['bucket']): Date | undefined => {\n if (!b) return undefined;\n if (b === 'hour') return new Date(Math.floor(d.getTime() / 36e5) * 36e5);\n const y = d.getUTCFullYear();\n const m = d.getUTCMonth();\n if (b === 'month') return new Date(Date.UTC(y, m, 1));\n const day = new Date(Date.UTC(y, m, d.getUTCDate()));\n if (b === 'day') return day;\n return new Date(day.getTime() - ((day.getUTCDay() + 6) % 7) * 864e5);\n};\n\n/** what recordRollup does INSTEAD of writing, for a caller that only wants the count */\nexport interface RecordRollupOptions {\n /**\n * Build the fan-out and return its size without touching the collection.\n *\n * relink()'s dry run needs to report exactly what a real run would write, and\n * the only way for that number to be exactly right is for the SAME function\n * to produce it — every gate below (the actor allowlist, a missing dim with\n * no `dimDefault`, a `subjects` filter that admits nothing) changes the count,\n * and a caller that modelled them separately would be a second copy of this\n * file's rules, drifting.\n *\n * The two counters below are suppressed under it for the same reason: a dry\n * run that moved `rollupSkipped` would double it on the real run that\n * follows, and report a drop that never happened.\n */\n dryRun?: boolean;\n}\n\n/**\n * Update-pipeline upsert so late/backfilled events correct EVERYTHING, not\n * just the boundaries. `$setOnInsert` for firstCapture/firstTraceId would pin\n * the cohort dimensions to whichever record LANDED first rather than whichever\n * OCCURRED first — silently wrong for offline clients, backfills, and retries.\n *\n * Returns the number of rollup DOCUMENTS this record touched — one per subject\n * the fan-out admitted, or one for a spec that does not fan out, or zero when a\n * gate declined. `emit()` and `ingest.ts` ignore it; relink() reports it, which\n * is the only reason it is not `void`.\n */\nexport async function recordRollup(\n RollupModel: Model<any>,\n doc: any,\n name: string,\n spec: RollupSpec,\n counters: TelemetryCounters,\n opts?: RecordRollupOptions,\n): Promise<number> {\n const dry = opts?.dryRun === true;\n\n // aggregate-plane actor gate: admin support browsing must never move a\n // customer aggregate; the raw row is untouched (RollupSpec.actors)\n if (spec.actors && doc.actor) {\n const actorType = String(doc.actor).split(':')[0];\n if (!spec.actors.includes(actorType)) return 0;\n }\n\n const as = spec.as ?? name;\n const at: Date = doc.occurredAt;\n const bucketAt = truncate(at, spec.bucket);\n const bucketKey = bucketAt ? bucketAt.toISOString() : '';\n\n // Non-subject dims resolved once. Absent a declared fallback, a missing dim\n // means the record cannot be keyed at all — an implicit 'null' bucket would\n // silently corrupt every group. `dimDefault` makes that bucket EXPLICIT: the\n // host names it, so \"no value\" is a group you can query rather than a drop\n // you have to notice in a counter.\n const fixed = new Map<DimSource, string>();\n for (const src of spec.by) {\n if (src === 'subject') continue;\n let v = resolveDim(src, doc);\n if (v == null || v === '') {\n if (spec.dimDefault === undefined) {\n if (!dry) {\n counters.rollupSkipped++;\n // …and WHICH family lost WHICH dim, so the scalar above becomes a\n // `dimDefault` line the System page can name. Keyed exactly as the\n // catalog labels a family and its dims (`label(src)` is the same `x=`\n // prefix written into `dims`), so a reader can join the two.\n bumpCounterMap(counters.rollupSkippedBy, `${as}|${label(src)}`);\n }\n return 0;\n }\n v = spec.dimDefault;\n }\n fixed.set(src, `${label(src)}=${String(v)}`);\n }\n\n // At most one `subject` dim per spec (asserted in validateRegistry).\n // dimDefault deliberately does NOT apply here: a non-subject dim that is\n // missing is a record we can still attribute to someone, while a record with\n // no matching subject cannot be attributed at all. Bucketing it under a\n // placeholder subject would invent a party that does not exist — and erasure\n // matches subject dims by their native `type:id` form, so the placeholder\n // would be unreachable by forget().\n const fansOut = spec.by.includes('subject');\n const refs: (string | null)[] = fansOut\n ? (doc.subjectKeys ?? []).filter(\n (r: string) => !spec.subjects || spec.subjects.includes(r.split(':')[0]!),\n )\n : [null];\n if (!refs.length) return 0;\n\n const firstCapture = Object.fromEntries(\n (spec.capture ?? [])\n .map((src) => [label(src), resolveDim(src, doc)] as const)\n .filter(([, v]) => v != null)\n .map(([k, v]) => [k, String(v)]),\n );\n\n const expiresAt =\n spec.retentionDays != null ? new Date(at.getTime() + spec.retentionDays * 864e5) : undefined;\n\n const ops = refs.map((ref) => {\n const dims = spec.by.map((src) => (src === 'subject' ? ref! : fixed.get(src)!));\n /** true when this record becomes the new earliest occurrence */\n const isNewFirst = {\n $or: [{ $eq: [{ $type: '$firstAt' }, 'missing'] }, { $lt: [at, '$firstAt'] }],\n };\n const sums = Object.fromEntries(\n (spec.sum ?? [])\n .map((k) => [k, doc.metrics?.get(k)] as const)\n .filter(([, v]) => typeof v === 'number')\n .map(([k, v]) => [`sums.${k}`, { $add: [{ $ifNull: [`$sums.${k}`, 0] }, v] }]),\n );\n return {\n updateOne: {\n filter: { _id: `${doc.tenantId}|${as}|${dims.join('|')}|${bucketKey}` },\n update: [\n {\n $set: {\n tenantId: doc.tenantId,\n as,\n dims,\n ...(ref ? { subjectType: ref.split(':')[0] } : {}),\n ...(bucketAt ? { bucketAt } : {}),\n ...(expiresAt ? { expiresAt } : {}),\n // aggregation $min/$max ignore missing, so correct on insert too\n firstAt: { $min: ['$firstAt', at] },\n lastAt: { $max: ['$lastAt', at] },\n count: { $add: [{ $ifNull: ['$count', 0] }, 1] },\n ...sums,\n firstTraceId: { $cond: [isNewFirst, doc.traceId ?? null, '$firstTraceId'] },\n firstCapture: { $cond: [isNewFirst, { $literal: firstCapture }, '$firstCapture'] },\n },\n },\n ],\n upsert: true,\n },\n };\n });\n\n // The dry run stops HERE, with the fan-out built and nothing sent. Everything\n // above this line is a decision; only this line is a write.\n if (dry) return ops.length;\n\n await RollupModel.bulkWrite(ops, { ordered: false });\n return ops.length;\n}\n","import { Schema, type Connection, type Model } from 'mongoose';\nimport type { Logger } from './types.js';\n\n/**\n * Key→timestamp checkpoint store for pull-importers (ported from maxed's\n * checkpoint.ts — recon decision #3: primitive, not hook).\n *\n * Values are ADVISORY. Every writer downstream of a checkpoint must be\n * idempotent (client event ids, usage idempotency keys), so a checkpoint that\n * is stale, reset, or lost costs a re-scan — never a duplicate. That property\n * is what lets an importer rewind its watermark by a safety overlap every run.\n * Reads and writes therefore swallow errors: checkpoint failure must never\n * take the batch down.\n */\n\nexport function buildCheckpointModel(connection: Connection, modelName: string, collection: string): Model<any> {\n const existing = connection.models?.[modelName];\n if (existing) return existing;\n const schema = new Schema(\n {\n /** stable scanner name, e.g. \"mailery-bridge\" */\n key: { type: String, required: true, unique: true },\n /** high-water mark: the scanner has processed everything at/before this */\n at: { type: Date, required: true },\n },\n { collection, timestamps: { createdAt: false, updatedAt: true }, versionKey: false },\n );\n return connection.model(modelName, schema);\n}\n\nexport interface Checkpoint {\n /** null on the first ever run — callers decide what \"from the beginning\" means */\n get(): Promise<Date | null>;\n advance(at: Date): Promise<void>;\n}\n\nexport function createCheckpointFactory(CheckpointModel: Model<any>, logger: Logger) {\n return function checkpoint(key: string): Checkpoint {\n return {\n async get() {\n try {\n const doc = await CheckpointModel.findOne({ key }).lean();\n return (doc as any)?.at ?? null;\n } catch (err) {\n // read failure → caller re-scans from its own floor; dedupe absorbs it\n logger.error({ err, key }, '[telemetry] checkpoint read failed');\n return null;\n }\n },\n async advance(at: Date) {\n try {\n await CheckpointModel.updateOne({ key }, { $set: { at } }, { upsert: true });\n } catch (err) {\n logger.error({ err, key, at }, '[telemetry] checkpoint write failed');\n }\n },\n };\n };\n}\n","import type { Model } from 'mongoose';\nimport {\n TelemetryKind, COUNTER_MAP_MAX, RESERVED_TENANT_MESSAGE, SAMPLE_RATE, bumpCounterMap,\n isPlatformScope, newId, traceKeep, plain,\n type TelemetryCounters, type Logger,\n} from './types.js';\nimport type { EventSpec, Registry } from './registry.js';\nimport { recordRollup, resolveDim } from './rollups.js';\n\n/**\n * Per-kind durability, the aggregate/evidence split, and (dormant) sampling\n * (schema §4.6). A record passes through two independent decisions:\n *\n * 1. Aggregate plane — rollups. See every VALID record, unconditionally.\n * 2. Evidence plane — the raw row. Subject to sampling and the burst cap.\n *\n * Sampling and capping are decisions about storing evidence, not about whether\n * the thing happened — so they must never bend an aggregate. Two inversions\n * exist, and both are the same rule: when the INSERT is the dedupe, the insert\n * must gate aggregation too. `kind=usage` (unique idempotencyKey) and any\n * record carrying a `dedupeKey` therefore save first and roll up after — a\n * retried usage row is the same money, and a redelivered webhook is the same\n * event. Idempotency that still lets rollups run twice does not fix the bug.\n */\n\nexport interface EmitCtx {\n registry: Registry;\n byKind: Record<TelemetryKind, Model<any>>;\n RollupModel: Model<any>;\n rejects: () => { insertOne(doc: any): Promise<unknown> };\n counters: TelemetryCounters;\n logger: Logger;\n /** in-flight fire-and-forget writes, awaited by t.flush() */\n track: (p: Promise<unknown>) => void;\n /** write-time subject linking, or null when no `subjectLinker` is configured */\n linkSubjects?: LinkSubjects | null;\n}\n\nexport interface EmitInput {\n tenantId: string;\n subjects?: Array<{ type: string; id: string; role?: string }>;\n attrs?: Record<string, string>;\n metrics?: Record<string, number>;\n /** keep despite sampling — set automatically for money/errors */\n forceKeep?: boolean;\n /**\n * Caller idempotency for event/state/span/error. Trusted SERVER callers only\n * — the wire path dedupes on the client `_id` instead. Deterministic per\n * logical occurrence, e.g. `stripe:${event.id}` or `lifecycle:${accountId}:${day}`.\n */\n dedupeKey?: string;\n /** await the write with {w:'majority', j:true} and rethrow — overrides EventSpec.durable */\n durable?: boolean;\n [k: string]: unknown;\n}\n\n/** What emit() did. `Promise<void>` could not distinguish \"written\" from \"queued\". */\nexport interface EmitResult {\n /** the record _id — usable for correlation even when the row was not stored */\n id: string;\n /**\n * written — BOTH planes are on disk and awaited: the row, and its rollups.\n * Readable immediately, with no flush(). One meaning, on every\n * path that returns it — durable specs, kind=usage, and\n * insert-gated dedupeKey writes alike.\n * A rollup that FAILS is quarantined and counted rather than\n * thrown, as on every other path — awaiting an aggregate must not\n * turn its failure into a report that the row does not exist.\n * queued — validated and aggregated; the save is in flight, t.flush() awaits it\n * deduped — dedupeKey already present: nothing written, nothing aggregated\n * sampled — evidence plane declined; aggregates were still updated\n * capped — burst cap declined; aggregates were still updated\n * rejected — unregistered or failed validation; quarantined in the rejects collection\n */\n outcome: 'written' | 'queued' | 'deduped' | 'sampled' | 'capped' | 'rejected';\n}\n\n/**\n * Count attrs keys the record's spec does not declare, BEFORE anything parses\n * them.\n *\n * What actually happens to those keys, so nobody has to guess: model.ts's\n * pre('validate') hook parses `attrs` as `spec.attrs.strict()`. Under the\n * default `validation: 'lenient'` (0.7.0) an undeclared key is STRIPPED, its\n * removal counted in `attrsDropped`, and the record is written without it.\n * Under `'strict'` the whole record is quarantined and counted in `rejected`,\n * which is what every version before 0.7.0 did unconditionally.\n *\n * Either way this counter is the GROUPING of the drift, and under the lenient\n * default it is the ONLY warning you get — there is no quarantine row to\n * notice any more, by design. The quarantine listed 41 failed writes one at a\n * time and a human read none of them; this says \"all 41 carried `codec`\",\n * which is a zod line the System page can hand you (see suggest.ts).\n *\n * Keys are sanitized the way the writer sanitizes them (dots → underscores, as\n * mongoose Map keys demand), or a client's `gen_ai.model` would read as\n * undeclared against a perfectly well declared `gen_ai_model`.\n */\nexport function noteUndeclaredAttrs(\n counters: TelemetryCounters,\n name: string,\n spec: Pick<EventSpec, 'attrs'>,\n attrs: unknown,\n): void {\n if (!attrs || typeof attrs !== 'object') return;\n const keys = attrs instanceof Map ? [...attrs.keys()] : Object.keys(attrs);\n const shape = (spec.attrs as { shape?: Record<string, unknown> } | undefined)?.shape;\n for (const raw of keys) {\n const key = String(raw).replace(/\\./g, '_');\n if (shape && Object.prototype.hasOwnProperty.call(shape, key)) continue;\n // bounded: the key half is client-controlled, so it folds past the cap\n bumpCounterMap(counters.undeclaredAttrs, `${name}|${key}`);\n }\n}\n\n// ── write-time subject linking ───────────────────────────────────────────────\n\n/**\n * The host's answer to \"who else is this record about?\", asked once per record,\n * on the way to disk.\n *\n * NOT `SubjectAdapter` (dashboard.ts), which labels refs at READ time and\n * changes nothing about what is stored. This one changes the row.\n *\n * The failure mode it exists for: a desktop client knows its install and\n * nothing else, so every record it sends carries `machine:<installId>` and no\n * `user`. The host can map most of those to an account — but doing that at read\n * time leaves a cohort funnel anchored on `user` reading zero for every desktop\n * stage. `import.completed` is there in volume and invisible to the only\n * question anyone asked of it. Joining at write time puts the party on the row\n * AND on its rollups, and the rollups are the half a read-time join can never\n * reach: a lifetime `by:['subject']` family is keyed on the subject the record\n * was written with, forever.\n */\nexport interface SubjectLinker {\n /**\n * Additional subjects to attach to a record being written. Return `[]` when\n * nothing links — that is an answer, and it is counted as one.\n *\n * MUST be fast, and is expected to be CACHED. It runs on the ingest hot path,\n * once per record, and the package bounds it rather than trusting it: a throw\n * or an overrun writes the record unlinked. It should not throw; the package\n * guards anyway.\n */\n link(\n subjects: Array<{ type: string; id: string; role?: string }>,\n ctx: { name: string; tenantId: string },\n ):\n | Array<{ type: string; id: string; role?: string }>\n | Promise<Array<{ type: string; id: string; role?: string }>>;\n}\n\ntype SubjectRef = { type: string; id: string; role?: string };\n\n/**\n * Total subjects one record may carry once linking has run. The envelope is\n * multi-party by design, but `subjectKeys` is a multikey index term and every\n * subject fans a `by:['subject']` rollup out one more time — so an unbounded\n * array is an unbounded write amplification with a host's cache bug behind it.\n */\nexport const SUBJECT_MAX = 8;\n\n/** what link() gets before the record is written unlinked */\nexport const SUBJECT_LINK_TIMEOUT_MS = 50;\n\n/** merged subjects to write, or null when nothing changed */\nexport type LinkSubjects = (\n name: string,\n spec: Pick<EventSpec, 'subjects'>,\n tenantId: string,\n declared: unknown,\n) => Promise<SubjectRef[] | null>;\n\n/** the race token — a Symbol so no host error can ever impersonate a timeout */\nconst LINK_TIMEOUT = Symbol('telemetry.subjectLink.timeout');\n\n/**\n * Wrap a host `SubjectLinker` in the guarantees the write path needs.\n *\n * Returns `null` — not a pass-through — when no linker is configured, so a host\n * without one runs the code 0.4.0 ran rather than an extra `await` per record.\n *\n * Every failure resolves the same way: write the record with the subjects it\n * came with, and count. Ingest is at-least-once and unattended, so a resolver\n * that hangs must cost a record its `user` and never its existence — an\n * unlinked row is a worse row, a dropped row is a lie about what happened.\n */\nexport function createSubjectLinking(opts: {\n linker?: SubjectLinker;\n timeoutMs?: number;\n counters: TelemetryCounters;\n logger: Logger;\n}): LinkSubjects | null {\n const { linker, counters, logger } = opts;\n if (!linker) return null;\n const timeoutMs = opts.timeoutMs ?? SUBJECT_LINK_TIMEOUT_MS;\n\n // Once per reason, ever. This fires from the write path, so a line per record\n // IS the outage — and none of these are things a human reads twice. The set\n // is bounded for the same reason the counter maps are: one of the keys\n // carries an event name and a subject type.\n const warned = new Set<string>();\n const warnOnce = (key: string, msg: string) => {\n if (warned.has(key) || warned.size >= COUNTER_MAP_MAX) return;\n warned.add(key);\n logger.warn(msg);\n };\n\n return async function linkSubjects(name, spec, tenantId, declared) {\n const have: SubjectRef[] = Array.isArray(declared) ? declared : [];\n\n // The host is asked about a COPY of the well-formed refs. Handing it the\n // array that is about to be written would make a stray `push` in someone\n // else's memo cache a mutation of this record; malformed entries are left\n // out because validation is about to reject them anyway and the host should\n // not have to defend against them.\n const seen = new Set<string>();\n const view: SubjectRef[] = [];\n for (const s of have) {\n const ref = wellFormed(s);\n if (!ref) continue;\n seen.add(`${ref.type}:${ref.id}`);\n view.push(ref);\n }\n\n let out: unknown;\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n out = await Promise.race([\n // the async wrapper turns a SYNCHRONOUS throw into a rejection, so a\n // linker that dies on its first line lands in the same catch as one\n // whose promise rejects\n (async () => linker.link(view, { name, tenantId }))(),\n new Promise((_, reject) => {\n timer = setTimeout(() => reject(LINK_TIMEOUT), timeoutMs);\n }),\n ]);\n } catch (e) {\n if (e === LINK_TIMEOUT) {\n counters.subjectLinkTimeouts++;\n warnOnce(\n 'timeout',\n `[telemetry] subjectLinker.link() exceeded ${timeoutMs}ms — records are being written ` +\n 'UNLINKED rather than waiting. The hook is expected to answer from a cache; a resolver ' +\n 'that queries per record cannot keep up with ingest. Warned once — the count is ' +\n 'counters.subjectLinkTimeouts.',\n );\n } else {\n counters.subjectLinkErrors++;\n warnOnce(\n 'threw',\n `[telemetry] subjectLinker.link() threw — records are being written unlinked: ${e}. ` +\n 'Warned once — the count is counters.subjectLinkErrors.',\n );\n }\n return null;\n } finally {\n clearTimeout(timer);\n }\n\n if (!Array.isArray(out)) {\n counters.subjectLinkErrors++;\n warnOnce(\n 'shape',\n `[telemetry] subjectLinker.link() resolved to ${typeof out}, not an array — records are ` +\n 'being written unlinked. Return [] when nothing links. Warned once — the count is ' +\n 'counters.subjectLinkErrors.',\n );\n return null;\n }\n if (!out.length) {\n counters.subjectLinkMisses++;\n return null;\n }\n\n // Room is measured against what the record already declares, so a caller\n // that arrives at the cap loses its LINKS and keeps its own subjects — the\n // host's own refs are never displaced by a derived one.\n let room = Math.max(0, SUBJECT_MAX - have.length);\n let capped = 0;\n const add: SubjectRef[] = [];\n\n for (const s of out) {\n const ref = wellFormed(s);\n if (!ref) {\n counters.subjectLinkErrors++;\n warnOnce(\n 'entry',\n '[telemetry] subjectLinker returned an entry that is not { type, id } — dropped. ' +\n 'Warned once — the count is counters.subjectLinkErrors.',\n );\n continue;\n }\n // A ref the record already carries is never doubled, and the DECLARED one\n // survives whole — including its `role`, which the caller knew and the\n // linker is guessing at.\n const key = `${ref.type}:${ref.id}`;\n if (seen.has(key)) continue;\n\n // A linked type the registry does not declare is WRITTEN, and counted.\n //\n // Refusing it here was the obvious rule and it is the wrong one, because\n // `EventSpec.subjects` is a REQUIRED list — `model.ts` quarantines a\n // record missing any type declared there. So the only way to satisfy a\n // refusal is to make the type mandatory, and a linked type is mandatory\n // for nobody: linking exists precisely because SOME records resolve and\n // some do not. Declaring `user` on a desktop event to permit the link\n // would quarantine every record from a machine that has not been\n // activated yet — deleting the pre-activation funnel to describe the\n // post-activation one. A refusal that can only be satisfied by data loss\n // is not a rule, it is a dead feature: the type stays undeclared, every\n // link is dropped, and the hook does nothing at all.\n //\n // Undeclared is therefore a fact to REPORT, not to enforce. The registry\n // stays honest because the count says exactly which name is carrying\n // which extra type, and `deriveSuggestions` can turn that into \"declare\n // it\" advice on the day the link becomes total.\n if (!spec.subjects.includes(ref.type)) {\n counters.subjectLinkUndeclared++;\n }\n if (room <= 0) {\n capped++;\n continue;\n }\n seen.add(key);\n room--;\n add.push(ref);\n }\n\n counters.subjectLinkCapped += capped;\n // Nothing survived. Deliberately NOT counted as a miss: a miss is the host\n // saying no link exists, which is a different fact from a link it named and\n // the package refused.\n if (!add.length) return null;\n counters.subjectsLinked += add.length;\n return [...have, ...add];\n };\n}\n\n/** a ref the envelope can actually store, copied — or null */\nfunction wellFormed(s: unknown): SubjectRef | null {\n if (!s || typeof s !== 'object') return null;\n const { type, id, role } = s as SubjectRef;\n if (typeof type !== 'string' || !type) return null;\n if (typeof id !== 'string' || !id) return null;\n return typeof role === 'string' && role ? { type, id, role } : { type, id };\n}\n\nexport function createEmitter(ctx: EmitCtx) {\n const { registry, byKind, RollupModel, rejects, counters } = ctx;\n\n /** per-process token buckets — a storm cap, approximate on purpose, not an SLA */\n const burstBuckets = new Map<string, { n: number; resetAt: number }>();\n const burstAllow = (key: string, maxPerMinute: number): boolean => {\n const now = Date.now();\n let b = burstBuckets.get(key);\n if (!b || now >= b.resetAt) {\n if (burstBuckets.size > 10_000) burstBuckets.clear(); // storm of DISTINCT keys\n b = { n: 0, resetAt: now + 60_000 };\n burstBuckets.set(key, b);\n }\n return ++b.n <= maxPerMinute;\n };\n\n return async function emit(name: string, doc: EmitInput): Promise<EmitResult> {\n // minted up front so every return path — including the ones that store\n // nothing — can hand the caller an id to correlate on\n const id = newId();\n\n /** quarantine + count, without the document (nothing is hydrated yet) */\n const reject = (reason: string): EmitResult => {\n counters.rejected++;\n ctx.track(\n rejects().insertOne({ at: new Date(), name, reason, raw: plain(doc) }).catch(() => {}),\n );\n return { id, outcome: 'rejected' };\n };\n\n // '*' is the dashboard's cross-tenant READ scope; a row carrying it would\n // turn a tenant name into a privilege escalation. Quarantined rather than\n // thrown for the same reason everything else here is: hosts call emit()\n // fire-and-forget, and an unhandled rejection on attacker-shaped input is a\n // way to stop the process. The refusal is loud where it counts — counters,\n // quarantine, the System page — and nothing is written either way.\n if (isPlatformScope(doc.tenantId)) return reject(RESERVED_TENANT_MESSAGE);\n\n const spec = registry[name];\n // unregistered names quarantine rather than throw — the caller may be a\n // stale client; the operator finds it in rejects + counters\n if (!spec) return reject('unregistered event');\n\n const dedupeKey = doc.dedupeKey;\n if (dedupeKey !== undefined && (typeof dedupeKey !== 'string' || !dedupeKey || dedupeKey.length > 200)) {\n return reject('dedupeKey must be a non-empty string of at most 200 chars');\n }\n\n const kind = spec.kind;\n const baseRate = spec.sampleRate ?? SAMPLE_RATE[kind];\n\n // A span carrying money or an error must survive, or the usage→span join\n // dangles. A record with a dedupeKey must survive for a subtler reason: its\n // AGGREGATION is gated on its own insert (below), so sampling or capping the\n // evidence away would take the rollup with it — the aggregate would silently\n // lose the record instead of merely losing the row. dedupeKey therefore\n // implies forced: never sampled, never burst-capped.\n const forced =\n !!doc.forceKeep ||\n kind === TelemetryKind.Usage ||\n !!doc.error ||\n dedupeKey != null ||\n (doc.metrics as any)?.cost_usd != null;\n\n // per-call override beats the spec; usage is durable either way\n const durable = kind === TelemetryKind.Usage || (doc.durable ?? spec.durable ?? false);\n\n const Model = byKind[kind];\n // `durable` is a routing instruction, not data — destructured out the same\n // way forceKeep is, so it never lands on the document. `dedupeKey` is NOT:\n // it is a stored, indexed field and rides through in `rest`.\n const { forceKeep: _drop, durable: _durable, ...rest } = doc;\n\n // ── write-time subject linking ──\n // HERE, and not after hydration, because the merged subjects have to be on\n // the document before pre('validate') derives `subjectKeys` — and\n // subjectKeys is what recordRollup fans a `by:['subject']` family out over.\n // Link any later and the row carries a party its own milestone rollup has\n // never heard of, which is the read/write split this feature exists to\n // close.\n //\n // Bounded, guarded, and never fatal: see createSubjectLinking(). One\n // ordering consequence is worth stating rather than discovering — on the\n // insert-gated path below, the INSERT is the dedupe verdict, so a record\n // that turns out to be a redelivery has already asked the linker by the\n // time it learns nothing will be written. It writes nothing and aggregates\n // nothing, as before; the cost of the duplicate is one cached lookup.\n const linked = ctx.linkSubjects\n ? await ctx.linkSubjects(name, spec, doc.tenantId, doc.subjects)\n : null;\n\n // `...rest` FIRST. Spreading it last would let a caller override `forced`,\n // `sampleRate`, `name`, or `_id` — and a cost-bearing span passed\n // forced:false gets sampled away, dangling the usage→span join (ops rule 6).\n // Dotted keys sanitized HERE, not just in the hook — mongoose Map casting\n // rejects \".\" keys at assignment, which is before pre('validate') runs.\n const safe = (o?: Record<string, unknown>) =>\n new Map(Object.entries(o ?? {}).map(([k, v]) => [k.replace(/\\./g, '_'), v]));\n const payload = {\n ...rest,\n _id: id,\n name,\n // computed like everything below it, and absent when nothing linked, so a\n // host with no linker hands the model the exact object 0.4.0 did\n ...(linked ? { subjects: linked } : {}),\n sampleRate: forced ? 1 : baseRate,\n forced,\n attrs: safe(doc.attrs),\n metrics: safe(doc.metrics),\n };\n\n // Observed before hydration, because the hook below is where they die.\n noteUndeclaredAttrs(counters, name, spec, doc.attrs);\n\n const onFail = async (e: unknown) => {\n counters.rejected++;\n // plain() first — JSON.stringify(Map) is '{}' and would erase every subject\n await rejects()\n .insertOne({ at: new Date(), name, reason: String(e), raw: plain(doc) })\n .catch(() => {});\n };\n\n // Hydrate + validate ONCE, for every record — kept, sampled, or capped.\n // The pre('validate') hook derives subjectKeys, sanitizes dotted attr keys,\n // and runs the registry checks, so the aggregate plane below never sees an\n // invalid or under-derived record.\n const d = new Model(payload);\n try {\n await d.validate();\n } catch (e) {\n await onFail(e);\n if (kind === TelemetryKind.Usage) throw e; // caller must know\n return { id, outcome: 'rejected' };\n }\n\n /**\n * Fire the aggregate plane and HAND BACK the writes, so a `durable` emit can\n * await them (below). Still tracked either way — t.flush() drains them for\n * everyone else.\n *\n * A rollup failure stays a quarantine-and-count, never a throw, on every\n * path including durable: the row is already on disk by then, and turning a\n * failed aggregate into an exception would tell the caller nothing was\n * written when something was. Drops are reported through counters and the\n * rejects collection, as everywhere else.\n */\n const rollup = (): Promise<unknown>[] =>\n (spec.rollups ?? []).map((r) => {\n const p = recordRollup(RollupModel, d, name, r, counters).catch(onFail);\n ctx.track(p);\n return p;\n });\n\n // hook already ran; skip the re-validate on save\n const saveOpts = {\n validateBeforeSave: false,\n ...(durable ? { writeConcern: { w: 'majority', j: true } } : {}),\n } as any;\n\n // ── insert-gated: the write IS the dedupe, so it must precede the rollup ──\n // Usage (unique idempotencyKey) and any record with a dedupeKey. A\n // duplicate returns having aggregated NOTHING; that is the entire point.\n // The save is awaited here whether or not `durable` was asked for — gating\n // requires it — so the outcome is 'written', never 'queued'; `durable` adds\n // the write concern and the rethrow on top.\n if (kind === TelemetryKind.Usage || dedupeKey != null) {\n try {\n await d.save(saveOpts);\n } catch (e: any) {\n if (isDuplicateKey(e)) {\n counters.deduped++; // dedupe working — no row, no re-count\n return { id, outcome: 'deduped' };\n }\n await onFail(e);\n if (durable) throw e; // money, and anything else the caller chose to await\n return { id, outcome: 'rejected' };\n }\n // Aggregates awaited too, and NOT only when `durable` — because this\n // branch returns 'written', and that outcome has to mean one thing. A\n // gated write whose rollups were still in flight would be 'written' with\n // a weaker guarantee than the durable path's 'written', which is the\n // exact ambiguity Promise<void> had before EmitResult replaced it.\n //\n // The cost is one round trip per rollup family on a write that already\n // awaited its insert, and kind=usage — unconditionally durable, and the\n // case that matters most, since usage rollups are money — was paying it\n // regardless. Callers who do not want to wait have `queued`.\n await Promise.all(rollup());\n return { id, outcome: 'written' };\n }\n\n // ── aggregate plane: unconditional ──\n const aggregates = rollup();\n\n // ── evidence plane: sampling verdict, then burst cap ──\n if (!forced && !traceKeep(doc.traceId as string | undefined, baseRate)) {\n counters.sampled++;\n return { id, outcome: 'sampled' };\n }\n\n // Cost-bearing records are exempt from the cap — the usage→span join\n // outranks storm control, and money volume is bounded by spend anyway.\n const burst = spec.burst;\n if (burst && (doc.metrics as any)?.cost_usd == null) {\n const v = burst.key ? resolveDim(burst.key, d) : '';\n if (!burstAllow(`${doc.tenantId}|${name}|${v ?? ''}`, burst.maxPerMinute)) {\n counters.capped++;\n return { id, outcome: 'capped' };\n }\n }\n\n // Declared durable: await the row and rethrow, so a host whose cost ledger\n // is a span can await THIS write instead of t.flush(), which drains every\n // in-flight write globally and serializes a busy worker.\n //\n // The ROLLUPS are awaited here too. `durable` exists to remove the race\n // between \"the emit resolved\" and \"the data is readable\", and a host that\n // awaited the row and then read the aggregate could otherwise legitimately\n // see a stale one — the same race, one plane over.\n if (durable) {\n try {\n await d.save(saveOpts);\n } catch (e) {\n await onFail(e);\n throw e;\n }\n await Promise.all(aggregates);\n return { id, outcome: 'written' };\n }\n\n // Fire-and-forget, but never silent — failures quarantine, and t.flush()\n // awaits stragglers.\n ctx.track(d.save(saveOpts).catch(onFail));\n return { id, outcome: 'queued' };\n };\n}\n\nexport function isDuplicateKey(e: any): boolean {\n return e?.code === 11000 || e?.cause?.code === 11000;\n}\n","import { createHash } from 'node:crypto';\nimport type { Collection, Model } from 'mongoose';\nimport {\n TelemetryKind, PLATFORM_SCOPE, RESERVED_TENANT_MESSAGE, isPlatformScope, type EntityRef,\n} from './types.js';\n\n/**\n * Erasure, actually implemented (schema §4.7). Covers subjects, actor,\n * onBehalfOf, and client — every place an id can appear, because `data` is\n * registry-declared-or-unstored.\n *\n * DELETE only when the ref is the sole party on the row. Any row with\n * surviving subjects is REDACTED instead: forgetting a user must not destroy\n * the org's business record. Usage rows are always redacted (statutory\n * retention).\n */\n\nexport interface ForgetCtx {\n TelemetryModel: Model<any>;\n RollupModel: Model<any>;\n rejects: () => Collection;\n aliases: () => Collection;\n views: () => Collection;\n pepper: () => string;\n /**\n * The host asserting that a subject ref names the same party in every tenant.\n * The package cannot verify it, so it is declared rather than detected — and\n * it is what lets step 6 reach platform-scoped saved views. See the comment\n * there for why the default has to be off.\n */\n globalSubjectRefs: () => boolean;\n}\n\nexport interface ForgetResult {\n deleted: number;\n redacted: number;\n rollups: number;\n aliases: number;\n views: number;\n}\n\nexport function createForget(ctx: ForgetCtx) {\n /** keeps the `type:` prefix so subjectKeys stays re-derivable on any later save */\n const pseudoId = (ref: string) =>\n 'redacted_' + createHash('sha256').update(ref + ctx.pepper()).digest('hex').slice(0, 16);\n\n return async function forget(tenantId: string, ref: EntityRef): Promise<ForgetResult> {\n const { TelemetryModel, RollupModel } = ctx;\n // No '*' here, and deliberately NOT as \"erase across every tenant\": erasure\n // deletes and rewrites rows, so a scope that matched everything would make\n // one typo unbounded. A platform-wide erasure is N tenant-scoped calls, and\n // the caller has to name each one. Throws — forget() is always awaited.\n if (isPlatformScope(tenantId)) throw new Error(RESERVED_TENANT_MESSAGE);\n const [type, rawId] = ref.split(':') as [string, string];\n if (!type || !rawId) throw new Error(`telemetry: forget ref \"${ref}\" is not \"type:id\"`);\n const newId = pseudoId(ref);\n const newRef = `${type}:${newId}`;\n\n const match = { tenantId, $or: [{ subjectKeys: ref }, { otherPrincipals: ref }] };\n\n // 1. sole-party, non-financial rows: delete outright\n const del = await TelemetryModel.deleteMany({\n ...match,\n kind: { $ne: TelemetryKind.Usage },\n subjectKeys: { $eq: ref, $size: 1 }, // ref is the ONLY subject\n otherPrincipals: { $in: [[], null] },\n });\n\n // 2. everything else: keep the row, destroy the linkage.\n // Driver-level updateMany: mongoose 9 gates pipeline updates behind an\n // option that mongoose 7/8 don't know — the driver accepts them everywhere.\n const red = await TelemetryModel.collection.updateMany(match, [\n {\n $set: {\n subjects: {\n $map: {\n input: '$subjects',\n as: 's',\n in: {\n $cond: [\n { $eq: [{ $concat: ['$$s.type', ':', '$$s.id'] }, ref] },\n { $mergeObjects: ['$$s', { id: newId }] },\n '$$s',\n ],\n },\n },\n },\n subjectKeys: {\n $map: {\n input: '$subjectKeys',\n as: 'k',\n in: { $cond: [{ $eq: ['$$k', ref] }, newRef, '$$k'] },\n },\n },\n otherPrincipals: {\n $map: {\n input: { $ifNull: ['$otherPrincipals', []] },\n as: 'k',\n in: { $cond: [{ $eq: ['$$k', ref] }, newRef, '$$k'] },\n },\n },\n actor: { $cond: [{ $eq: ['$actor', ref] }, newRef, '$actor'] },\n onBehalfOf: { $cond: [{ $eq: ['$onBehalfOf', ref] }, newRef, '$onBehalfOf'] },\n client: '$$REMOVE',\n redactedAt: '$$NOW',\n },\n },\n ]);\n\n // 3. derived rollups — REKEY, never delete. Deleting a person's rollups\n // retroactively shrinks every cohort they were counted in, so funnel\n // denominators change under you. Aggregates survive; the person does\n // not. _id is immutable in Mongo, so insert-then-delete rather than $set.\n //\n // Only rollups carrying the ref as a DIMENSION are touched. A rollup\n // grouped on something else — an issue keyed on error.fingerprint —\n // never held the id, which is exactly why non-subject rollups are safe\n // to keep forever.\n const rolls = await RollupModel.find({ tenantId, dims: ref }).lean();\n let rollups = 0;\n if (rolls.length) {\n await RollupModel.bulkWrite(\n (rolls as any[]).map((r) => {\n const dims = r.dims.map((d: string) => (d === ref ? newRef : d));\n const bucketKey = r.bucketAt ? new Date(r.bucketAt).toISOString() : '';\n return {\n insertOne: {\n document: { ...r, _id: `${tenantId}|${r.as}|${dims.join('|')}|${bucketKey}`, dims },\n },\n };\n }),\n { ordered: false },\n ).catch((e: any) => {\n // re-running forget() for the same ref collides on _id — already erased, no-op\n const errs = e?.writeErrors ?? [];\n if (e?.code !== 11000 && !(errs.length && errs.every((w: any) => w.code === 11000))) throw e;\n });\n rollups = (await RollupModel.deleteMany({ tenantId, dims: ref })).deletedCount;\n }\n\n // 4. quarantine holds raw payloads — in scope for erasure too\n await ctx.rejects().deleteMany({\n 'raw.tenantId': tenantId,\n $or: [\n { 'raw.subjects': { $elemMatch: { type, id: rawId } } },\n { 'raw.actor': ref },\n { 'raw.onBehalfOf': ref },\n ],\n });\n\n // 5. aliases are pure linkage — anon→user. Either side matching is enough;\n // there is nothing to redact, only to delete.\n const aliases = (\n await ctx.aliases().deleteMany({ tenantId, $or: [{ anonRef: ref }, { userRef: ref }] })\n ).deletedCount;\n\n // 6. saved dashboard views: ownerRef is a person. Private views die with\n // them; shared ones stay useful to the tenant, so only the owner link\n // is redacted (dashboards §3 — same delete-vs-redact rule as rows).\n //\n // A person who used the cross-tenant dashboard owns views stored under\n // PLATFORM_SCOPE, which is not a tenant — so a tenant-scoped forget()\n // misses them and erasure is incomplete. Reaching them is only SAFE when\n // a ref names one party globally; if ids are per-tenant, 'user:u_1' is a\n // different person in each and one tenant's erasure would delete\n // another's views. The package cannot tell which world it is in, so the\n // host declares it and the default is the conservative one.\n //\n // Note the asymmetry with the guard at the top: that refuses '*' as the\n // ERASURE SCOPE (unbounded rewrite of every tenant's rows). This reaches\n // '*' rows owned by one named person. Bounded by the ref, not the tenant.\n const viewScope = ctx.globalSubjectRefs()\n ? { $in: [tenantId, PLATFORM_SCOPE] }\n : tenantId;\n const views =\n (await ctx.views().deleteMany({ tenantId: viewScope, ownerRef: ref, shared: { $ne: true } })).deletedCount +\n (await ctx.views().updateMany(\n { tenantId: viewScope, ownerRef: ref, shared: true },\n { $set: { ownerRef: newRef } },\n )).modifiedCount;\n\n return { deleted: del.deletedCount ?? 0, redacted: red.modifiedCount ?? 0, rollups, aliases, views };\n };\n}\n","import type { Model } from 'mongoose';\nimport type { Registry } from './registry.js';\nimport type { LinkSubjects } from './emit.js';\nimport { recordRollup } from './rollups.js';\nimport type { Logger, TelemetryCounters } from './types.js';\n\n/**\n * The backfill for write-time subject linking (0.5.0) — the operation a host\n * runs ONCE, on the day it configures a `subjectLinker`, to make the records it\n * already has answer the question the new ones can.\n *\n * `subjectLinker` links on the way to disk. That is not an implementation\n * detail, it is the whole reason the hook exists: a lifetime `by:['subject']`\n * rollup is keyed on the subject the record was written WITH, permanently, so a\n * read-time join can reach the raw rows and never the aggregates. Which means a\n * host that adopts linking on a Tuesday has two populations. Records after\n * Tuesday carry `user:u_1` on the row and in a `subjects:['user']` family.\n * Records before it carry `machine:m1` and nothing else, and the family has no\n * member for any of them — so a lifetime milestone is missing every one, and a\n * cohort funnel anchored on `user` reads ZERO for every stage those events\n * feed, while the events sit right there, real and correctly timestamped.\n *\n * Nothing at read time closes that. The aggregate is already written. The rows\n * have to be relinked and the affected rollups replayed, which is this file.\n *\n * Two properties carry the whole design:\n *\n * 1. It reuses `createSubjectLinking()` — the SAME merge `emit()` and\n * `ingest.ts` run. Dedupe on `type:id`, the declared ref winning whole,\n * `SUBJECT_MAX`, the timeout, the six counters. A backfill with its own\n * merge rules would be a second policy that quietly disagrees with the\n * write path about what a linked row looks like, and the disagreement\n * would show up as an aggregate nobody can reconcile.\n *\n * 2. It is idempotent BY CONSTRUCTION rather than by bookkeeping. A row that\n * already carries the linked subject offers it to the merge, the merge\n * dedupes it, and NOTHING is new — so nothing is written and nothing is\n * replayed. There is no watermark to corrupt and no marker field to\n * forget. That matters more here than anywhere else in the package,\n * because `recordRollup` `$add`s 1 per call: a replay that runs twice\n * inflates a historical `count` that no reader can distinguish from a real\n * one. An aggregate that is merely missing data announces itself. An\n * aggregate that is 1.3× too big does not.\n */\n\nexport interface RelinkOptions {\n /**\n * Restrict to these event names. Default: every stored record, whatever its\n * name — including names the registry no longer declares, which are counted\n * in `skipped` (see below) rather than quietly relinked.\n *\n * A name that is not in the registry THROWS, before any I/O. A typo that\n * silently relinks nothing is exactly the failure this package tests for\n * elsewhere: it looks like a clean run.\n */\n names?: string[];\n /** only records at/after this instant (`occurredAt`) */\n since?: Date;\n /**\n * Stop after this many records are EXAMINED — not linked. A cap on work, so\n * an operator can probe a huge collection cheaply; it says nothing about how\n * many rows changed. Default unbounded.\n */\n limit?: number;\n /**\n * Report what would change and write NOTHING. **Defaults to `true`.**\n *\n * This operation mutates historical aggregates, so the short call has to be\n * the safe one — `await t.relink()` tells you what it would do. Writing is\n * the thing you opt into, with `{ dryRun: false }`.\n *\n * A dry run still ASKS the host's linker (there is no other way to know what\n * would link), so `t.counters.subjectsLinked` and its five siblings move.\n * Nothing on disk does.\n */\n dryRun?: boolean;\n /** records fetched per batch, and the `onProgress` cadence. Default 500. */\n batchSize?: number;\n /**\n * Called after each batch with the CUMULATIVE result so far, for progress\n * output on a run that may take hours. Guarded: a printer that throws does\n * not kill the backfill.\n */\n onProgress?: (r: RelinkResult) => void;\n}\n\nexport interface RelinkResult {\n /** rows read */\n examined: number;\n /** rows that gained at least one subject */\n linked: number;\n /** subjects added in total — two links on one row count twice */\n subjects: number;\n /** rollup documents written (or, under `dryRun`, that would have been) */\n rollups: number;\n /**\n * Rows where the linker answered `[]`. Not a failure — \"no link exists\" is an\n * answer, and on a backfill it is the expected answer for most rows.\n */\n misses: number;\n /**\n * Rows where the linker threw, rejected, timed out, or answered with\n * something that is not a list of refs. Counted once per ROW, however many\n * ways it went wrong; `t.counters.subjectLinkErrors` / `subjectLinkTimeouts`\n * keep the finer split, including which of the four it was.\n */\n errors: number;\n /**\n * Rows the run declined to offer the linker at all, plus one standing for a\n * run that declined everything.\n *\n * Two things land here. A stored row whose `name` the registry no longer\n * declares: we cannot know which rollup families it once fed, so we cannot\n * replay them, and relinking the row without them would leave the row and its\n * aggregates disagreeing — which is the exact bug this operation exists to\n * fix, inverted. And a call with no `subjectLinker` configured, which returns\n * `skipped: 1` having read nothing: counting the rows it refused to read\n * would mean reading them.\n */\n skipped: number;\n}\n\n/** records fetched per batch, and how often `onProgress` fires */\nexport const RELINK_BATCH_SIZE = 500;\n\nexport interface RelinkCtx {\n registry: Registry;\n /** the BASE model — every kind is a discriminator on one collection */\n TelemetryModel: Model<any>;\n RollupModel: Model<any>;\n counters: TelemetryCounters;\n logger: Logger;\n /** the guarded 0.5.0 merge, or null when no `subjectLinker` is configured */\n linkSubjects: LinkSubjects | null;\n}\n\ntype SubjectRef = { type: string; id: string; role?: string };\n\nconst refKey = (s: { type: string; id: string }) => `${s.type}:${s.id}`;\n\nexport function createRelink(ctx: RelinkCtx) {\n const { registry, TelemetryModel, RollupModel, counters, logger, linkSubjects } = ctx;\n\n return async function relink(opts: RelinkOptions = {}): Promise<RelinkResult> {\n const dryRun = opts.dryRun !== false;\n const batchSize = opts.batchSize ?? RELINK_BATCH_SIZE;\n const result: RelinkResult = {\n examined: 0, linked: 0, subjects: 0, rollups: 0, misses: 0, errors: 0, skipped: 0,\n };\n\n if (opts.names) {\n const unknown = opts.names.filter((n) => !registry[n]);\n if (unknown.length) {\n throw new Error(\n `telemetry: relink() was given names this registry does not declare: ${unknown.join(', ')}. ` +\n 'A name with no spec has no rollup families to replay, so relinking it could only ' +\n 'desynchronize its rows from its aggregates. Omit `names` to sweep everything.',\n );\n }\n }\n\n // Nothing to do, and nothing worth throwing about: a host may call this\n // from a boot path or a cron that does not know how the instance was\n // configured, and \"you have no linker\" is a fact, not an exception.\n if (!linkSubjects) {\n logger.warn(\n '[telemetry] relink() has no subjectLinker to ask — nothing was read and nothing was ' +\n 'written. Configure createTelemetry({ subjectLinker }) first; relink() backfills what ' +\n 'that hook would have done, it does not replace it.',\n );\n result.skipped = 1;\n return result;\n }\n\n // Mongo reads `limit: 0` as NO LIMIT, so a caller asking for zero records\n // would get the entire collection — the one arithmetic mistake in this file\n // that could not be undone. Handled before the query is built.\n if (opts.limit != null && opts.limit <= 0) return result;\n\n const filter: Record<string, unknown> = {};\n if (opts.names) filter.name = { $in: opts.names };\n if (opts.since) filter.occurredAt = { $gte: opts.since };\n\n const query = TelemetryModel.find(filter)\n // Pinned to the `_id` index on purpose, and NOT sorted.\n //\n // This cursor updates the very documents it is walking. Left to the\n // planner, a filter on `name` invites an index that a relink MOVES the\n // document within — `{tenantId, subjectKeys, occurredAt}` is multikey on\n // the array we are adding to, so a row could be delivered a second time\n // under its new key. `_id` is the one key our writes never touch, so the\n // scan cannot re-deliver. (A re-delivery would be harmless — the merge\n // dedupes — but it would eat `limit` and inflate `examined`, and a\n // backfill whose progress numbers lie is a backfill nobody trusts.)\n //\n // A `sort({_id: 1})` would express the same thing and risk a blocking\n // in-memory sort on a collection too big for one, which is precisely the\n // collection this operation exists for.\n .hint({ _id: 1 })\n .batchSize(batchSize);\n if (opts.limit != null) query.limit(opts.limit);\n\n const progress = () => {\n if (!opts.onProgress) return;\n try {\n opts.onProgress({ ...result });\n } catch (e) {\n logger.warn(`[telemetry] relink() onProgress threw — ignored, the backfill continues: ${e}`);\n }\n };\n\n const cursor = query.cursor();\n let sinceProgress = 0;\n try {\n for await (const doc of cursor) {\n result.examined++;\n sinceProgress++;\n if (sinceProgress >= batchSize) {\n sinceProgress = 0;\n progress();\n }\n\n const spec = registry[doc.name];\n if (!spec) {\n result.skipped++;\n continue;\n }\n\n // The host is asked about PLAIN refs, not the mongoose subdocuments —\n // the same shape the write path hands it, so a linker cannot tell a\n // backfill from a live write and cannot behave differently on one.\n const declared: SubjectRef[] = (doc.subjects ?? []).map((s: any) =>\n (s.role ? { type: s.type, id: s.id, role: s.role } : { type: s.type, id: s.id }),\n );\n\n // Why the counters and not the return value: `LinkSubjects` answers\n // `null` for every outcome that changes nothing — a miss, a throw, a\n // timeout, garbage, and a link the merge deduped away. They are the\n // same value and they are not the same event, so the split is read off\n // the deltas the shared implementation already records. Errors are\n // folded to one per ROW here (a single row can produce several, one per\n // junk entry) because this result counts rows.\n const m0 = counters.subjectLinkMisses;\n const e0 = counters.subjectLinkErrors + counters.subjectLinkTimeouts;\n const merged = await linkSubjects(doc.name, spec, doc.tenantId, declared);\n result.misses += counters.subjectLinkMisses - m0;\n if (counters.subjectLinkErrors + counters.subjectLinkTimeouts > e0) result.errors++;\n\n if (!merged) continue;\n\n const had = new Set<string>(declared.map(refKey));\n const mergedKeys: string[] = [];\n const newKeys: string[] = [];\n for (const s of merged) {\n const key = refKey(s);\n if (mergedKeys.includes(key)) continue;\n mergedKeys.push(key);\n if (!had.has(key)) newKeys.push(key);\n }\n // The merge already guarantees this, and asserting it costs nothing: a\n // replay over zero new refs is the one thing that must never happen\n // twice.\n if (!newKeys.length) continue;\n\n result.linked++;\n result.subjects += newKeys.length;\n\n // ── the row FIRST, then its aggregates ──\n //\n // The order is the crash policy, and it is not symmetric. Replay first\n // and die before the row is updated, and the re-run finds a row that\n // still looks unlinked, links it again, and adds a SECOND 1 to every\n // count it already moved. Update the row first and die before the\n // replay, and the re-run finds the ref already present, adds nothing,\n // and one record is missing from one rollup.\n //\n // So the second one, always: this operation fails toward an aggregate\n // that is short, never one that is long. A short aggregate can be\n // spotted against the rows it came from. A long one cannot be spotted\n // at all.\n //\n // Written through `updateOne` rather than `doc.save()` deliberately —\n // saving would re-run `pre('validate')`, which re-parses `attrs` and\n // `data` against TODAY's registry. A registry that has tightened since\n // these rows were written would quarantine historical records that were\n // valid when they landed, and a backfill has no business deleting the\n // history it was asked to repair. `subjectKeys` is derived here by the\n // same rule that hook uses, because the rollup fan-out reads\n // `subjectKeys` and a row updated without it relinks and still\n // aggregates to nothing.\n if (!dryRun) {\n await TelemetryModel.updateOne(\n { _id: doc._id },\n { $set: { subjects: merged, subjectKeys: mergedKeys } },\n );\n }\n\n // In memory only, and never saved: the fan-out must see the NEW refs\n // and nothing else. `recordRollup` adds 1 per (document, subject) it is\n // handed, so handing it the merged list would re-count every subject\n // the original write already counted — the double that this whole file\n // is arranged to prevent.\n doc.subjectKeys = newKeys;\n\n for (const r of spec.rollups ?? []) {\n // A family that does not group by `subject` counted this record once\n // at write time and cannot gain a group from a new one — its dims are\n // attrs and fields that have not changed. Replaying it would be a\n // straight double. This one line is the exactly-once condition;\n // everything else follows from the merge.\n if (!r.by.includes('subject')) continue;\n // A `subjects` filter that does not admit any of the new refs leaves\n // recordRollup with an empty fan-out, which it declines. That is what\n // keeps a family the ORIGINAL subjects already satisfied untouched:\n // it is never handed those subjects again.\n result.rollups += await recordRollup(RollupModel, doc, doc.name, r, counters, { dryRun });\n }\n }\n } finally {\n await cursor.close().catch(() => {});\n }\n\n if (sinceProgress) progress();\n return result;\n };\n}\n","import type { Collection, Model } from 'mongoose';\nimport { REJECT_TTL_DAYS } from './types.js';\nimport type { Registry } from './registry.js';\n\n/**\n * Registry-driven payload indexes (schema §4.4) — replaces the wildcard. A\n * wildcard index cannot compound with tenantId (pre-Mongo 7.0), so any attr\n * query would scan across every tenant — both a perf problem and the exact\n * isolation hole scoped() exists to close. Attrs are bounded and declared, so\n * pay for targeted indexes instead of insert cost on everything.\n *\n * Every payload index is tenant-prefixed and time-sorted. The partial filter\n * pins `name`, so a query must include { name } to use it. Undeclared attrs\n * stay queryable via a $match on {tenantId, name, occurredAt} first — bounded,\n * no index needed, fine for ad-hoc at small-SaaS volume.\n */\n\n/** Mongo caps a collection at 64 indexes. Base + discriminators use ~10. Budget the rest. */\nexport const INDEX_BUDGET = 24;\n\nexport interface SyncCtx {\n registry: Registry;\n TelemetryModel: Model<any>;\n models: Model<any>[];\n rejects: () => Collection;\n}\n\nexport function createSyncIndexes(ctx: SyncCtx) {\n return async function syncIndexes(): Promise<void> {\n // Model.init() awaited before first write (traps #3): cold-DB writes racing\n // async index builds silently duplicate — the unique idempotency index and\n // deterministic rollup _ids depend on this.\n await Promise.all(ctx.models.map((m) => m.init()));\n\n // one generator, two payload maps — attrs (string equality) and metrics\n // (numeric range). Identical shape: tenant-prefixed, name-pinned, time-sorted.\n const plan = (name: string, kind: 'attr' | 'metric', key: string) => ({\n name: `${kind}_${name.replace(/\\./g, '_')}_${key}`,\n keys: {\n tenantId: 1,\n [`${kind === 'attr' ? 'attrs' : 'metrics'}.${key}`]: 1,\n occurredAt: -1,\n } as Record<string, 1 | -1>,\n partial: { name }, // keeps each index to just that event's rows\n });\n const planned = Object.entries(ctx.registry).flatMap(([name, spec]) => [\n ...(spec.indexedAttrs ?? []).map((k) => plan(name, 'attr', k)),\n ...(spec.indexedMetrics ?? []).map((k) => plan(name, 'metric', k)),\n ]);\n\n const coll = ctx.TelemetryModel.collection;\n const plannedNames = new Set(planned.map((p) => p.name));\n\n // Drop orphans FIRST. If the budget check ran first, removing an entry to\n // get back under the cap would still throw, and the stale index would never\n // be dropped — unrecoverable without manual intervention.\n for (const ix of await coll.indexes()) {\n if (\n (ix.name?.startsWith('attr_') || ix.name?.startsWith('metric_')) &&\n !plannedNames.has(ix.name)\n ) {\n await coll.dropIndex(ix.name);\n }\n }\n\n if (planned.length > INDEX_BUDGET) {\n throw new Error(`telemetry: ${planned.length} payload indexes exceeds budget ${INDEX_BUDGET}`);\n }\n\n for (const p of planned) {\n await coll.createIndex(p.keys, {\n name: p.name,\n partialFilterExpression: p.partial,\n background: true,\n });\n }\n\n // quarantined rejects expire on their own — nothing bounds them otherwise\n await ctx.rejects().createIndex({ at: 1 }, { expireAfterSeconds: REJECT_TTL_DAYS * 86400 });\n };\n}\n","import { randomBytes, scryptSync, timingSafeEqual } from 'node:crypto';\nimport { Schema, type Connection, type Model } from 'mongoose';\nimport { TelemetryKind, RESERVED_TENANT_MESSAGE, isPlatformScope } from './types.js';\n\n/**\n * Keys — the key IS the configuration (instrumentation §2). Client init is\n * { key, url, release } and nothing else: service, env, tenant resolution,\n * kind allowlist, CORS, and rate limits all hang off the key server-side.\n *\n * Format:\n * pk_<label>_tk_<24hex> publishable — the id is the whole credential\n * sk_<label>_tk_<24hex>_<48hex> secret — id + secret half; only a hash is stored\n *\n * <label> is cosmetic ('live', 'test', …); the tk_ id is the lookup key.\n */\n\nexport const KeyKind = { Publishable: 'publishable', Secret: 'secret' } as const;\nexport type KeyKind = (typeof KeyKind)[keyof typeof KeyKind];\n\n/**\n * How tenantId resolves for records written with this key:\n * - fixed: the key carries it. Single-tenant apps, internal tools, CLI builds.\n * - session: the host resolves it from the request (contextAdapter).\n * - claimed: the payload asserts it. Secret keys only — enforced here.\n */\nexport const TenantMode = { Fixed: 'fixed', Session: 'session', Claimed: 'claimed' } as const;\nexport type TenantMode = (typeof TenantMode)[keyof typeof TenantMode];\n\nconst KEY_RE = /^(pk|sk)_([a-z0-9]+)_(tk_[a-f0-9]{24})(?:_([a-f0-9]{48}))?$/;\n\nexport interface ParsedKey {\n kind: KeyKind;\n label: string;\n id: string;\n secret?: string;\n}\n\nexport function parseKeyString(raw: string | undefined): ParsedKey | null {\n if (!raw) return null;\n const m = KEY_RE.exec(raw.trim());\n if (!m) return null;\n const [, prefix, label, id, secret] = m;\n if (prefix === 'sk' && !secret) return null;\n if (prefix === 'pk' && secret) return null;\n return { kind: prefix === 'pk' ? KeyKind.Publishable : KeyKind.Secret, label: label!, id: id!, secret };\n}\n\n// scrypt params picked once and versioned IN the hash string (open item §10\n// closed): a future param change bumps the prefix, old hashes keep verifying.\nconst SCRYPT_VERSION = 'scrypt1';\nconst SCRYPT = { N: 16384, r: 8, p: 1, keylen: 32 };\n\nexport function hashSecret(secret: string): string {\n const salt = randomBytes(16).toString('hex');\n const hash = scryptSync(secret, salt, SCRYPT.keylen, SCRYPT).toString('hex');\n return `${SCRYPT_VERSION}$${salt}$${hash}`;\n}\n\n/** constant-time — a key check must not leak how much of the secret matched */\nexport function verifySecret(secret: string, stored: string | undefined): boolean {\n if (!stored) return false;\n const [version, salt, hex] = stored.split('$');\n if (version !== SCRYPT_VERSION || !salt || !hex) return false;\n const expected = Buffer.from(hex, 'hex');\n const actual = scryptSync(secret, salt, SCRYPT.keylen, SCRYPT);\n return expected.length === actual.length && timingSafeEqual(expected, actual);\n}\n\nexport function buildKeyModel(connection: Connection, modelName: string, collection: string): Model<any> {\n const existing = connection.models?.[modelName];\n if (existing) return existing;\n const schema = new Schema(\n {\n /** the tk_ id embedded in the key string — lookup is a point read */\n _id: { type: String, required: true },\n kind: { type: String, required: true, enum: Object.values(KeyKind) },\n /** sk_ only — versioned scrypt hash of the secret half */\n secretHash: String,\n\n tenantMode: { type: String, required: true, enum: Object.values(TenantMode) },\n /** required iff tenantMode = fixed */\n tenantId: String,\n\n /** stamped onto every record — the client cannot lie about where it runs */\n service: { type: String, required: true },\n env: { type: String, required: true },\n\n /** CORS allowlist. pk_ only; empty = no browser origins accepted. */\n origins: { type: [String], default: [] },\n /** pk_ defaults to event/error/span; sk_ to all five */\n allowedKinds: { type: [String], required: true },\n /** optional narrowing to a subset of registry names */\n allowedNames: { type: [String], default: undefined },\n\n /** records/min across the key. Distinct from EventSpec.burst (per-group). */\n maxPerMinute: { type: Number, required: true, default: 600 },\n\n createdAt: { type: Date, required: true },\n revokedAt: Date,\n /** touched at most once/min, not per request */\n lastUsedAt: Date,\n },\n { collection, versionKey: false },\n );\n schema.index({ revokedAt: 1 });\n return connection.model(modelName, schema);\n}\n\nexport interface CreateKeyInput {\n kind: KeyKind;\n tenantMode: TenantMode;\n tenantId?: string;\n service: string;\n env: string;\n label?: string;\n origins?: string[];\n allowedKinds?: string[];\n allowedNames?: string[];\n maxPerMinute?: number;\n}\n\n/**\n * Mint a key. The full key string is returned ONCE and never reconstructable —\n * only the hash of an sk_ secret is stored. Boot-time trust assertions live\n * here so a misconfigured key cannot exist (instrumentation §2):\n * claimed ⇒ secret · fixed ⇒ tenantId · publishable ⇒ no usage, no claimed\n */\nexport async function createKey(KeyModel: Model<any>, input: CreateKeyInput): Promise<{ key: string; id: string }> {\n const {\n kind, tenantMode, tenantId, service, env,\n label = 'live', origins = [], allowedNames, maxPerMinute = 600,\n } = input;\n\n if (tenantMode === TenantMode.Claimed && kind !== KeyKind.Secret) {\n throw new Error('telemetry: tenantMode \"claimed\" requires a secret key');\n }\n if (tenantMode === TenantMode.Fixed && !tenantId) {\n throw new Error('telemetry: tenantMode \"fixed\" requires tenantId');\n }\n // A fixed key IS its tenantId — minting one on '*' would hand a wire\n // credential the dashboard's cross-tenant scope. The other two modes carry no\n // tenantId to check here; ingest guards them once the tenant has resolved.\n if (isPlatformScope(tenantId)) throw new Error(RESERVED_TENANT_MESSAGE);\n const allowedKinds =\n input.allowedKinds ??\n (kind === KeyKind.Publishable\n ? [TelemetryKind.Event, TelemetryKind.Error, TelemetryKind.Span]\n : Object.values(TelemetryKind));\n if (kind === KeyKind.Publishable && allowedKinds.includes(TelemetryKind.Usage)) {\n throw new Error('telemetry: a publishable key may never write usage');\n }\n\n const id = `tk_${randomBytes(12).toString('hex')}`;\n const secret = kind === KeyKind.Secret ? randomBytes(24).toString('hex') : undefined;\n\n await KeyModel.create({\n _id: id,\n kind,\n secretHash: secret ? hashSecret(secret) : undefined,\n tenantMode,\n tenantId,\n service,\n env,\n origins,\n allowedKinds,\n allowedNames,\n maxPerMinute,\n createdAt: new Date(),\n });\n\n const prefix = kind === KeyKind.Publishable ? 'pk' : 'sk';\n return { key: secret ? `${prefix}_${label}_${id}_${secret}` : `${prefix}_${label}_${id}`, id };\n}\n","import express from 'express';\nimport type { NextFunction, Request, Response, Router } from 'express';\nimport { TelemetryKind, RESERVED_TENANT_MESSAGE, isPlatformScope, plain } from './types.js';\nimport { KeyKind, TenantMode, parseKeyString, verifySecret } from './keys.js';\nimport { noteUndeclaredAttrs } from './emit.js';\nimport { recordRollup } from './rollups.js';\nimport type { Telemetry } from './index.js';\n\n/**\n * The wire ingest surface (instrumentation §3–4). One endpoint, batch-only.\n *\n * Trust in one line: a claim is not a fact. The handler's job is converting\n * key-derived facts and payload claims into one honest envelope — a browser\n * record claiming tenantId is not an attack to reject, it is a field to ignore.\n *\n * Error surface splits on key kind (traps §19): `pk_` NEVER 4xxes — telemetry\n * errors surfacing in browser consoles read as a broken page — so unknown\n * names, oversize, rate limits, revoked keys all drop, quarantine what's\n * parseable, count, and answer 202. `sk_` callers are programmers and get\n * honest 400/401/413/429.\n *\n * Delivery is at-least-once, so the plane order INVERTS from emit():\n * insert first (client-generated `_id`; duplicate ⇒ drop, NO rollup), then\n * aggregate. The plane order follows the delivery semantics (schema §4.6).\n */\n\nexport interface IngestContext {\n tenantId: string;\n subjects?: Array<{ type: string; id: string; role?: string }>;\n actor?: string;\n}\n\nexport interface ContextAdapter {\n /** INBOUND: who is making this request? Only consulted for tenantMode=session. */\n resolveContext(req: Request): IngestContext | null | Promise<IngestContext | null>;\n}\n\nexport interface CreateIngestOptions {\n telemetry: Telemetry;\n contextAdapter?: ContextAdapter;\n /** batch caps — the defaults are the wire contract */\n maxRecords?: number;\n bodyLimit?: string;\n /** key cache TTL ms (60s). Tests turn it down. */\n keyCacheMs?: number;\n}\n\nconst BATCH_MAX = 100;\n\ninterface CachedKey {\n doc: any | null;\n at: number;\n}\n\nexport function createIngest(opts: CreateIngestOptions): Router {\n const { telemetry: t, contextAdapter, maxRecords = BATCH_MAX, bodyLimit = '512kb', keyCacheMs = 60_000 } = opts;\n const KeyModel = t.models.keys;\n const registry = t.registry;\n const logger = t.logger;\n\n const keyCache = new Map<string, CachedKey>();\n const buckets = new Map<string, { n: number; resetAt: number }>();\n\n const takeRecords = (keyId: string, maxPerMinute: number, n: number): number => {\n const now = Date.now();\n let b = buckets.get(keyId);\n if (!b || now >= b.resetAt) {\n b = { n: 0, resetAt: now + 60_000 };\n buckets.set(keyId, b);\n }\n const room = Math.max(0, maxPerMinute - b.n);\n const taken = Math.min(room, n);\n b.n += taken;\n return taken;\n };\n\n const loadKey = async (id: string): Promise<any | null> => {\n const hit = keyCache.get(id);\n if (hit && Date.now() - hit.at < keyCacheMs) return hit.doc;\n const doc = await KeyModel.findById(id).lean();\n keyCache.set(id, { doc: doc ?? null, at: Date.now() }); // negative-cache junk ids too\n return doc ?? null;\n };\n\n const quarantine = (name: string, reason: string, raw: unknown) => {\n t.counters.rejected++;\n void t.collections.rejects()\n .insertOne({ at: new Date(), name, reason, raw: plain(raw) })\n .catch(() => {});\n };\n\n const router = express.Router();\n\n // Preflight cannot be key-scoped (the browser has not sent Authorization\n // yet) — reflect the origin and let the POST enforce the per-key allowlist.\n router.options('/', (req, res) => {\n const origin = req.headers.origin;\n if (origin) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Vary', 'Origin');\n res.setHeader('Access-Control-Allow-Methods', 'POST');\n res.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');\n res.setHeader('Access-Control-Max-Age', '600');\n }\n res.status(204).end();\n });\n\n // Auth resolves BEFORE the body parser so the error middleware knows which\n // error surface (pk drop / sk honest) applies to parse failures.\n router.post(\n '/',\n async (req: Request & { telemetryKey?: any }, res, next) => {\n const bearer = /^Bearer\\s+(.+)$/i.exec(String(req.headers.authorization ?? ''))?.[1];\n // sendBeacon cannot set headers — pk_ may ride the query string. sk_ may not.\n const fromQuery = typeof req.query.key === 'string' ? req.query.key : undefined;\n const parsed = parseKeyString(bearer) ?? (fromQuery?.startsWith('pk_') ? parseKeyString(fromQuery) : null);\n\n const drop = () => res.status(202).json({ accepted: 0, rejected: 0 });\n\n if (!parsed) {\n // no attributable caller: an sk_-shaped credential gets honesty, all\n // else is noise — 202 and gone\n if (bearer?.startsWith('sk_') || fromQuery?.startsWith('sk_')) {\n return res.status(401).json({ error: 'invalid_key' });\n }\n return drop();\n }\n\n const doc = await loadKey(parsed.id);\n const skFail = (status: number, error: string) => res.status(status).json({ error });\n if (!doc || doc.revokedAt) {\n return parsed.kind === KeyKind.Secret ? skFail(401, doc ? 'revoked_key' : 'invalid_key') : drop();\n }\n if (doc.kind !== parsed.kind) {\n return parsed.kind === KeyKind.Secret ? skFail(401, 'invalid_key') : drop();\n }\n if (parsed.kind === KeyKind.Secret && !verifySecret(parsed.secret!, doc.secretHash)) {\n return skFail(401, 'invalid_key');\n }\n\n // browser origin allowlist — pk_ only; no ACAO header means the browser\n // never lets the page read the response, and we drop the write too\n const origin = req.headers.origin;\n if (parsed.kind === KeyKind.Publishable && origin) {\n if (!doc.origins?.includes(origin)) return drop();\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Vary', 'Origin');\n }\n\n if (!doc.lastUsedAt || Date.now() - new Date(doc.lastUsedAt).getTime() > 60_000) {\n doc.lastUsedAt = new Date();\n void KeyModel.updateOne({ _id: doc._id }, { $set: { lastUsedAt: doc.lastUsedAt } }).catch(() => {});\n }\n\n req.telemetryKey = doc;\n next();\n },\n express.json({ limit: bodyLimit }),\n async (req: Request & { telemetryKey?: any }, res) => {\n const key = req.telemetryKey!;\n const pk = key.kind === KeyKind.Publishable;\n const receivedAt = new Date();\n const body = (req.body ?? {}) as Record<string, any>;\n\n let accepted = 0;\n let rejected = 0;\n const respond = () => res.status(202).json({ accepted, rejected });\n\n let records: any[] = Array.isArray(body.records) ? body.records : [];\n if (records.length > maxRecords) {\n if (!pk) return res.status(413).json({ error: 'batch_too_large', max: maxRecords });\n rejected += records.length - maxRecords;\n records = records.slice(0, maxRecords);\n }\n\n // per-key rate limit, counted in records — pk drops the overflow, sk is told\n const granted = takeRecords(key._id, key.maxPerMinute, records.length);\n if (granted < records.length) {\n if (!pk) return res.status(429).json({ error: 'rate_limited' });\n t.counters.capped += records.length - granted;\n rejected += records.length - granted;\n records = records.slice(0, granted);\n }\n\n // ── tenant resolution: the key's, the host's, or the payload's. No fourth path. ──\n let ctx: IngestContext | null = null;\n if (key.tenantMode === TenantMode.Fixed) {\n ctx = { tenantId: key.tenantId };\n } else if (key.tenantMode === TenantMode.Session) {\n if (!contextAdapter) {\n logger.warn('[telemetry] session-mode key but no contextAdapter configured');\n return pk ? respond() : res.status(500).json({ error: 'no_context_adapter' });\n }\n ctx = await contextAdapter.resolveContext(req);\n if (!ctx) {\n // pk: an unauthenticated browser is normal traffic, not an error\n rejected += records.length;\n return pk ? respond() : res.status(401).json({ error: 'no_session' });\n }\n } else {\n // claimed — sk_ only, asserted at key creation\n const claimed = body.context?.tenantId;\n if (typeof claimed !== 'string' || !claimed) {\n return res.status(400).json({ error: 'tenant_required' });\n }\n ctx = { tenantId: claimed };\n }\n const tenantId = ctx.tenantId;\n\n // ── the reserved token, checked ONCE, after resolution ──\n // Deliberately here and not in the `claimed` branch: all three paths mint\n // a tenantId from outside the package. `claimed` is the payload asserting\n // one, `session` is a host adapter that could compute one, and `fixed`\n // reads a key doc that may predate createKey()'s guard. A claim is not a\n // fact — and '*' is not even a tenant. pk_ never 4xxes (traps §19), so it\n // drops and counts; sk_ callers are programmers and are told why.\n if (isPlatformScope(tenantId)) {\n logger.warn(`[telemetry] ingest refused a batch: ${RESERVED_TENANT_MESSAGE}`);\n t.counters.rejected += records.length;\n rejected += records.length;\n return pk ? respond() : res.status(400).json({ error: 'reserved_tenant' });\n }\n\n // server computes the skew; client timestamps lie (schema §9 fix)\n const sentAt = body.sentAt ? Date.parse(body.sentAt) : NaN;\n const clockSkewMs = Number.isFinite(sentAt) ? sentAt - receivedAt.getTime() : 0;\n\n // defaults merge UNDER the claim — a batch that omits context details is\n // normal traffic, and platform/appVersion are envelope-required\n const batchClient = {\n platform: 'web',\n appVersion: String(body.release ?? 'unknown'),\n ...(body.client && typeof body.client === 'object' ? body.client : {}),\n clockSkewMs,\n };\n\n const subjectsOf = (raw: unknown): Array<{ type: string; id: string; role?: string }> =>\n Array.isArray(raw)\n ? raw\n .filter((s: any) => s && typeof s.type === 'string' && typeof s.id === 'string')\n .map((s: any) => ({ type: s.type, id: String(s.id), ...(s.role ? { role: String(s.role) } : {}) }))\n : [];\n\n // merge order, lowest to highest: batch claims < record subjects < host\n // context — the session cookie outranks the JS claim (instrumentation §4)\n const claimSubjects = subjectsOf(body.context?.subjects);\n const hostSubjects = subjectsOf(ctx.subjects);\n const mergeSubjects = (recordSubjects: unknown) => {\n const byType = new Map<string, Array<{ type: string; id: string; role?: string }>>();\n for (const layer of [claimSubjects, subjectsOf(recordSubjects), hostSubjects]) {\n const grouped = new Map<string, Array<{ type: string; id: string; role?: string }>>();\n for (const s of layer) {\n grouped.set(s.type, [...(grouped.get(s.type) ?? []), s]);\n }\n for (const [type, entries] of grouped) byType.set(type, entries);\n }\n return [...byType.values()].flat();\n };\n const batchActor = typeof body.context?.actor === 'string' ? body.context.actor : undefined;\n\n for (const rec of records) {\n const name = typeof rec?.name === 'string' ? rec.name : '';\n const fail = (reason: string) => {\n rejected++;\n quarantine(name || '(unnamed)', reason, rec);\n };\n\n // ── the identify control record: pure linkage, never stored as telemetry ──\n if (name === '$identify') {\n const anonRef = String(rec.anonRef ?? '');\n const userRef = String(rec.userRef ?? '');\n if (!/^.+:.+$/.test(anonRef) || !/^.+:.+$/.test(userRef)) {\n fail('malformed $identify');\n continue;\n }\n await t.collections.aliases().updateOne(\n { _id: `${tenantId}|${anonRef}` } as any,\n { $set: { tenantId, anonRef, userRef, linkedAt: receivedAt } },\n { upsert: true },\n );\n accepted++;\n continue;\n }\n\n const spec = registry[name];\n if (!spec) {\n fail('unregistered event');\n continue;\n }\n if (!key.allowedKinds.includes(spec.kind)) {\n fail(`kind ${spec.kind} not allowed for this key`);\n continue;\n }\n if (spec.origin === 'server' && pk) {\n // the CLIENT_MILESTONES guarantee: a browser may assert\n // wizard_started, never converted — server-origin names need sk_\n fail('server-origin name over a publishable key');\n continue;\n }\n if (key.allowedNames?.length && !key.allowedNames.includes(name)) {\n fail('name not allowed for this key');\n continue;\n }\n const id = typeof rec._id === 'string' && rec._id.length >= 16 && rec._id.length <= 64 ? rec._id : null;\n if (!id) {\n // without a client id there is no idempotency — the §3 contract\n fail('missing client _id');\n continue;\n }\n\n const occurredRaw = rec.occurredAt ? Date.parse(rec.occurredAt) : NaN;\n const occurredAt = Number.isFinite(occurredRaw)\n ? new Date(occurredRaw - clockSkewMs) // §3.3: corrected BEFORE rollups run\n : receivedAt;\n\n const safeMap = (o: unknown) =>\n o && typeof o === 'object'\n ? new Map(Object.entries(o as Record<string, unknown>).map(([k, v]) => [k.replace(/\\./g, '_'), v]))\n : new Map();\n\n // The wire is where a stale client's undeclared attr actually shows up\n // — a shipped desktop build sending a key the server's registry does\n // not know yet. Counted here for the same reason emit() counts it: the\n // strict parse below rejects the whole record, and the quarantine says\n // so one row at a time.\n noteUndeclaredAttrs(t.counters, name, spec, rec.attrs);\n\n // ── write-time subject linking, on the path that actually needs it ──\n // The desktop client knows its install and nothing else, so this — the\n // wire — is where `machine:<installId>` with no `user` arrives. Ingest\n // does not call emit() (at-least-once delivery inverts the plane order,\n // §4.6), so the hook is invoked HERE, from the same instance-wide\n // implementation emit() uses. Before construction, for the same reason\n // as there: pre('validate') derives `subjectKeys` and the rollups below\n // fan out over it.\n const subjects = mergeSubjects(rec.subjects);\n const linked = t.linkSubjects\n ? await t.linkSubjects(name, spec, tenantId, subjects)\n : null;\n\n const Model = t.models.byKind[spec.kind as TelemetryKind];\n const d = new Model({\n // facts the wire may not assert: tenant, service, env, origin, plane\n // fields (forced/sampleRate stripped by construction — only the\n // allowlisted fields below ever reach the document)\n _id: id,\n name,\n tenantId,\n occurredAt,\n severity: typeof rec.severity === 'string' ? rec.severity : undefined,\n subjects: linked ?? subjects,\n actor: ctx.actor ?? (typeof rec.actor === 'string' ? rec.actor : batchActor),\n onBehalfOf: typeof rec.onBehalfOf === 'string' ? rec.onBehalfOf : undefined,\n service: key.service,\n env: key.env,\n release: typeof body.release === 'string' ? body.release : undefined,\n origin: 'client',\n client: batchClient,\n traceId: typeof rec.traceId === 'string' ? rec.traceId : undefined,\n spanId: typeof rec.spanId === 'string' ? rec.spanId : undefined,\n parentId: typeof rec.parentId === 'string' ? rec.parentId : undefined,\n durationMs: typeof rec.durationMs === 'number' ? rec.durationMs : undefined,\n attrs: safeMap(rec.attrs),\n metrics: safeMap(rec.metrics),\n data: rec.data,\n body: typeof rec.body === 'string' ? rec.body : undefined,\n error: rec.error,\n state: rec.state,\n usage: rec.usage,\n });\n\n try {\n await d.validate();\n } catch (e) {\n fail(String(e));\n continue;\n }\n\n // ── insert-gated rollups: at-least-once transport, so the insert IS the dedupe ──\n try {\n await d.save({\n validateBeforeSave: false,\n ...(spec.kind === TelemetryKind.Usage ? { writeConcern: { w: 'majority', j: true } } : {}),\n } as any);\n } catch (e: any) {\n if (e?.code === 11000 || e?.cause?.code === 11000) {\n accepted++; // a retry of a record we already have — the contract working\n continue;\n }\n fail(String(e));\n continue;\n }\n for (const r of spec.rollups ?? []) {\n await recordRollup(t.models.rollups, d, name, r, t.counters).catch((e) =>\n quarantine(name, `rollup: ${e}`, rec),\n );\n }\n accepted++;\n }\n\n respond();\n },\n );\n\n // body-parser failures (bad JSON, over 512KB): pk_ swallows, sk_ hears the truth\n router.use((err: any, req: Request & { telemetryKey?: any }, res: Response, _next: NextFunction) => {\n if (req.telemetryKey?.kind === KeyKind.Secret) {\n const status = err?.type === 'entity.too.large' ? 413 : 400;\n return res.status(status).json({ error: err?.type ?? 'bad_request' });\n }\n t.counters.rejected++;\n res.status(202).json({ accepted: 0, rejected: 1 });\n });\n\n return router;\n}\n","import type { z } from 'zod';\nimport { BUILTIN_PLATFORMS } from './model.js';\nimport type { DimSource, Registry, RollupSpec } from './registry.js';\nimport {\n Env, LogLevel, Origin, RETENTION_DAYS, TELEMETRY_KINDS, TelemetryKind,\n} from './types.js';\n\n/**\n * The derived catalog (reports §3): everything a reader can ask this instance,\n * computed from the registry alone. Pure — no Mongo, no I/O — and built once at\n * createDashboard() / createTelemetryMcp(), boot-time like validateRegistry and\n * for the same reason: if the catalog cannot be built, the registry is wrong.\n *\n * It exists so that nothing is written twice. The registry already says which\n * events exist, which attrs and metrics they carry, which are indexed, and\n * which rollup families they feed; a page that names `cost_usd` is restating a\n * fact the package already knows. The rule this file installs is reports §11.1:\n * a page may not name a metric, an attr, or a family — it asks the catalog.\n */\n\nexport interface Catalog {\n events: Record<string, EventFacet>;\n families: Record<string, FamilyFacet>;\n /** name prefix before the first '.' → event names. An undotted name namespaces to itself. */\n namespaces: Record<string, string[]>;\n /** dims every record carries — filterable/groupable raw for every source */\n envelope: DimFacet[];\n /** every subject type named by any spec's `subjects` or any rollup's `subjects` */\n subjectTypes: string[];\n}\n\nexport interface EventFacet {\n kind: TelemetryKind;\n origin: Origin | 'any';\n subjects: string[];\n description: string;\n namespace: string;\n /** one per declared attr, typed, followed by this kind's own envelope fields */\n dims: DimFacet[];\n /** 'count' first, then per metric key: sum:, avg:, p50:, p95:, p99: */\n measures: MeasureFacet[];\n /** rollup family names this event feeds (its `as`, or its own name) */\n families: string[];\n indexedAttrs: string[];\n indexedMetrics: string[];\n /** the EFFECTIVE retention — the spec's override, else RETENTION_DAYS[kind] */\n retentionDays: number | null;\n}\n\nexport interface FamilyFacet {\n as: string;\n /** the grain, in declared order (pinned per family by validateRegistry) */\n by: DimSource[];\n /** rollups.ts `label(src)` per dim — the `x=` prefix written into `dims` */\n labels: string[];\n bucket: 'hour' | 'day' | 'week' | 'month' | null;\n /** a lifetime rollup has no bucket, and its `firstAt` IS the milestone */\n lifetime: boolean;\n /** the spec's `subjects` when `by` has a subject dim, else [] */\n subjectTypes: string[];\n sums: string[];\n /** labels of `capture` sources */\n capture: string[];\n /** event names declaring this family, registry order */\n feeders: string[];\n retentionDays: number | null;\n}\n\nexport interface DimFacet {\n /**\n * The DimSource form, so it passes straight through to a rollup `by`, to\n * `groupBy`, and to a filter term: 'attr:model' | 'field:client.platform' |\n * 'subjectType' | 'actorType'.\n */\n key: string;\n /** what rollups.ts writes before '=' — 'model', 'client.platform'; for the two pseudo-dims, the key itself */\n label: string;\n type: 'string' | 'enum' | 'number' | 'boolean' | 'date';\n /** closed domain when known: z.enum / z.literal values, envelope enums */\n values?: string[];\n optional: boolean;\n /** true when a real index exists — an `indexedAttrs` attr, or a base-indexed envelope field */\n indexed: boolean;\n}\n\nexport interface MeasureFacet {\n /** 'count' | 'sum:cost_usd' | 'avg:cost_usd' | 'p95:duration_ms' … */\n key: string;\n metric?: string;\n /** families whose `sum` carries this metric — exact answers. Only 'sum:' keys ever have one. */\n exactVia: string[];\n}\n\nexport interface DeriveCatalogOptions {\n /**\n * Host additions to `client.platform`, exactly as CreateTelemetryConfig\n * .platforms extends them — the catalog reports the same closed domain the\n * writer enforces, or it would offer a filter value no record can carry.\n */\n platforms?: readonly string[];\n}\n\n/** the projection the SPA has always booted on — names and shapes, never zod objects */\nexport interface RegistryProjectionEntry {\n kind: TelemetryKind;\n origin: Origin | 'any';\n subjects: string[];\n description: string;\n attrKeys: string[];\n metricKeys: string[];\n indexedAttrs: string[];\n indexedMetrics: string[];\n rollups: {\n as: string;\n by: DimSource[];\n bucket: RollupSpec['bucket'] | null;\n sum: string[];\n subjects: string[];\n }[];\n}\n\nexport type RegistryProjection = Record<string, RegistryProjectionEntry>;\n\n// ── dimension labels ────────────────────────────────────────────────────────\n\n/**\n * rollups.ts writes `${label(src)}=${value}` into `dims`, so the catalog has to\n * agree with it character for character or a groupBy would match nothing. The\n * bare `subject` source has no ':' and labels to itself, which is also what\n * that file's `slice(indexOf(':') + 1)` produces.\n */\nconst label = (src: DimSource): string => src.slice(src.indexOf(':') + 1);\n\n// ── the zod walk ────────────────────────────────────────────────────────────\n\n/**\n * zod 4 leaf `def.type` → the catalog's type. `z.coerce.*` is the base type\n * with `def.coerce` set, so it needs no case of its own; `z.int()` is a\n * ZodNumberFormat whose def.type is already 'number', and 'int' is listed\n * anyway so a future zod that names it does not silently degrade to 'string'.\n */\nconst LEAF_TYPES: Record<string, DimFacet['type']> = {\n string: 'string',\n number: 'number',\n int: 'number',\n bigint: 'number',\n boolean: 'boolean',\n date: 'date',\n};\n\ninterface WalkedAttr {\n type: DimFacet['type'];\n values?: string[];\n optional: boolean;\n}\n\n/**\n * Unwrap a declared attr schema to its leaf and read the leaf's type and, when\n * the domain is closed, its values.\n *\n * Deliberately NOT `z.toJSONSchema`: this needs five cases, and a JSON-schema\n * round trip would put a second vocabulary between the registry and the UI.\n * Anything the walker does not recognise is 'string', which is honest — attrs\n * are strings after Mongoose casting anyway (registry.ts).\n */\nfunction walkAttr(schema: unknown): WalkedAttr {\n let node: any = schema;\n let optional = false;\n\n // Bounded because a lazy or self-referential schema would otherwise hang\n // boot; twenty wrappers is already pathological.\n for (let depth = 0; node && depth < 20; depth++) {\n const def = node._zod?.def ?? node.def;\n if (!def?.type) break;\n\n switch (def.type) {\n // these three all mean \"the value may be absent from a stored record\",\n // which is the only thing `optional` claims\n case 'optional':\n case 'nullable':\n case 'default':\n optional = true;\n node = def.innerType;\n continue;\n\n case 'catch':\n case 'readonly':\n node = def.innerType;\n continue;\n\n // a pipe is `in -> out`; the INPUT side is what a caller may send and so\n // what a stored value was validated as. The output of a transform is\n // frequently a shape no filter could ever be written against.\n case 'pipe':\n node = def.in;\n continue;\n\n case 'enum': {\n // `.options` rather than Object.values(def.entries) because a numeric\n // TS enum's entries carry its reverse mapping too\n const options = Array.isArray(node.options) ? node.options : Object.values(def.entries ?? {});\n return { type: 'enum', values: options.map(String), optional };\n }\n\n case 'literal':\n return { type: 'enum', values: [...(def.values ?? [])].map(String), optional };\n\n default:\n return { type: LEAF_TYPES[def.type] ?? 'string', optional };\n }\n }\n\n return { type: 'string', optional };\n}\n\n// ── envelope dims ───────────────────────────────────────────────────────────\n\nconst dim = (\n key: string,\n type: DimFacet['type'],\n o: { values?: readonly string[]; optional?: boolean; indexed?: boolean } = {},\n): DimFacet => ({\n key,\n // the two pseudo-dims are derived at query time from subjectKeys / actor, so\n // they carry no `field:` prefix and label to themselves\n label: key.startsWith('field:') ? key.slice(6) : key,\n type,\n ...(o.values ? { values: [...o.values] } : {}),\n optional: o.optional ?? false,\n indexed: o.indexed ?? false,\n});\n\n/**\n * Fixed, not inferred. These are `field:` sources a rollup may already declare,\n * so the labels agree with what rollups.ts writes into `dims`. `indexed` is\n * true only where model.ts actually builds a base index over the field —\n * {tenantId, kind, name, occurredAt} and {tenantId, subjectKeys, occurredAt}.\n */\nconst envelopeDims = (platforms: readonly string[]): DimFacet[] => [\n dim('field:kind', 'enum', { values: TELEMETRY_KINDS, indexed: true }),\n dim('field:name', 'string', { indexed: true }),\n dim('field:severity', 'enum', { values: Object.values(LogLevel) }),\n dim('field:env', 'enum', { values: Object.values(Env) }),\n dim('field:service', 'string'),\n dim('field:release', 'string'),\n dim('field:origin', 'enum', { values: Object.values(Origin) }),\n // client context is absent on server-origin records, so both of its dims are optional\n dim('field:client.platform', 'enum', { values: platforms, optional: true }),\n dim('field:client.appVersion', 'string', { optional: true }),\n dim('subjectType', 'string', { optional: true, indexed: true }),\n dim('actorType', 'string', { optional: true }),\n];\n\n/**\n * The discriminator's own fields, offered only on events of that kind — a usage\n * event's dims include its meter, an event event's do not. `indexed` again\n * tracks the real discriminator indexes in model.ts, which is why\n * `error.type` is false while `state.key` is true: the error index is on\n * `error.fingerprint`.\n */\nconst kindDims = (kind: TelemetryKind): DimFacet[] => {\n switch (kind) {\n case TelemetryKind.Usage:\n return [\n dim('field:usage.meter', 'string', { indexed: true }),\n dim('field:usage.billedTo', 'string'),\n dim('field:usage.unit', 'string'),\n ];\n case TelemetryKind.State:\n return [\n dim('field:state.key', 'string', { indexed: true }),\n dim('field:state.to', 'string', { indexed: true }),\n ];\n case TelemetryKind.Error:\n return [dim('field:error.type', 'string'), dim('field:error.handled', 'boolean')];\n default:\n return [];\n }\n};\n\n// ── the derivation ──────────────────────────────────────────────────────────\n\n/** the three raw-only operators every metric gets beside its exact `sum:` */\nconst RAW_OPS = ['avg', 'p50', 'p95', 'p99'] as const;\n\nexport function deriveCatalog(registry: Registry, opts: DeriveCatalogOptions = {}): Catalog {\n // union, never replacement — a host adding 'watchos' keeps 'web' (model.ts)\n const platforms = [...new Set([...BUILTIN_PLATFORMS, ...(opts.platforms ?? [])])];\n\n // Families first: an EventFacet names the families it feeds and a family\n // names every event that feeds it, so the family pass has to see the whole\n // registry before any event facet can be finished.\n const families: Record<string, FamilyFacet> = {};\n for (const [name, spec] of Object.entries(registry)) {\n for (const r of spec.rollups ?? []) {\n const as = r.as ?? name;\n const seen = families[as];\n\n if (!seen) {\n families[as] = {\n as,\n by: [...r.by],\n labels: r.by.map(label),\n bucket: r.bucket ?? null,\n lifetime: !r.bucket,\n // `subjects` only means anything when there is a subject dim to\n // restrict; without one it selects nothing and claiming it would\n // offer a subject filter the family cannot answer\n subjectTypes: r.by.includes('subject') ? [...(r.subjects ?? [])] : [],\n sums: [...(r.sum ?? [])],\n capture: (r.capture ?? []).map(label),\n feeders: [name],\n retentionDays: r.retentionDays ?? null,\n };\n continue;\n }\n\n // `by`, `bucket` and `subjects` are pinned per family by validateRegistry\n // — two shapes under one `as` is a boot error — so the first feeder\n // settles the grain and later ones cannot disagree. `sum` and `capture`\n // are NOT pinned, because a second name may accumulate another metric\n // into the same docs, so they union in declaration order: that is what a\n // reader of the family can actually find in it. `retentionDays` is taken\n // from the first feeder; it is stamped per record by whichever spec\n // produced it, so a family fed by two different TTLs genuinely has two.\n for (const k of r.sum ?? []) if (!seen.sums.includes(k)) seen.sums.push(k);\n for (const c of r.capture ?? []) {\n const l = label(c);\n if (!seen.capture.includes(l)) seen.capture.push(l);\n }\n if (!seen.feeders.includes(name)) seen.feeders.push(name);\n }\n }\n\n const events: Record<string, EventFacet> = {};\n const namespaces: Record<string, string[]> = {};\n const subjectTypes: string[] = [];\n const noteSubject = (t: string) => {\n if (!subjectTypes.includes(t)) subjectTypes.push(t);\n };\n\n for (const [name, spec] of Object.entries(registry)) {\n const dot = name.indexOf('.');\n const namespace = dot === -1 ? name : name.slice(0, dot);\n (namespaces[namespace] ??= []).push(name);\n\n for (const s of spec.subjects) noteSubject(s);\n\n const indexedAttrs = [...(spec.indexedAttrs ?? [])];\n const dims: DimFacet[] = Object.entries((spec.attrs?.shape ?? {}) as Record<string, z.ZodType>).map(\n ([key, schema]) => {\n const walked = walkAttr(schema);\n return {\n key: `attr:${key}`,\n label: key,\n type: walked.type,\n ...(walked.values ? { values: walked.values } : {}),\n optional: walked.optional,\n indexed: indexedAttrs.includes(key),\n };\n },\n );\n dims.push(...kindDims(spec.kind));\n\n // this event's OWN declarations, per family. `exactVia` must not name a\n // family that sums the metric only because a DIFFERENT feeder said so —\n // this event's records would not be in that total.\n const eventFamilies: string[] = [];\n const ownSums = new Map<string, Set<string>>();\n for (const r of spec.rollups ?? []) {\n const as = r.as ?? name;\n if (!eventFamilies.includes(as)) eventFamilies.push(as);\n const set = ownSums.get(as) ?? new Set<string>();\n for (const k of r.sum ?? []) set.add(k);\n ownSums.set(as, set);\n for (const s of r.subjects ?? []) noteSubject(s);\n }\n\n const measures: MeasureFacet[] = [{ key: 'count', exactVia: [] }];\n for (const k of Object.keys(spec.metrics?.shape ?? {})) {\n measures.push({\n key: `sum:${k}`,\n metric: k,\n exactVia: eventFamilies.filter((as) => ownSums.get(as)?.has(k)),\n });\n for (const op of RAW_OPS) measures.push({ key: `${op}:${k}`, metric: k, exactVia: [] });\n }\n // durationMs lives on the envelope for kind=span rather than in `metrics`,\n // so it is a measure no registry can declare and every span has\n if (spec.kind === TelemetryKind.Span) {\n for (const op of RAW_OPS) {\n measures.push({ key: `${op}:durationMs`, metric: 'durationMs', exactVia: [] });\n }\n }\n\n events[name] = {\n kind: spec.kind,\n origin: spec.origin,\n subjects: [...spec.subjects],\n description: spec.description,\n namespace,\n dims,\n measures,\n families: eventFamilies,\n indexedAttrs,\n indexedMetrics: [...(spec.indexedMetrics ?? [])],\n // `hasOwnProperty` rather than `??`, exactly as model.ts stamps expiresAt:\n // an explicit `retentionDays: null` means immortal and must not fall\n // through to the per-kind default\n retentionDays: Object.prototype.hasOwnProperty.call(spec, 'retentionDays')\n ? spec.retentionDays ?? null\n : RETENTION_DAYS[spec.kind],\n };\n }\n\n return { events, families, namespaces, envelope: envelopeDims(platforms), subjectTypes };\n}\n\n/**\n * The catalog, narrowed back to the projection `/api/registry` and\n * `describe_telemetry` have always returned. It exists so that adding the\n * catalog costs the SPA nothing: the `registry` key keeps its exact shape while\n * `catalog` arrives beside it.\n *\n * One nuance the old per-event code did not have: `sum` is read off the FAMILY,\n * so two names feeding one family with different `sum` lists both report the\n * union. That is the more useful answer — it is what the family's docs actually\n * accumulate — and validateRegistry already forbids the mismatches that would\n * matter (`by`, `bucket`, `subjects`).\n */\nexport function projectRegistry(catalog: Catalog): RegistryProjection {\n return Object.fromEntries(\n Object.entries(catalog.events).map(([name, e]) => [\n name,\n {\n kind: e.kind,\n origin: e.origin,\n subjects: e.subjects,\n description: e.description,\n attrKeys: e.dims.filter((d) => d.key.startsWith('attr:')).map((d) => d.label),\n // every metric key gets exactly one `sum:` measure and nothing else does\n metricKeys: e.measures.filter((m) => m.key.startsWith('sum:')).map((m) => m.metric!),\n indexedAttrs: e.indexedAttrs,\n indexedMetrics: e.indexedMetrics,\n rollups: e.families.map((as) => {\n const f = catalog.families[as]!;\n return { as: f.as, by: f.by, bucket: f.bucket, sum: f.sums, subjects: f.subjectTypes };\n }),\n },\n ]),\n );\n}\n","import type { Catalog } from './catalog.js';\nimport { COUNTER_OVERFLOW_KEY, type TelemetryCounters } from './types.js';\n\n/**\n * The loop closed in the other direction (reports §9).\n *\n * Everywhere else in this package the registry tells the data what is allowed.\n * Here the data tells the registry what it is missing — and it can, because\n * nothing was ever dropped silently: `undeclaredAttrs` knows which attr key\n * keeps arriving undeclared, `rollupSkippedBy` knows which family keeps losing\n * which dim, and the quarantine knows which name nobody registered.\n *\n * Each of those is one registry line away from being fixed, so each suggestion\n * carries that line as `fix` — pasteable, not prose. Nothing here writes\n * anything: the host still edits the registry by hand. The package just stops\n * making it guess.\n *\n * Pure — no Mongo, no I/O — and unit-tested that way, like `deriveCatalog` and\n * `resolveReport`.\n */\n\nexport interface Suggestion {\n kind: 'undeclared_attr' | 'missing_dim_default' | 'unregistered_event';\n /** the registry entry to touch — an event name, or a rollup family name */\n target: string;\n /** attr key or dim label, when the suggestion is about one */\n key?: string;\n count: number;\n /** one sentence a human reads */\n message: string;\n /** the registry change, as code */\n fix: string;\n}\n\nexport interface DeriveSuggestionsInput {\n counters: TelemetryCounters;\n catalog: Catalog;\n /**\n * The quarantine rows the caller already fetched. `name` and `reason` are all\n * that is read; the index signature is there so a driver's `WithId<Document>`\n * passes straight in without a cast.\n */\n quarantine?: readonly { name?: unknown; reason?: unknown; [k: string]: unknown }[];\n}\n\n/**\n * emit.ts and ingest.ts both quarantine an unknown name with exactly this\n * reason, and model.ts's hook throws `telemetry: unregistered event \"x\"` for\n * the direct-model path — a substring test matches all three without matching\n * anything else.\n */\nconst UNREGISTERED_REASON = 'unregistered event';\n\n/** the returned list, capped. A System page is a thing a human reads. */\nexport const MAX_SUGGESTIONS = 50;\n\n/**\n * Quarantine names are client-controlled, and `fix` is rendered as code. Cap\n * the length and quote anything that is not plainly a bare name, so a hostile\n * event name cannot be dressed up as surrounding syntax.\n */\nconst NAME_MAX = 120;\nconst quote = (s: string) => (/^[A-Za-z0-9_.:$-]+$/.test(s) ? `'${s}'` : JSON.stringify(s));\n/** an object key that needs no quoting is written bare, the way a registry does */\nconst prop = (s: string) => (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(s) ? s : quote(s));\nconst times = (n: number) => `${n} time${n === 1 ? '' : 's'}`;\n\n/** split `${target}|${key}` on the FIRST '|' — the key half may contain more */\nconst split = (k: string): [string, string] => {\n const i = k.indexOf('|');\n return i === -1 ? [k, ''] : [k.slice(0, i), k.slice(i + 1)];\n};\n\nexport function deriveSuggestions(input: DeriveSuggestionsInput): Suggestion[] {\n const { counters, catalog, quarantine = [] } = input;\n const out: Suggestion[] = [];\n\n // ── undeclared attrs: the zod line that would let the record through ──\n for (const [k, count] of Object.entries(counters.undeclaredAttrs ?? {})) {\n // the fold-here bucket names no event and no key, so there is no line to\n // paste — it is a counter to look at, not a suggestion to act on\n if (k === COUNTER_OVERFLOW_KEY || !count) continue;\n const [name, key] = split(k);\n if (!name || !key) continue;\n\n const facet = catalog.events[name];\n const line = `${prop(key)}: z.string().max(64),`;\n // No attr dims at all means the spec declares no `attrs` object, and a bare\n // key line would have nothing to land in — so hand over the whole block.\n const hasAttrs = !!facet?.dims.some((d) => d.key.startsWith('attr:'));\n out.push({\n kind: 'undeclared_attr',\n target: name,\n key,\n count,\n message: `\\`${name}\\` has been sent with attr \\`${key}\\` ${times(count)} — not declared`,\n fix: hasAttrs ? line : `attrs: z.object({ ${prop(key)}: z.string().max(64) }),`,\n });\n }\n\n // ── skipped rollups: the dimDefault that would make the drop a group ──\n for (const [k, count] of Object.entries(counters.rollupSkippedBy ?? {})) {\n if (k === COUNTER_OVERFLOW_KEY || !count) continue;\n const [as, dim] = split(k);\n if (!as || !dim) continue;\n\n // Naming the feeders matters: `dimDefault` is declared per rollup on an\n // EVENT, not on the family, so \"add it to `screens_viewed`\" is not yet an\n // instruction — the catalog knows which specs to open.\n const feeders = catalog.families[as]?.feeders ?? [];\n const where = feeders.length\n ? `// on the \\`${as}\\` rollup of ${feeders.map((f) => `\\`${f}\\``).join(', ')}\\n`\n : '';\n out.push({\n kind: 'missing_dim_default',\n target: as,\n key: dim,\n count,\n message:\n `\\`${as}\\` skipped ${count} record${count === 1 ? '' : 's'} with no \\`${dim}\\` — ` +\n 'declare `dimDefault`',\n fix: `${where}dimDefault: 'unknown',`,\n });\n }\n\n // ── unregistered names: the stub that would stop the quarantine ──\n const unregistered = new Map<string, number>();\n for (const row of quarantine) {\n if (typeof row?.reason !== 'string' || !row.reason.includes(UNREGISTERED_REASON)) continue;\n const name = typeof row.name === 'string' ? row.name.slice(0, NAME_MAX) : '';\n if (!name || name === '(unnamed)') continue;\n unregistered.set(name, (unregistered.get(name) ?? 0) + 1);\n }\n for (const [name, count] of unregistered) {\n out.push({\n kind: 'unregistered_event',\n target: name,\n count,\n message: `\\`${name}\\` was rejected ${times(count)} — not in the registry`,\n // the minimum that boots: validateRegistry wants a kind, an origin, and\n // a subjects array, and nothing here can guess the rest\n fix: `${quote(name)}: { kind: 'event', origin: 'client', subjects: [], description: '' },`,\n });\n }\n\n // Loudest first. Ties break on target then key so the same counters always\n // produce the same page — a list that reshuffles between refreshes is one\n // nobody trusts.\n out.sort(\n (a, b) =>\n b.count - a.count ||\n a.target.localeCompare(b.target) ||\n (a.key ?? '').localeCompare(b.key ?? ''),\n );\n return out.slice(0, MAX_SUGGESTIONS);\n}\n","import type { Model } from 'mongoose';\nimport type { Registry, RollupSpec } from './registry.js';\nimport { truncate } from './rollups.js';\nimport type { TimeRange } from './query.js';\n\n/**\n * The sixth read primitive: cohort funnels over lifetime milestone rollups\n * (cohort-math §1). Every host that models milestones as lifetime rollups then\n * rewrites the same three things — stage ordering, the cohort window, and the\n * median time-to-step aggregation. This file is that code, once.\n *\n * The formulas are ported verbatim from maxed's `src/server/telemetry/funnel.ts`\n * (recon: plans/cohort-math.md). Names differ where maxed's were host-specific\n * or actively wrong; the mapping is exact and total:\n *\n * maxed here why\n * ─────────────────────────────────────────────────────────────────────────\n * accounts subjects the package counts subjects, not accounts\n * first first unchanged — |{s : stage 1 present}|\n * pctOfFirst pctOfFirst unchanged\n * pctOfPrevious pctOfPrevious unchanged\n * medianDaysFromSignup medianDaysFromAnchor the anchor milestone is configurable here\n * medianDaysFromPrevious medianDaysFromPrevious unchanged\n * StageSummary.stuckAccounts notReached reached k−1, not k (drop-off INTO k)\n * accountsStuckAt(k) stalledAt reached k, not k+1 (drop-off OUT OF k)\n *\n * The last two are the deliberate divergence. maxed ships both quantities under\n * the word \"stuck\", and its `accountsStuckAt` reports every CONVERTED subject as\n * stuck because the terminal stage has no k+1 to fail (cohort-math H3). Here the\n * two quantities have two names and `stalledAt` is **null** on the terminal\n * stage — \"how many stalled here\" has no answer when there is nowhere to go\n * next, and 0 would be as wrong as `subjects`.\n *\n * Interval convention: the package is half-open (`$gte`/`$lt`) everywhere and\n * stays that way. maxed's cohort window is closed on both ends (cohort-math R6),\n * so `cohort.endInclusive` exists to reproduce it — and is translated to a\n * half-open bound HERE (see `cohortWindow`) rather than leaking `$lte` into the\n * read layer.\n */\n\n// ── shapes ──────────────────────────────────────────────────────────────────\n\nexport interface FunnelStageSpec {\n /** the lifetime rollup family whose doc marks this stage — `firstAt` IS the timestamp */\n as: string;\n /** stable identifier in the response. Default: `as` */\n key?: string;\n label?: string;\n description?: string;\n}\n\nexport interface FunnelCohortWindow extends TimeRange {\n /**\n * Include `to` itself. Default FALSE — the package is half-open everywhere and\n * that is the correct convention. maxed's funnel is closed on both ends\n * (cohort-math R6), so a host migrating off it sets this to keep its numbers.\n */\n endInclusive?: boolean;\n}\n\nexport interface FunnelParams {\n /** ordered stages. A stage may be reached without its predecessor — see LITERAL below. */\n stages: readonly FunnelStageSpec[];\n /** the milestone that assigns cohort membership and anchors time-to-step. Default: `stages[0].as` */\n anchor?: string;\n /** the cohort window, applied to the ANCHOR family's `firstAt` */\n cohort: FunnelCohortWindow;\n /** exit families — counted, never staged (cohort-math §1.4) */\n exits?: readonly FunnelStageSpec[];\n /** restrict the cohort to one subject type ('account') */\n subjectType?: string;\n /** also slice the cohort by anchor date. UTC, Monday-start weeks — `truncate()` */\n interval?: 'day' | 'week' | 'month';\n /** cohort size cap. Clamped to `limits.funnel`; hitting it sets `truncated`. */\n limit?: number;\n}\n\nexport interface FunnelStageResult {\n /** 1-based position in `stages` */\n order: number;\n key: string;\n as: string;\n label: string;\n description?: string;\n /** subjects with this stage present. NOT monotonic — see LITERAL below. */\n subjects: number;\n /** 0–100, unrounded. null when stage 1's count is 0. */\n pctOfFirst: number | null;\n /** 0–100, unrounded. null on stage 1 and whenever the previous count is 0 — never 0, never Infinity. */\n pctOfPrevious: number | null;\n /** fractional days, unrounded. null on an empty sample. */\n medianDaysFromAnchor: number | null;\n /** fractional days, unrounded. null on stage 1 and on an empty sample. */\n medianDaysFromPrevious: number | null;\n /** reached the PREVIOUS stage and not this one — drop-off INTO this stage. 0 on stage 1. */\n notReached: number;\n /** reached this stage and not the NEXT — drop-off OUT OF it. null on the terminal stage. */\n stalledAt: number | null;\n}\n\nexport interface FunnelExitResult {\n key: string;\n as: string;\n label: string;\n subjects: number;\n}\n\nexport interface FunnelSlice {\n /** the truncated anchor date — UTC bucket start, not a \"2026-W31\" label */\n at: Date;\n subjects: number;\n stages: FunnelStageResult[];\n}\n\nexport interface FunnelResult {\n /** cohort size: subjects whose ANCHOR firstAt fell in the window */\n cohortSubjects: number;\n /** |{ s : stage 1 present }| — the `pctOfFirst` denominator. Equals cohortSubjects when the anchor IS stage 1. */\n first: number;\n stages: FunnelStageResult[];\n exits: FunnelExitResult[];\n /** present only when `interval` was asked for; ascending by `at` */\n slices: FunnelSlice[] | null;\n /** the cohort read hit its cap — every number below is an UNDERCOUNT (traps §18: no silent caps) */\n truncated: boolean;\n cohort: { from: Date; to: Date; endInclusive: boolean; anchor: string };\n dataSource: 'rollups';\n}\n\n/** one subject's assembled milestone index — the input `summarizeStages` reasons over */\nexport interface CohortSubject {\n ref: string;\n /** the anchor milestone's firstAt. Never null via `runFunnel`; the branch exists per cohort-math R9. */\n anchorAt: Date | null;\n /** stage key → first occurrence */\n stages: Record<string, Date>;\n /** exit key → first occurrence */\n exits: Record<string, Date>;\n}\n\ninterface ResolvedStage {\n order: number;\n key: string;\n as: string;\n label: string;\n description?: string;\n}\n\n// ── pure math ───────────────────────────────────────────────────────────────\n\nconst DAY_MS = 86_400_000;\n\n/**\n * Mean of the two middles on even counts — NOT the lower middle (cohort-math R1).\n * Empty set is null, never 0: \"nobody got here\" and \"everybody got here\n * instantly\" are different facts and a chart must be able to tell them apart.\n * No rounding anywhere; the caller formats.\n */\nexport function median(values: readonly number[]): number | null {\n if (values.length === 0) return null;\n const s = [...values].sort((a, b) => a - b);\n const mid = s.length >> 1;\n return s.length % 2 === 1 ? s[mid]! : (s[mid - 1]! + s[mid]!) / 2;\n}\n\n/**\n * The stage table. Pure — same input, same output, no Mongo — so the equivalence\n * test can pin it cell by cell.\n *\n * LITERAL, never backfilled (cohort-math R4): a subject counts at stage N only\n * if a stage-N doc exists for it. Reaching N+1 does not imply N. So stage counts\n * are NOT required to be non-increasing, `pctOfPrevious` may exceed 100%, and a\n * skipping subject contributes to `subjects` for the later stage but to nothing\n * else on that row — not `prevReached`, not the fromPrevious sample, not\n * `notReached`. That is a data fact, not a bug, and smoothing it would invent\n * subjects that never existed.\n */\nexport function summarizeStages(\n subjects: readonly CohortSubject[],\n stages: readonly ResolvedStage[],\n): FunnelStageResult[] {\n const firstKey = stages[0]?.key;\n const first = firstKey ? subjects.filter((s) => s.stages[firstKey]).length : 0;\n\n return stages.map((st, i) => {\n const prev = i > 0 ? stages[i - 1]! : null;\n const next = i < stages.length - 1 ? stages[i + 1]! : null;\n\n const reached: CohortSubject[] = [];\n const fromAnchor: number[] = [];\n for (const s of subjects) {\n const at = s.stages[st.key];\n if (!at) continue;\n reached.push(s);\n // a subject with no anchor is excluded from the SAMPLE but still counted\n // in `subjects` (cohort-math R9) — unreachable through runFunnel, kept\n // because summarizeStages is exported and can be fed from elsewhere\n if (s.anchorAt) fromAnchor.push((at.getTime() - s.anchorAt.getTime()) / DAY_MS);\n }\n\n let prevReached = 0;\n let notReached = 0;\n const fromPrevious: number[] = [];\n if (prev) {\n for (const s of subjects) {\n const p = s.stages[prev.key];\n if (!p) continue;\n prevReached += 1;\n const cur = s.stages[st.key];\n if (cur) fromPrevious.push((cur.getTime() - p.getTime()) / DAY_MS);\n else notReached += 1;\n }\n }\n\n // `pctOfPrevious` divides ALL subjects that reached this stage by only those\n // that reached the previous one — two independent counts, not a conversion\n // rate (cohort-math H4). Ported deliberately: changing it would silently\n // disagree with the funnel a migrating host is reading today.\n return {\n order: st.order,\n key: st.key,\n as: st.as,\n label: st.label,\n ...(st.description ? { description: st.description } : {}),\n subjects: reached.length,\n pctOfFirst: first > 0 ? (reached.length / first) * 100 : null,\n pctOfPrevious: prev ? (prevReached > 0 ? (reached.length / prevReached) * 100 : null) : null,\n medianDaysFromAnchor: median(fromAnchor),\n medianDaysFromPrevious: prev ? median(fromPrevious) : null,\n notReached,\n // the divergence: maxed's `!next` clause makes every subject that reached\n // the terminal stage \"stuck\" there. null says \"undefined\", which is true.\n stalledAt: next ? subjects.filter((s) => s.stages[st.key] && !s.stages[next.key]).length : null,\n };\n });\n}\n\n// ── registry lookup ─────────────────────────────────────────────────────────\n\n/** the first declaration of a rollup family — validateRegistry pins the shape, so it speaks for all */\nexport function findFamily(registry: Registry, as: string): { name: string; spec: RollupSpec } | null {\n for (const [name, s] of Object.entries(registry)) {\n for (const r of s.rollups ?? []) {\n if ((r.as ?? name) === as) return { name, spec: r };\n }\n }\n return null;\n}\n\n/**\n * A milestone family is a LIFETIME rollup keyed on exactly one subject dim. Any\n * other shape cannot answer \"when did this subject first reach this stage\" —\n * a bucketed family has one doc per period, and an extra dim has one doc per\n * (subject, value). Both would produce a plausible wrong number, so this throws\n * instead. A registry mistake must fail loudly; that is what this package is for.\n */\nexport function requireMilestoneFamily(registry: Registry, as: string, primitive: string): RollupSpec {\n const found = findFamily(registry, as);\n if (!found) {\n throw new Error(\n `telemetry: ${primitive} — no rollup family \"${as}\" is declared. Add a \\`rollups: [{ as: '${as}', ` +\n `by: ['subject'], subjects: [...] }]\\` block to the event that marks it.`,\n );\n }\n const { name, spec } = found;\n const shape = `by: [${spec.by.map((d) => `'${d}'`).join(', ')}]${spec.bucket ? `, bucket: '${spec.bucket}'` : ''}`;\n if (spec.bucket) {\n throw new Error(\n `telemetry: ${primitive} — rollup family \"${as}\" (declared on \"${name}\") is BUCKETED (${shape}). ` +\n `A milestone needs a lifetime family so \\`firstAt\\` is the one moment the subject reached it; ` +\n `a bucketed family has one doc per period and would count the same subject repeatedly.`,\n );\n }\n if (spec.by.length !== 1 || spec.by[0] !== 'subject') {\n throw new Error(\n `telemetry: ${primitive} — rollup family \"${as}\" (declared on \"${name}\") is keyed ${shape}, ` +\n `but a milestone must be keyed by exactly one subject dim (\\`by: ['subject']\\`). ` +\n `Extra dims split one subject across several docs, which would over-count every stage.`,\n );\n }\n return spec;\n}\n\n// ── the read ────────────────────────────────────────────────────────────────\n\nexport interface FunnelCtx {\n RollupModel: Model<any>;\n registry: Registry;\n /** cohort size cap — config, per traps §18 */\n cohortCap: number;\n /**\n * The tenancy term for a scope, INJECTED. This file computes cohort math; it\n * does not get to decide who may read across tenants, and hard-wiring\n * `{ tenantId }` here would put that policy in two places. query.ts owns it.\n */\n scopeMatch: (scope: string) => Record<string, unknown>;\n}\n\n/**\n * Closed → half-open, exactly. BSON dates are integer milliseconds, so\n * `{$lte: e}` and `{$lt: e + 1ms}` select identically — which is why\n * `endInclusive` can be honoured without a `$lte` ever reaching the query layer.\n */\nfunction cohortWindow(c: FunnelCohortWindow): { from: Date; to: Date; endInclusive: boolean } {\n const endInclusive = c.endInclusive === true;\n return { from: c.from, to: endInclusive ? new Date(c.to.getTime() + 1) : c.to, endInclusive };\n}\n\nexport async function runFunnel(\n ctx: FunnelCtx,\n scope: string,\n params: FunnelParams,\n): Promise<FunnelResult> {\n if (!params.stages?.length) throw new Error('telemetry: funnel() needs at least one stage');\n\n const stages: ResolvedStage[] = params.stages.map((s, i) => ({\n order: i + 1,\n key: s.key ?? s.as,\n as: s.as,\n label: s.label ?? s.key ?? s.as,\n ...(s.description ? { description: s.description } : {}),\n }));\n const exits: ResolvedStage[] = (params.exits ?? []).map((s, i) => ({\n order: i + 1,\n key: s.key ?? s.as,\n as: s.as,\n label: s.label ?? s.key ?? s.as,\n }));\n\n // ANCHOR, not first-event (cohort-math R5): a subject whose earliest record is\n // a page view three weeks before signup is still assigned by the signup. A\n // subject with no anchor doc in the window is absent from the cohort entirely\n // — every other milestone it has is invisible, counted at no stage.\n const anchor = params.anchor ?? stages[0]!.as;\n\n requireMilestoneFamily(ctx.registry, anchor, 'funnel()');\n for (const s of [...stages, ...exits]) requireMilestoneFamily(ctx.registry, s.as, 'funnel()');\n\n const { from, to, endInclusive } = cohortWindow(params.cohort);\n const cap = Math.min(Math.max(1, params.limit ?? ctx.cohortCap), ctx.cohortCap);\n\n const cohortMatch: Record<string, unknown> = {\n ...ctx.scopeMatch(scope),\n as: anchor,\n // AMBIGUOUS-2 (cohort-math): maxed's cohort read overwrites per row with no\n // ordering, so its `signupAt` is whichever row Mongo returned last —\n // nondeterministic. Unreachable here by construction: the rollup's `firstAt`\n // is a `$min` maintained on write, so the anchor timestamp is the EARLIEST\n // occurrence, always, matching the tie-break rule maxed uses everywhere else\n // (R12). We take min(at) and the storage enforces it.\n firstAt: { $gte: from, $lt: to },\n };\n if (params.subjectType) cohortMatch.subjectType = params.subjectType;\n\n // limit+1 so \"hit the cap\" is a fact, not an inference off an exact match\n const cohortRows = await ctx.RollupModel.find(cohortMatch)\n .sort({ firstAt: 1 })\n .limit(cap + 1)\n .lean();\n const truncated = cohortRows.length > cap;\n if (truncated) cohortRows.pop();\n\n // A subject ref is unique only WITHIN a tenant, so the index is keyed by\n // (tenant, ref). Under a cross-tenant scope two tenants' 'account:a1' are two\n // subjects; keying on the ref alone would braid their milestones into one\n // funnel and report a conversion that never happened.\n const keyOf = (r: any) => `${r.tenantId ?? ''}|${r.dims?.[0]}`;\n const index = new Map<string, CohortSubject>();\n const refs = new Set<string>();\n const tenants = new Set<string>();\n for (const r of cohortRows as any[]) {\n const ref = r.dims?.[0];\n if (!ref) continue;\n refs.add(ref);\n tenants.add(String(r.tenantId ?? ''));\n index.set(keyOf(r), { ref, anchorAt: r.firstAt, stages: {}, exits: {} });\n }\n\n if (refs.size) {\n const byAs = new Map<string, ResolvedStage[]>();\n for (const s of [...stages, ...exits]) {\n const list = byAs.get(s.as) ?? [];\n list.push(s);\n byAs.set(s.as, list);\n }\n // One read for every stage of every cohort member — the multi-subject gap\n // (cohort-math G3). N single-subject reads or an uncapped family scan were\n // the alternatives; the second truncates a large cohort silently.\n const stageRows = await ctx.RollupModel.find({\n ...ctx.scopeMatch(scope),\n as: { $in: [...byAs.keys()] },\n dims: { $in: [...refs] },\n // AMBIGUOUS-1 (cohort-math): maxed collects stages with `at >= cohortStart`\n // and no upper bound. We keep the lower bound — reading (a), as-written.\n // Reasons: (1) it is what maxed does, and an equivalence test against a\n // table computed under the other reading would prove nothing; (2) over\n // rollup storage the predicate reads \"first reached no earlier than the\n // cohort opened\", which is the only reading under which a cohort's funnel\n // is a function of its own window — drop the bound and a backfill dated\n // before the window silently adds stages to a report already published.\n // No UPPER bound, deliberately: a conversion landing months after the\n // window still belongs to its cohort (R7).\n firstAt: { $gte: from },\n })\n // The exact worst case of the query as written: a lifetime by:['subject']\n // family holds at most one doc per (tenant, subject), and `dims` matches\n // refs across every tenant in the cohort. Under a single-tenant scope that\n // is index.size × families. The bound cannot bite; it is here because §18\n // says every read carries its limit, not because we expect to reach it.\n .limit(refs.size * tenants.size * byAs.size + 1)\n .lean();\n\n for (const r of stageRows as any[]) {\n const subject = index.get(keyOf(r));\n if (!subject) continue;\n for (const s of byAs.get(r.as) ?? []) {\n const bag = exits.includes(s) ? subject.exits : subject.stages;\n const prevAt = bag[s.key];\n // earliest wins (R12) — belt and braces, `firstAt` is already a $min\n if (!prevAt || r.firstAt < prevAt) bag[s.key] = r.firstAt;\n }\n }\n }\n\n const subjects = [...index.values()];\n const summary = summarizeStages(subjects, stages);\n\n let slices: FunnelSlice[] | null = null;\n if (params.interval) {\n const groups = new Map<number, CohortSubject[]>();\n for (const s of subjects) {\n // subjects with no anchor date are dropped from the slices, matching\n // maxed (adminTelemetry.ts:660-666); unreachable via this path\n if (!s.anchorAt) continue;\n const at = truncate(s.anchorAt, params.interval)!;\n const k = at.getTime();\n groups.set(k, [...(groups.get(k) ?? []), s]);\n }\n slices = [...groups.entries()]\n .sort((a, b) => a[0] - b[0])\n .map(([k, members]) => ({\n at: new Date(k),\n subjects: members.length,\n stages: summarizeStages(members, stages),\n }));\n }\n\n return {\n cohortSubjects: subjects.length,\n first: stages[0] ? subjects.filter((s) => s.stages[stages[0]!.key]).length : 0,\n stages: summary,\n exits: exits.map((e) => ({\n key: e.key,\n as: e.as,\n label: e.label,\n subjects: subjects.filter((s) => s.exits[e.key]).length,\n })),\n slices,\n truncated,\n cohort: { from: params.cohort.from, to: params.cohort.to, endInclusive, anchor },\n dataSource: 'rollups' as const,\n };\n}\n","import type { Model } from 'mongoose';\nimport { isPlatformScope } from './types.js';\nimport type { Registry, RollupSpec } from './registry.js';\nimport { findFamily, runFunnel, type FunnelParams, type FunnelResult } from './funnel.js';\n\n/**\n * The six read primitives (dashboards §2). Everything the UI renders comes\n * through these — kind pages never touch Mongo, which is the seam that lets\n * span/event route to a columnar store later without touching a component.\n *\n * Traps §18 is law here, but per primitive rather than blanket. A time range is\n * REQUIRED by records, series, distribution, journey and distinctCount, and a\n * cohort window by funnel; `rollups()`'s range is OPTIONAL because a lifetime\n * family has no time axis to filter on; `trace()` takes NONE — it is pinned by\n * an indexed traceId and bounded by the trace itself.\n *\n * What is universal is the cap: every primitive carries its `$limit` INSIDE the\n * pipeline rather than applying it to a materialised result, the caps are\n * config, and the five that can cut an answer short — rollups, distribution,\n * distinctCount, funnel, breakdown — report `truncated` rather than\n * undercounting in silence. What each cap BOUNDS differs, and QueryLimits below\n * says which are output caps and which are scan caps: breakdown's, like\n * series', bounds the groups returned and never the rows read. The slow-query\n * counter is an adapter. Every response reports\n * `dataSource` (recon #2) so a spliced number can always say which store\n * answered.\n *\n * Tenancy: every primitive takes a SCOPE, not a tenant. A scope is a tenantId,\n * or PLATFORM_SCOPE ('*') for a cross-tenant read. `'*'` is only ever reachable\n * because a host's `viewerAdapter` put it on the Viewer — an authorization\n * decision the package does not make and cannot second-guess. The write side\n * treats '*' as reserved (types.ts), so no stored row can ever carry it and\n * \"omit the tenant term\" is unambiguous.\n *\n * Row-shaped primitives (records/rollups/trace/journey) already return the\n * stored `tenantId` on every row, which is what makes a cross-tenant number\n * attributable — do not project it away.\n */\n\n/**\n * Two kinds of cap live here and the difference is worth stating, because the\n * word \"limit\" hides it. An OUTPUT cap bounds what the response contains: its\n * `$limit` sits after the `$group`/sort or rides an indexed cursor, so the work\n * behind it is bounded by the range and the indexes, not by the number. A SCAN\n * cap bounds what the primitive reads, which means an answer past it is an\n * undercount — so every scan-capped primitive reports `truncated`.\n */\nexport interface QueryLimits {\n // ── output caps ──\n records: number;\n series: number;\n rollups: number;\n trace: number;\n journey: number;\n /**\n * Distinct GROUPS one breakdown() returns — the top N by measure, read as\n * cap+1 so truncation is observed. Never a bound on rows scanned: \"the top\n * models this quarter\" is exactly the question Mongo folds a million rows\n * into in one pass (reports §6).\n */\n breakdown: number;\n /**\n * Distinct VALUES one /values lookup returns — the top N by count, read as\n * cap+1 so truncation is observed. Never a bound on rows scanned: the\n * `$limit` sits after the `$group`, exactly as breakdown's does (reports §5).\n */\n values: number;\n\n // ── scan caps ──\n /** raw docs distribution will scan before it reports an undercount */\n distribution: number;\n /** rollup docs distinctCount will scan before it reports an undercount */\n distinct: number;\n /** subjects in one funnel cohort */\n funnel: number;\n}\n\nexport const DEFAULT_LIMITS: QueryLimits = {\n records: 200,\n series: 744, // a month of hourly buckets\n rollups: 500,\n trace: 500,\n journey: 500,\n breakdown: 50, // top groups — a starting point, to be measured on real hosts\n values: 200, // top values of one dimension — a picker, not a table\n distribution: 100_000,\n distinct: 100_000,\n funnel: 5_000,\n};\n\nexport interface RecordFilter {\n kind?: string;\n /**\n * One event name, or a SET of them as an `$in`. The set form exists because a\n * namespace or a rollup family is several names, and without it the only\n * honest read for one was \"every record of that kind in the range\" — a scan\n * sold as a filter (reports §6). An empty array is treated as absent, never\n * as a term that matches nothing.\n */\n name?: string | string[];\n severity?: string;\n env?: string;\n service?: string;\n release?: string;\n /** pin to one subject: 'user:u_1' */\n subject?: string;\n traceId?: string;\n /** equality on declared attrs */\n attrs?: Record<string, string>;\n /** range on declared metrics */\n metrics?: Record<string, { gte?: number; lte?: number }>;\n /** the customer toggle: exclude these actor TYPES ('admin', 'system') */\n excludeActorTypes?: string[];\n}\n\nexport interface TimeRange {\n from: Date;\n to: Date;\n}\n\n/** one group of a breakdown; `at` only when an `interval` was asked for */\nexport interface BreakdownRow {\n dims: (string | null)[];\n at?: Date;\n value: number;\n}\n\nexport interface BreakdownResult {\n rows: BreakdownRow[];\n /** distinct groups RETURNED — never more than the cap */\n groups: number;\n /** more groups existed than the cap; the ones kept are the top by measure */\n truncated: boolean;\n /**\n * The per-bucket pass hit ITS ceiling (`limits.series` buckets per returned\n * group), so some group is missing buckets. Always false without an\n * `interval`, and separate from `truncated` because they cut different axes:\n * one drops groups, the other drops periods of a group that IS shown.\n */\n bucketsTruncated: boolean;\n dataSource: 'raw';\n}\n\nconst esc = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** exported for values.ts — the raw step must match rows exactly as the primitives do */\nexport function buildMatch(scope: string, range: TimeRange, f: RecordFilter): Record<string, unknown> {\n const match: Record<string, any> = {\n // the ONLY place the tenant term is optional. Omitted under '*' — every\n // other term still applies, and the time range is still mandatory (§18).\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n occurredAt: { $gte: range.from, $lt: range.to },\n };\n for (const k of ['kind', 'name', 'severity', 'env', 'service', 'release', 'traceId'] as const) {\n const v = f[k];\n // only `name` is ever a set; an empty one is an absent term rather than an\n // `$in: []` that silently matches nothing\n if (Array.isArray(v)) {\n if (v.length) match[k] = { $in: v };\n } else if (v) match[k] = v;\n }\n if (f.subject) match.subjectKeys = f.subject;\n for (const [k, v] of Object.entries(f.attrs ?? {})) match[`attrs.${k}`] = v;\n for (const [k, r] of Object.entries(f.metrics ?? {})) {\n const term: Record<string, number> = {};\n if (r.gte != null) term.$gte = r.gte;\n if (r.lte != null) term.$lte = r.lte;\n if (Object.keys(term).length) match[`metrics.${k}`] = term;\n }\n if (f.excludeActorTypes?.length) {\n // a record with NO actor is a customer fact; only typed actors are excludable\n match.$and = [\n ...(match.$and ?? []),\n {\n $or: [\n { actor: { $exists: false } },\n { actor: { $not: new RegExp(`^(${f.excludeActorTypes.map(esc).join('|')}):`) } },\n ],\n },\n ];\n }\n return match;\n}\n\nexport type Interval = 'hour' | 'day' | 'week' | 'month';\n\nconst INTERVALS: readonly Interval[] = ['hour', 'day', 'week', 'month'];\n\n/** weeks start Monday, UTC — the same truncation everywhere it is asked for */\nconst truncTo = (path: string, unit: Interval) => ({\n $dateTrunc: { date: path, unit, ...(unit === 'week' ? { startOfWeek: 'monday' } : {}) },\n});\n\n/**\n * The measure grammar, in ONE place: `count` (default), `sum:<metric>`,\n * `avg:<metric>`. series() and breakdown() must agree on what a measure means\n * — two copies of this regex is two chances for \"sum:cost_usd\" to mean\n * different things on a chart and in the table beside it.\n *\n * `count` sums 1/sampleRate rather than counting documents, so it extrapolates\n * correctly the day a rate drops below 1 (§5.3).\n *\n * `durationMs` is the one metric name that is not in `metrics`: a span's\n * duration lives on the ENVELOPE, which is where distribution() has always read\n * it from. Resolving it to `$metrics.durationMs` here would have aggregated a\n * path no record carries and reported 0 — a number, confidently wrong — so the\n * branch is in the shared accumulator rather than in either caller.\n */\nfunction measureAccumulator(measure: string): Record<string, unknown> {\n const m = /^(sum|avg):(.+)$/.exec(measure);\n if (!m) return { $sum: { $divide: [1, { $ifNull: ['$sampleRate', 1] }] } };\n const path = m[2] === 'durationMs' ? '$durationMs' : `$metrics.${m[2]}`;\n return m[1] === 'sum' ? { $sum: path } : { $avg: path };\n}\n\nconst badRequest = (message: string) =>\n Object.assign(new Error(`telemetry: breakdown() — ${message}`), { status: 400 });\n\n/**\n * The envelope paths breakdown() will `$group` on. An ALLOWLIST, not a\n * passthrough: every one of these is either indexed or low-cardinality\n * enveloped metadata. `data.*` and `body` are deliberately absent — they are\n * free-form user content with no index behind them, and a `$group` over an\n * arbitrary path is an unbounded scan of exactly the payloads the rest of this\n * package works to keep out of aggregates.\n */\nconst BREAKDOWN_FIELDS: readonly string[] = [\n 'kind', 'name', 'severity', 'env', 'service', 'release', 'origin',\n 'client.platform', 'client.appVersion',\n 'usage.meter', 'usage.billedTo', 'usage.unit',\n 'state.key', 'state.to',\n 'error.type', 'error.handled',\n];\n\n/** 'user:u_1' → 'user'; null for an absent ref, never a thrown $split */\nconst typePrefix = (ref: unknown) => ({\n $let: {\n vars: { ref },\n in: {\n $cond: [\n { $eq: [{ $type: '$$ref' }, 'string'] },\n { $arrayElemAt: [{ $split: ['$$ref', ':'] }, 0] },\n null,\n ],\n },\n },\n});\n\n/**\n * One groupBy token → the aggregation expression it groups on. The syntax is\n * the catalog's and the rollup `by` syntax, so a dim key passes straight\n * through from one to the other.\n *\n * Every expression resolves an absent value to an explicit `null` rather than\n * leaving the field missing: a record with no `plan` is a group (\"none\"), not a\n * row to drop. That is the raw-side analogue of a family's `dimDefault`.\n */\nexport function dimExpression(dim: string): unknown {\n if (dim.startsWith('attr:')) {\n const key = dim.slice(5);\n if (!key) throw badRequest('`attr:` needs a key, e.g. \"attr:plan\"');\n return { $ifNull: [`$attrs.${key}`, null] };\n }\n if (dim.startsWith('field:')) {\n const path = dim.slice(6);\n if (!BREAKDOWN_FIELDS.includes(path)) {\n throw badRequest(\n `\"field:${path}\" is not groupable. Allowed paths: ${BREAKDOWN_FIELDS.join(', ')}. ` +\n 'Grouping by `data.*`, `body`, or an arbitrary path is refused — those are unindexed ' +\n 'free-form content, and a $group over them scans it all. Use `attr:<key>` for a declared attr.',\n );\n }\n return { $ifNull: [`$${path}`, null] };\n }\n if (dim === 'subjectType') return typePrefix({ $arrayElemAt: ['$subjectKeys', 0] });\n if (dim === 'actorType') return typePrefix('$actor');\n throw badRequest(\n `\"${dim}\" is not a dimension. Use \"attr:<key>\", \"field:<path>\", \"subjectType\" or \"actorType\".`,\n );\n}\n\n/** simple TTL cache with in-flight coalescing — proven shape in maxed.\n * Exported so values.ts memoizes on exactly these semantics rather than\n * keeping a second copy that could drift on eviction or error handling. */\nexport class QueryCache {\n private store = new Map<string, { at: number; value: Promise<unknown> }>();\n constructor(private ttlMs: number, private cap: number) {}\n get<T>(key: string, produce: () => Promise<T>): Promise<T> {\n const hit = this.store.get(key);\n if (hit && Date.now() - hit.at < this.ttlMs) return hit.value as Promise<T>;\n const value = produce();\n // a failed query must not be cached as the answer for ten minutes\n value.catch(() => this.store.delete(key));\n if (this.store.size >= this.cap) {\n const oldest = [...this.store.entries()].sort((a, b) => a[1].at - b[1].at)[0];\n if (oldest) this.store.delete(oldest[0]);\n }\n this.store.set(key, { at: Date.now(), value });\n return value;\n }\n}\n\nexport interface QueryCtx {\n TelemetryModel: Model<any>;\n RollupModel: Model<any>;\n registry: Registry;\n limits?: Partial<QueryLimits>;\n /** called with { op, ms, params } when a read exceeds slowMs (default 500) */\n onSlowQuery?: (info: { op: string; ms: number; params: unknown }) => void;\n slowMs?: number;\n cacheTtlMs?: number;\n cacheSize?: number;\n}\n\nexport function createQueries(ctx: QueryCtx) {\n const limits = { ...DEFAULT_LIMITS, ...ctx.limits };\n const slowMs = ctx.slowMs ?? 500;\n const cache = new QueryCache(ctx.cacheTtlMs ?? 10 * 60_000, ctx.cacheSize ?? 60);\n\n const timed = async <T>(op: string, params: unknown, run: () => Promise<T>): Promise<T> => {\n const t0 = Date.now();\n try {\n return await run();\n } finally {\n const ms = Date.now() - t0;\n if (ms > slowMs) ctx.onSlowQuery?.({ op, ms, params });\n }\n };\n\n return {\n /** cursor-paged raw envelope reads — tables, lists, detail drawers */\n async records(\n scope: string,\n range: TimeRange,\n filter: RecordFilter = {},\n opts: { limit?: number; cursor?: string } = {},\n ) {\n const limit = Math.min(Math.max(1, opts.limit ?? limits.records), limits.records);\n const match = buildMatch(scope, range, filter);\n if (opts.cursor) {\n // keyset on (occurredAt desc, _id desc) — never $skip\n const [atIso, id] = JSON.parse(Buffer.from(opts.cursor, 'base64url').toString());\n const at = new Date(atIso);\n match.$and = [\n ...((match.$and as unknown[]) ?? []),\n { $or: [{ occurredAt: { $lt: at } }, { occurredAt: at, _id: { $lt: id } }] },\n ];\n }\n return timed('records', { scope, filter }, async () => {\n const items = await ctx.TelemetryModel.find(match)\n .sort({ occurredAt: -1, _id: -1 })\n .limit(limit + 1)\n .lean();\n const more = items.length > limit;\n if (more) items.pop();\n const last: any = items[items.length - 1];\n return {\n items,\n nextCursor: more\n ? Buffer.from(JSON.stringify([new Date(last.occurredAt).toISOString(), last._id])).toString('base64url')\n : null,\n dataSource: 'raw' as const,\n };\n });\n },\n\n /** time-series at query time. count extrapolates by 1/sampleRate (§5.3) —\n * exact while rates sit at 1, still honest the day one drops.\n *\n * Under PLATFORM_SCOPE this aggregates ACROSS tenants into one bucket per\n * interval. That is the platform-wide chart, not a bug — the sum of every\n * tenant is the number a platform operator came for. A per-tenant\n * breakdown is a different question; ask it with rollups() or by scoping\n * to a tenant. Same for distribution() below. */\n series(\n scope: string,\n range: TimeRange,\n filter: RecordFilter,\n opts: { measure?: string; interval?: Interval } = {},\n ) {\n const { measure = 'count', interval = 'day' } = opts;\n const key = JSON.stringify(['series', scope, range.from, range.to, filter, measure, interval]);\n return cache.get(key, () =>\n timed('series', { scope, filter, measure, interval }, async () => {\n const buckets = await ctx.TelemetryModel.aggregate([\n { $match: buildMatch(scope, range, filter) },\n { $group: { _id: truncTo('$occurredAt', interval), value: measureAccumulator(measure) } },\n { $sort: { _id: 1 } },\n { $limit: limits.series },\n ] as any[]);\n return { buckets: buckets.map((b: any) => ({ at: b._id, value: b.value })), dataSource: 'raw' as const };\n }),\n );\n },\n\n /**\n * Top groups of a measure by one or two dimensions — \"which models cost the\n * most\", \"errors by release\", \"events by platform per week\". The primitive\n * that replaces a page's client-side grouping of whatever rows it happened\n * to have fetched, which answered \"this page\" while reading like it\n * answered the range (reports §6).\n *\n * THE CAP IS ON GROUPS RETURNED, NEVER ON ROWS SCANNED. Every `$limit`\n * below sits AFTER a `$group`, exactly as series() does: the scan is bounded\n * by buildMatch — tenant, range, filters, indexes — and nothing else, so a\n * quarter of a million records is one pass and 50 rows. Truncation\n * therefore keeps the TOP groups by measure, which is what a breakdown\n * table means; a cap on documents scanned would return an arbitrary prefix\n * and call it the top.\n *\n * With an `interval` this runs a SECOND aggregate restricted to the top\n * groups, rather than one pipeline that groups by (dims, bucket) and folds.\n * Two reasons: the ranking must be the measure over the WHOLE range (the\n * same number the no-interval call reports), and folding in one pass means\n * `$push`-ing every bucket of every group before the cap can apply — the\n * unbounded intermediate this primitive exists to avoid. The restriction is\n * an `$expr`/`$or` over the ≤ cap tuples because a dim can be a computed\n * expression (subjectType), which a plain `$in` on a path cannot address.\n *\n * Under PLATFORM_SCOPE it aggregates ACROSS tenants, like series() — one\n * set of groups with every tenant summed into it, which is the platform-wide\n * table a platform operator came for. Ask for a per-tenant split by scoping\n * to a tenant, or with rollups().\n */\n breakdown(\n scope: string,\n range: TimeRange,\n filter: RecordFilter,\n opts: {\n /** 1–2 of `attr:<key>` | `field:<path>` | `subjectType` | `actorType` */\n groupBy: string[];\n measure?: string;\n interval?: Interval;\n /** groups, clamped to limits.breakdown */\n limit?: number;\n },\n ) {\n const groupBy = opts.groupBy ?? [];\n if (groupBy.length < 1 || groupBy.length > 2) {\n // three dims is a pivot table nobody can read and a group count that\n // multiplies; zero is series() with extra steps\n throw badRequest(`groupBy takes 1 or 2 dimensions, got ${groupBy.length}`);\n }\n const measure = opts.measure ?? 'count';\n const interval = opts.interval;\n if (interval && !INTERVALS.includes(interval)) {\n throw badRequest(`interval must be one of ${INTERVALS.join(', ')}`);\n }\n // resolved (and refused) BEFORE the cache key is built — an invalid dim is\n // a 400 on every call, not a rejection remembered for ten minutes\n const dims = groupBy.map(dimExpression);\n const cap = Math.min(Math.max(1, opts.limit ?? limits.breakdown), limits.breakdown);\n const key = JSON.stringify([\n 'breakdown', scope, range.from, range.to, filter, groupBy, measure, interval ?? null, cap,\n ]);\n return cache.get(key, () =>\n timed('breakdown', { scope, filter, groupBy, measure, interval }, async (): Promise<BreakdownResult> => {\n const match = buildMatch(scope, range, filter);\n const dimId = Object.fromEntries(dims.map((expr, i) => [`d${i}`, expr]));\n // cap+1 so truncation is OBSERVED rather than inferred from an exact\n // match, the same read rollups() and distribution() do\n const top = await ctx.TelemetryModel.aggregate([\n { $match: match },\n { $group: { _id: dimId, value: measureAccumulator(measure) } },\n { $sort: { value: -1, _id: 1 } },\n { $limit: cap + 1 },\n ] as any[]);\n const truncated = top.length > cap;\n if (truncated) top.pop();\n const tuples: (string | null)[][] = top.map((g: any) =>\n groupBy.map((_, i) => g._id?.[`d${i}`] ?? null),\n );\n if (!interval) {\n return {\n rows: top.map((g: any, i: number) => ({ dims: tuples[i]!, value: g.value })),\n groups: top.length,\n truncated,\n bucketsTruncated: false,\n dataSource: 'raw' as const,\n };\n }\n if (!tuples.length) {\n return { rows: [], groups: 0, truncated, bucketsTruncated: false, dataSource: 'raw' as const };\n }\n const inTop = {\n $or: tuples.map((t) => ({ $and: dims.map((expr, i) => ({ $eq: [expr, t[i] ?? null] })) })),\n };\n // this pass has a ceiling of its own — buckets × groups — and it used\n // to be the one cap in the file that could cut an answer without\n // saying so. Read as cap+1, like every other one, and reported as\n // `bucketsTruncated`.\n const bucketCap = limits.series * top.length;\n const perBucket = await ctx.TelemetryModel.aggregate([\n { $match: { ...match, $expr: inTop } },\n { $group: { _id: { at: truncTo('$occurredAt', interval), ...dimId }, value: measureAccumulator(measure) } },\n // `at` is the first key of `_id`, so one BSON sort orders by bucket\n // then by dims — deterministic without a second sort key\n { $sort: { _id: 1 } },\n { $limit: bucketCap + 1 },\n ] as any[]);\n const bucketsTruncated = perBucket.length > bucketCap;\n if (bucketsTruncated) perBucket.pop();\n return {\n rows: perBucket.map((b: any) => ({\n dims: groupBy.map((_, i) => b._id?.[`d${i}`] ?? null) as (string | null)[],\n at: b._id.at as Date,\n value: b.value,\n })),\n groups: top.length,\n truncated,\n bucketsTruncated,\n dataSource: 'raw' as const,\n };\n }),\n );\n },\n\n /**\n * Percentiles + histogram off raw. Keep-all makes the SAMPLE complete —\n * no sampling stands between the match and the math (§5.3) — but the\n * computation is not exact and this comment used to claim it was:\n * `$percentile` runs `method: 'approximate'` (t-digest), and the scan stops\n * at `limits.distribution`.\n *\n * So the ceiling is read as cap+1 and `truncated` reports whether it was\n * actually reached, the same way rollups/distinctCount/funnel do. A match\n * wider than the ceiling is an undercount, and an undercount the response\n * does not mention is the silent cap this package refuses everywhere else.\n * Mongo 7+.\n */\n distribution(\n scope: string,\n range: TimeRange,\n filter: RecordFilter,\n opts: { measure?: string } = {},\n ) {\n const measure = opts.measure ?? 'durationMs';\n const path = measure === 'durationMs' ? '$durationMs' : `$metrics.${measure.replace(/^metric:/, '')}`;\n const key = JSON.stringify(['distribution', scope, range.from, range.to, filter, measure]);\n return cache.get(key, () =>\n timed('distribution', { scope, filter, measure }, async () => {\n const match = {\n ...buildMatch(scope, range, filter),\n [path.slice(1)]: { $exists: true },\n };\n // one scan ceiling, shared by both pipelines — and cap+1 so the\n // response can SAY it was truncated instead of quietly undercounting\n const cap = limits.distribution;\n const [summary] = await ctx.TelemetryModel.aggregate([\n { $match: match },\n { $limit: cap + 1 },\n {\n $group: {\n _id: null,\n p: { $percentile: { input: path, p: [0.5, 0.9, 0.95, 0.99], method: 'approximate' } },\n min: { $min: path },\n max: { $max: path },\n avg: { $avg: path },\n n: { $sum: 1 },\n },\n },\n ] as any[]);\n // `truncated` is always present, empty match included — a caller that\n // has to check whether the key exists before trusting it is back to\n // inferring the cap\n if (!summary) return { n: 0, truncated: false, dataSource: 'raw' as const };\n const [p50, p90, p95, p99] = summary.p;\n const histogram = await ctx.TelemetryModel.aggregate([\n { $match: match },\n { $limit: cap + 1 },\n { $bucketAuto: { groupBy: path, buckets: 20 } },\n ] as any[]);\n return {\n p50, p90, p95, p99,\n min: summary.min, max: summary.max, avg: summary.avg, n: summary.n,\n histogram: histogram.map((h: any) => ({ min: h._id.min, max: h._id.max, n: h.count })),\n truncated: summary.n > cap,\n dataSource: 'raw' as const,\n };\n }),\n );\n },\n\n /** rollup family reads — issues, spend, activity, milestones, funnels */\n rollups(\n scope: string,\n params: {\n as: string;\n /**\n * One dimension value, or several as an `$in`. The array form exists\n * because building an index for N subjects otherwise costs N queries or\n * an unfiltered family scan that the cap truncates — plausible, wrong,\n * and silent (cohort-math G3).\n */\n dims?: string | string[];\n subjectType?: string;\n /** the field `range` filters. Default: bucketAt when bucketed, lastAt otherwise. */\n on?: 'firstAt' | 'lastAt' | 'bucketAt';\n /**\n * Half-open (`$gte`/`$lt`), always. Applied to `on`.\n *\n * The default is today's behaviour and deliberately unchanged, but\n * `lastAt` is the MOST RECENT occurrence — cohort selection wants\n * `firstAt`, and on a once-per-subject milestone the two are equal only\n * until something re-emits it (cohort-math G1). `on: 'firstAt'` makes\n * that choice explicit rather than lucky; there is already an index for\n * it ({tenantId, as, subjectType, firstAt}).\n */\n range?: TimeRange;\n sort?: 'count' | 'lastAt' | 'firstAt' | 'bucketAt';\n limit?: number;\n },\n ) {\n const key = JSON.stringify(['rollups', scope, params]);\n return cache.get(key, () =>\n timed('rollups', { scope, params }, async () => {\n // family shape is pinned by validateRegistry, so the first declaration speaks for all\n let bucketed = false;\n outer: for (const [name, s] of Object.entries(ctx.registry)) {\n for (const r of s.rollups ?? []) {\n if ((r.as ?? name) === params.as) {\n bucketed = !!r.bucket;\n break outer;\n }\n }\n }\n // rollup rows carry their own tenantId, so a '*' read stays attributable\n const match: Record<string, any> = {\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n as: params.as,\n };\n if (params.dims) {\n match.dims = Array.isArray(params.dims) ? { $in: params.dims } : params.dims;\n }\n if (params.subjectType) match.subjectType = params.subjectType;\n if (params.range) {\n const on = params.on ?? (bucketed ? 'bucketAt' : 'lastAt');\n match[on] = { $gte: params.range.from, $lt: params.range.to };\n }\n const sortKey = params.sort ?? (bucketed ? 'bucketAt' : 'count');\n const limit = Math.min(Math.max(1, params.limit ?? limits.rollups), limits.rollups);\n // limit+1 so truncation is observed, not inferred from an exact match\n const rows = await ctx.RollupModel.find(match)\n .sort({ [sortKey]: sortKey === 'firstAt' || sortKey === 'bucketAt' ? 1 : -1 })\n .limit(limit + 1)\n .lean();\n const truncated = rows.length > limit;\n if (truncated) rows.pop();\n return { rows, bucketed, truncated, dataSource: 'rollups' as const };\n }),\n );\n },\n\n /** one trace, every kind, one time axis — the first join view */\n trace(scope: string, traceId: string) {\n return timed('trace', { scope, traceId }, async () => {\n const items = await ctx.TelemetryModel.find({\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n traceId,\n })\n .sort({ occurredAt: 1 })\n .limit(limits.trace)\n .lean();\n return { items, dataSource: 'raw' as const };\n });\n },\n\n /** one subject's whole story — records interleaved, milestones as markers */\n journey(scope: string, subjectRef: string, range: TimeRange, opts: { limit?: number } = {}) {\n return timed('journey', { scope, subjectRef }, async () => {\n const limit = Math.min(Math.max(1, opts.limit ?? limits.journey), limits.journey);\n // a subject ref is only unique WITHIN a tenant, so a '*' journey can\n // legitimately braid two tenants' 'user:u_1' together — every row and\n // milestone carries its tenantId, which is what keeps that readable\n const pin = isPlatformScope(scope) ? {} : { tenantId: scope };\n const [records, milestones] = await Promise.all([\n ctx.TelemetryModel.find({\n ...pin,\n subjectKeys: subjectRef,\n occurredAt: { $gte: range.from, $lt: range.to },\n })\n .sort({ occurredAt: -1 })\n .limit(limit)\n .lean(),\n // lifetime families only — bucketed activity rows would drown the markers\n ctx.RollupModel.find({ ...pin, dims: subjectRef, bucketAt: { $exists: false } })\n .sort({ firstAt: 1 })\n .limit(100)\n .lean(),\n ]);\n return { records, milestones, dataSource: 'raw+rollups' as const };\n });\n },\n\n /**\n * Distinct subjects per bucket, and over the whole range — DAU/MAU/WAU,\n * EXACTLY, with no sketch and no write-path change.\n *\n * The trick is that there is no trick. A family declared `by: ['subject']`\n * with a bucket already writes exactly ONE doc per (subject, bucket), which\n * is what the deterministic `_id` guarantees. So distinct-subjects-in-bucket\n * IS the doc count, and distinct-over-a-range is one `$group` on `dims`. An\n * HLL sketch would buy approximation we do not need and storage we would\n * have to maintain.\n *\n * `interval` may be COARSER than the family's own bucket (daily rows →\n * monthly MAU) — re-truncating bucket starts cannot split a bucket across\n * two periods, so the roll-up stays exact. Asking for finer than the family\n * writes cannot invent detail: it returns the family's own grain.\n */\n distinctCount(\n scope: string,\n params: {\n as: string;\n subjectType?: string;\n range: TimeRange;\n interval?: 'hour' | 'day' | 'week' | 'month';\n },\n ) {\n // A family with no subject dim or no bucket cannot answer this, and the\n // failure mode is a confident wrong number rather than an empty result —\n // so it throws, loudly, naming the family and the fix.\n const spec = requireDistinctFamily(ctx.registry, params.as);\n const interval = params.interval ?? spec.bucket!;\n const key = JSON.stringify(['distinctCount', scope, params]);\n return cache.get(key, () =>\n timed('distinctCount', { scope, params }, async () => {\n const match: Record<string, any> = {\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n as: params.as,\n bucketAt: { $gte: params.range.from, $lt: params.range.to },\n };\n if (params.subjectType) match.subjectType = params.subjectType;\n const cap = limits.distinct;\n const [out] = await ctx.RollupModel.aggregate([\n { $match: match },\n // one scan ceiling, shared by both branches — and cap+1 so the\n // response can SAY it was truncated instead of quietly undercounting\n { $limit: cap + 1 },\n {\n $facet: {\n buckets: [\n {\n $group: {\n _id: {\n at: { $dateTrunc: { date: '$bucketAt', unit: interval, ...(interval === 'week' ? { startOfWeek: 'monday' } : {}) } },\n dims: '$dims',\n },\n },\n },\n { $group: { _id: '$_id.at', value: { $sum: 1 } } },\n { $sort: { _id: 1 } },\n { $limit: limits.series },\n ],\n distinct: [{ $group: { _id: '$dims' } }, { $count: 'n' }],\n scanned: [{ $count: 'n' }],\n },\n },\n ] as any[]);\n const scanned = out?.scanned?.[0]?.n ?? 0;\n return {\n buckets: (out?.buckets ?? []).map((b: any) => ({ at: b._id, value: b.value })),\n /** distinct subjects across the WHOLE range — never the sum of the buckets */\n distinct: out?.distinct?.[0]?.n ?? 0,\n interval,\n truncated: scanned > cap,\n dataSource: 'rollups' as const,\n };\n }),\n );\n },\n\n /**\n * Cohort funnel over lifetime milestone families — stage counts, conversion,\n * and median time-to-step. See funnel.ts; the math lives there so it can be\n * unit-pinned without a database.\n */\n funnel(scope: string, params: FunnelParams): Promise<FunnelResult> {\n return timed('funnel', { scope, params }, () =>\n runFunnel(\n {\n RollupModel: ctx.RollupModel,\n registry: ctx.registry,\n cohortCap: limits.funnel,\n scopeMatch: (s) => (isPlatformScope(s) ? {} : { tenantId: s }),\n },\n scope,\n params,\n ),\n );\n },\n };\n}\n\n/**\n * distinctCount's precondition. The exactness argument rests entirely on the\n * family writing one doc per (subject, bucket), so each way of breaking that\n * gets its own message with its own fix — a registry mistake here would\n * otherwise surface as a number that looks like DAU and is not.\n */\nfunction requireDistinctFamily(registry: Registry, as: string): RollupSpec {\n const found = findFamily(registry, as);\n if (!found) {\n throw new Error(\n `telemetry: distinctCount() — no rollup family \"${as}\" is declared. Add ` +\n `\\`rollups: [{ as: '${as}', by: ['subject'], subjects: [...], bucket: 'day' }]\\` to the events that count as activity.`,\n );\n }\n const { name, spec } = found;\n const by = `by: [${spec.by.map((d) => `'${d}'`).join(', ')}]`;\n if (!spec.bucket) {\n throw new Error(\n `telemetry: distinctCount() — rollup family \"${as}\" (declared on \"${name}\") has no \\`bucket\\`. ` +\n `Distinct-per-period needs one doc per (subject, period); a lifetime family has one doc per subject ` +\n `forever, so every period would report the same number. Add \\`bucket: 'day'\\`, or ask this with rollups().`,\n );\n }\n if (!spec.by.includes('subject')) {\n throw new Error(\n `telemetry: distinctCount() — rollup family \"${as}\" (declared on \"${name}\") is keyed ${by} with no ` +\n `\\`subject\\` dim, so its docs count OCCURRENCES, not subjects. Add 'subject' to \\`by\\` (with \\`subjects: [...]\\`).`,\n );\n }\n if (spec.by.length !== 1) {\n throw new Error(\n `telemetry: distinctCount() — rollup family \"${as}\" (declared on \"${name}\") is keyed ${by}. Extra dims ` +\n `split one subject across several docs per period, so the count would exceed the true distinct total. ` +\n `Declare a second family with \\`by: ['subject']\\` for the distinct question.`,\n );\n }\n return spec;\n}\n\nexport type Queries = ReturnType<typeof createQueries>;\n","import type { Model } from 'mongoose';\nimport { isPlatformScope } from './types.js';\nimport type { Catalog, DimFacet } from './catalog.js';\nimport {\n DEFAULT_LIMITS, QueryCache, buildMatch, dimExpression,\n type QueryLimits, type TimeRange,\n} from './query.js';\n\n/**\n * `/values` — the observed domain of one dimension (reports §5).\n *\n * \"What values does this dimension actually take?\" is the question standing\n * between a report builder and every filter it offers. The answer has four\n * possible sources and they are tried cheapest first, with the response SAYING\n * which one answered — a picker built on a guess is a filter that silently\n * matches nothing:\n *\n * 1. `catalog` — the registry already declared a closed domain (a `z.enum`,\n * an envelope enum). Verbatim, in schema order, and NO read at all.\n * 2. `rollups` — some family is keyed by this dim, so every value that ever\n * hit an aggregate is one indexed `$group` away, with its count.\n * 3. `raw` — an indexed attr (or an envelope/pseudo dim) over a range.\n * 4. `none` — nothing can answer it. The UI offers free-text equality with\n * a *scan* badge, exactly as the FilterBar already does.\n *\n * This is NOT a tenth primitive. It is a lookup the report builder makes before\n * it names a value, which is why it lives beside the primitives rather than\n * inside `createQueries` — it reads the catalog, and the primitives deliberately\n * do not.\n *\n * The `none` path never throws, including when the raw step is the only\n * eligible one and no range was given. A caller that has to catch an exception\n * to learn \"you'll have to type it\" is a caller that will render an error page\n * over a working text box.\n */\n\nexport interface ValuesParams {\n /**\n * A `DimFacet.key`: `attr:model` | `field:client.platform` | `subjectType` |\n * `actorType`. The literal `'subject'` is also accepted, and is the only way\n * to ask a family for its subject refs — it is a rollup `by` source rather\n * than a catalog dim, so it can only ever be answered by step 2.\n */\n dim: string;\n /**\n * Restrict to these event names — a Report's source events. REQUIRED in\n * practice for the raw step (it decides whether the attr is indexed), and a\n * narrowing hint for the other two.\n */\n names?: string[];\n /** required by the raw step; ignored by the others */\n range?: TimeRange;\n /** values cap, default `limits.values` (200), clamped to it */\n limit?: number;\n}\n\nexport interface ValuesResult {\n /** catalog order for a declared enum, else by count desc then value asc */\n values: string[];\n /** parallel to `values` when the source can count — absent for 'catalog' */\n counts?: number[];\n source: 'catalog' | 'rollups' | 'raw' | 'none';\n /** the family that was read, when `source === 'rollups'` */\n via?: string;\n /** more values existed than the cap; the ones kept are the top by count */\n truncated: boolean;\n /** mirrors `source`, so a values response reads like every other one (recon #2) */\n dataSource: 'catalog' | 'rollups' | 'raw' | 'none';\n}\n\nexport interface ValuesCtx {\n catalog: Catalog;\n TelemetryModel: Model<any>;\n RollupModel: Model<any>;\n limits?: Partial<QueryLimits>;\n /** called with { op, ms, params } when a read exceeds slowMs (default 500) */\n onSlowQuery?: (info: { op: string; ms: number; params: unknown }) => void;\n slowMs?: number;\n cacheTtlMs?: number;\n cacheSize?: number;\n}\n\nconst empty = (source: ValuesResult['source']): ValuesResult => ({\n values: [], source, truncated: false, dataSource: source,\n});\n\n/** count the way series/breakdown do: 1/sampleRate, so a dropped rate still extrapolates */\nconst SAMPLED_COUNT = { $sum: { $divide: [1, { $ifNull: ['$sampleRate', 1] }] } };\n\nexport function createValues(ctx: ValuesCtx) {\n const limits = { ...DEFAULT_LIMITS, ...ctx.limits };\n const slowMs = ctx.slowMs ?? 500;\n const cache = new QueryCache(ctx.cacheTtlMs ?? 10 * 60_000, ctx.cacheSize ?? 60);\n const { catalog } = ctx;\n\n const timed = async <T>(op: string, params: unknown, run: () => Promise<T>): Promise<T> => {\n const t0 = Date.now();\n try {\n return await run();\n } finally {\n const ms = Date.now() - t0;\n if (ms > slowMs) ctx.onSlowQuery?.({ op, ms, params });\n }\n };\n\n /** the event facets a `names` restriction selects, in the order given; all of them otherwise */\n const eventNames = (names?: string[]): string[] =>\n names?.length ? names.filter((n) => catalog.events[n]) : Object.keys(catalog.events);\n\n /**\n * Step 1. Every DimFacet under this key that carries a closed domain, unioned\n * in first-seen order. Two events declaring different enums for one attr is\n * not a conflict — it is two closed domains, and their union is the set a\n * filter over both could ever match.\n */\n function fromCatalog(dim: string, names?: string[]): string[] {\n const facets: DimFacet[] = [];\n for (const d of catalog.envelope) if (d.key === dim) facets.push(d);\n for (const name of eventNames(names)) {\n for (const d of catalog.events[name]!.dims) if (d.key === dim) facets.push(d);\n }\n const out: string[] = [];\n for (const f of facets) for (const v of f.values ?? []) if (!out.includes(v)) out.push(v);\n return out;\n }\n\n /**\n * Step 2. The family whose `by` names this dim, fewest dims first — fewer\n * dims is fewer docs for the same domain, and the `by` comparison is literal\n * because a DimFacet.key IS a DimSource (catalog §3). `subjectType` and\n * `actorType` have no `by` equivalent — a family keyed by a subject writes\n * `'subject'`, whose values are refs, not types — so they fall through.\n */\n function pickFamily(dim: string, names?: string[]): { as: string; index: number; label: string } | null {\n if (dim === 'subjectType' || dim === 'actorType') return null;\n const matches = Object.values(catalog.families)\n .map((f) => ({ f, index: f.by.indexOf(dim as any) }))\n .filter(({ f, index }) =>\n index !== -1 && (!names?.length || f.feeders.some((n) => names.includes(n))))\n .sort((a, b) => a.f.by.length - b.f.by.length || a.f.as.localeCompare(b.f.as));\n const best = matches[0];\n return best ? { as: best.f.as, index: best.index, label: best.f.labels[best.index]! } : null;\n }\n\n /**\n * Step 3's precondition. `dimExpression` owns the vocabulary — a dim is\n * raw-readable exactly when the primitive that would group on it accepts it,\n * so there is no second allowlist to drift. On top of that an ATTR must be\n * genuinely indexed on one of the events in play: a `$group` over an\n * unindexed attr is the collection scan this package refuses to sell as a\n * lookup, and `none` (free text + a scan badge) is the honest answer.\n */\n function rawReadable(dim: string, names?: string[]): boolean {\n try {\n dimExpression(dim);\n } catch {\n return false;\n }\n if (!dim.startsWith('attr:')) return true;\n const key = dim.slice(5);\n return eventNames(names).some((n) => catalog.events[n]!.indexedAttrs.includes(key));\n }\n\n return async function values(scope: string, params: ValuesParams): Promise<ValuesResult> {\n const { dim, names, range } = params;\n if (!dim) return empty('none');\n const cap = Math.min(Math.max(1, params.limit ?? limits.values), limits.values);\n const key = JSON.stringify([\n 'values', scope, dim, names ?? null, range?.from ?? null, range?.to ?? null, cap,\n ]);\n\n return cache.get(key, () =>\n timed('values', { scope, dim, names }, async (): Promise<ValuesResult> => {\n // ── 1. the registry already said so ──\n const declared = fromCatalog(dim, names);\n if (declared.length) {\n return { values: declared, source: 'catalog', truncated: false, dataSource: 'catalog' };\n }\n\n // ── 2. what the aggregates have seen ──\n const family = pickFamily(dim, names);\n if (family) {\n // {tenantId, as, dims, bucketAt} answers the match on its prefix; the\n // $limit sits after the $group, so the cap bounds the ANSWER and the\n // scan stays bounded by the family\n const rows = await ctx.RollupModel.aggregate([\n {\n $match: {\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n as: family.as,\n },\n },\n { $project: { v: { $arrayElemAt: ['$dims', family.index] }, count: 1 } },\n { $match: { v: { $type: 'string' } } },\n { $group: { _id: '$v', count: { $sum: '$count' } } },\n { $sort: { count: -1, _id: 1 } },\n { $limit: cap + 1 },\n ] as any[]);\n const truncated = rows.length > cap;\n if (truncated) rows.pop();\n // rollups.ts writes `${label}=${value}` for every dim but the subject\n // one, which keeps its native `type:id` so erasure can match it — so\n // the prefix is stripped where it is actually present, never assumed\n const prefix = `${family.label}=`;\n return {\n values: rows.map((r: any) =>\n String(r._id).startsWith(prefix) ? String(r._id).slice(prefix.length) : String(r._id),\n ),\n counts: rows.map((r: any) => r.count),\n source: 'rollups',\n via: family.as,\n truncated,\n dataSource: 'rollups',\n };\n }\n\n // ── 3. the rows themselves, when an index answers them ──\n if (!rawReadable(dim, names)) return empty('none');\n // A missing range is not an error: the caller asked what it could offer\n // and the answer is \"nothing cheap\" — free text with a scan badge.\n if (!range) return empty('none');\n\n // `RecordFilter.name` takes the set directly, so the source events are\n // one indexed `$in` on {tenantId, kind, name, occurredAt} rather than a\n // restriction bolted onto the match afterwards\n const rows = await ctx.TelemetryModel.aggregate([\n { $match: buildMatch(scope, range, names?.length ? { name: names } : {}) },\n { $group: { _id: dimExpression(dim), count: SAMPLED_COUNT } },\n // a \"no value\" is not a value to pick — the null group is real\n // (breakdown reports it) but it is not something a filter can name\n { $match: { _id: { $ne: null } } },\n { $sort: { count: -1, _id: 1 } },\n { $limit: cap + 1 },\n ] as any[]);\n const truncated = rows.length > cap;\n if (truncated) rows.pop();\n return {\n values: rows.map((r: any) => String(r._id)),\n counts: rows.map((r: any) => r.count),\n source: 'raw',\n truncated,\n dataSource: 'raw',\n };\n }),\n );\n };\n}\n\nexport type Values = ReturnType<typeof createValues>;\n","import type { Catalog, DimFacet, FamilyFacet } from './catalog.js';\nimport type { Interval, QueryLimits, RecordFilter, TimeRange } from './query.js';\nimport type { TelemetryKind } from './types.js';\nimport type { ViewSpec } from './views.js';\n\n/**\n * The Report and its resolver (reports §4, §6). A Report is the one shape a\n * page renders, the explore UI builds, a saved view stores, a URL hash carries\n * and `run_report` executes. `resolveReport` is the pure function that turns\n * one into a Plan: the cheapest primitive that answers it EXACTLY, a raw plan\n * when nothing can, and a refusal with a reason when nothing at all can.\n *\n * Pure, like deriveCatalog and summarizeStages — no Mongo, no I/O, and\n * deterministic given `now`, so it is pinned by unit tests rather than by a\n * seeded database (reports §11.6). Nothing here executes anything — that is\n * execute.ts, which is the only file that needs a database to do its job.\n *\n * `Plan.args` is POSITIONAL and spreads straight into the named primitive:\n *\n * const plan = resolveReport(report, catalog);\n * if ('primitive' in plan) await q[plan.primitive](scope, ...plan.args);\n *\n * That is the entire contract between this file and query.ts, and it is why\n * nothing here imports a primitive — the resolver names one and hands over its\n * arguments, so adding a primitive costs a rule and no plumbing.\n */\n\n// ── the Report ──────────────────────────────────────────────────────────────\n\nexport type ReportSource =\n /** one registered name */\n | { event: string }\n /** every event under `library.*` */\n | { namespace: string }\n | { kind: TelemetryKind }\n /** read a rollup family directly */\n | { family: string };\n\n/** a shorthand from the UI's RANGES ('7d'), or an explicit half-open ISO pair */\nexport type ReportRange = string | { from: string; to: string };\n\nexport interface ReportFilter {\n /** a DimFacet.key: 'attr:model' | 'field:env' | 'subjectType' | 'field:name' … */\n dim: string;\n op: 'eq' | 'in' | 'gte' | 'lte';\n value: string | string[] | number;\n}\n\nexport interface Report {\n source: ReportSource;\n range: ReportRange;\n interval?: Interval;\n /** a MeasureFacet.key. Default 'count'; also 'distinct:<subjectType>' and 'funnel' */\n measure?: string;\n /** DimFacet.key[], at most two — three dims is a pivot nobody can read */\n groupBy?: string[];\n filters?: ReportFilter[];\n excludeActorTypes?: string[];\n /** a rendering hint carried with the Report; no primitive takes it today */\n sort?: 'value' | 'label' | 'time';\n limit?: number;\n /** same length, immediately before */\n compare?: 'previous';\n\n // ── funnel-only (`measure: 'funnel'`) ──\n /** lifetime `by: ['subject']` family names, in order */\n stages?: string[];\n anchor?: string;\n exits?: string[];\n subjectType?: string;\n}\n\n/**\n * The pre-Report `ViewSpec.query`. Every view saved before Reports existed is\n * this shape and must keep parsing, so it stays in the union and\n * `normalizeQuery()` lifts it.\n *\n * @deprecated write a {@link Report}. The `display` key this shape used to\n * carry is REMOVED (reports §8): the renderer decides from the Report itself,\n * and a chart/table toggle would be a UI preference rather than view state. A\n * stored view that still carries the key keeps parsing — `spec` is a Mixed\n * document — and the key is ignored.\n */\nexport interface LegacyQuery {\n range?: string;\n filters?: Record<string, unknown>;\n groupBy?: string;\n sort?: string;\n}\n\n// ── the Plan ────────────────────────────────────────────────────────────────\n\nexport type PlanPrimitive =\n | 'records' | 'series' | 'breakdown' | 'distribution'\n | 'rollups' | 'distinctCount' | 'funnel';\n\n/**\n * How the executor folds a `rollups` plan. `rollups()` has no server-side\n * groupBy — it returns the family's own docs, and the requested dims ARE that\n * family's dims, so the grouping is a fold over rows rather than a second read.\n * `labels[i]` is the `dims` prefix rollups.ts writes for `groupBy[i]`; a subject\n * dim labels to 'subject' and its stored value is the bare `type:id` ref.\n */\nexport interface PlanShape {\n groupBy: string[];\n labels: string[];\n measure: string;\n interval?: Interval;\n /** filters the fold applies, because rollups() can only pin whole dims */\n filters?: { dim: string; label: string; op: ReportFilter['op']; value: ReportFilter['value'] }[];\n}\n\nexport interface Plan {\n primitive: PlanPrimitive;\n /** positional args AFTER scope — the executor is literally `q[primitive](scope, ...args)` */\n args: unknown[];\n exactness: 'exact' | 'raw' | 'scan';\n /** the family that answers it, when one does */\n via?: string;\n /** human sentence — the UI badge and the MCP explanation */\n why: string;\n /** how to fold the rows a `rollups` plan returns */\n shape?: PlanShape;\n /** present when `compare: 'previous'` — same primitive, range shifted back by its own length */\n previous?: { args: unknown[] };\n}\n\nexport interface Unavailable {\n unavailable: true;\n why: string;\n}\n\n// ── ranges ──────────────────────────────────────────────────────────────────\n\n/** the UI's RANGES (util.js), which is the vocabulary a stored view speaks */\nconst RANGE_MS: Record<string, number> = {\n '1h': 36e5,\n '24h': 864e5,\n '7d': 7 * 864e5,\n '30d': 30 * 864e5,\n '90d': 90 * 864e5,\n};\n\nconst badRequest = (message: string) =>\n Object.assign(new Error(`telemetry: ${message}`), { status: 400 });\n\n/**\n * A ReportRange → the half-open pair every primitive takes. Shorthands end at\n * `now`, which is injectable so the resolver stays deterministic under test.\n *\n * An unrecognised shorthand THROWS rather than defaulting to 7d the way\n * util.js does: on the client a wrong default draws a chart, here it would\n * silently answer a different question than the one asked.\n */\nexport function rangeOf(range: ReportRange, now: Date = new Date()): TimeRange {\n if (typeof range === 'string') {\n const ms = RANGE_MS[range] ?? spanOf(range);\n if (ms == null) {\n throw badRequest(\n `range \"${range}\" is not a known shorthand — use one of ${Object.keys(RANGE_MS).join(', ')}, ` +\n 'an `<n>h`/`<n>d` form, or an explicit { from, to } ISO pair',\n );\n }\n return { from: new Date(now.getTime() - ms), to: now };\n }\n const from = new Date(range.from);\n const to = new Date(range.to);\n if (Number.isNaN(from.getTime()) || Number.isNaN(to.getTime()) || from >= to) {\n throw badRequest(\n `range { from: \"${range.from}\", to: \"${range.to}\" } is not valid — \\`from\\` must be a valid ` +\n 'ISO time strictly before `to` (the package is half-open everywhere)',\n );\n }\n return { from, to };\n}\n\n/** '14d' / '6h' — the generic form mcp.ts already accepts off a stored view */\nfunction spanOf(range: string): number | null {\n const m = /^(\\d+)([hd])$/.exec(range);\n if (!m) return null;\n return Number(m[1]) * (m[2] === 'h' ? 36e5 : 864e5);\n}\n\n/**\n * The interval that keeps a range under ~120 buckets — util.js `intervalFor`,\n * extended to explicit pairs by their span so a Report built from a date picker\n * lands on the same grain as one built from the range chips.\n */\nexport function intervalForRange(range: ReportRange, now: Date = new Date()): Interval {\n if (typeof range === 'string' && RANGE_MS[range] != null) {\n return range === '1h' || range === '24h' ? 'hour' : range === '90d' ? 'week' : 'day';\n }\n const { from, to } = rangeOf(range, now);\n const ms = to.getTime() - from.getTime();\n if (ms <= 864e5) return 'hour';\n if (ms < 90 * 864e5) return 'day';\n return 'week';\n}\n\n/** hour < day < week < month — a family may be FINER than the interval asked for, never coarser */\nconst INTERVAL_RANK: Record<Interval, number> = { hour: 0, day: 1, week: 2, month: 3 };\n\n/** the previous window of the same length, immediately before: [from - (to - from), from) */\nconst shift = (range: TimeRange): TimeRange => ({\n from: new Date(range.from.getTime() - (range.to.getTime() - range.from.getTime())),\n to: range.from,\n});\n\n// ── source expansion ────────────────────────────────────────────────────────\n\ninterface ResolvedSource {\n form: 'event' | 'namespace' | 'kind' | 'family';\n /** the event names this source expands to, registry order */\n events: string[];\n /** set only by `{ kind }`, where the kind term IS the source and is therefore complete */\n kind?: TelemetryKind;\n family?: FamilyFacet;\n}\n\nfunction expandSource(source: ReportSource, catalog: Catalog): ResolvedSource | Unavailable {\n if ('event' in source) {\n if (!catalog.events[source.event]) {\n return unavailable(\n `no event named \"${source.event}\" is registered — the catalog knows ${count(Object.keys(catalog.events).length, 'event')}, ` +\n 'so either the name is a typo or the registry never declared it',\n );\n }\n return { form: 'event', events: [source.event] };\n }\n if ('namespace' in source) {\n const events = catalog.namespaces[source.namespace];\n if (!events?.length) {\n return unavailable(\n `no event name starts with \"${source.namespace}.\" — the registered namespaces are ` +\n `${Object.keys(catalog.namespaces).join(', ')}`,\n );\n }\n return { form: 'namespace', events: [...events] };\n }\n if ('kind' in source) {\n const events = Object.keys(catalog.events).filter((n) => catalog.events[n]!.kind === source.kind);\n if (!events.length) {\n return unavailable(\n `no event is registered with kind \"${source.kind}\" — declare one, or pick a kind the registry uses`,\n );\n }\n return { form: 'kind', events, kind: source.kind };\n }\n const family = catalog.families[source.family];\n if (!family) {\n return unavailable(\n `no rollup family \"${source.family}\" is declared — add a \\`rollups: [{ as: '${source.family}', by: [...] }]\\` ` +\n 'block to the event that should feed it',\n );\n }\n return { form: 'family', events: [...family.feeders], family };\n}\n\n// ── dimensions ──────────────────────────────────────────────────────────────\n\n/**\n * Filter-only pseudo dims: they are RecordFilter keys with real indexes behind\n * them, but they are not groupable and so they are not in the catalog. A saved\n * view's `filters.subject` lifts to one of these.\n */\nconst FILTER_ONLY: Record<string, keyof RecordFilter> = {\n 'field:subject': 'subject',\n 'field:traceId': 'traceId',\n};\n\n/**\n * Every dim this source can offer: the envelope, plus each event's own attrs\n * and kind fields. A key several events declare is `indexed` only when ALL of\n * them index it — one unindexed feeder makes the whole read a scan, and\n * claiming otherwise sells a scan as a lookup (reports §11.3).\n */\nfunction dimsFor(catalog: Catalog, events: string[]): Map<string, DimFacet> {\n const out = new Map<string, DimFacet>();\n for (const d of catalog.envelope) out.set(d.key, d);\n for (const name of events) {\n for (const d of catalog.events[name]?.dims ?? []) {\n const seen = out.get(d.key);\n out.set(d.key, seen ? { ...seen, indexed: seen.indexed && d.indexed } : d);\n }\n }\n return out;\n}\n\n/** the measure keys this source declares — 'count', 'sum:cost_usd', 'p95:durationMs' … */\nconst measureDeclared = (catalog: Catalog, events: string[], key: string): boolean =>\n key === 'count' || events.some((n) => catalog.events[n]?.measures.some((m) => m.key === key));\n\nconst MEASURE_OP = /^(sum|avg|p50|p90|p95|p99):(.+)$/;\n\n// ── the resolver ────────────────────────────────────────────────────────────\n\nconst unavailable = (why: string): Unavailable => ({ unavailable: true, why });\n\nconst count = (n: number, noun: string) => `${n} ${noun}${n === 1 ? '' : 's'}`;\n\nexport interface ResolveOptions {\n /** injected so a plan is deterministic — shorthand ranges end here */\n now?: Date;\n limits?: Partial<QueryLimits>;\n}\n\n/**\n * Report → Plan, first match wins (reports §6). The order is a preference\n * order: an exact rollup read beats a raw scan, and a refusal beats a query\n * that 400s at the database.\n *\n * One deviation from the plan's table, because the table's rows overlap:\n * `records` is tried BEFORE `series`. A Report with no measure still has the\n * default measure 'count', so the series rule would match everything and the\n * records rule would be unreachable. Asking for a measure — `measure: 'count'`\n * explicitly — is what distinguishes \"chart this\" from \"show me the rows\".\n */\nexport function resolveReport(report: Report, catalog: Catalog, opts: ResolveOptions = {}): Plan | Unavailable {\n const now = opts.now ?? new Date();\n const limits = opts.limits ?? {};\n const src = expandSource(report.source, catalog);\n if ('unavailable' in src) return src;\n\n const measure = report.measure ?? 'count';\n const groupBy = report.groupBy ?? [];\n if (groupBy.length > 2) {\n return unavailable(\n `groupBy takes at most 2 dimensions, got ${groupBy.length} (${groupBy.join(', ')}) — three dims is a ` +\n 'pivot table nobody can read and a group count that multiplies',\n );\n }\n if (report.interval && INTERVAL_RANK[report.interval] == null) {\n return unavailable(`interval \"${report.interval}\" is not one of hour, day, week, month`);\n }\n\n // 1 — cohort funnels, over lifetime milestone families only\n if (measure === 'funnel') return planFunnel(report, catalog, now, limits);\n\n // 2 — distinct subjects per period, off a bucketed single-subject family\n if (measure.startsWith('distinct:')) return planDistinct(report, catalog, src, measure, now);\n\n const opMatch = MEASURE_OP.exec(measure);\n if (measure !== 'count' && !opMatch) {\n return unavailable(\n `measure \"${measure}\" is not a measure — use 'count', 'sum:<metric>', 'avg:<metric>', ` +\n \"'p50|p95|p99:<metric>', 'distinct:<subjectType>' or 'funnel'\",\n );\n }\n if (opMatch && !measureDeclared(catalog, src.events, measure)) {\n return unavailable(\n `\"${measure}\" names a metric no source event declares — add \\`${opMatch[2]}\\` to the \\`metrics\\` ` +\n `object of ${src.events.join(', ')}, or pick one of ${metricList(catalog, src.events)}`,\n );\n }\n\n // 3 — exact, via one indexed rollup read\n const exact = planRollups(report, catalog, src, measure, groupBy, now, limits);\n if (exact) return exact;\n\n // 4–7 — raw. One filter build, four dispatches.\n const filter = toRecordFilter(report, catalog, src);\n if ('unavailable' in filter) return filter;\n const range = rangeOf(report.range, now);\n const dims = dimsFor(catalog, src.events);\n const touched = [...groupBy, ...(report.filters ?? []).map((f) => f.dim)];\n const unindexed = touched.find((k) => !(dims.get(k)?.indexed ?? FILTER_ONLY[k] != null));\n // the source itself is always pinned by an indexed term now (a name, a name\n // set, or a kind), so the only thing left that can make a read a scan is a\n // dimension with no index behind it\n const scanWhy = unindexed\n ? ` — \"${unindexed}\" has no index behind it, so this is a collection scan bounded only by the range` +\n (unindexed.startsWith('attr:') ? `; add \"${unindexed.slice(5)}\" to \\`indexedAttrs\\` to make it a lookup` : '')\n : '';\n const exactness = unindexed != null ? 'scan' : 'raw';\n\n // 6 — percentiles come off the raw distribution, and only without a groupBy\n if (opMatch && opMatch[1] !== 'sum' && opMatch[1] !== 'avg') {\n if (groupBy.length) {\n return unavailable(\n `percentiles per group are not offered yet (reports §13) — \"${measure}\" with ` +\n `groupBy ${groupBy.join(', ')} would be one distribution() read per group. Drop the groupBy, ` +\n 'or filter to one group and ask again',\n );\n }\n return withCompare(report, {\n primitive: 'distribution',\n args: [range, filter, { measure: opMatch[2]! }],\n exactness,\n why:\n `${measure} is approximate by construction ($percentile t-digest over the matched records)` +\n `${scanWhy}`,\n });\n }\n\n // 4 — top groups by one or two dims\n if (groupBy.length) {\n const bad = groupBy.find((k) => !dims.has(k));\n if (bad) {\n return unavailable(\n `\"${bad}\" is not a dimension of ${describe(src)} — group by one of ${[...dims.keys()].join(', ')}`,\n );\n }\n return withCompare(report, {\n primitive: 'breakdown',\n args: [\n range,\n filter,\n {\n groupBy,\n measure,\n ...(report.interval ? { interval: report.interval } : {}),\n ...(report.limit ? { limit: capped(report.limit, limits.breakdown) } : {}),\n },\n ],\n exactness,\n why: `raw ${measure} by ${groupBy.join(' × ')} over the range${scanWhy}`,\n });\n }\n\n // 7 — no measure, no groupBy, no interval: the reader wants the rows\n if (!report.measure && !report.interval) {\n return withCompare(report, {\n primitive: 'records',\n args: [range, filter, report.limit ? { limit: capped(report.limit, limits.records) } : {}],\n exactness,\n why: `the matching records themselves, newest first${scanWhy}`,\n });\n }\n\n // 5 — one line over time\n const interval = report.interval ?? intervalForRange(report.range, now);\n return withCompare(report, {\n primitive: 'series',\n args: [range, filter, { measure, interval }],\n exactness,\n why: `raw ${measure} per ${interval} over the range${scanWhy}`,\n });\n}\n\nconst capped = (limit: number, cap: number | undefined) =>\n cap == null ? limit : Math.max(1, Math.min(limit, cap));\n\nconst describe = (src: ResolvedSource) =>\n src.form === 'family' ? `family \"${src.family!.as}\"` : src.events.join(', ');\n\nconst metricList = (catalog: Catalog, events: string[]) => {\n const keys = new Set<string>();\n for (const n of events) for (const m of catalog.events[n]?.measures ?? []) keys.add(m.key);\n return keys.size ? [...keys].join(', ') : 'nothing but count';\n};\n\n// ── rule 1: funnel ──────────────────────────────────────────────────────────\n\n/**\n * Every stage, the anchor and every exit must be a lifetime `by: ['subject']`\n * family. The predicate and the messages mirror funnel.ts `requireMilestoneFamily`\n * — that function takes a Registry and this file only ever sees a Catalog, so\n * the FamilyFacet carries the same three facts (`lifetime`, `by`, `feeders`)\n * and the refusals read the same. A resolver that refused for a different\n * reason than the primitive throws for would be worse than no check at all.\n */\nfunction planFunnel(\n report: Report,\n catalog: Catalog,\n now: Date,\n limits: Partial<QueryLimits>,\n): Plan | Unavailable {\n const stages = report.stages ?? [];\n if (!stages.length) {\n return unavailable(\n \"`measure: 'funnel'` needs `stages` — one or more lifetime `by: ['subject']` rollup family names, \" +\n 'in the order a subject reaches them',\n );\n }\n const anchor = report.anchor ?? stages[0]!;\n const exits = report.exits ?? [];\n for (const as of [...stages, anchor, ...exits]) {\n const refusal = milestoneRefusal(catalog, as);\n if (refusal) return unavailable(refusal);\n }\n\n // one funnel is one population: two stages restricted to different subject\n // types would report conversions between subjects that are not the same party\n const first = catalog.families[stages[0]!]!;\n for (const as of [...stages.slice(1), anchor]) {\n const f = catalog.families[as]!;\n if (!sameSet(f.subjectTypes, first.subjectTypes)) {\n return unavailable(\n `funnel stages must share one subject type: \"${stages[0]}\" is declared \\`subjects: [${first.subjectTypes.join(', ')}]\\` ` +\n `and \"${as}\" is \\`subjects: [${f.subjectTypes.join(', ')}]\\` — two populations cannot convert into each other`,\n );\n }\n }\n if (report.subjectType && !first.subjectTypes.includes(report.subjectType)) {\n return unavailable(\n `subjectType \"${report.subjectType}\" is not one of the stages' subjects (${first.subjectTypes.join(', ')}) — ` +\n 'the cohort would be empty',\n );\n }\n if (report.interval === 'hour') {\n return unavailable(\n 'funnel slices are day, week or month — an hourly cohort slice is not offered, because a cohort is ' +\n 'assembled from lifetime milestones with no hourly grain to slice on',\n );\n }\n\n const params: Record<string, unknown> = {\n stages: stages.map((as) => ({ as })),\n anchor,\n ...(exits.length ? { exits: exits.map((as) => ({ as })) } : {}),\n cohort: rangeOf(report.range, now),\n ...(report.subjectType ? { subjectType: report.subjectType } : {}),\n ...(report.interval ? { interval: report.interval } : {}),\n ...(report.limit ? { limit: capped(report.limit, limits.funnel) } : {}),\n };\n return withCompare(report, {\n primitive: 'funnel',\n args: [params],\n exactness: 'exact',\n via: anchor,\n why:\n `cohort funnel over ${count(stages.length, 'lifetime milestone family')}, anchored on \"${anchor}\" — ` +\n 'rollups only, no raw scan',\n });\n}\n\n/** the funnel.ts precondition, said against a FamilyFacet. null when the family qualifies. */\nfunction milestoneRefusal(catalog: Catalog, as: string): string | null {\n const f = catalog.families[as];\n if (!f) {\n return (\n `no rollup family \"${as}\" is declared. Add a \\`rollups: [{ as: '${as}', by: ['subject'], subjects: [...] }]\\` ` +\n 'block to the event that marks it'\n );\n }\n const shape = `by: [${f.by.map((d) => `'${d}'`).join(', ')}]${f.bucket ? `, bucket: '${f.bucket}'` : ''}`;\n if (!f.lifetime) {\n return (\n `rollup family \"${as}\" (declared on \"${f.feeders[0]}\") is BUCKETED (${shape}). A milestone needs a ` +\n 'lifetime family so `firstAt` is the one moment the subject reached it; a bucketed family has one doc ' +\n 'per period and would count the same subject repeatedly'\n );\n }\n if (f.by.length !== 1 || f.by[0] !== 'subject') {\n return (\n `rollup family \"${as}\" (declared on \"${f.feeders[0]}\") is keyed ${shape}, but a milestone must be keyed ` +\n \"by exactly one subject dim (`by: ['subject']`). Extra dims split one subject across several docs, \" +\n 'which would over-count every stage'\n );\n }\n return null;\n}\n\n// ── rule 2: distinct ────────────────────────────────────────────────────────\n\nfunction planDistinct(\n report: Report,\n catalog: Catalog,\n src: ResolvedSource,\n measure: string,\n now: Date,\n): Plan | Unavailable {\n const subjectType = measure.slice('distinct:'.length);\n if (!subjectType) {\n return unavailable(\n `\"${measure}\" needs a subject type — 'distinct:account', one of ${catalog.subjectTypes.join(', ')}`,\n );\n }\n if (!catalog.subjectTypes.includes(subjectType)) {\n return unavailable(\n `no event or rollup declares the subject type \"${subjectType}\" — the registry knows ` +\n `${catalog.subjectTypes.join(', ') || 'no subject types at all'}`,\n );\n }\n if (report.groupBy?.length) {\n return unavailable(\n `distinct counts take no groupBy: distinctCount() answers one series per family, and \"${report.groupBy.join(', ')}\" ` +\n \"would need a family keyed by those dims AND `by: ['subject']`, which cannot count subjects exactly\",\n );\n }\n\n // one doc per (subject, bucket) is the whole exactness argument — the same\n // predicate query.ts `requireDistinctFamily` enforces at read time\n const wanted = new Set(src.events);\n const fits = Object.values(catalog.families).filter(\n (f) =>\n f.bucket != null &&\n f.by.length === 1 &&\n f.by[0] === 'subject' &&\n f.subjectTypes.includes(subjectType) &&\n src.events.every((e) => f.feeders.includes(e)),\n );\n const family = fits.find((f) => sameSet(f.feeders, [...wanted])) ?? fits[0];\n if (!family) {\n return unavailable(\n `no bucketed \\`by: ['subject']\\` family covers ${src.events.join(', ')} for subject type \"${subjectType}\" — ` +\n `declare \\`rollups: [{ as: 'activity', by: ['subject'], subjects: ['${subjectType}'], bucket: 'day' }]\\` ` +\n 'on the events that count as activity',\n );\n }\n const superset = !sameSet(family.feeders, [...wanted]);\n return withCompare(report, {\n primitive: 'distinctCount',\n args: [\n {\n as: family.as,\n subjectType,\n range: rangeOf(report.range, now),\n ...(report.interval ? { interval: report.interval } : {}),\n },\n ],\n exactness: 'exact',\n via: family.as,\n why:\n `\"${family.as}\" writes exactly one doc per (subject, ${family.bucket}), so distinct subjects IS the doc ` +\n 'count — exact, no sketch' +\n (superset\n ? `. Its feeders (${family.feeders.join(', ')}) are a SUPERSET of the source (${src.events.join(', ')}), ` +\n 'so the count includes subjects who only did the others'\n : ''),\n });\n}\n\n// ── rule 3: exact via rollups ───────────────────────────────────────────────\n\n/** a family dim in groupBy/filter vocabulary — the subject dim is asked for as `subjectType` */\nconst famDims = (f: FamilyFacet) => f.by.map((b) => (b === 'subject' ? 'subjectType' : (b as string)));\n\n/**\n * The cheapest read in the package: a family whose docs ARE the answer. Every\n * condition below is a way the family could be a different question than the\n * one asked, and any one of them falling through to raw is correct — a raw plan\n * is slower, never wrong.\n *\n * Returns null (not Unavailable) when nothing matches, because \"no family\n * answers this exactly\" is not a refusal.\n */\nfunction planRollups(\n report: Report,\n catalog: Catalog,\n src: ResolvedSource,\n measure: string,\n groupBy: string[],\n now: Date,\n limits: Partial<QueryLimits>,\n): Plan | null {\n // an actor-type exclusion is a WRITE-time decision for a family (`actors`),\n // so a read-time one cannot be applied to rows already accumulated\n if (report.excludeActorTypes?.length) return null;\n\n const candidates = src.family\n ? [src.family]\n : Object.values(catalog.families).filter((f) => sameSet(f.feeders, src.events));\n\n const op = MEASURE_OP.exec(measure);\n const filters = report.filters ?? [];\n const fits = candidates.filter((f) => {\n const dims = famDims(f);\n if (!groupBy.every((k) => dims.includes(k))) return false;\n if (report.interval && (!f.bucket || INTERVAL_RANK[f.bucket] > INTERVAL_RANK[report.interval])) return false;\n if (op) {\n // `sum` is stored; `avg` is sums[k]/count, which is exact off the same doc\n if ((op[1] !== 'sum' && op[1] !== 'avg') || !f.sums.includes(op[2]!)) return false;\n }\n // a rollup `dims` entry is a STRING ('region=eu'), so a family dim answers\n // equality and set membership and nothing else — a numeric bound belongs to\n // the raw path, where it can read `metrics.<k>`\n return filters.every(\n (t) => (dims.includes(t.dim) && (t.op === 'eq' || t.op === 'in')) || nameFilterCovers(t, f),\n );\n });\n // fewest dims wins: the cheapest read and the tightest match, since a wider\n // family would have to be folded down to the same groups anyway\n const family = fits.sort((a, b) => a.by.length - b.by.length)[0];\n if (!family) return null;\n\n const dims = famDims(family);\n const range = rangeOf(report.range, now);\n const on = family.lifetime ? 'firstAt' : 'bucketAt';\n // a `field:name` term is already answered by the family's feeders; the rest\n // are dim equalities the executor applies while folding the rows\n const fold = filters.filter((t) => dims.includes(t.dim));\n return withCompare(report, {\n primitive: 'rollups',\n args: [\n {\n as: family.as,\n on,\n range,\n sort: family.lifetime ? 'count' : 'bucketAt',\n ...(report.limit ? { limit: capped(report.limit, limits.rollups) } : {}),\n },\n ],\n exactness: 'exact',\n via: family.as,\n shape: {\n groupBy,\n labels: groupBy.map((k) => family.labels[dims.indexOf(k)]!),\n measure,\n ...(report.interval ? { interval: report.interval } : {}),\n ...(fold.length\n ? { filters: fold.map((t) => ({ ...t, label: family.labels[dims.indexOf(t.dim)]! })) }\n : {}),\n },\n why:\n `family \"${family.as}\" is keyed by ${dims.join(', ') || 'nothing but its feeders'} and maintained on write, ` +\n `so this is one indexed rollup read over \\`${on}\\` instead of a raw scan` +\n (op?.[1] === 'avg'\n ? `. avg:${op[2]} is exact off a rollup: the executor divides sums.${op[2]} by count`\n : '') +\n (report.interval && family.bucket !== report.interval\n ? `. Its ${family.bucket} buckets roll up into ${report.interval} without splitting one`\n : ''),\n });\n}\n\n/**\n * A `field:name` filter is not a family dim — a rollup doc does not record which\n * event wrote it — but it costs nothing when the names it admits already cover\n * every feeder, because then it removes nothing the family holds.\n */\nfunction nameFilterCovers(t: ReportFilter, f: FamilyFacet): boolean {\n if (t.dim !== 'field:name') return false;\n const admitted = t.op === 'eq' ? [String(t.value)] : t.op === 'in' ? [...(t.value as string[])].map(String) : null;\n return admitted != null && f.feeders.every((n) => admitted.includes(n));\n}\n\n// ── the raw filter ──────────────────────────────────────────────────────────\n\n/** the RecordFilter keys a `field:` filter maps onto, equality only */\nconst FIELD_TERMS: Record<string, keyof RecordFilter> = {\n 'field:kind': 'kind',\n 'field:name': 'name',\n 'field:severity': 'severity',\n 'field:env': 'env',\n 'field:service': 'service',\n 'field:release': 'release',\n ...FILTER_ONLY,\n};\n\n/**\n * Report → RecordFilter, the shape every raw primitive takes. Deliberately\n * total over what RecordFilter can EXPRESS and refusing everything else: this\n * plan step is where \"the query layer is missing a parameter\" gets said out\n * loud (dashboards law 6) rather than papered over with a filter that reads\n * more records than the Report asked about.\n */\nfunction toRecordFilter(report: Report, catalog: Catalog, src: ResolvedSource): RecordFilter | Unavailable {\n const filter: RecordFilter = {};\n\n if (src.events.length === 1) {\n // one name pins the read exactly, whichever source form named it\n filter.name = src.events[0];\n } else if (src.kind) {\n // a kind term IS the source: `{ kind }` expanded to every event declaring\n // it, so one indexed equality covers exactly that set for less than an\n // `$in` over every name in it\n filter.kind = src.kind;\n } else {\n // a namespace or a family is several names, and `RecordFilter.name` takes\n // the set — so the read is the source, exactly, rather than \"every record\n // of that kind in the range\" with a note apologising for it\n filter.name = [...src.events];\n }\n\n for (const t of report.filters ?? []) {\n const term = FIELD_TERMS[t.dim];\n if (term) {\n if (t.op !== 'eq') {\n return unavailable(\n `\"${t.dim}\" supports equality only on the raw path — RecordFilter.${String(term)} is one string, ` +\n `and \"${t.op}\" would need a term query.ts does not build`,\n );\n }\n (filter as Record<string, unknown>)[term] = String(t.value);\n continue;\n }\n if (t.dim.startsWith('attr:')) {\n const key = t.dim.slice(5);\n if (t.op === 'eq') {\n (filter.attrs ??= {})[key] = String(t.value);\n continue;\n }\n if (t.op === 'gte' || t.op === 'lte') {\n // a numeric bound names a METRIC — `metrics.<k>` is the only ranged\n // term buildMatch writes, and attrs are strings after casting\n if (!measureDeclared(catalog, src.events, `sum:${key}`)) {\n return unavailable(\n `\"${t.dim} ${t.op}\" is a numeric bound, which only a declared metric can carry — add \\`${key}\\` to ` +\n `the \\`metrics\\` object of ${src.events.join(', ')}, or filter it as an equality`,\n );\n }\n const range = ((filter.metrics ??= {})[key] ??= {});\n range[t.op] = Number(t.value);\n continue;\n }\n return unavailable(\n `\"${t.dim}\" supports equality (or a gte/lte bound on a metric) — an \\`in\\` over attrs would need a ` +\n '`$in` term buildMatch does not write',\n );\n }\n if (t.dim === 'subjectType' || t.dim === 'actorType') {\n return unavailable(\n `\"${t.dim}\" is derived at query time from ${t.dim === 'subjectType' ? '`subjectKeys`' : '`actor`'} and ` +\n 'RecordFilter has no term for it — group by it instead, pin one subject with `field:subject`' +\n (t.dim === 'actorType' ? ', or use `excludeActorTypes`' : ''),\n );\n }\n return unavailable(\n `\"${t.dim}\" is not filterable on the raw path — RecordFilter carries ${Object.keys(FIELD_TERMS).join(', ')}, ` +\n '`attr:<key>` and metric bounds',\n );\n }\n\n if (report.excludeActorTypes?.length) filter.excludeActorTypes = [...report.excludeActorTypes];\n return filter;\n}\n\n// ── compare ─────────────────────────────────────────────────────────────────\n\n/**\n * `compare: 'previous'` is pure arithmetic on the Report: the same plan, its\n * range shifted back by its own length. No primitive changes, and the executor\n * runs the same call twice.\n *\n * Each primitive keeps its range in a different place, which is exactly why the\n * shift lives here rather than in seven call sites.\n */\nfunction withCompare(report: Report, plan: Plan): Plan {\n if (report.compare !== 'previous') return plan;\n const [first, ...rest] = plan.args;\n if (plan.primitive === 'rollups' || plan.primitive === 'distinctCount' || plan.primitive === 'funnel') {\n const params = first as Record<string, unknown>;\n const key = plan.primitive === 'funnel' ? 'cohort' : 'range';\n const window = params[key] as (TimeRange & { endInclusive?: boolean }) | undefined;\n if (!window) return plan;\n return { ...plan, previous: { args: [{ ...params, [key]: { ...window, ...shift(window) } }, ...rest] } };\n }\n return { ...plan, previous: { args: [shift(first as TimeRange), ...rest] } };\n}\n\nconst sameSet = (a: readonly string[], b: readonly string[]) =>\n a.length === b.length && a.every((x) => b.includes(x));\n\n// ── the URL form (reports §4, §11.4) ────────────────────────────────────────\n\n/**\n * A Report is a URL. These two are inverses — `parseReportQuery(reportToQuery(r))`\n * deep-equals `r` — and they are the ONLY encoding: `GET /api/report` reads it,\n * the explore hash carries it, and util.js implements the same grammar on the\n * client. A Report that needed state a URL cannot hold would mean the query\n * layer is missing a parameter (dashboards law 6), not that the encoder needs a\n * blob.\n *\n * source=event:llm.completion&range=7d&interval=day&measure=sum:cost_usd\n * &groupBy=attr:gen_ai_request_model&filter=attr:feature:eq:chat&compare=previous\n *\n * Everything is flat and human-typable. `filter` REPEATS (express parses repeats\n * into an array; one stays a string, and both are accepted), because a term's\n * value may contain a comma — an `in` list is exactly that.\n */\nconst FILTER_OPS = new Set<ReportFilter['op']>(['eq', 'in', 'gte', 'lte']);\nconst SORTS = new Set(['value', 'label', 'time']);\n\nexport function parseReportQuery(q: Record<string, unknown>): Report {\n /** a repeated param takes its first value; every param but `filter` is single */\n const str = (k: string): string | undefined => {\n const v = Array.isArray(q[k]) ? (q[k] as unknown[])[0] : q[k];\n return typeof v === 'string' && v ? v : undefined;\n };\n const list = (k: string): string[] =>\n (str(k) ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n\n const raw = str('source');\n if (!raw) {\n throw badRequest(\n '`source` is required — one of source=event:<name>, namespace:<ns>, kind:<kind>, family:<as>',\n );\n }\n const cut = raw.indexOf(':');\n const form = cut > 0 ? raw.slice(0, cut) : '';\n const named = cut > 0 ? raw.slice(cut + 1) : '';\n if (!named || !['event', 'namespace', 'kind', 'family'].includes(form)) {\n throw badRequest(\n `\\`source\\` must be \"event:<name>\", \"namespace:<ns>\", \"kind:<kind>\" or \"family:<as>\" — got \"${raw}\"`,\n );\n }\n const source: ReportSource =\n form === 'event'\n ? { event: named }\n : form === 'namespace'\n ? { namespace: named }\n : form === 'kind'\n ? { kind: named as TelemetryKind }\n : { family: named };\n\n // the shorthand wins when both are present: it is the Report's own param, and\n // the shell's from/to ride along on every URL the SPA builds\n const shorthand = str('range');\n const from = str('from');\n const to = str('to');\n if (!shorthand && !(from && to)) {\n throw badRequest('a range is required — either `range=7d` or both `from` and `to` as ISO times');\n }\n const range: ReportRange = shorthand ?? { from: from!, to: to! };\n\n const interval = str('interval');\n if (interval && INTERVAL_RANK[interval as Interval] == null) {\n throw badRequest(`\\`interval\\` must be one of hour, day, week, month — got \"${interval}\"`);\n }\n const sort = str('sort');\n if (sort && !SORTS.has(sort)) {\n throw badRequest(`\\`sort\\` must be one of value, label, time — got \"${sort}\"`);\n }\n const compare = str('compare');\n if (compare && compare !== 'previous') {\n throw badRequest(`\\`compare\\` takes only \"previous\" — got \"${compare}\"`);\n }\n const limitRaw = str('limit');\n const limit = limitRaw == null ? undefined : Number(limitRaw);\n if (limit != null && (!Number.isInteger(limit) || limit < 1)) {\n throw badRequest(`\\`limit\\` must be a positive integer — got \"${limitRaw}\"`);\n }\n\n const measure = str('measure');\n const groupBy = list('groupBy');\n const excludeActorTypes = list('excludeActors');\n const stages = list('stages');\n const exits = list('exits');\n const anchor = str('anchor');\n const subjectType = str('subjectType');\n const filters = (\n q.filter == null ? [] : Array.isArray(q.filter) ? q.filter.map(String) : [String(q.filter)]\n ).map(parseFilterTerm);\n\n return {\n source,\n range,\n ...(interval ? { interval: interval as Interval } : {}),\n ...(measure ? { measure } : {}),\n ...(groupBy.length ? { groupBy } : {}),\n ...(filters.length ? { filters } : {}),\n ...(excludeActorTypes.length ? { excludeActorTypes } : {}),\n ...(sort ? { sort: sort as Report['sort'] } : {}),\n ...(limit != null ? { limit } : {}),\n ...(compare ? { compare: 'previous' as const } : {}),\n ...(stages.length ? { stages } : {}),\n ...(anchor ? { anchor } : {}),\n ...(exits.length ? { exits } : {}),\n ...(subjectType ? { subjectType } : {}),\n };\n}\n\n/**\n * `<dim>:<op>:<value>`, where the DIM itself contains a colon (`attr:model`) and\n * so may the value (`field:subject:eq:user:u_1`). The op is therefore found\n * rather than positioned: the FIRST token that is one of the four operators\n * ends the dim and begins the value. A dim whose last segment is literally\n * \"eq\"/\"in\"/\"gte\"/\"lte\" would mis-split, which is the price of a grammar a\n * person can type; nothing in the catalog's vocabulary produces one.\n */\nfunction parseFilterTerm(term: string): ReportFilter {\n const parts = term.split(':');\n const i = parts.findIndex((p) => FILTER_OPS.has(p as ReportFilter['op']));\n const rest = i < 0 ? '' : parts.slice(i + 1).join(':');\n // an EMPTY value is refused with the rest: `field:env:eq:` reads as \"env is\n // the empty string\", which nothing stores — it is a half-typed URL, and\n // answering it would return zero rows that look like an answer\n if (i < 1 || !rest) {\n throw badRequest(\n `\\`filter\\` must be \"<dim>:<op>:<value>\" with op one of eq, in, gte, lte — got \"${term}\"`,\n );\n }\n const dim = parts.slice(0, i).join(':');\n const op = parts[i] as ReportFilter['op'];\n if (op === 'in') {\n const values = rest.split(',').map((s) => s.trim()).filter(Boolean);\n if (!values.length) throw badRequest(`\\`filter\\` \"${term}\" has an empty \\`in\\` list`);\n return { dim, op, value: values };\n }\n if (op === 'gte' || op === 'lte') {\n const n = Number(rest);\n if (Number.isNaN(n)) throw badRequest(`\\`filter\\` bound \"${term}\" is not a number`);\n return { dim, op, value: n };\n }\n return { dim, op, value: rest };\n}\n\n/**\n * The inverse. `filter` is the one key that can hold several values — one term\n * stays a string so the URL reads the way a person would write it, several\n * become the repeated-param array express parses back.\n */\nexport function reportToQuery(report: Report): Record<string, string | string[]> {\n const s = report.source;\n const q: Record<string, string | string[]> = {\n source:\n 'event' in s\n ? `event:${s.event}`\n : 'namespace' in s\n ? `namespace:${s.namespace}`\n : 'kind' in s\n ? `kind:${s.kind}`\n : `family:${s.family}`,\n };\n if (typeof report.range === 'string') q.range = report.range;\n else {\n q.from = report.range.from;\n q.to = report.range.to;\n }\n if (report.interval) q.interval = report.interval;\n if (report.measure) q.measure = report.measure;\n if (report.groupBy?.length) q.groupBy = report.groupBy.join(',');\n if (report.filters?.length) {\n const terms = report.filters.map(\n (f) => `${f.dim}:${f.op}:${Array.isArray(f.value) ? f.value.join(',') : String(f.value)}`,\n );\n q.filter = terms.length === 1 ? terms[0]! : terms;\n }\n if (report.excludeActorTypes?.length) q.excludeActors = report.excludeActorTypes.join(',');\n if (report.sort) q.sort = report.sort;\n if (report.limit != null) q.limit = String(report.limit);\n if (report.compare) q.compare = report.compare;\n if (report.stages?.length) q.stages = report.stages.join(',');\n if (report.anchor) q.anchor = report.anchor;\n if (report.exits?.length) q.exits = report.exits.join(',');\n if (report.subjectType) q.subjectType = report.subjectType;\n return q;\n}\n\n// ── the legacy lift ─────────────────────────────────────────────────────────\n\n/** legacy filter key → the DimFacet key its equality term becomes */\nconst LEGACY_DIMS: Record<string, string> = {\n kind: 'field:kind',\n name: 'field:name',\n severity: 'field:severity',\n env: 'field:env',\n service: 'field:service',\n release: 'field:release',\n subject: 'field:subject',\n traceId: 'field:traceId',\n};\n\n/**\n * The stored-view lift (reports §4). `ViewSpec.query` is a `Report` now — the\n * derived ones included — but every view saved before this shipped is\n * `{ range, filters, groupBy, sort }`, a Mixed document that must keep parsing.\n *\n * Returns null when nothing in the query identifies a source, because a legacy\n * query that names neither an event, a kind nor a family is not a Report — it\n * is a page's default, and the caller's own fallback is the honest answer.\n */\nexport function normalizeQuery(query: ViewSpec['query'] | null | undefined): Report | null {\n if (!query || typeof query !== 'object') return null;\n if ('source' in query && query.source) return query as Report;\n\n const q = query as LegacyQuery;\n const filters = (q.filters ?? {}) as Record<string, unknown>;\n const str = (v: unknown) => (typeof v === 'string' && v ? v : null);\n\n // a family read is more specific than a kind page, and a name more specific\n // than either — whichever is present wins in that order\n const name = str(filters.name);\n const family = str(filters.rollup);\n const kind = str(filters.kind);\n const source: ReportSource | null = name\n ? { event: name }\n : family\n ? { family }\n : kind\n ? { kind: kind as TelemetryKind }\n : null;\n if (!source) return null;\n\n const consumed = name ? 'name' : family ? 'rollup' : 'kind';\n const terms: ReportFilter[] = [];\n for (const [k, v] of Object.entries(filters)) {\n if (k === consumed || k === 'rollup') continue;\n if (k === 'excludeActorTypes') continue;\n if (k === 'attrs') {\n // the FilterBar's own encoding, both ways round: an object, or 'a:b,c:d'\n const entries =\n typeof v === 'string'\n ? v.split(',').map((pair) => pair.split(':').map((s) => s.trim()))\n : Object.entries((v ?? {}) as Record<string, unknown>).map(([a, b]) => [a, String(b)]);\n for (const [key, value] of entries) {\n if (key && value != null) terms.push({ dim: `attr:${key}`, op: 'eq', value: String(value) });\n }\n continue;\n }\n const dim = LEGACY_DIMS[k];\n const value = str(v);\n if (dim && value) terms.push({ dim, op: 'eq', value });\n }\n\n const groupBy = (q.groupBy ?? '')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n const sort = q.sort === 'value' || q.sort === 'label' || q.sort === 'time' ? q.sort : undefined;\n const actors = filters.excludeActorTypes;\n\n return {\n source,\n range: q.range ?? '7d',\n ...(terms.length ? { filters: terms } : {}),\n ...(groupBy.length ? { groupBy } : {}),\n ...(sort ? { sort } : {}),\n ...(Array.isArray(actors) && actors.length ? { excludeActorTypes: actors.map(String) } : {}),\n };\n}\n","import { truncate } from './rollups.js';\nimport { resolveReport, type Plan, type PlanShape, type Report } from './report.js';\nimport type { Catalog } from './catalog.js';\nimport type { BreakdownRow, Queries, QueryLimits } from './query.js';\n\n/**\n * The executor (reports §6). `resolveReport` picks a primitive and its\n * arguments; this runs them. One function, two doors — `GET /api/report` and\n * the `run_report` MCP tool — so a Report means the same thing over HTTP and to\n * an agent, and neither door invents a query of its own.\n *\n * It lives here rather than in report.ts because report.ts is PURE: type-only\n * imports, no Mongo, unit-pinned like deriveCatalog. Executing needs `Queries`,\n * which is the whole database. The seam between them is `Plan.args`:\n *\n * const result = await q[plan.primitive](scope, ...plan.args);\n *\n * That is the entire dispatch. There is no per-primitive adapter here, and the\n * moment one appears the plan shape is wrong.\n *\n * The one thing this file DOES translate is a `rollups` plan, and `foldRollups`\n * below says why: rollups() has no server-side groupBy, so the requested groups\n * are a fold over the docs it returns. The fold produces the same row shape\n * `breakdown()` does, so a renderer never learns which store answered — which\n * is the point of planning an exact read in the first place.\n */\n\nexport interface ExecuteOptions {\n /** injected so a plan is deterministic — shorthand ranges end here */\n now?: Date;\n /** forwarded to the resolver, which uses them to cap the plan's own limits */\n limits?: Partial<QueryLimits>;\n /**\n * Applied to a `records` plan's items before they leave. The dashboard has no\n * redactor (its viewer is already inside the tenant); mcp.ts passes its own,\n * because an agent reading raw `data` payloads is the exposure that tool\n * suite defaults against.\n */\n redact?: (items: any[]) => any[];\n}\n\nexport interface ReportResult {\n /** the Report as executed — after a legacy lift, so the caller can see what ran */\n report: Report;\n plan: Plan;\n /** the primitive's own result, EXCEPT a rollups plan, which arrives folded */\n result: unknown;\n /** present when `compare: 'previous'` — the same call, range shifted back */\n previous?: unknown;\n /** which store answered, read off the result rather than assumed */\n dataSource: 'raw' | 'rollups' | 'raw+rollups';\n}\n\n/**\n * Report → the answer. Refusals are 400s: `Unavailable` is not an exception in\n * the resolver (a refusal is an answer), but by the time someone has asked for\n * the DATA it is — the `why` is the message, verbatim, because it already names\n * the offending key and the registry change that would fix it.\n */\nexport async function executeReport(\n q: Queries,\n scope: string,\n report: Report,\n catalog: Catalog,\n opts: ExecuteOptions = {},\n): Promise<ReportResult> {\n const plan = resolveReport(report, catalog, { now: opts.now, limits: opts.limits });\n if ('unavailable' in plan) throw Object.assign(new Error(plan.why), { status: 400 });\n\n const run = async (args: unknown[]): Promise<unknown> => {\n // the contract, verbatim. `args` is positional and typed `unknown[]`, so the\n // cast is the one place the plan's promise is taken on trust — report.test.ts\n // pins the args shape per primitive, dashboard.test.ts executes all seven.\n const raw: any = await (q as any)[plan.primitive](scope, ...args);\n if (plan.primitive === 'rollups' && plan.shape) {\n return foldRollups(raw?.rows ?? [], plan.shape, !!raw?.truncated);\n }\n if (plan.primitive === 'records' && opts.redact) {\n return { ...raw, items: opts.redact(raw?.items ?? []) };\n }\n return raw;\n };\n\n const [result, previous] = await Promise.all([\n run(plan.args),\n plan.previous ? run(plan.previous.args) : Promise.resolve(undefined),\n ]);\n return {\n report,\n plan,\n result,\n ...(plan.previous ? { previous } : {}),\n dataSource: (result as any)?.dataSource ?? 'raw',\n };\n}\n\n// ── folding a rollups plan ──────────────────────────────────────────────────\n\n/** the fields the fold reads off a rollup doc — see rollups.ts for the full shape */\nexport interface RollupDoc {\n /** dimension values in the family's `by` order: 'region=eu', or a bare 'user:u_1' */\n dims: string[];\n bucketAt?: Date | string | null;\n count?: number;\n sums?: Record<string, number> | Map<string, number> | null;\n}\n\n/** what breakdown() returns, from the rollup store instead of the raw one */\nexport interface FoldedRollups {\n rows: BreakdownRow[];\n /** distinct group tuples, ignoring the time axis — the same count breakdown reports */\n groups: number;\n /** the rollup read hit its cap, so groups are missing */\n truncated: boolean;\n dataSource: 'rollups';\n}\n\nconst MEASURE_OP = /^(sum|avg):(.+)$/;\n\n/**\n * A family's docs ARE the groups: the requested dims are its own `by` dims, so\n * grouping is arithmetic over rows already read, not a second query. This folds\n * them into the shape `breakdown()` returns — `{ dims, at?, value }` sorted the\n * same way — so the two are interchangeable and a chart cannot tell which store\n * answered. dashboard.test.ts asserts exactly that, number for number, on one\n * seed.\n *\n * Pure: no Mongo, no clock. `truncated` is the primitive's own flag, passed\n * through rather than re-derived, because a fold cannot know what it never saw.\n */\nexport function foldRollups(\n rows: readonly RollupDoc[],\n shape: PlanShape,\n truncated = false,\n): FoldedRollups {\n const op = MEASURE_OP.exec(shape.measure);\n const groups = new Map<string, { dims: (string | null)[]; at?: Date; sum: number; count: number }>();\n\n for (const doc of rows) {\n const dims = doc?.dims ?? [];\n if (!(shape.filters ?? []).every((f) => admits(f, dimValue(dims, f.label)))) continue;\n const tuple = shape.labels.map((label) => dimValue(dims, label));\n // a family may bucket FINER than the interval asked for (day rows → weeks);\n // re-truncating a bucket start cannot split one, so the roll-up stays exact\n const at =\n shape.interval && doc.bucketAt ? truncate(new Date(doc.bucketAt as any), shape.interval) : undefined;\n const key = `${JSON.stringify(tuple)}|${at ? at.getTime() : ''}`;\n let g = groups.get(key);\n if (!g) groups.set(key, (g = { dims: tuple, ...(at ? { at } : {}), sum: 0, count: 0 }));\n g.count += typeof doc.count === 'number' ? doc.count : 0;\n if (op) g.sum += sumOf(doc.sums, op[2]!);\n }\n\n const rowsOut: BreakdownRow[] = [...groups.values()].map((g) => ({\n dims: g.dims,\n ...(g.at ? { at: g.at } : {}),\n // avg is sums[k]/count off the SAME doc, which is exact — not an average of\n // averages, which is what folding a per-bucket mean would have produced\n value: !op ? g.count : op[1] === 'sum' ? g.sum : g.count ? g.sum / g.count : 0,\n }));\n rowsOut.sort(\n shape.interval\n ? (a, b) => (a.at?.getTime() ?? 0) - (b.at?.getTime() ?? 0) || byDims(a, b)\n : (a, b) => b.value - a.value || byDims(a, b),\n );\n\n return {\n rows: rowsOut,\n groups: new Set([...groups.values()].map((g) => JSON.stringify(g.dims))).size,\n truncated,\n dataSource: 'rollups',\n };\n}\n\n/**\n * One dim value out of a doc's `dims`, by the label rollups.ts wrote in front of\n * it. A SUBJECT dim is the exception and keeps its native `type:id` ref with no\n * `label=` prefix — erasure matches those directly (rollups.ts) — so it is\n * found as the entry that carries no `=` at all, and returned whole. That is\n * also what `breakdown()` returns for `subjectType`'s sibling dims, so the two\n * row shapes stay comparable.\n */\nfunction dimValue(dims: readonly string[], label: string): string | null {\n const prefix = `${label}=`;\n for (const d of dims) if (d.startsWith(prefix)) return d.slice(prefix.length);\n for (const d of dims) if (!d.includes('=')) return d;\n return null;\n}\n\n/** the fold's half of a filter — rollups() can only pin whole dims (reports §6) */\nfunction admits(f: NonNullable<PlanShape['filters']>[number], value: string | null): boolean {\n if (f.op === 'in') return (f.value as unknown[]).map(String).includes(String(value));\n if (f.op === 'gte' || f.op === 'lte') {\n const n = Number(value);\n if (Number.isNaN(n)) return false;\n return f.op === 'gte' ? n >= Number(f.value) : n <= Number(f.value);\n }\n return String(value) === String(f.value);\n}\n\n/** lean() hands back a plain object; a hydrated doc hands back a Map. Read both. */\nfunction sumOf(sums: RollupDoc['sums'], key: string): number {\n if (!sums) return 0;\n const v = sums instanceof Map ? sums.get(key) : (sums as Record<string, number>)[key];\n return typeof v === 'number' ? v : 0;\n}\n\n/** breakdown sorts ties by its `_id` tuple; matching that keeps the two orders identical */\nfunction byDims(a: BreakdownRow, b: BreakdownRow): number {\n for (let i = 0; i < a.dims.length; i++) {\n const x = a.dims[i] ?? '';\n const y = b.dims[i] ?? '';\n if (x !== y) return x < y ? -1 : 1;\n }\n return 0;\n}\n","import { Schema, type Connection, type Model } from 'mongoose';\nimport { deriveCatalog, type Catalog } from './catalog.js';\nimport type { Registry } from './registry.js';\nimport { intervalForRange, type LegacyQuery, type Report } from './report.js';\nimport { newId } from './types.js';\n\n/**\n * Views — one shape, three producers (dashboards §3). A view is nothing but\n * named query state; derived views come from the registry for free, configured\n * ones ship in host code, saved ones live in `<collection>_views`. Name\n * collisions shadow saved → configured → derived, so a user can override a\n * default without editing anything.\n *\n * Tenancy: views scope on the LITERAL viewer scope, including PLATFORM_SCOPE.\n * '*' is an escape hatch for reading telemetry, not a master key to other\n * people's saved state, so it does NOT fan out here the way it does in the\n * query primitives. A platform viewer's views live in their own '*' namespace:\n * invisible to every tenant, and every tenant's views invisible to them. Both\n * directions fall out of the same literal match — in resolveViews below and in\n * the router's delete/ownership lookup, which must stay literal for the same\n * reason (a platform admin's `role: 'admin'` is admin OF the platform scope).\n *\n * Erasure across that boundary is opt-in. forget(tenantId, ref) is\n * tenant-scoped and '*' is not a tenant, so a person's PLATFORM-scoped views\n * are missed by default — set `globalSubjectRefs` on createTelemetry() and\n * forget() reaches them too. The flag is the host asserting that a ref names\n * one party globally; without that, `user:u_1` is a different person in every\n * tenant and one tenant's erasure would delete another's views. Bounded by the\n * named ref either way — never by the tenant, which is the escape hatch this\n * namespace exists to deny.\n */\n\nexport interface ViewSpec {\n name: string;\n icon?: string;\n page: 'errors' | 'traces' | 'events' | 'journeys' | 'usage' | 'overview' | 'system' | 'explore';\n /**\n * A Report (reports §4) — or the pre-Report shape, which every stored view\n * still carries and `normalizeQuery()` lifts. `spec` is a Mixed document, so\n * nothing has to migrate: a query with no `source` is read as legacy and a\n * query with one is read as a Report.\n */\n query: Report | LegacyQuery;\n}\n\nexport function buildViewModel(connection: Connection, modelName: string, collection: string): Model<any> {\n const existing = connection.models?.[modelName];\n if (existing) return existing;\n const schema = new Schema(\n {\n _id: { type: String, required: true },\n tenantId: { type: String, required: true },\n /** a person — forget() deletes private views, redacts this on shared ones */\n ownerRef: String,\n shared: { type: Boolean, default: false },\n spec: { type: Schema.Types.Mixed, required: true },\n createdAt: { type: Date, required: true },\n },\n { collection, versionKey: false },\n );\n schema.index({ tenantId: 1, shared: 1 });\n schema.index({ tenantId: 1, ownerRef: 1 });\n return connection.model(modelName, schema);\n}\n\nconst KIND_PAGE: Record<string, ViewSpec['page']> = {\n error: 'errors',\n span: 'traces',\n event: 'events',\n state: 'journeys',\n usage: 'usage',\n};\n\n/**\n * Derived views — generated from the registry at load, zero config, and every\n * one of them a {@link Report} (reports §8). They exist because the registry\n * already knows enough to write them, so five shapes fall out of it:\n *\n * | shape | name | what it answers |\n * |---|---|---|\n * | per event | `<name>` | that one name over a week |\n * | per family | `rollup: <as>` | the family's own docs — the cheapest read there is |\n * | per namespace | `namespace: <ns>` | `library.*` split by name over a month |\n * | per usage event | `spend: <name>` | its `*_usd` sum per day |\n * | per subject type | `funnel: <type>` | its lifetime milestones as a cohort funnel |\n *\n * The catalog is what makes the last three writable, and it is PURE — so this\n * function keeps its one-argument signature and derives one when a caller\n * (resolveViews, off a request) has none to hand. `createDashboard` and\n * `createTelemetryMcp` both built theirs at boot and pass it through.\n *\n * Determinism matters more than it looks: these names are the sidebar, and a\n * list that reshuffles between requests is one nobody can link into. Every loop\n * below walks the catalog in registry order.\n */\nexport function deriveViews(\n registry: Registry,\n catalog: Catalog = deriveCatalog(registry),\n): Array<ViewSpec & { origin: 'derived' }> {\n const views: Array<ViewSpec & { origin: 'derived' }> = [];\n const derived = (name: string, page: ViewSpec['page'], query: Report) =>\n views.push({ origin: 'derived', name, page, query });\n\n // ── one per event: the name, charted over a week ──\n for (const [name, e] of Object.entries(catalog.events)) {\n derived(name, KIND_PAGE[e.kind] ?? 'events', {\n source: { event: name },\n range: '7d',\n interval: intervalForRange('7d'),\n });\n }\n\n // ── one per rollup family: read the family itself, which is always exact ──\n for (const as of Object.keys(catalog.families)) {\n derived(`rollup: ${as}`, 'journeys', { source: { family: as }, range: '30d' });\n }\n\n // ── one per namespace: `library.*` broken out by name ──\n // A namespace of one event is that event's own view under a second name, so\n // it is skipped rather than duplicated into the sidebar.\n for (const [ns, names] of Object.entries(catalog.namespaces)) {\n if (names.length < 2) continue;\n derived(`namespace: ${ns}`, 'explore', {\n source: { namespace: ns },\n range: '30d',\n interval: 'day',\n groupBy: ['field:name'],\n });\n }\n\n // ── one per usage event that meters money ──\n // `*_usd` is a formatting CONVENTION (dashboards §4), which makes it the one\n // thing about a metric this file may read off a key. It never names one.\n for (const [name, e] of Object.entries(catalog.events)) {\n if (e.kind !== 'usage') continue;\n const money = e.measures.find((m) => m.key.startsWith('sum:') && m.key.endsWith('_usd'));\n if (!money) continue;\n derived(`spend: ${name}`, 'usage', {\n source: { event: name },\n range: '30d',\n interval: 'day',\n measure: money.key,\n });\n }\n\n // ── one funnel per subject type ──\n // Stages are the lifetime single-subject families of that type, in registry\n // order — the order the host typed them in, which is the only sequence a\n // registry can claim. The UI re-orders them by observed median `firstAt`\n // (reports §7); this default has no data to read.\n for (const subjectType of catalog.subjectTypes) {\n const stages = Object.values(catalog.families)\n .filter((f) => f.lifetime && f.by.length === 1 && f.by[0] === 'subject' && f.subjectTypes.includes(subjectType))\n .map((f) => f.as);\n // one stage is not a funnel — it is a count, and there is already a view for it\n if (stages.length < 2) continue;\n derived(`funnel: ${subjectType}`, 'journeys', {\n // any source expands; the family the funnel is anchored on is the honest one\n source: { family: stages[0]! },\n range: '30d',\n interval: 'week',\n measure: 'funnel',\n stages,\n anchor: stages[0]!,\n subjectType,\n });\n }\n\n return views;\n}\n\nexport interface ResolvedView extends ViewSpec {\n origin: 'derived' | 'configured' | 'saved';\n id?: string;\n ownerRef?: string;\n shared?: boolean;\n}\n\n/** merge the three producers; name collisions resolve saved → configured → derived */\nexport async function resolveViews(opts: {\n ViewModel: Model<any>;\n registry: Registry;\n /** the caller's boot-time catalog, so a request does not re-derive one */\n catalog?: Catalog;\n configured: ViewSpec[];\n /** the viewer's scope — a tenantId, or PLATFORM_SCOPE. Matched literally. */\n tenantId: string;\n viewerRef?: string;\n}): Promise<ResolvedView[]> {\n const byName = new Map<string, ResolvedView>();\n for (const v of deriveViews(opts.registry, opts.catalog)) byName.set(v.name, v);\n for (const v of opts.configured) byName.set(v.name, { ...v, origin: 'configured' });\n const saved = await opts.ViewModel.find({\n tenantId: opts.tenantId,\n $or: [{ shared: true }, ...(opts.viewerRef ? [{ ownerRef: opts.viewerRef }] : [])],\n })\n .sort({ createdAt: 1 })\n .limit(200)\n .lean();\n for (const doc of saved as any[]) {\n byName.set(doc.spec.name, {\n ...doc.spec,\n origin: 'saved',\n id: doc._id,\n ownerRef: doc.ownerRef,\n shared: doc.shared,\n });\n }\n return [...byName.values()];\n}\n\nexport async function saveView(opts: {\n ViewModel: Model<any>;\n tenantId: string;\n viewerRef?: string;\n spec: ViewSpec;\n shared: boolean;\n}): Promise<{ id: string }> {\n // a viewer without an identity cannot own a private view — share or nothing\n if (!opts.shared && !opts.viewerRef) {\n throw Object.assign(new Error('private views need a viewer identity'), { status: 400 });\n }\n const id = newId();\n await opts.ViewModel.create({\n _id: id,\n tenantId: opts.tenantId,\n ownerRef: opts.viewerRef,\n shared: opts.shared,\n spec: opts.spec,\n createdAt: new Date(),\n });\n return { id };\n}\n","import express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { NextFunction, Request, Response, Router } from 'express';\nimport { INDEX_BUDGET } from './indexes.js';\nimport { isPlatformScope } from './types.js';\nimport { deriveCatalog, projectRegistry } from './catalog.js';\nimport { deriveSuggestions } from './suggest.js';\nimport { createQueries, type QueryLimits, type RecordFilter, type TimeRange } from './query.js';\nimport { createValues } from './values.js';\nimport { parseReportQuery, resolveReport } from './report.js';\nimport { executeReport } from './execute.js';\nimport { buildViewModel, resolveViews, saveView, type ViewSpec } from './views.js';\nimport type { Telemetry } from './index.js';\n\n/**\n * The read surface (dashboards §2–§8): one express router serving /api/* for\n * the six query primitives plus views/system, and the built React SPA with\n * hashed assets and SPA fallback. Never an app, never a server — the host\n * mounts it.\n *\n * Access control is the named inbound adapter: viewerAdapter.resolveViewer.\n * The router refuses to CONSTRUCT without it — an unauthenticated telemetry\n * dashboard is a data leak with charts.\n */\n\nexport interface Viewer {\n /**\n * The read scope: a tenantId, or PLATFORM_SCOPE (`'*'`) for a cross-tenant\n * read — a support console, a platform-wide cost page.\n *\n * `'*'` is an authorization decision, and it is the HOST's to make. The\n * package never infers platform admin from a role, a header, or a config\n * flag; it only makes the escape hatch expressible, so that a host needing a\n * cross-tenant read says so through this adapter instead of reaching around\n * `scoped()` with a raw model. Return `'*'` only for viewers you have already\n * authorized. `'*'` is reserved on the write side, so no stored row carries\n * it and no tenant can ever be named it.\n */\n tenantId: string;\n /** 'admin' unlocks System writes (key revoke); anything else is read-only there */\n role: string;\n /** who this person is — owns saved views; e.g. 'user:u_1' */\n viewerRef?: string;\n}\n\nexport interface ViewerAdapter {\n resolveViewer(req: Request): Viewer | null | Promise<Viewer | null>;\n}\n\nexport interface SubjectAdapter {\n /** pretty labels for subject refs; absent refs render raw */\n describe(refs: string[]): Promise<Record<string, { label: string; href?: string }>>;\n}\n\nexport interface CreateDashboardOptions {\n telemetry: Telemetry;\n viewerAdapter: ViewerAdapter;\n subjectAdapter?: SubjectAdapter;\n /** configured views — versioned in host code (dashboards §3) */\n views?: ViewSpec[];\n queryLimits?: Partial<QueryLimits>;\n onSlowQuery?: (info: { op: string; ms: number; params: unknown }) => void;\n /** threshold onSlowQuery fires above, ms. Default 500. Forwarded to createQueries. */\n slowMs?: number;\n /** in-process query cache TTL, ms. Default 600_000. Forwarded to createQueries. */\n cacheTtlMs?: number;\n /** cached query results kept before eviction. Default 60. Forwarded to createQueries. */\n cacheSize?: number;\n /** where the browser sees this router mounted — MUST match (traps #8) */\n mountPath?: string;\n /** where the SPA calls /api — defaults to mountPath */\n apiBase?: string;\n title?: string;\n spaDir?: string;\n}\n\nconst here = path.dirname(fileURLToPath(import.meta.url));\n\n// Published builds run from dist/index.js, so the UI bundle sits alongside at\n// dist/ui; running from source it is two levels up. Pick whichever exists —\n// a build flag gets one of the two cases wrong (traps #7).\nconst SPA_DIR_CANDIDATES = ['./ui', '../../dist/ui'];\n\nexport function defaultSpaDir(): string {\n for (const candidate of SPA_DIR_CANDIDATES) {\n const dir = path.resolve(here, candidate);\n if (fs.existsSync(path.join(dir, 'index.html'))) return dir;\n }\n return path.resolve(here, SPA_DIR_CANDIDATES[SPA_DIR_CANDIDATES.length - 1]!);\n}\n\nfunction escapeJson(value: unknown): string {\n // `</script>` inside injected JSON would close the tag early — escape at `<`\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n}\n\nconst parseRange = (q: Record<string, unknown>): TimeRange => {\n const to = q.to ? new Date(String(q.to)) : new Date();\n const from = q.from\n ? new Date(String(q.from))\n : new Date(to.getTime() - 7 * 864e5);\n if (Number.isNaN(from.getTime()) || Number.isNaN(to.getTime()) || from >= to) {\n throw Object.assign(new Error('invalid time range'), { status: 400 });\n }\n return { from, to };\n};\n\nconst parseFilter = (q: Record<string, unknown>): RecordFilter => {\n const f: RecordFilter = {};\n for (const k of ['kind', 'name', 'severity', 'env', 'service', 'release', 'subject', 'traceId'] as const) {\n if (typeof q[k] === 'string' && q[k]) (f as any)[k] = q[k];\n }\n // `name=a,b` is the name-SET term — a namespace or a rollup family is several\n // event names, and reading them as one `$in` is what makes that read exact\n // instead of \"every record of that kind\". Names never contain a comma\n // (validateRegistry), so the split is unambiguous, and one name stays a\n // string so every URL that exists keeps its shape.\n if (typeof q.name === 'string' && q.name.includes(',')) {\n const names = q.name.split(',').map((s) => s.trim()).filter(Boolean);\n if (names.length) f.name = names.length === 1 ? names[0] : names;\n }\n if (typeof q.attrs === 'string' && q.attrs) {\n // attrs=format:pdf,route:/reports\n f.attrs = Object.fromEntries(\n String(q.attrs)\n .split(',')\n .map((p) => p.split(':'))\n .filter((p) => p.length >= 2)\n .map(([k, ...v]) => [k!, v.join(':')]),\n );\n }\n if (typeof q.metrics === 'string' && q.metrics) {\n // metrics=cost_usd>0.5,tokens_in<100\n f.metrics = {};\n for (const term of String(q.metrics).split(',')) {\n const m = /^([\\w.]+)([<>])(-?[\\d.]+)$/.exec(term);\n if (m) f.metrics[m[1]!] = m[2] === '>' ? { gte: Number(m[3]) } : { lte: Number(m[3]) };\n }\n }\n if (typeof q.excludeActors === 'string' && q.excludeActors) {\n f.excludeActorTypes = String(q.excludeActors).split(',').filter(Boolean);\n }\n return f;\n};\n\n/** the fields `rollups()` will range-filter on — an allowlist, not a passthrough */\nconst ROLLUP_ON = ['firstAt', 'lastAt', 'bucketAt'] as const;\n\n/** the fields `rollups()` will ORDER by — an allowlist for the same reason */\nconst ROLLUP_SORT = ['count', 'lastAt', 'firstAt', 'bucketAt'] as const;\n\n/** an `$in` from a URL is still a scan, so the repeated-param form is bounded */\nconst MAX_DIMS = 100;\n\n/**\n * `?dims=user:u_1&dims=user:u_2` — the repeated-param form express already\n * parses into an array — is the multi-subject read. One value stays a string,\n * so the single-dim URLs that exist keep working unchanged.\n *\n * Validated rather than coerced: more than MAX_DIMS values, or a nested value\n * where a string belongs (`?dims[0][k]=v` under the extended parser), is a 400\n * rather than a silently narrowed `$in`. Silently dropping half a cohort is the\n * failure the array form exists to prevent, so it must not be reintroduced by\n * the parser that reads it.\n */\nconst parseDims = (v: unknown): string | string[] | undefined => {\n if (typeof v === 'string') return v || undefined;\n if (!Array.isArray(v)) return undefined;\n if (v.length > MAX_DIMS) {\n throw Object.assign(new Error(`at most ${MAX_DIMS} dims values`), { status: 400 });\n }\n if (!v.every((d) => typeof d === 'string' && d)) {\n throw Object.assign(new Error('dims must be non-empty strings'), { status: 400 });\n }\n return v.length ? (v as string[]) : undefined;\n};\n\nexport function createDashboard(opts: CreateDashboardOptions): Router {\n const { telemetry: t, viewerAdapter, subjectAdapter, views: configured = [] } = opts;\n if (!viewerAdapter?.resolveViewer) {\n throw new Error(\n 'telemetry: createDashboard requires a viewerAdapter — an unauthenticated telemetry dashboard is a data leak with charts',\n );\n }\n\n const mountPath = opts.mountPath ?? '/telemetry';\n const apiBase = opts.apiBase ?? mountPath;\n const title = opts.title ?? 'Telemetry';\n const spaDir = opts.spaDir ?? defaultSpaDir();\n\n const conn = t.models.telemetry.db!;\n const ViewModel = buildViewModel(\n conn as any,\n `${t.models.telemetry.modelName}View`,\n `${t.models.telemetry.collection.collectionName}_views`,\n );\n\n const q = createQueries({\n TelemetryModel: t.models.telemetry,\n RollupModel: t.models.rollups,\n registry: t.registry,\n limits: opts.queryLimits,\n onSlowQuery: opts.onSlowQuery,\n // forwarded, not re-defaulted — an onSlowQuery pinned at the 500ms default\n // is a callback the host cannot aim\n slowMs: opts.slowMs,\n cacheTtlMs: opts.cacheTtlMs,\n cacheSize: opts.cacheSize,\n });\n\n // Derived once, here, for the same reason validateRegistry runs at boot: if\n // the catalog cannot be built the registry is wrong, and a request is the\n // wrong place to find that out. The `client.platform` enum is per instance\n // (CreateTelemetryConfig.platforms extends the builtin list) and the\n // Telemetry handle does not carry it, so it is read back off the compiled\n // schema — the same closed domain the writer enforces.\n const catalog = deriveCatalog(t.registry, {\n platforms: (t.models.telemetry.schema.path('client') as any)?.schema?.path('platform')?.enumValues,\n });\n const registry = projectRegistry(catalog);\n\n // the observed domain of a dimension (reports §5). Built here rather than\n // inside createQueries because it reads the CATALOG — it is the lookup the\n // report builder makes before it names a value, not a tenth primitive.\n const values = createValues({\n catalog,\n TelemetryModel: t.models.telemetry,\n RollupModel: t.models.rollups,\n limits: opts.queryLimits,\n onSlowQuery: opts.onSlowQuery,\n slowMs: opts.slowMs,\n cacheTtlMs: opts.cacheTtlMs,\n cacheSize: opts.cacheSize,\n });\n\n const api = express.Router();\n api.use(express.json({ limit: '64kb' }));\n\n // ── the gate ──\n api.use(async (req: Request & { viewer?: Viewer }, res, next) => {\n try {\n const viewer = await viewerAdapter.resolveViewer(req);\n if (!viewer?.tenantId) return res.status(401).json({ error: 'unauthenticated' });\n req.viewer = viewer;\n next();\n } catch (e) {\n next(e);\n }\n });\n\n const h =\n (fn: (req: Request & { viewer?: Viewer }, res: Response) => Promise<unknown>) =>\n (req: Request, res: Response, next: NextFunction) => {\n fn(req as any, res).then((body) => {\n if (!res.headersSent) res.json(body);\n }, next);\n };\n\n // the SPA's one boot call — it learns its scope here, because a cross-tenant\n // number that cannot say which tenant it came from is unusable\n api.get('/registry', h(async (req) => ({\n registry,\n catalog,\n kinds: ['event', 'error', 'span', 'state', 'usage'],\n role: req.viewer!.role,\n scope: req.viewer!.tenantId,\n platform: isPlatformScope(req.viewer!.tenantId),\n })));\n\n api.get('/records', h(async (req) =>\n q.records(req.viewer!.tenantId, parseRange(req.query), parseFilter(req.query), {\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n cursor: typeof req.query.cursor === 'string' ? req.query.cursor : undefined,\n }),\n ));\n\n api.get('/series', h(async (req) =>\n q.series(req.viewer!.tenantId, parseRange(req.query), parseFilter(req.query), {\n measure: typeof req.query.measure === 'string' ? req.query.measure : undefined,\n interval: (req.query.interval as any) || undefined,\n }),\n ));\n\n api.get('/distribution', h(async (req) =>\n q.distribution(req.viewer!.tenantId, parseRange(req.query), parseFilter(req.query), {\n measure: typeof req.query.measure === 'string' ? req.query.measure : undefined,\n }),\n ));\n\n /**\n * `?groupBy=attr:model,field:client.platform` — comma-separated so a\n * breakdown stays a URL, like the funnel's `stages`. The primitive owns the\n * vocabulary: an unknown dim, a refused path, three dims or a bad interval\n * all throw with `status: 400` and their own message, which the error\n * middleware surfaces verbatim rather than flattening into 'bad_request'.\n */\n api.get('/breakdown', h(async (req) =>\n q.breakdown(req.viewer!.tenantId, parseRange(req.query), parseFilter(req.query), {\n groupBy: String(req.query.groupBy ?? '').split(',').map((s) => s.trim()).filter(Boolean),\n measure: typeof req.query.measure === 'string' ? req.query.measure : undefined,\n interval: (req.query.interval as any) || undefined,\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n }),\n ));\n\n api.get('/rollups', h(async (req) => {\n if (typeof req.query.as !== 'string' || !req.query.as) {\n throw Object.assign(new Error('rollup family required'), { status: 400 });\n }\n // an unrecognised `on` would range-filter on a field that does not exist and\n // return an empty family — a 400 says so instead\n const on = req.query.on;\n if (on !== undefined && !ROLLUP_ON.includes(on as any)) {\n throw Object.assign(new Error(`on must be one of ${ROLLUP_ON.join(', ')}`), { status: 400 });\n }\n // `sort` reaches Mongo's .sort() — an unvalidated passthrough lets a caller\n // order by an unindexed field and turn a bounded read into a blocking\n // in-memory sort. Same hole `on` had, same allowlist.\n const sort = req.query.sort;\n if (sort !== undefined && !ROLLUP_SORT.includes(sort as any)) {\n throw Object.assign(new Error(`sort must be one of ${ROLLUP_SORT.join(', ')}`), { status: 400 });\n }\n return q.rollups(req.viewer!.tenantId, {\n as: req.query.as,\n dims: parseDims(req.query.dims),\n subjectType: typeof req.query.subjectType === 'string' ? req.query.subjectType : undefined,\n // cohort selection wants firstAt; the default is still bucketAt when\n // bucketed, lastAt otherwise — see query.ts\n on: on as (typeof ROLLUP_ON)[number] | undefined,\n range: req.query.from || req.query.to ? parseRange(req.query) : undefined,\n sort: sort as (typeof ROLLUP_SORT)[number] | undefined,\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n });\n }));\n\n api.get('/trace/:traceId', h(async (req) => q.trace(req.viewer!.tenantId, String(req.params.traceId))));\n\n api.get('/journey/:ref', h(async (req) =>\n q.journey(req.viewer!.tenantId, String(req.params.ref), parseRange(req.query), {\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n }),\n ));\n\n /**\n * A cohort primitive throws when the named family cannot answer the question\n * asked of it — a registry mistake, which is a 400 with the explanation, not\n * a 500 that hides it. `status` already set (parseRange's 400) is respected.\n */\n const badRequest = async <T>(run: () => Promise<T>): Promise<T> => {\n try {\n return await run();\n } catch (e: any) {\n throw Object.assign(e, { status: e?.status ?? 400 });\n }\n };\n\n // ── the two cohort primitives (cohort-math S6/S8) ──\n // Stages arrive as a comma-separated family list so a funnel stays a URL —\n // `?stages=signed_up,activated,converted`. A view is a named URL (dashboards\n // §11.6); a funnel that needed a POST body could not be one.\n api.get('/funnel', h(async (req) => {\n const parseStages = (v: unknown) =>\n String(v ?? '').split(',').map((s) => s.trim()).filter(Boolean).map((as) => ({ as }));\n const stages = parseStages(req.query.stages);\n if (!stages.length) {\n throw Object.assign(new Error('funnel needs `stages` — a comma-separated list of rollup families'), { status: 400 });\n }\n // a registry mistake is the caller's to fix, not a 500 — the validator's\n // message names the family and the change, so surface it verbatim\n return badRequest(() => q.funnel(req.viewer!.tenantId, {\n stages,\n exits: parseStages(req.query.exits),\n anchor: typeof req.query.anchor === 'string' ? req.query.anchor : undefined,\n // the cohort window is the shell's own range, half-open like everything else\n cohort: { ...parseRange(req.query), endInclusive: req.query.endInclusive === 'true' },\n subjectType: typeof req.query.subjectType === 'string' ? req.query.subjectType : undefined,\n interval: (req.query.interval as any) || undefined,\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n }));\n }));\n\n api.get('/distinct', h(async (req) => {\n if (typeof req.query.as !== 'string' || !req.query.as) {\n throw Object.assign(new Error('rollup family required'), { status: 400 });\n }\n return badRequest(() => q.distinctCount(req.viewer!.tenantId, {\n as: req.query.as as string,\n subjectType: typeof req.query.subjectType === 'string' ? req.query.subjectType : undefined,\n range: parseRange(req.query),\n interval: (req.query.interval as any) || undefined,\n }));\n }));\n\n /**\n * The observed domain of one dimension — what turns the FilterBar's\n * `window.prompt` into a picker (reports §5). `names` is the Report's source\n * events, comma-separated so this stays a URL like everything else.\n *\n * The range is OPTIONAL here, unlike every raw-reading route: a dim the\n * catalog or the rollups can answer needs no window, and a dim that would\n * need one answers `source: 'none'` rather than 400 — the caller's fallback\n * is a text box, not an error.\n */\n api.get('/values', h(async (req) => {\n const dim = typeof req.query.dim === 'string' ? req.query.dim.trim() : '';\n if (!dim) {\n throw Object.assign(new Error('dim required'), { status: 400 });\n }\n const names = String(req.query.names ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n return values(req.viewer!.tenantId, {\n dim,\n names: names.length ? names : undefined,\n range: req.query.from || req.query.to ? parseRange(req.query) : undefined,\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n });\n }));\n\n api.get('/subjects/describe', h(async (req) => {\n const refs = String(req.query.refs ?? '').split(',').filter(Boolean).slice(0, 100);\n if (!subjectAdapter) return { refs: {} }; // refs render raw — the documented fallback\n return { refs: await subjectAdapter.describe(refs) };\n }));\n\n /**\n * ── the Report, over HTTP (reports §4, §6) ──\n *\n * A Report IS this URL: `?source=event:llm.completion&range=7d&measure=sum:cost_usd\n * &groupBy=attr:gen_ai_request_model&filter=attr:feature:eq:chat`. One route\n * behind every chart, because the resolver picks the primitive — so the SPA\n * stops choosing an endpoint per page and asks the question instead.\n * `parseReportQuery`/`reportToQuery` are inverses and util.js speaks the same\n * grammar, which is what keeps a shared link and a saved view the same thing.\n */\n api.get('/report', h(async (req) =>\n badRequest(() =>\n executeReport(q, req.viewer!.tenantId, parseReportQuery(req.query as Record<string, unknown>), catalog),\n ),\n ));\n\n /**\n * The dry run. Same URL, no read: it answers `Plan | Unavailable` with a 200,\n * because a refusal is an ANSWER here — the UI greys the option and shows the\n * `why`, and an agent learns the cost of a question before paying it. (An\n * Unavailable on `/report` itself IS a 400: by then the caller asked for\n * data.) A malformed URL is still a 400 either way.\n */\n api.get('/report/plan', h(async (req) =>\n badRequest(async () =>\n resolveReport(parseReportQuery(req.query as Record<string, unknown>), catalog),\n ),\n ));\n\n // ── views: one shape, three producers ──\n api.get('/views', h(async (req) => ({\n views: await resolveViews({\n ViewModel,\n registry: t.registry,\n catalog,\n configured,\n tenantId: req.viewer!.tenantId,\n viewerRef: req.viewer!.viewerRef,\n }),\n })));\n\n api.post('/views', h(async (req) => {\n const { spec, shared = false } = (req.body ?? {}) as { spec?: ViewSpec; shared?: boolean };\n if (!spec?.name || !spec?.page || typeof spec.query !== 'object') {\n throw Object.assign(new Error('view spec required'), { status: 400 });\n }\n return saveView({\n ViewModel,\n tenantId: req.viewer!.tenantId,\n viewerRef: req.viewer!.viewerRef,\n spec,\n shared: !!shared,\n });\n }));\n\n api.delete('/views/:id', h(async (req, res) => {\n // LITERAL scope match, '*' included — see views.ts. The platform scope\n // reads telemetry across tenants; it does not own other people's saved\n // views, and `role: 'admin'` below is admin OF this scope. A view outside\n // the caller's scope reports removed:0 rather than 403: whether that id\n // exists elsewhere is not this viewer's business either.\n const doc = await ViewModel.findOne({ _id: req.params.id, tenantId: req.viewer!.tenantId }).lean() as any;\n if (!doc) return { removed: 0 };\n const mine = doc.ownerRef && doc.ownerRef === req.viewer!.viewerRef;\n if (!mine && req.viewer!.role !== 'admin') {\n res.status(403).json({ error: 'forbidden' });\n return undefined as never;\n }\n await ViewModel.deleteOne({ _id: doc._id });\n return { removed: 1 };\n }));\n\n // ── System — where \"never drop silently\" becomes visible. Not optional. ──\n api.get('/system', h(async (req) => {\n // Quarantined rejects hold RAW payloads — subjects, attrs, the lot. An\n // unfiltered find() here handed every tenant's failed writes to any\n // authenticated viewer, which is the same leak the query primitives are\n // scoped to prevent, reached by a route that never went through them.\n // Scoped like everything else; '*' still sees all, by authorization.\n const quarantine = await t.collections.rejects()\n .find(\n isPlatformScope(req.viewer!.tenantId) ? {} : { 'raw.tenantId': req.viewer!.tenantId },\n { sort: { at: -1 }, limit: 50 } as any,\n )\n .toArray()\n .catch(() => []);\n const indexes = await t.models.telemetry.collection.indexes().catch(() => []);\n const keys = req.viewer!.role === 'admin'\n ? await t.models.keys.find({}, { secretHash: 0 }).sort({ createdAt: -1 }).limit(100).lean()\n : [];\n return {\n counters: t.counters,\n quarantine,\n indexCount: indexes.length,\n indexBudget: INDEX_BUDGET,\n keys,\n role: req.viewer!.role,\n // The same three sources, read the other way round: what the data says\n // the registry is missing, each with the line that would fix it. Derived\n // from the counters and the quarantine ALREADY fetched above, so the\n // page costs no extra read. Nothing is written — the host still edits\n // the registry by hand (reports §9).\n suggestions: deriveSuggestions({ counters: t.counters, catalog, quarantine }),\n };\n }));\n\n api.post('/system/keys/:id/revoke', h(async (req, res) => {\n if (req.viewer!.role !== 'admin') {\n res.status(403).json({ error: 'forbidden' });\n return undefined as never;\n }\n const r = await t.models.keys.updateOne(\n { _id: req.params.id, revokedAt: null },\n { $set: { revokedAt: new Date() } },\n );\n return { revoked: r.modifiedCount ?? 0 };\n }));\n\n // JSON errors, never an HTML stack page — the template's smoke contract\n api.use((err: any, _req: Request, res: Response, _next: NextFunction) => {\n const status = err?.status ?? 500;\n if (status >= 500) t.logger.error('[telemetry:dashboard]', err);\n res.status(status).json({ error: status >= 500 ? 'internal_error' : String(err?.message ?? 'bad_request') });\n });\n\n // ── the router: /api/* + SPA with hashed assets + fallback ──\n const router = express.Router();\n router.use('/api', api);\n\n router.use('/_assets', express.static(path.join(spaDir, '_assets'), {\n maxAge: '1y',\n immutable: true,\n index: false,\n }));\n\n const base = `${mountPath.replace(/\\/$/, '')}/`;\n router.get(/.*/, (_req, res) => {\n let html: string;\n try {\n html = fs.readFileSync(path.join(spaDir, 'index.html'), 'utf8');\n } catch {\n return res.status(503).type('text/plain').send(\n 'telemetry: UI bundle not found. Run `npm run build` in the package, or pass an explicit `spaDir`.',\n );\n }\n const config = escapeJson({ apiBase: `${apiBase.replace(/\\/$/, '')}/api`, mountPath, title });\n // the shell must never cache — a heuristically-cached index.html keeps\n // referencing dead hashed assets across deploys. Assets cache hard instead.\n res.setHeader('Cache-Control', 'no-store');\n res.type('html').send(\n html.replace(\n '<!--telemetry-config-->',\n `<base href=\"${base}\" />\\n <script>window.__TELEMETRY__=${config}</script>`,\n ),\n );\n });\n\n return router;\n}\n","import type { Collection, Connection } from 'mongoose';\nimport { RETENTION_DAYS, newCounters, noopLogger, type EntityRef, type Logger } from './types.js';\nimport { validateRegistry, type Registry } from './registry.js';\nimport { buildTelemetryModels } from './model.js';\nimport { buildRollupModel } from './rollups.js';\nimport { buildCheckpointModel, createCheckpointFactory } from './checkpoint.js';\nimport { createEmitter, createSubjectLinking, type EmitInput, type SubjectLinker } from './emit.js';\nimport { createForget } from './forget.js';\nimport { createRelink } from './relink.js';\nimport { createSyncIndexes } from './indexes.js';\nimport { buildKeyModel, createKey, type CreateKeyInput } from './keys.js';\n\nexport { defineRegistry, boundedMeta, validateRegistry } from './registry.js';\nexport type { Registry, EventSpec, RollupSpec, DimSource } from './registry.js';\nexport {\n TelemetryKind, LogLevel, Env, Origin,\n BODY_MAX_CHARS, COUNTER_MAP_MAX, COUNTER_OVERFLOW_KEY, PLATFORM_SCOPE, RETENTION_DAYS,\n SAMPLE_RATE, SCHEMA_VERSION,\n isPlatformScope, newId, traceKeep, plain,\n} from './types.js';\nexport type { TelemetryCounters, Logger, EntityRef, ValidationPolicy } from './types.js';\nimport type { ValidationPolicy } from './types.js';\nexport { INDEX_BUDGET } from './indexes.js';\nexport { truncate, resolveDim } from './rollups.js';\nexport type { ForgetResult } from './forget.js';\nexport { RELINK_BATCH_SIZE } from './relink.js';\nexport type { RelinkOptions, RelinkResult } from './relink.js';\nexport type { Checkpoint } from './checkpoint.js';\nexport { SUBJECT_MAX, SUBJECT_LINK_TIMEOUT_MS } from './emit.js';\nexport type { EmitInput, EmitResult, LinkSubjects, SubjectLinker } from './emit.js';\nexport { KeyKind, TenantMode, parseKeyString, hashSecret, verifySecret, createKey } from './keys.js';\nexport type { CreateKeyInput, ParsedKey } from './keys.js';\nexport { createIngest } from './ingest.js';\nexport type { ContextAdapter, CreateIngestOptions, IngestContext } from './ingest.js';\nexport { createDashboard, defaultSpaDir } from './dashboard.js';\nexport type {\n CreateDashboardOptions, SubjectAdapter, Viewer, ViewerAdapter,\n} from './dashboard.js';\nexport { deriveCatalog, projectRegistry } from './catalog.js';\nexport type {\n Catalog, DeriveCatalogOptions, DimFacet, EventFacet, FamilyFacet, MeasureFacet,\n RegistryProjection, RegistryProjectionEntry,\n} from './catalog.js';\nexport { deriveSuggestions, MAX_SUGGESTIONS } from './suggest.js';\nexport type { DeriveSuggestionsInput, Suggestion } from './suggest.js';\nexport { createQueries, DEFAULT_LIMITS } from './query.js';\nexport type { Queries, QueryLimits, RecordFilter, TimeRange } from './query.js';\nexport { createValues } from './values.js';\nexport type { Values, ValuesCtx, ValuesParams, ValuesResult } from './values.js';\nexport { median, summarizeStages, findFamily, requireMilestoneFamily } from './funnel.js';\nexport type {\n CohortSubject, FunnelCohortWindow, FunnelExitResult, FunnelParams,\n FunnelResult, FunnelSlice, FunnelStageResult, FunnelStageSpec,\n} from './funnel.js';\nexport { deriveViews } from './views.js';\nexport type { ResolvedView, ViewSpec } from './views.js';\nexport {\n intervalForRange, normalizeQuery, parseReportQuery, rangeOf, reportToQuery, resolveReport,\n} from './report.js';\nexport type {\n LegacyQuery, Plan, PlanPrimitive, PlanShape, Report, ReportFilter, ReportRange,\n ReportSource, ResolveOptions, Unavailable,\n} from './report.js';\nexport { executeReport, foldRollups } from './execute.js';\nexport type { ExecuteOptions, FoldedRollups, ReportResult, RollupDoc } from './execute.js';\n\nexport interface CreateTelemetryConfig {\n /** the host-owned event registry — see defineRegistry() */\n registry: Registry;\n /** a mongoose Connection, or the mongoose module itself (its default connection is used) */\n connection: Connection | { connection: Connection };\n /** base collection name; six siblings derive from it: `<collection>_rollups`,\n * `_rejects`, `_aliases`, `_checkpoints`, `_keys`, `_views` */\n collection?: string;\n /**\n * Mongoose model name. Set it when two instances share one connection —\n * a reused name silently reuses the FIRST instance's registry (traps #2).\n */\n modelName?: string;\n /** secret pepper for forget()'s pseudonymous rekeying. Falls back to TELEMETRY_PEPPER. */\n pepper?: string;\n /**\n * Host additions to `client.platform`. EXTENDS the builtin list\n * ['web','electron','ios','android','server','cli'] — a host adding 'watchos'\n * keeps 'web'.\n */\n platforms?: readonly string[];\n /** override BODY_MAX_CHARS for this instance */\n bodyMax?: number;\n /**\n * What a vocabulary mismatch costs. Default `'lenient'`: an attr or metric\n * the registry does not accept is stripped, counted by name in\n * `counters.attrsDropped` / `counters.metricsDropped`, and the record is\n * written. `'strict'` restores the pre-0.7.0 behaviour of quarantining the\n * whole record. See ValidationPolicy in types.ts for why the default moved.\n */\n validation?: ValidationPolicy;\n /**\n * Declares that a subject ref (`type:id`) names the same party in EVERY\n * tenant. The package cannot verify that, so it is asserted rather than\n * detected. Only effect today: forget() also erases the person's\n * platform-scoped saved views, which a tenant-scoped call otherwise misses.\n * Leave it off when ids are minted per tenant — there, `user:u_1` is a\n * different person in each and one tenant's erasure would reach another's.\n */\n globalSubjectRefs?: boolean;\n /**\n * Attach additional subjects to a record AT WRITE TIME — the desktop\n * `machine:<installId>` that the host can resolve to a `user`, joined once,\n * onto the row and its rollups, instead of at every read that ever wants it.\n *\n * See SubjectLinker in emit.ts for what it must not do. In one line: it must\n * be cached, because it runs once per record on the ingest path, and it can\n * never fail a write — a slow or broken linker costs records their link, not\n * their existence.\n */\n subjectLinker?: SubjectLinker;\n /**\n * What `subjectLinker.link()` gets per record before the write proceeds\n * UNLINKED and counts a timeout. Default 50ms. Raise it only if you have\n * measured the resolver; the default is chosen so a host outage degrades\n * telemetry rather than stalling ingest behind it.\n */\n subjectLinkTimeoutMs?: number;\n logger?: Logger;\n}\n\n/**\n * The package factory. Returns the write path, erasure, tenant-scoped reads,\n * and the checkpoint primitive. Routers (ingest, dashboard) are separate\n * factories that take this instance — they never build their own storage.\n *\n * const t = createTelemetry({ registry, connection: mongoose })\n * await t.syncIndexes() // boot: indexes + TTLs, awaited before first write\n * await t.emit('user.signed_up', { tenantId, subjects: [...], attrs: {...} })\n */\nexport function createTelemetry(config: CreateTelemetryConfig) {\n const {\n registry,\n collection = 'telemetry',\n modelName = 'Telemetry',\n logger = noopLogger,\n } = config;\n\n // boot-time contract checks — misconfiguration fails deploy, not dashboards\n validateRegistry(registry);\n\n // A spec declaring `data` and no retentionDays inherits RETENTION_DAYS[kind],\n // so evidence a host went out of its way to declare gets a fuse nobody chose\n // — and `expiresAt` is stamped per row at WRITE time, so it is unrecoverable\n // after the fact. Warn once at boot. An explicit retentionDays (including\n // `null` for immortal) is a choice and silences this; the warning is about\n // the host not having made one.\n for (const [name, spec] of Object.entries(registry)) {\n if (!spec.data) continue;\n if (Object.prototype.hasOwnProperty.call(spec, 'retentionDays')) continue;\n const days = RETENTION_DAYS[spec.kind];\n if (days == null) continue;\n logger.warn(\n `[telemetry] \"${name}\" declares \\`data\\` but inherits retentionDays=${days} from kind=${spec.kind} — ` +\n `its payloads are stamped to expire in ${days} days, and that cannot be undone after the write. ` +\n `Set an explicit retentionDays (null = immortal) to choose, and to silence this.`,\n );\n }\n\n const conn: Connection =\n (config.connection as { connection: Connection }).connection ??\n (config.connection as Connection);\n\n const counters = newCounters();\n const { TelemetryModel, byKind } = buildTelemetryModels({\n connection: conn, registry, counters, modelName, collection,\n platforms: config.platforms, bodyMax: config.bodyMax, validation: config.validation,\n });\n const RollupModel = buildRollupModel(conn, `${modelName}Rollup`, `${collection}_rollups`);\n const CheckpointModel = buildCheckpointModel(conn, `${modelName}Checkpoint`, `${collection}_checkpoints`);\n const KeyModel = buildKeyModel(conn, `${modelName}Key`, `${collection}_keys`);\n\n const rejects = () => conn.db!.collection(`${collection}_rejects`);\n const aliases = () => conn.db!.collection(`${collection}_aliases`);\n const views = () => conn.db!.collection(`${collection}_views`);\n\n // fire-and-forget writes are tracked so flush() can await stragglers —\n // tests and SIGTERM handlers both need \"everything emitted is queryable\"\n const inFlight = new Set<Promise<unknown>>();\n const track = (p: Promise<unknown>) => {\n inFlight.add(p);\n void p.finally(() => inFlight.delete(p));\n };\n\n // Resolved ONCE, and shared with the ingest router below rather than built\n // twice: the linker is a policy (dedupe, the declared-type refusal, the cap,\n // the timeout), and a policy that exists in two places is two policies.\n const linkSubjects = createSubjectLinking({\n linker: config.subjectLinker,\n timeoutMs: config.subjectLinkTimeoutMs,\n counters,\n logger,\n });\n\n const emit = createEmitter({\n registry, byKind, RollupModel, rejects, counters, logger, track, linkSubjects,\n });\n\n const forget = createForget({\n TelemetryModel,\n RollupModel,\n rejects: rejects as () => Collection,\n aliases: aliases as () => Collection,\n views: views as () => Collection,\n pepper: () => {\n const p = config.pepper ?? process.env.TELEMETRY_PEPPER;\n if (!p) {\n throw new Error(\n 'telemetry: forget() needs a pepper — pass `pepper` to createTelemetry() or set TELEMETRY_PEPPER',\n );\n }\n return p;\n },\n globalSubjectRefs: () => config.globalSubjectRefs === true,\n });\n\n // The BACKFILL half of subject linking, and it takes the same `linkSubjects`\n // the write path uses rather than a merge of its own — see relink.ts for why\n // a second copy of those rules would be unreconcilable rather than merely\n // duplicated.\n const relink = createRelink({\n registry, TelemetryModel, RollupModel, counters, logger, linkSubjects,\n });\n\n const syncIndexes = createSyncIndexes({\n registry,\n TelemetryModel,\n models: [TelemetryModel, ...Object.values(byKind), RollupModel, CheckpointModel, KeyModel],\n rejects: rejects as () => Collection,\n });\n\n return {\n /** write — the only write */\n emit,\n /** erasure: delete sole-party rows, redact shared ones, rekey rollups, drop aliases */\n forget,\n /**\n * Backfill: re-ask the `subjectLinker` about records ALREADY on disk, and\n * replay the rollups the new subjects reach.\n *\n * Linking happens at write time, so configuring it fixes the future and\n * nothing else — a lifetime `by:['subject']` family is keyed on the subject\n * the record was written with, and a read-time join cannot reach back into\n * it. This is how a host catches up the backlog it adopted the hook with.\n *\n * DRY RUN BY DEFAULT: it rewrites historical aggregates, so the short call\n * reports and the writing call says `{ dryRun: false }`. Idempotent by\n * construction — a row that already carries the linked subject yields\n * nothing new, so a second run is a no-op.\n */\n relink,\n /**\n * Tenant scope is not optional — force every read through here. The five\n * dashboard query primitives (records/series/distribution/rollups/journey)\n * build on these in the read layer.\n *\n * scoped() does NOT know about PLATFORM_SCOPE, and the omission is\n * deliberate. This is the host-facing isolation primitive, and its\n * guarantee is worth more unconditional: whatever string goes in, only rows\n * carrying that string come out. `scoped('*')` therefore scopes to the\n * literal '*' — and since '*' is reserved on the write side, it matches\n * nothing. The cross-tenant escape hatch lives one layer up, in the query\n * primitives behind viewerAdapter, where an authorization decision has\n * actually been made about who is asking.\n */\n scoped(tenantId: string) {\n // the pin spreads LAST — `{ tenantId, ...q }` would let a caller-supplied\n // tenantId in q override the scope, the exact hole scoped() exists to close\n return {\n find: (q: Record<string, unknown> = {}) => TelemetryModel.find({ ...q, tenantId }),\n aggregate: (stages: Record<string, unknown>[]) =>\n TelemetryModel.aggregate([{ $match: { tenantId } }, ...stages] as any[]),\n rollups: (q: Record<string, unknown> = {}) => RollupModel.find({ ...q, tenantId }),\n rollupAggregate: (stages: Record<string, unknown>[]) =>\n RollupModel.aggregate([{ $match: { tenantId } }, ...stages] as any[]),\n };\n },\n /** pull-importer watermark — advisory; downstream writers must be idempotent */\n checkpoint: createCheckpointFactory(CheckpointModel, logger),\n /** boot: build declared + registry-driven indexes, await before first write */\n syncIndexes,\n /** await in-flight fire-and-forget writes (tests, graceful shutdown) */\n async flush() {\n while (inFlight.size) await Promise.allSettled([...inFlight]);\n },\n /** drop/default/cap counts — surface on /metrics so drops are never silent */\n counters,\n /** the registry, exposed for the router factories — hosts should import their own */\n registry,\n /**\n * Write-time subject linking, exposed for the router factories. `null` when\n * no `subjectLinker` is configured.\n *\n * The wire path does not go through emit() — createIngest() builds its\n * record itself, because at-least-once delivery inverts the plane order\n * (insert first, THEN aggregate). So it reaches the linker the same way it\n * reaches the registry and the models: off the instance, running the one\n * implementation, rather than growing a second copy of the rules.\n */\n linkSubjects,\n logger,\n /** mint an ingest key; the full key string is returned once, never again */\n createKey: (input: CreateKeyInput) => createKey(KeyModel, input),\n /** the models, exposed for hosts and the router factories */\n models: {\n telemetry: TelemetryModel,\n byKind,\n rollups: RollupModel,\n checkpoints: CheckpointModel,\n keys: KeyModel,\n },\n /** side collections (rejects/aliases live outside mongoose models) */\n collections: { rejects, aliases },\n };\n}\n\nexport type Telemetry = ReturnType<typeof createTelemetry>;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/server/types.ts","../src/server/registry.ts","../src/server/model.ts","../src/server/rollups.ts","../src/server/checkpoint.ts","../src/server/emit.ts","../src/server/forget.ts","../src/server/relink.ts","../src/server/indexes.ts","../src/server/sourcemaps.ts","../src/server/keys.ts","../src/server/ingest.ts","../src/server/catalog.ts","../src/server/suggest.ts","../src/server/funnel.ts","../src/server/query.ts","../src/server/values.ts","../src/server/report.ts","../src/server/execute.ts","../src/server/views.ts","../src/server/dashboard.ts","../src/server/index.ts"],"names":["label","Schema","capped","newId","express","count","dim","path","rows","truncated","badRequest","dims","value","MEASURE_OP"],"mappings":"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","file":"index.js","sourcesContent":["import { uuidv7 } from 'uuidv7';\n\n/**\n * UUIDv7 — time-ordered, insertion-local. Node's crypto.randomUUID() is v4:\n * random, NOT sortable. Do not substitute it here; _ids double as insertion\n * order and traceIds are sampled on their low 32 bits (schema §2.6).\n */\nexport const newId = uuidv7;\n\nexport const TelemetryKind = {\n Event: 'event',\n Error: 'error',\n Span: 'span',\n State: 'state',\n Usage: 'usage',\n} as const;\nexport type TelemetryKind = (typeof TelemetryKind)[keyof typeof TelemetryKind];\n\nexport const TELEMETRY_KINDS: readonly TelemetryKind[] = Object.values(TelemetryKind);\n\nexport const LogLevel = {\n Debug: 'debug', Info: 'info', Warn: 'warn', Error: 'error', Fatal: 'fatal',\n} as const;\nexport type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];\n\nexport const Env = { Prod: 'prod', Staging: 'staging', Dev: 'dev' } as const;\nexport type Env = (typeof Env)[keyof typeof Env];\n\nexport const Origin = { Server: 'server', Client: 'client' } as const;\nexport type Origin = (typeof Origin)[keyof typeof Origin];\n\nexport type EntityRef = `${string}:${string}`;\n\nexport const UNKNOWN = 'unknown';\n\n/**\n * The platform read scope. A dashboard `Viewer` whose tenantId is `'*'` reads\n * ACROSS tenants — a support console, a platform-wide cost page. The package\n * never decides who is a platform admin; the host's `viewerAdapter` does. All\n * `'*'` buys is that the escape hatch is expressible and inside the boundary\n * instead of a host reaching around `scoped()`.\n *\n * Which is exactly why it is RESERVED on the write side. A tenant literally\n * named `'*'` would silently become a cross-tenant read — privilege escalation\n * via a string — so every path that can mint a tenantId from outside the\n * package refuses it: emit(), forget(), createKey() in fixed mode, and the\n * ingest handler once the tenant has resolved (key / session / claimed alike).\n */\nexport const PLATFORM_SCOPE = '*';\n\n/** true when a scope is the cross-tenant platform scope rather than a tenant */\nexport const isPlatformScope = (tenantId: unknown): boolean => tenantId === PLATFORM_SCOPE;\n\n/** one wording for the refusal, so the reservation is named wherever it bites */\nexport const RESERVED_TENANT_MESSAGE =\n `telemetry: tenantId \"${PLATFORM_SCOPE}\" is reserved for the dashboard's cross-tenant ` +\n 'platform scope and may never be written';\n\n/** null = never expires. Sized for small-SaaS volume; per-name override in EventSpec. */\nexport const RETENTION_DAYS: Record<TelemetryKind, number | null> = {\n // keep-all + 90d is cheap at this scale, and it makes p95-by-route a raw\n // query instead of a rollup design (schema §2.1)\n [TelemetryKind.Span]: 90,\n [TelemetryKind.Error]: 90,\n [TelemetryKind.Event]: 730,\n [TelemetryKind.State]: 730,\n [TelemetryKind.Usage]: null, // money is immortal\n};\n\n/**\n * Keep-all across the board — small-SaaS scale, exactness beats extrapolation.\n * The per-trace machinery stays, dormant: turn a kind down here (or one name\n * via EventSpec.sampleRate) when volume ever demands it. Rollups are exact\n * either way — they run before the verdict (schema §4.6).\n */\nexport const SAMPLE_RATE: Record<TelemetryKind, number> = {\n [TelemetryKind.Span]: 1,\n [TelemetryKind.Event]: 1,\n [TelemetryKind.Error]: 1, // raw storage burst-capped per fingerprint instead\n [TelemetryKind.State]: 1,\n [TelemetryKind.Usage]: 1, // NEVER sample. money.\n};\n\nexport const REJECT_TTL_DAYS = 30;\nexport const SCHEMA_VERSION = 2;\n\n/**\n * `body` is the only unbounded field on the envelope, and it feeds Mongo's\n * 16 MB document ceiling. Every other bound in the package is stated and\n * enforced (boundedMeta 4 KB, batch 512 KB / 100 records, index budget 24), so\n * this one is too. Override per instance with CreateTelemetryConfig.bodyMax.\n */\nexport const BODY_MAX_CHARS = 16_384;\n\n/** surfaced via t.counters so drops are never silent */\nexport interface TelemetryCounters {\n rejected: number;\n defaulted: number;\n sampled: number;\n capped: number;\n rollupSkipped: number;\n /** an insert-gated write whose dedupeKey (or usage.idempotencyKey) already existed */\n deduped: number;\n /** a `body` clipped to bodyMax — the row survives, marked */\n truncated: number;\n /**\n * `rollupSkipped`, attributed: `${family}|${dimLabel}` → count. Which family\n * dropped which dim — the difference between \"12 records went missing\" and\n * \"`screens_viewed` has no `dimDefault` for `name`\", which is a registry line\n * you can go and write. The scalar above is unchanged and still counts every\n * skip; this is additive.\n */\n rollupSkippedBy: Record<string, number>;\n /**\n * attrs keys seen on a record that its spec does not declare:\n * `${name}|${key}` → count. Under the default `validation: 'lenient'` those\n * keys are STRIPPED and the record is written (see attrsDropped below);\n * under `'strict'` the record is rejected. Either way this is the map that\n * names the registry line you are missing — suggest.ts turns it into zod.\n */\n undeclaredAttrs: Record<string, number>;\n /**\n * `${name}|${key}` → count: an attr REMOVED so the record could still be\n * written, under `validation: 'lenient'`. Two causes, one number, because\n * the fix is the same registry line either way: the key is undeclared, or\n * its value fell outside the declared schema (a client shipped a sixth\n * enum member the registry still lists five of).\n *\n * `${name}|(missing)` means stripping could not rescue the object — a\n * REQUIRED attr was absent — and the record was written without it anyway.\n * That one is an emitter bug, not registry drift.\n *\n * A non-zero value here is not an incident: it is the vocabulary drifting,\n * visible, while the events keep landing. Zero under `'strict'`.\n */\n attrsDropped: Record<string, number>;\n /** metrics keys removed for the same reasons — see attrsDropped. */\n metricsDropped: Record<string, number>;\n /**\n * Write-time subject linking (createSubjectLinking() in emit.ts). All six are\n * zero for a host with no `subjectLinker`, and they exist because linking is\n * the one part of the write path that runs HOST code: every way it can fail\n * ends in a record written unlinked, and a silently unlinked record is\n * indistinguishable from one nobody could link. The split says which.\n */\n /** subjects actually ADDED to records — two links on one record count twice */\n subjectsLinked: number;\n /** records where the linker answered `[]` — no link exists, which is an answer */\n subjectLinkMisses: number;\n /** the linker threw, rejected, or returned something that is not a list of refs */\n subjectLinkErrors: number;\n /** the linker outran subjectLinkTimeoutMs and the record was written unlinked */\n subjectLinkTimeouts: number;\n /** a linked subject whose `type` the event's EventSpec.subjects does not declare */\n subjectLinkUndeclared: number;\n /** a linked subject dropped because the record already held SUBJECT_MAX of them */\n subjectLinkCapped: number;\n}\n\nexport const newCounters = (): TelemetryCounters => ({\n rejected: 0, defaulted: 0, sampled: 0, capped: 0, rollupSkipped: 0,\n deduped: 0, truncated: 0, rollupSkippedBy: {}, undeclaredAttrs: {},\n attrsDropped: {}, metricsDropped: {},\n subjectsLinked: 0, subjectLinkMisses: 0, subjectLinkErrors: 0,\n subjectLinkTimeouts: 0, subjectLinkUndeclared: 0, subjectLinkCapped: 0,\n});\n\n/**\n * Distinct keys either attributed counter map will hold. Both are keyed on\n * data a CLIENT controls — an event name, an attr key — so an unbounded map is\n * a way to grow this process's heap from the outside. Past the cap every new\n * key folds into one `(other)` bucket: the total stays honest, only the\n * attribution stops. A host seeing `(other)` climbing has either a hostile\n * client or a registry that is very far behind.\n */\n/**\n * What a record does when its attrs or metrics do not match the registry.\n *\n * `'lenient'` (the default): strip the offending keys, count them, and WRITE\n * the record. `'strict'`: reject the whole record into the quarantine.\n *\n * The default is lenient because the strict failure mode is the expensive one\n * and it is silent. A registry is a vocabulary maintained in one repo about\n * events emitted from another; the day a client ships a sixth value for a\n * five-value enum, strict mode throws away the WHOLE record — its name, its\n * subject, its metrics, its place in a funnel — to punish one attr. And it\n * does so behind a 202, so nothing surfaces at the emitter. Losing\n * `export.completed` because `outputs` gained an option is not validation\n * working; it is a schema mismatch deleting the evidence a product decision\n * would have been made from.\n *\n * What strictness legitimately protects is unchanged: `data` is still parsed\n * strictly (it is the one free-text corner, so it is a privacy boundary, not a\n * vocabulary one), a missing REQUIRED SUBJECT is still a hard reject (that is\n * structural, not drift), and rollup dimension cardinality is still bounded —\n * a stripped attr simply resolves to the family's `dimDefault`.\n */\nexport type ValidationPolicy = 'lenient' | 'strict';\n\nexport const COUNTER_MAP_MAX = 1000;\n\n/** the fold-here bucket, shaped like a real key so readers can split it the same way */\nexport const COUNTER_OVERFLOW_KEY = '(other)|(other)';\n\n/** `map[key]++`, bounded. Names no registry entry once it folds — see COUNTER_MAP_MAX. */\nexport const bumpCounterMap = (map: Record<string, number>, key: string): void => {\n const seen = map[key];\n if (seen !== undefined) {\n map[key] = seen + 1;\n return;\n }\n // The size check is O(n) and runs only on a key never seen before; once the\n // overflow bucket exists the map is known full, so it short-circuits and a\n // storm of distinct keys stays O(1) per record.\n if (map[COUNTER_OVERFLOW_KEY] !== undefined || Object.keys(map).length >= COUNTER_MAP_MAX) {\n map[COUNTER_OVERFLOW_KEY] = (map[COUNTER_OVERFLOW_KEY] ?? 0) + 1;\n return;\n }\n map[key] = 1;\n};\n\n/**\n * Consistent probability sampling — deterministic per trace, no propagation\n * needed. A traceId with no parseable hex tail silently degrades to per-record\n * sampling, which invalidates every per-trace aggregate (schema §2.6). That is\n * a bug in the caller's id generation, so it fails loudly in dev rather than\n * skewing data in prod.\n */\nexport const traceKeep = (traceId: string | undefined, rate: number): boolean => {\n if (rate >= 1) return true;\n if (!traceId) return Math.random() < rate;\n const tail = parseInt(traceId.slice(-8), 16);\n if (!Number.isFinite(tail)) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `telemetry: traceId \"${traceId}\" has no parseable hex tail — trace-consistent ` +\n `sampling is impossible and would degrade to per-record. Use UUIDv7 or a ` +\n `32-hex OTel trace id.`,\n );\n }\n return Math.random() < rate;\n }\n return tail / 0xffffffff < rate;\n};\n\n/** Map has no toJSON — JSON.stringify(new Map()) is '{}'. Never stringify raw. */\nexport const plain = (v: unknown): unknown =>\n v instanceof Map ? Object.fromEntries([...v].map(([k, x]) => [k, plain(x)]))\n : Array.isArray(v) ? v.map(plain)\n : v instanceof Date ? v\n : v && typeof v === 'object' ? Object.fromEntries(Object.entries(v).map(([k, x]) => [k, plain(x)]))\n : v;\n\nexport interface Logger {\n info(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n}\n\nexport const noopLogger: Logger = { info() {}, warn() {}, error() {} };\n","import { z } from 'zod';\nimport { TelemetryKind, TELEMETRY_KINDS } from './types.js';\n\n/**\n * The registry is the single contract: it drives validation, TypeScript types,\n * derived rollups, and index creation. It is HOST-OWNED — the host authors it\n * in their own code and passes it to createTelemetry(); this package never\n * ships event names (schema §4.2, instrumentation §8).\n */\n\n/**\n * A dimension source. `subject` fans the rollup out over matching subject refs;\n * `attr:`/`field:` read one value off the record.\n */\nexport type DimSource = 'subject' | `attr:${string}` | `field:${string}`;\n\n/**\n * Derived aggregate maintained on write (schema §4.5). One primitive, four\n * jobs: milestones, issue grouping, windowed spend, activity/retention.\n */\nexport interface RollupSpec {\n /** rollup family — several event names may feed one. Default: the event name */\n as?: string;\n /** dimensions, in order. At most one `subject`. */\n by: readonly DimSource[];\n /** when `by` includes `subject`, restrict to these subject types */\n subjects?: readonly string[];\n /**\n * Actor TYPE allowlist — a record whose `actor` has a type not listed here\n * skips this rollup; the raw row is unaffected. Absent = all actors; a record\n * with no actor always passes. This is how \"admin support browsing never\n * moves a customer aggregate\" is declared rather than disciplined.\n */\n actors?: readonly string[];\n /** time bucket (UTC). Omit for a lifetime rollup — that is the classic milestone.\n * `hour` is for incident-grade dashboards; anything finer is the wrong store. */\n bucket?: 'hour' | 'day' | 'week' | 'month';\n /** metric keys accumulated with $add */\n sum?: readonly string[];\n /** dimension sources snapshotted at FIRST occurrence — cohort dimensions */\n capture?: readonly DimSource[];\n /**\n * Bucket name for a non-subject dim that resolves null/empty. Absent keeps\n * the default: skip the record and count it in `rollupSkipped`. Present makes\n * \"no value\" an explicit, queryable group instead of a silent drop.\n *\n * The SUBJECT dim is unaffected — see the fan-out comment in rollups.ts.\n */\n dimDefault?: string;\n /** rollup TTL. Omit or null = immortal (bucketed rollups usually want a number) */\n retentionDays?: number | null;\n}\n\nexport interface EventSpec {\n kind: TelemetryKind;\n origin: 'server' | 'client' | 'any';\n /** subject TYPES that must be present (any number of ids per type) */\n subjects: readonly string[];\n /** attrs values are STRINGS after Mongoose casting — use z.string()/z.enum()/z.coerce.* */\n attrs?: z.ZodObject<any>;\n metrics?: z.ZodObject<any>;\n /**\n * `data` is UNSTORED unless declared here. Closes the erasure hole.\n *\n * Declare an OBJECT schema (or `boundedMeta()`). The type is the looser\n * `ZodType` so `boundedMeta()`'s transform fits, but `EmitInput.data` is an\n * object — a scalar schema like `z.string()` is expressible here and\n * unreachable through emit().\n */\n data?: z.ZodType<any>;\n /** attrs keys that get a real partial compound index built at boot */\n indexedAttrs?: readonly string[];\n /** metrics keys, same machinery — enables indexed numeric range queries */\n indexedMetrics?: readonly string[];\n /** derived aggregates maintained on write — funnels, issues, spend, retention */\n rollups?: readonly RollupSpec[];\n /** overrides RETENTION_DAYS[kind]. null = immortal */\n retentionDays?: number | null;\n /** overrides SAMPLE_RATE[kind]. Dormant by default — every kind ships at 1. */\n sampleRate?: number;\n /**\n * Rate cap on RAW storage per resolved key, per minute. Rollups still see\n * every record, so counts stay exact while an error storm or a client in a\n * retry loop cannot flood the collection. Omit `key` to cap the name whole.\n */\n burst?: { key?: DimSource; maxPerMinute: number };\n /**\n * Await the write with `{w:'majority', j:true}` and rethrow on failure — the\n * contract usage has always had, now declarable. For the host whose cost\n * ledger is a span: without it the only way to await was t.flush(), which\n * drains every in-flight write globally and serializes a busy worker.\n * kind=usage is durable unconditionally, with or without this flag.\n */\n durable?: boolean;\n description: string;\n}\n\nexport type Registry = Record<string, EventSpec>;\n\n/** Identity with a `const` type parameter so literal specs keep their shapes. */\nexport function defineRegistry<const R extends Registry>(specs: R): R {\n return specs;\n}\n\n/**\n * The maxed-shaped `data` escape hatch (build-plan §0.5): scalars only, ≤12\n * keys, strings ≤200 chars, one nesting level, ≤4 KB serialized. Violation\n * drops the WHOLE object — never truncates — so a stored payload is always\n * exactly what the caller sent. Parsing never throws; out-of-bounds resolves\n * to undefined and emit() counts the drop.\n */\nexport function boundedMeta(): z.ZodType<Record<string, unknown> | undefined> {\n const scalar = (v: unknown) =>\n v === null || typeof v === 'boolean' ||\n (typeof v === 'number' && Number.isFinite(v)) ||\n (typeof v === 'string' && v.length <= 200);\n\n const flat = (v: unknown): boolean => {\n if (scalar(v)) return true;\n if (Array.isArray(v)) return v.length <= 20 && v.every(scalar);\n if (v && typeof v === 'object' && !(v instanceof Date)) {\n const entries = Object.entries(v as Record<string, unknown>);\n return entries.length <= 12 && entries.every(([, x]) => scalar(x));\n }\n return false;\n };\n\n const bounded = (v: unknown): v is Record<string, unknown> => {\n if (!v || typeof v !== 'object' || Array.isArray(v) || v instanceof Date) return false;\n const entries = Object.entries(v as Record<string, unknown>);\n if (entries.length > 12) return false;\n if (!entries.every(([, x]) => flat(x))) return false;\n try {\n return JSON.stringify(v).length <= 4096;\n } catch {\n return false; // circular\n }\n };\n\n return z.unknown().transform((v) => (bounded(v) ? (v as Record<string, unknown>) : undefined));\n}\n\nconst DIM_RE = /^(subject|attr:.+|field:.+)$/;\n\n/**\n * Boot-time registry validation — misconfiguration fails deploy, not\n * dashboards. Covers per-spec sanity AND the cross-spec family-shape rule:\n * two events feeding one `as` with different `by` shapes produce docs whose\n * dims array means different things at the same position — silently\n * unqueryable (schema §4.5).\n */\nexport function validateRegistry(registry: Registry): void {\n const shapes = new Map<string, string>();\n\n for (const [name, spec] of Object.entries(registry)) {\n const fail = (msg: string) => {\n throw new Error(`telemetry: registry \"${name}\": ${msg}`);\n };\n\n if (!TELEMETRY_KINDS.includes(spec.kind)) fail(`unknown kind \"${spec.kind}\"`);\n if (!['server', 'client', 'any'].includes(spec.origin)) fail(`unknown origin \"${spec.origin}\"`);\n if (!Array.isArray(spec.subjects)) fail('`subjects` must be an array of subject types');\n if (spec.sampleRate != null && !(spec.sampleRate > 0 && spec.sampleRate <= 1)) {\n fail(`sampleRate ${spec.sampleRate} outside (0, 1]`);\n }\n if (spec.burst && !(spec.burst.maxPerMinute > 0)) fail('burst.maxPerMinute must be positive');\n if (spec.burst?.key && !DIM_RE.test(spec.burst.key)) fail(`bad burst key \"${spec.burst.key}\"`);\n for (const k of spec.indexedAttrs ?? []) {\n if (!spec.attrs || !(k in spec.attrs.shape)) fail(`indexedAttrs \"${k}\" not declared in attrs`);\n }\n for (const k of spec.indexedMetrics ?? []) {\n if (!spec.metrics || !(k in spec.metrics.shape)) fail(`indexedMetrics \"${k}\" not declared in metrics`);\n }\n\n for (const r of spec.rollups ?? []) {\n if (!r.by?.length) fail('rollup has empty `by`');\n for (const d of r.by) if (!DIM_RE.test(d)) fail(`bad dim source \"${d}\"`);\n if (r.by.filter((d) => d === 'subject').length > 1) {\n fail('rollup has more than one subject dim');\n }\n if (r.by.includes('subject') && !r.subjects?.length) {\n fail('rollup uses subject without `subjects`');\n }\n if (r.actors && !r.actors.length) fail('rollup `actors` must be non-empty when present');\n if (r.dimDefault !== undefined) {\n // dims are `label=value` and the rollup `_id` joins them on `|`, so\n // either character in the bucket name corrupts the key itself\n if (typeof r.dimDefault !== 'string' || !r.dimDefault) {\n fail('rollup `dimDefault` must be a non-empty string');\n }\n if (/[|=]/.test(r.dimDefault)) fail(`rollup dimDefault \"${r.dimDefault}\" may not contain \"|\" or \"=\"`);\n }\n\n const as = r.as ?? name;\n // shape = dims + bucket + subject classes: any mismatch makes docs in one\n // family mean different things at the same array position (or triggers\n // the null-join inflation of schema §5.4), so all three pin per family.\n // dimDefault is NOT part of the shape — it changes which bucket a record\n // lands in, never what a position MEANS, so two names may feed one family\n // with different fallbacks.\n const shape =\n r.by.join(',') + '|' + (r.bucket ?? '') + '|' + [...(r.subjects ?? [])].sort().join(',');\n const seen = shapes.get(as);\n if (seen && seen !== shape) {\n throw new Error(`telemetry: rollup family \"${as}\" declared with two shapes: ${seen} / ${shape}`);\n }\n shapes.set(as, shape);\n }\n }\n}\n","import { Schema, type Connection, type Model } from 'mongoose';\nimport {\n TelemetryKind, LogLevel, Env, Origin,\n BODY_MAX_CHARS, RETENTION_DAYS, SCHEMA_VERSION, UNKNOWN, newId, bumpCounterMap,\n type TelemetryCounters, type ValidationPolicy,\n} from './types.js';\nimport type { Registry } from './registry.js';\n\n/** Mongoose Map keys cannot contain dots. gen_ai.request.model -> gen_ai_request_model */\nconst safeKey = (k: string) => k.replace(/\\./g, '_');\nconst sanitize = <T>(m?: Map<string, T>) =>\n m ? new Map([...m].map(([k, v]) => [safeKey(k), v] as [string, T])) : m;\n\n// ── subdocs ─────────────────────────────────────────────────────────────────\n\nconst SubjectRefSchema = new Schema(\n {\n type: { type: String, required: true }, // user | org | team | session\n id: { type: String, required: true },\n /** disambiguates same-type parties: sender | recipient | impersonated */\n role: { type: String },\n },\n { _id: false },\n);\n\n/**\n * The platforms this package ships knowing about. A host may EXTEND the list\n * (CreateTelemetryConfig.platforms) but never replace it — a host adding\n * 'watchos' must not lose 'web'.\n */\nexport const BUILTIN_PLATFORMS = ['web', 'electron', 'ios', 'android', 'server', 'cli'] as const;\n\n/**\n * A factory, not a module-level const, because the enum varies per instance.\n * Everything else in the envelope is open on purpose (`name`, `feature`,\n * `attrs`); a closed platform enum was the one place a host had to lie.\n */\nconst buildClientContextSchema = (platforms: readonly string[]) =>\n new Schema(\n {\n platform: { type: String, required: true, enum: platforms },\n appVersion: { type: String, required: true },\n userAgent: String,\n os: String,\n osVersion: String,\n browser: String,\n browserVersion: String,\n deviceType: String, // desktop | mobile | tablet\n locale: String,\n timezone: String,\n screenW: Number,\n screenH: Number,\n viewportW: Number,\n viewportH: Number,\n connection: String, // 4g | wifi | slow-2g\n online: Boolean,\n /** client clock minus server clock, ms — client timestamps lie */\n clockSkewMs: Number,\n },\n { _id: false },\n );\n\nconst StackFrameSchema = new Schema(\n {\n filename: String,\n fn: String,\n lineno: Number,\n colno: Number,\n inApp: Boolean,\n context: [String],\n },\n { _id: false },\n);\n\nconst ErrorDetailSchema = new Schema(\n {\n type: { type: String, required: true },\n message: { type: String, required: true },\n handled: { type: Boolean, required: true, default: false },\n /** grouping key */\n fingerprint: { type: String, required: true },\n frames: [StackFrameSchema],\n },\n { _id: false },\n);\n\nconst StateDetailSchema = new Schema(\n {\n key: { type: String, required: true }, // 'lifecycle' | 'onboarding_step'\n from: String,\n to: { type: String, required: true },\n /** how long the subject sat in `from` — answers \"where do they stall\" */\n previousSinceMs: Number,\n },\n { _id: false },\n);\n\nconst UsageDetailSchema = new Schema(\n {\n meter: { type: String, required: true },\n quantity: { type: Number, required: true },\n unit: { type: String, required: true },\n /**\n * Authoritative money. `metrics.cost_usd` is a BSON double — fine as a\n * measure, wrong as the thing that becomes an invoice. Money is\n * authoritative only on kind=usage; the metric is a lossy copy.\n */\n amount: Schema.Types.Decimal128,\n currency: String,\n /** at-least-once dedupe. Deterministic, e.g. `${traceId}:${spanId}` */\n idempotencyKey: { type: String, required: true },\n /** who pays — 'org:o_9'. Distinct from subject and from actor. */\n billedTo: { type: String, required: true },\n billable: { type: Boolean, required: true, default: true },\n priceVersion: String,\n /** corrections are new reversing rows; never UPDATE a billed row */\n reverses: String,\n },\n { _id: false },\n);\n\n// ── base schema ─────────────────────────────────────────────────────────────\n\nfunction buildBaseSchema(\n collection: string,\n registry: Registry,\n counters: TelemetryCounters,\n opts: { platforms: readonly string[]; bodyMax: number; validation: ValidationPolicy },\n) {\n const validation = opts.validation;\n const schema = new Schema(\n {\n /** UUIDv7 — sortable, insertion-local, replaces the ObjectId */\n _id: { type: String, required: true },\n schemaVersion: { type: Number, required: true },\n occurredAt: { type: Date, required: true },\n name: { type: String, required: true },\n severity: { type: String, required: true, enum: Object.values(LogLevel), default: LogLevel.Info },\n\n // ── identity ──\n /** tenancy root: shard key, access boundary, index prefix. The only promoted id. */\n tenantId: { type: String, required: true },\n /** multi-party capable: two users, sender/recipient, admin+impersonated */\n subjects: { type: [SubjectRefSchema], default: [] },\n /** derived: ['user:u_1','org:o_9'] */\n subjectKeys: { type: [String] },\n /** who caused it */\n actor: String,\n /** impersonation / delegation */\n onBehalfOf: String,\n /** derived: actor/onBehalfOf NOT already in subjects. Erasure completeness. */\n otherPrincipals: { type: [String] },\n\n // ── origin — required, but filled by the pre-validate hook, NEVER `default:`.\n // A schema default is applied at construction, before the hook, which would\n // silently stamp dev traffic as prod and pin counters.defaulted at zero\n // forever (schema §7 / ops rule 5).\n service: { type: String, required: true },\n release: { type: String, required: true },\n env: { type: String, required: true, enum: Object.values(Env) },\n\n origin: { type: String, enum: Object.values(Origin), default: Origin.Server },\n /** required for client-origin events (enforced by the registry hook, not the schema) */\n client: buildClientContextSchema(opts.platforms),\n\n /**\n * Caller-supplied idempotency for the four non-usage kinds — a Stripe\n * webhook redelivery, a nightly lifecycle diff, a bridge that rewinds its\n * watermark by design. Trusted server callers only; the wire dedupes on\n * the client `_id` instead.\n *\n * Deliberately NOT an `_id` passthrough: `_id` is a UUIDv7 and doubles as\n * insertion order (§2.6), so letting a caller supply an arbitrary string\n * would break that invariant for every reader that sorts on it.\n */\n dedupeKey: String,\n\n // ── correlation ──\n traceId: String,\n spanId: String,\n parentId: String,\n durationMs: Number,\n\n // ── payload — no wildcard index; registry-driven indexes instead (§4.4) ──\n /** STRING VALUES ONLY — Mongoose casts on assignment. Numbers belong in metrics. */\n attrs: { type: Map, of: String, default: {} },\n metrics: { type: Map, of: Number, default: {} },\n /** only stored when the registry declares a schema for it */\n data: { type: Schema.Types.Mixed },\n body: String,\n\n // ── ops ──\n /** 1 = kept everything. 0.05 = multiply counts by 20 when aggregating. */\n sampleRate: { type: Number, default: 1 },\n /** kept despite sampling (carried money or an error). NOT representative. */\n forced: { type: Boolean, default: false },\n expiresAt: Date,\n /** set by forget() — row survives, identifiers do not */\n redactedAt: Date,\n },\n {\n collection,\n discriminatorKey: 'kind',\n timestamps: { createdAt: 'receivedAt', updatedAt: false },\n versionKey: false,\n minimize: false,\n },\n );\n\n // every subject, tenant-scoped and time-sorted, from ONE multikey compound\n // index — explain()-verified 2026-08-10 (schema §2.5)\n schema.index({ tenantId: 1, subjectKeys: 1, occurredAt: -1 });\n schema.index({ tenantId: 1, kind: 1, name: 1, occurredAt: -1 });\n schema.index(\n { traceId: 1, occurredAt: 1 },\n { partialFilterExpression: { traceId: { $exists: true } } },\n );\n // erasure completeness — usually a tiny array, so cheap to maintain.\n // `.0 $exists` = \"array non-empty\"; `$ne: []` is illegal in a partial filter.\n schema.index(\n { tenantId: 1, otherPrincipals: 1 },\n { partialFilterExpression: { 'otherPrincipals.0': { $exists: true } } },\n );\n // partial: usage rows have no expiresAt and must not be indexed as null\n schema.index(\n { expiresAt: 1 },\n { expireAfterSeconds: 0, partialFilterExpression: { expiresAt: { $exists: true } } },\n );\n // caller idempotency, tenant-scoped. The partial filter is load-bearing for\n // exactly the reason it is on usage.idempotencyKey (ops rule 4): without it\n // every record WITHOUT a dedupeKey indexes null and the second one collides.\n schema.index(\n { tenantId: 1, dedupeKey: 1 },\n { unique: true, partialFilterExpression: { dedupeKey: { $exists: true } } },\n );\n\n schema.pre('validate', function (this: any) {\n this._id ??= newId();\n this.schemaVersion ??= SCHEMA_VERSION;\n this.occurredAt ??= new Date();\n\n this.attrs = sanitize(this.attrs);\n this.metrics = sanitize(this.metrics);\n\n // `body` is the sole unbounded field feeding the 16 MB document limit.\n // Enforced HERE rather than in emit() so every write path is covered —\n // emit, ingest, and direct model use alike.\n //\n // This deliberately DIVERGES from boundedMeta's drop-never-truncate\n // doctrine, and the difference is the data, not the mood: `data` is\n // structured evidence where a partial object is a lie about what the caller\n // sent, whereas `body` is prose/log text where a marked prefix is strictly\n // more useful than nothing. The marker is visible so no reader mistakes the\n // prefix for the whole.\n if (typeof this.body === 'string' && this.body.length > opts.bodyMax) {\n const dropped = this.body.length - opts.bodyMax;\n this.body = `${this.body.slice(0, opts.bodyMax)}… [truncated ${dropped} chars]`;\n counters.truncated++;\n }\n\n // ── derived identity arrays ──\n const refs: string[] = (this.subjects ?? []).map((s: any) => `${s.type}:${s.id}`);\n this.subjectKeys = [...new Set(refs)];\n this.otherPrincipals = [\n ...new Set(\n [this.actor, this.onBehalfOf].filter((r): r is string => !!r && !refs.includes(r)),\n ),\n ];\n\n // Never fail on missing origin metadata — default and COUNT.\n for (const f of ['service', 'release'] as const) {\n if (!this[f]) {\n this[f] = UNKNOWN;\n counters.defaulted++;\n }\n }\n if (!this.env) {\n this.env = process.env.NODE_ENV === 'production' ? Env.Prod : Env.Dev;\n }\n\n const spec = registry[this.name];\n if (!spec) throw new Error(`telemetry: unregistered event \"${this.name}\"`);\n if (spec.kind !== this.kind) throw new Error(`telemetry: \"${this.name}\" is kind=${spec.kind}`);\n\n // retention: per-event override, else per-kind. `in` rather than `??` so an\n // explicit `retentionDays: null` means immortal.\n const days = 'retentionDays' in spec ? spec.retentionDays : RETENTION_DAYS[this.kind as TelemetryKind];\n if (days != null && !this.expiresAt) {\n this.expiresAt = new Date(this.occurredAt.getTime() + days * 864e5);\n }\n\n const haveTypes = new Set((this.subjects ?? []).map((s: any) => s.type));\n for (const t of spec.subjects) {\n if (!haveTypes.has(t)) throw new Error(`telemetry: \"${this.name}\" requires subject \"${t}\"`);\n }\n if (spec.origin === Origin.Client && !this.client) {\n throw new Error(`telemetry: \"${this.name}\" is client-origin and requires client context`);\n }\n\n // per-kind requiredness lives HERE so the guarantee never depends on how a\n // particular mongoose version merges discriminator schema requiredness\n if (this.kind === TelemetryKind.Span) {\n for (const f of ['traceId', 'spanId'] as const) {\n if (!this[f]) throw new Error(`telemetry: span requires ${f}`);\n }\n if (typeof this.durationMs !== 'number') throw new Error('telemetry: span requires durationMs');\n }\n if (this.kind === TelemetryKind.State && !this.state?.to) {\n throw new Error('telemetry: state requires state.to');\n }\n\n /**\n * Validate attrs/metrics against the spec.\n *\n * Under `validation: 'strict'` this throws and the whole record is\n * quarantined — the behaviour every version before 0.7.0 had, and the one\n * that quietly deletes an `export.completed` because its `outputs` enum\n * grew a sixth member in another repo.\n *\n * Under `'lenient'` (the default) the offending KEYS are removed, counted\n * by name, and the record is written with whatever survived. The record is\n * the valuable part: its name, its subject, its timestamp, its metrics and\n * its place in a funnel do not become wrong because one attr drifted.\n *\n * The Map is mutated rather than the parsed object returned, because the\n * Map is what mongoose persists — the success path here has never written\n * `r.data` back, and this must not start coercing values that used to pass\n * through untouched.\n */\n const check = (\n label: 'attrs' | 'metrics',\n m: Map<string, unknown> | undefined,\n zschema?: any,\n ) => {\n const obj = Object.fromEntries(m ?? []);\n const dropped = label === 'attrs' ? counters.attrsDropped : counters.metricsDropped;\n const note = (key: string) => bumpCounterMap(dropped, `${this.name}|${key}`);\n\n if (!zschema) {\n if (!Object.keys(obj).length) return;\n if (validation === 'strict') throw new Error(`telemetry: \"${this.name}\" declares no ${label}`);\n for (const key of Object.keys(obj)) {\n note(key);\n m?.delete(key);\n }\n return;\n }\n\n const s = zschema.strict?.() ?? zschema;\n const r = s.safeParse(obj);\n if (r.success) return;\n if (validation === 'strict') {\n throw new Error(`telemetry: ${label} invalid for \"${this.name}\": ${r.error.message}`);\n }\n\n // Which keys did zod object to? `unrecognized_keys` names them directly;\n // every other issue is attributed to the head of its path.\n const bad = new Set<string>();\n for (const issue of r.error.issues as any[]) {\n if (issue.code === 'unrecognized_keys' && Array.isArray(issue.keys)) {\n for (const k of issue.keys) bad.add(String(k));\n } else if (Array.isArray(issue.path) && issue.path.length) {\n bad.add(String(issue.path[0]));\n }\n }\n\n for (const key of bad) {\n // A key zod named but the record does not carry is a REQUIRED attr the\n // emitter omitted. Nothing to strip; count it under its own label so it\n // reads as the emitter bug it is rather than as registry drift.\n if (m?.has(key)) {\n note(key);\n m.delete(key);\n } else {\n note('(missing)');\n }\n }\n };\n check('attrs', this.attrs, spec.attrs);\n check('metrics', this.metrics, spec.metrics);\n\n // `data` is dropped unless the registry declares a schema for it. This is\n // what makes delete-by-subject a guarantee rather than best-effort.\n if (this.data != null) {\n const s: any = spec.data;\n if (!s) {\n this.data = undefined;\n counters.rejected++;\n } else {\n const strict = s.strict?.() ?? s;\n const r = strict.safeParse(this.data);\n if (!r.success) throw new Error(`telemetry: data invalid for \"${this.name}\": ${r.error.message}`);\n if (r.data === undefined) counters.rejected++; // boundedMeta out-of-bounds: drop whole, never truncate\n this.data = r.data;\n }\n }\n });\n\n return schema;\n}\n\n// ── discriminators ──────────────────────────────────────────────────────────\n\nexport interface TelemetryModels {\n /** the base model — query across every kind */\n TelemetryModel: Model<any>;\n /** per-kind discriminator models */\n byKind: Record<TelemetryKind, Model<any>>;\n}\n\n/**\n * Model factory. Mongoose keeps compiled models in a per-connection registry,\n * so a name collision throws OverwriteModelError. Reuse an already-compiled\n * model when the name is taken (standards/traps.md #2) — but note the caveat:\n * the reused model closed over the FIRST instance's registry and counters.\n * Hosts running two registries on one connection must set distinct modelNames.\n */\nexport function buildTelemetryModels(opts: {\n connection: Connection;\n registry: Registry;\n counters: TelemetryCounters;\n modelName: string;\n collection: string;\n /** host additions to the builtin platform enum — union, never replacement */\n platforms?: readonly string[];\n bodyMax?: number;\n /** what a vocabulary mismatch costs — see ValidationPolicy. Default 'lenient'. */\n validation?: ValidationPolicy;\n}): TelemetryModels {\n const { connection, registry, counters, modelName, collection } = opts;\n const platforms = [...new Set([...BUILTIN_PLATFORMS, ...(opts.platforms ?? [])])];\n const bodyMax = opts.bodyMax ?? BODY_MAX_CHARS;\n\n const existing = connection.models?.[modelName];\n if (existing) {\n return {\n TelemetryModel: existing,\n byKind: Object.fromEntries(\n Object.values(TelemetryKind).map((k) => [k, (existing.discriminators ?? {})[`${modelName}_${k}`] ?? existing]),\n ) as Record<TelemetryKind, Model<any>>,\n };\n }\n\n const base = buildBaseSchema(collection, registry, counters, {\n platforms,\n bodyMax,\n validation: opts.validation ?? 'lenient',\n });\n const TelemetryModel = connection.model(modelName, base);\n\n const disc = (kind: TelemetryKind, build: () => Schema) =>\n TelemetryModel.discriminator(`${modelName}_${kind}`, build(), kind);\n\n const byKind: Record<TelemetryKind, Model<any>> = {\n [TelemetryKind.Event]: disc(TelemetryKind.Event, () => new Schema({})), // envelope suffices\n\n [TelemetryKind.Error]: disc(TelemetryKind.Error, () => {\n const s = new Schema({ error: { type: ErrorDetailSchema, required: true } });\n s.index(\n { tenantId: 1, 'error.fingerprint': 1, occurredAt: -1 },\n { partialFilterExpression: { kind: TelemetryKind.Error } },\n );\n return s;\n }),\n\n [TelemetryKind.Span]: disc(TelemetryKind.Span, () => {\n // traceId/spanId/durationMs requiredness enforced in the pre-validate hook\n const s = new Schema({});\n s.index(\n { traceId: 1, parentId: 1 },\n { partialFilterExpression: { kind: TelemetryKind.Span } },\n );\n return s;\n }),\n\n [TelemetryKind.State]: disc(TelemetryKind.State, () => {\n const s = new Schema({ state: { type: StateDetailSchema, required: true } });\n s.index(\n { tenantId: 1, 'state.key': 1, 'state.to': 1, occurredAt: -1 },\n { partialFilterExpression: { kind: TelemetryKind.State } },\n );\n return s;\n }),\n\n [TelemetryKind.Usage]: disc(TelemetryKind.Usage, () => {\n const s = new Schema({ usage: { type: UsageDetailSchema, required: true } });\n // partialFilterExpression is load-bearing: discriminator indexes apply to\n // the WHOLE collection, so without it every non-usage doc indexes\n // idempotencyKey as null and the second one collides (ops rule 4)\n s.index(\n { 'usage.idempotencyKey': 1 },\n { unique: true, partialFilterExpression: { kind: TelemetryKind.Usage } },\n );\n s.index(\n { tenantId: 1, 'usage.meter': 1, occurredAt: 1 },\n { partialFilterExpression: { kind: TelemetryKind.Usage } },\n );\n return s;\n }),\n };\n\n return { TelemetryModel, byKind };\n}\n","import { Schema, type Connection, type Model } from 'mongoose';\nimport type { DimSource, Registry, RollupSpec } from './registry.js';\nimport { bumpCounterMap, type TelemetryCounters } from './types.js';\n\n/**\n * One derived-aggregate primitive (schema §4.5). Group a stream of records by\n * a declared tuple and keep first / last / count / sums. The registry declares\n * the tuple; this file is agnostic — the same operation is a milestone, an\n * issue group, windowed spend, and an activity/retention stream.\n */\n\nexport function buildRollupModel(connection: Connection, modelName: string, collection: string): Model<any> {\n const existing = connection.models?.[modelName];\n if (existing) return existing;\n\n const schema = new Schema(\n {\n /** `${tenantId}|${as}|${dims.join('|')}|${bucketKey}` — deterministic, upsert-safe */\n _id: { type: String, required: true },\n tenantId: { type: String, required: true },\n /** rollup family. Several event names may feed one. */\n as: { type: String, required: true },\n /**\n * Dimension values in spec order. Subject dims keep their native\n * `type:id` form ('user:u_1') so erasure can match them directly;\n * everything else is `key=value`. Flattened strings for the same reason\n * subjectKeys is — never compound-index two fields of one subdoc array.\n */\n dims: { type: [String], required: true },\n /** denormalized prefix of the subject dim, when there is one — §5.4 hazard */\n subjectType: String,\n /** UTC-truncated bucket start; absent on lifetime rollups */\n bucketAt: Date,\n\n firstAt: { type: Date, required: true },\n lastAt: { type: Date, required: true },\n count: { type: Number, required: true, default: 0 },\n /** registry `sum` keys accumulated across every contributing record */\n sums: { type: Map, of: Number, default: {} },\n /** registry `capture` snapshot at FIRST occurrence — cohort dimensions */\n firstCapture: { type: Map, of: String, default: {} },\n firstTraceId: String,\n expiresAt: Date,\n },\n { collection, versionKey: false },\n );\n\n // cohort scan within one family, ordered by first occurrence\n schema.index({ tenantId: 1, as: 1, subjectType: 1, firstAt: 1 });\n // slice a family by dimension value, newest bucket first\n schema.index({ tenantId: 1, as: 1, dims: 1, bucketAt: -1 });\n // erasure + per-subject journey across ALL families — no `as` prefix on purpose\n schema.index({ tenantId: 1, dims: 1 });\n schema.index(\n { expiresAt: 1 },\n { expireAfterSeconds: 0, partialFilterExpression: { expiresAt: { $exists: true } } },\n );\n\n return connection.model(modelName, schema);\n}\n\n// ── dimension resolution ────────────────────────────────────────────────────\n\nconst path = (o: any, p: string): unknown =>\n typeof o?.get === 'function' ? o.get(p) : p.split('.').reduce((a: any, k) => a?.[k], o);\n\n/** `subject` is handled by fan-out, so it resolves to undefined here.\n * Exported: emit()'s burst cap keys on the same sources. */\nexport const resolveDim = (src: DimSource, doc: any): unknown =>\n src.startsWith('attr:') ? doc.attrs?.get(src.slice(5))\n : src.startsWith('field:') ? path(doc, src.slice(6))\n : undefined;\n\nconst label = (src: DimSource) => src.slice(src.indexOf(':') + 1);\n\n/** UTC. Weeks start Monday. */\nexport const truncate = (d: Date, b?: RollupSpec['bucket']): Date | undefined => {\n if (!b) return undefined;\n if (b === 'hour') return new Date(Math.floor(d.getTime() / 36e5) * 36e5);\n const y = d.getUTCFullYear();\n const m = d.getUTCMonth();\n if (b === 'month') return new Date(Date.UTC(y, m, 1));\n const day = new Date(Date.UTC(y, m, d.getUTCDate()));\n if (b === 'day') return day;\n return new Date(day.getTime() - ((day.getUTCDay() + 6) % 7) * 864e5);\n};\n\n/** what recordRollup does INSTEAD of writing, for a caller that only wants the count */\nexport interface RecordRollupOptions {\n /**\n * Build the fan-out and return its size without touching the collection.\n *\n * relink()'s dry run needs to report exactly what a real run would write, and\n * the only way for that number to be exactly right is for the SAME function\n * to produce it — every gate below (the actor allowlist, a missing dim with\n * no `dimDefault`, a `subjects` filter that admits nothing) changes the count,\n * and a caller that modelled them separately would be a second copy of this\n * file's rules, drifting.\n *\n * The two counters below are suppressed under it for the same reason: a dry\n * run that moved `rollupSkipped` would double it on the real run that\n * follows, and report a drop that never happened.\n */\n dryRun?: boolean;\n}\n\n/**\n * Update-pipeline upsert so late/backfilled events correct EVERYTHING, not\n * just the boundaries. `$setOnInsert` for firstCapture/firstTraceId would pin\n * the cohort dimensions to whichever record LANDED first rather than whichever\n * OCCURRED first — silently wrong for offline clients, backfills, and retries.\n *\n * Returns the number of rollup DOCUMENTS this record touched — one per subject\n * the fan-out admitted, or one for a spec that does not fan out, or zero when a\n * gate declined. `emit()` and `ingest.ts` ignore it; relink() reports it, which\n * is the only reason it is not `void`.\n */\nexport async function recordRollup(\n RollupModel: Model<any>,\n doc: any,\n name: string,\n spec: RollupSpec,\n counters: TelemetryCounters,\n opts?: RecordRollupOptions,\n): Promise<number> {\n const dry = opts?.dryRun === true;\n\n // aggregate-plane actor gate: admin support browsing must never move a\n // customer aggregate; the raw row is untouched (RollupSpec.actors)\n if (spec.actors && doc.actor) {\n const actorType = String(doc.actor).split(':')[0];\n if (!spec.actors.includes(actorType)) return 0;\n }\n\n const as = spec.as ?? name;\n const at: Date = doc.occurredAt;\n const bucketAt = truncate(at, spec.bucket);\n const bucketKey = bucketAt ? bucketAt.toISOString() : '';\n\n // Non-subject dims resolved once. Absent a declared fallback, a missing dim\n // means the record cannot be keyed at all — an implicit 'null' bucket would\n // silently corrupt every group. `dimDefault` makes that bucket EXPLICIT: the\n // host names it, so \"no value\" is a group you can query rather than a drop\n // you have to notice in a counter.\n const fixed = new Map<DimSource, string>();\n for (const src of spec.by) {\n if (src === 'subject') continue;\n let v = resolveDim(src, doc);\n if (v == null || v === '') {\n if (spec.dimDefault === undefined) {\n if (!dry) {\n counters.rollupSkipped++;\n // …and WHICH family lost WHICH dim, so the scalar above becomes a\n // `dimDefault` line the System page can name. Keyed exactly as the\n // catalog labels a family and its dims (`label(src)` is the same `x=`\n // prefix written into `dims`), so a reader can join the two.\n bumpCounterMap(counters.rollupSkippedBy, `${as}|${label(src)}`);\n }\n return 0;\n }\n v = spec.dimDefault;\n }\n fixed.set(src, `${label(src)}=${String(v)}`);\n }\n\n // At most one `subject` dim per spec (asserted in validateRegistry).\n // dimDefault deliberately does NOT apply here: a non-subject dim that is\n // missing is a record we can still attribute to someone, while a record with\n // no matching subject cannot be attributed at all. Bucketing it under a\n // placeholder subject would invent a party that does not exist — and erasure\n // matches subject dims by their native `type:id` form, so the placeholder\n // would be unreachable by forget().\n const fansOut = spec.by.includes('subject');\n const refs: (string | null)[] = fansOut\n ? (doc.subjectKeys ?? []).filter(\n (r: string) => !spec.subjects || spec.subjects.includes(r.split(':')[0]!),\n )\n : [null];\n if (!refs.length) return 0;\n\n const firstCapture = Object.fromEntries(\n (spec.capture ?? [])\n .map((src) => [label(src), resolveDim(src, doc)] as const)\n .filter(([, v]) => v != null)\n .map(([k, v]) => [k, String(v)]),\n );\n\n const expiresAt =\n spec.retentionDays != null ? new Date(at.getTime() + spec.retentionDays * 864e5) : undefined;\n\n const ops = refs.map((ref) => {\n const dims = spec.by.map((src) => (src === 'subject' ? ref! : fixed.get(src)!));\n /** true when this record becomes the new earliest occurrence */\n const isNewFirst = {\n $or: [{ $eq: [{ $type: '$firstAt' }, 'missing'] }, { $lt: [at, '$firstAt'] }],\n };\n const sums = Object.fromEntries(\n (spec.sum ?? [])\n .map((k) => [k, doc.metrics?.get(k)] as const)\n .filter(([, v]) => typeof v === 'number')\n .map(([k, v]) => [`sums.${k}`, { $add: [{ $ifNull: [`$sums.${k}`, 0] }, v] }]),\n );\n return {\n updateOne: {\n filter: { _id: `${doc.tenantId}|${as}|${dims.join('|')}|${bucketKey}` },\n update: [\n {\n $set: {\n tenantId: doc.tenantId,\n as,\n dims,\n ...(ref ? { subjectType: ref.split(':')[0] } : {}),\n ...(bucketAt ? { bucketAt } : {}),\n ...(expiresAt ? { expiresAt } : {}),\n // aggregation $min/$max ignore missing, so correct on insert too\n firstAt: { $min: ['$firstAt', at] },\n lastAt: { $max: ['$lastAt', at] },\n count: { $add: [{ $ifNull: ['$count', 0] }, 1] },\n ...sums,\n firstTraceId: { $cond: [isNewFirst, doc.traceId ?? null, '$firstTraceId'] },\n firstCapture: { $cond: [isNewFirst, { $literal: firstCapture }, '$firstCapture'] },\n },\n },\n ],\n upsert: true,\n },\n };\n });\n\n // The dry run stops HERE, with the fan-out built and nothing sent. Everything\n // above this line is a decision; only this line is a write.\n if (dry) return ops.length;\n\n await RollupModel.bulkWrite(ops, { ordered: false });\n return ops.length;\n}\n","import { Schema, type Connection, type Model } from 'mongoose';\nimport type { Logger } from './types.js';\n\n/**\n * Key→timestamp checkpoint store for pull-importers (ported from maxed's\n * checkpoint.ts — recon decision #3: primitive, not hook).\n *\n * Values are ADVISORY. Every writer downstream of a checkpoint must be\n * idempotent (client event ids, usage idempotency keys), so a checkpoint that\n * is stale, reset, or lost costs a re-scan — never a duplicate. That property\n * is what lets an importer rewind its watermark by a safety overlap every run.\n * Reads and writes therefore swallow errors: checkpoint failure must never\n * take the batch down.\n */\n\nexport function buildCheckpointModel(connection: Connection, modelName: string, collection: string): Model<any> {\n const existing = connection.models?.[modelName];\n if (existing) return existing;\n const schema = new Schema(\n {\n /** stable scanner name, e.g. \"mailery-bridge\" */\n key: { type: String, required: true, unique: true },\n /** high-water mark: the scanner has processed everything at/before this */\n at: { type: Date, required: true },\n },\n { collection, timestamps: { createdAt: false, updatedAt: true }, versionKey: false },\n );\n return connection.model(modelName, schema);\n}\n\nexport interface Checkpoint {\n /** null on the first ever run — callers decide what \"from the beginning\" means */\n get(): Promise<Date | null>;\n advance(at: Date): Promise<void>;\n}\n\nexport function createCheckpointFactory(CheckpointModel: Model<any>, logger: Logger) {\n return function checkpoint(key: string): Checkpoint {\n return {\n async get() {\n try {\n const doc = await CheckpointModel.findOne({ key }).lean();\n return (doc as any)?.at ?? null;\n } catch (err) {\n // read failure → caller re-scans from its own floor; dedupe absorbs it\n logger.error({ err, key }, '[telemetry] checkpoint read failed');\n return null;\n }\n },\n async advance(at: Date) {\n try {\n await CheckpointModel.updateOne({ key }, { $set: { at } }, { upsert: true });\n } catch (err) {\n logger.error({ err, key, at }, '[telemetry] checkpoint write failed');\n }\n },\n };\n };\n}\n","import type { Model } from 'mongoose';\nimport {\n TelemetryKind, COUNTER_MAP_MAX, RESERVED_TENANT_MESSAGE, SAMPLE_RATE, bumpCounterMap,\n isPlatformScope, newId, traceKeep, plain,\n type TelemetryCounters, type Logger,\n} from './types.js';\nimport type { EventSpec, Registry } from './registry.js';\nimport { recordRollup, resolveDim } from './rollups.js';\n\n/**\n * Per-kind durability, the aggregate/evidence split, and (dormant) sampling\n * (schema §4.6). A record passes through two independent decisions:\n *\n * 1. Aggregate plane — rollups. See every VALID record, unconditionally.\n * 2. Evidence plane — the raw row. Subject to sampling and the burst cap.\n *\n * Sampling and capping are decisions about storing evidence, not about whether\n * the thing happened — so they must never bend an aggregate. Two inversions\n * exist, and both are the same rule: when the INSERT is the dedupe, the insert\n * must gate aggregation too. `kind=usage` (unique idempotencyKey) and any\n * record carrying a `dedupeKey` therefore save first and roll up after — a\n * retried usage row is the same money, and a redelivered webhook is the same\n * event. Idempotency that still lets rollups run twice does not fix the bug.\n */\n\nexport interface EmitCtx {\n registry: Registry;\n byKind: Record<TelemetryKind, Model<any>>;\n RollupModel: Model<any>;\n rejects: () => { insertOne(doc: any): Promise<unknown> };\n counters: TelemetryCounters;\n logger: Logger;\n /** in-flight fire-and-forget writes, awaited by t.flush() */\n track: (p: Promise<unknown>) => void;\n /** write-time subject linking, or null when no `subjectLinker` is configured */\n linkSubjects?: LinkSubjects | null;\n}\n\nexport interface EmitInput {\n tenantId: string;\n subjects?: Array<{ type: string; id: string; role?: string }>;\n attrs?: Record<string, string>;\n metrics?: Record<string, number>;\n /** keep despite sampling — set automatically for money/errors */\n forceKeep?: boolean;\n /**\n * Caller idempotency for event/state/span/error. Trusted SERVER callers only\n * — the wire path dedupes on the client `_id` instead. Deterministic per\n * logical occurrence, e.g. `stripe:${event.id}` or `lifecycle:${accountId}:${day}`.\n */\n dedupeKey?: string;\n /** await the write with {w:'majority', j:true} and rethrow — overrides EventSpec.durable */\n durable?: boolean;\n [k: string]: unknown;\n}\n\n/** What emit() did. `Promise<void>` could not distinguish \"written\" from \"queued\". */\nexport interface EmitResult {\n /** the record _id — usable for correlation even when the row was not stored */\n id: string;\n /**\n * written — BOTH planes are on disk and awaited: the row, and its rollups.\n * Readable immediately, with no flush(). One meaning, on every\n * path that returns it — durable specs, kind=usage, and\n * insert-gated dedupeKey writes alike.\n * A rollup that FAILS is quarantined and counted rather than\n * thrown, as on every other path — awaiting an aggregate must not\n * turn its failure into a report that the row does not exist.\n * queued — validated and aggregated; the save is in flight, t.flush() awaits it\n * deduped — dedupeKey already present: nothing written, nothing aggregated\n * sampled — evidence plane declined; aggregates were still updated\n * capped — burst cap declined; aggregates were still updated\n * rejected — unregistered or failed validation; quarantined in the rejects collection\n */\n outcome: 'written' | 'queued' | 'deduped' | 'sampled' | 'capped' | 'rejected';\n}\n\n/**\n * Count attrs keys the record's spec does not declare, BEFORE anything parses\n * them.\n *\n * What actually happens to those keys, so nobody has to guess: model.ts's\n * pre('validate') hook parses `attrs` as `spec.attrs.strict()`. Under the\n * default `validation: 'lenient'` (0.7.0) an undeclared key is STRIPPED, its\n * removal counted in `attrsDropped`, and the record is written without it.\n * Under `'strict'` the whole record is quarantined and counted in `rejected`,\n * which is what every version before 0.7.0 did unconditionally.\n *\n * Either way this counter is the GROUPING of the drift, and under the lenient\n * default it is the ONLY warning you get — there is no quarantine row to\n * notice any more, by design. The quarantine listed 41 failed writes one at a\n * time and a human read none of them; this says \"all 41 carried `codec`\",\n * which is a zod line the System page can hand you (see suggest.ts).\n *\n * Keys are sanitized the way the writer sanitizes them (dots → underscores, as\n * mongoose Map keys demand), or a client's `gen_ai.model` would read as\n * undeclared against a perfectly well declared `gen_ai_model`.\n */\nexport function noteUndeclaredAttrs(\n counters: TelemetryCounters,\n name: string,\n spec: Pick<EventSpec, 'attrs'>,\n attrs: unknown,\n): void {\n if (!attrs || typeof attrs !== 'object') return;\n const keys = attrs instanceof Map ? [...attrs.keys()] : Object.keys(attrs);\n const shape = (spec.attrs as { shape?: Record<string, unknown> } | undefined)?.shape;\n for (const raw of keys) {\n const key = String(raw).replace(/\\./g, '_');\n if (shape && Object.prototype.hasOwnProperty.call(shape, key)) continue;\n // bounded: the key half is client-controlled, so it folds past the cap\n bumpCounterMap(counters.undeclaredAttrs, `${name}|${key}`);\n }\n}\n\n// ── write-time subject linking ───────────────────────────────────────────────\n\n/**\n * The host's answer to \"who else is this record about?\", asked once per record,\n * on the way to disk.\n *\n * NOT `SubjectAdapter` (dashboard.ts), which labels refs at READ time and\n * changes nothing about what is stored. This one changes the row.\n *\n * The failure mode it exists for: a desktop client knows its install and\n * nothing else, so every record it sends carries `machine:<installId>` and no\n * `user`. The host can map most of those to an account — but doing that at read\n * time leaves a cohort funnel anchored on `user` reading zero for every desktop\n * stage. `import.completed` is there in volume and invisible to the only\n * question anyone asked of it. Joining at write time puts the party on the row\n * AND on its rollups, and the rollups are the half a read-time join can never\n * reach: a lifetime `by:['subject']` family is keyed on the subject the record\n * was written with, forever.\n */\nexport interface SubjectLinker {\n /**\n * Additional subjects to attach to a record being written. Return `[]` when\n * nothing links — that is an answer, and it is counted as one.\n *\n * MUST be fast, and is expected to be CACHED. It runs on the ingest hot path,\n * once per record, and the package bounds it rather than trusting it: a throw\n * or an overrun writes the record unlinked. It should not throw; the package\n * guards anyway.\n */\n link(\n subjects: Array<{ type: string; id: string; role?: string }>,\n ctx: { name: string; tenantId: string },\n ):\n | Array<{ type: string; id: string; role?: string }>\n | Promise<Array<{ type: string; id: string; role?: string }>>;\n}\n\ntype SubjectRef = { type: string; id: string; role?: string };\n\n/**\n * Total subjects one record may carry once linking has run. The envelope is\n * multi-party by design, but `subjectKeys` is a multikey index term and every\n * subject fans a `by:['subject']` rollup out one more time — so an unbounded\n * array is an unbounded write amplification with a host's cache bug behind it.\n */\nexport const SUBJECT_MAX = 8;\n\n/** what link() gets before the record is written unlinked */\nexport const SUBJECT_LINK_TIMEOUT_MS = 50;\n\n/** merged subjects to write, or null when nothing changed */\nexport type LinkSubjects = (\n name: string,\n spec: Pick<EventSpec, 'subjects'>,\n tenantId: string,\n declared: unknown,\n) => Promise<SubjectRef[] | null>;\n\n/** the race token — a Symbol so no host error can ever impersonate a timeout */\nconst LINK_TIMEOUT = Symbol('telemetry.subjectLink.timeout');\n\n/**\n * Wrap a host `SubjectLinker` in the guarantees the write path needs.\n *\n * Returns `null` — not a pass-through — when no linker is configured, so a host\n * without one runs the code 0.4.0 ran rather than an extra `await` per record.\n *\n * Every failure resolves the same way: write the record with the subjects it\n * came with, and count. Ingest is at-least-once and unattended, so a resolver\n * that hangs must cost a record its `user` and never its existence — an\n * unlinked row is a worse row, a dropped row is a lie about what happened.\n */\nexport function createSubjectLinking(opts: {\n linker?: SubjectLinker;\n timeoutMs?: number;\n counters: TelemetryCounters;\n logger: Logger;\n}): LinkSubjects | null {\n const { linker, counters, logger } = opts;\n if (!linker) return null;\n const timeoutMs = opts.timeoutMs ?? SUBJECT_LINK_TIMEOUT_MS;\n\n // Once per reason, ever. This fires from the write path, so a line per record\n // IS the outage — and none of these are things a human reads twice. The set\n // is bounded for the same reason the counter maps are: one of the keys\n // carries an event name and a subject type.\n const warned = new Set<string>();\n const warnOnce = (key: string, msg: string) => {\n if (warned.has(key) || warned.size >= COUNTER_MAP_MAX) return;\n warned.add(key);\n logger.warn(msg);\n };\n\n return async function linkSubjects(name, spec, tenantId, declared) {\n const have: SubjectRef[] = Array.isArray(declared) ? declared : [];\n\n // The host is asked about a COPY of the well-formed refs. Handing it the\n // array that is about to be written would make a stray `push` in someone\n // else's memo cache a mutation of this record; malformed entries are left\n // out because validation is about to reject them anyway and the host should\n // not have to defend against them.\n const seen = new Set<string>();\n const view: SubjectRef[] = [];\n for (const s of have) {\n const ref = wellFormed(s);\n if (!ref) continue;\n seen.add(`${ref.type}:${ref.id}`);\n view.push(ref);\n }\n\n let out: unknown;\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n out = await Promise.race([\n // the async wrapper turns a SYNCHRONOUS throw into a rejection, so a\n // linker that dies on its first line lands in the same catch as one\n // whose promise rejects\n (async () => linker.link(view, { name, tenantId }))(),\n new Promise((_, reject) => {\n timer = setTimeout(() => reject(LINK_TIMEOUT), timeoutMs);\n }),\n ]);\n } catch (e) {\n if (e === LINK_TIMEOUT) {\n counters.subjectLinkTimeouts++;\n warnOnce(\n 'timeout',\n `[telemetry] subjectLinker.link() exceeded ${timeoutMs}ms — records are being written ` +\n 'UNLINKED rather than waiting. The hook is expected to answer from a cache; a resolver ' +\n 'that queries per record cannot keep up with ingest. Warned once — the count is ' +\n 'counters.subjectLinkTimeouts.',\n );\n } else {\n counters.subjectLinkErrors++;\n warnOnce(\n 'threw',\n `[telemetry] subjectLinker.link() threw — records are being written unlinked: ${e}. ` +\n 'Warned once — the count is counters.subjectLinkErrors.',\n );\n }\n return null;\n } finally {\n clearTimeout(timer);\n }\n\n if (!Array.isArray(out)) {\n counters.subjectLinkErrors++;\n warnOnce(\n 'shape',\n `[telemetry] subjectLinker.link() resolved to ${typeof out}, not an array — records are ` +\n 'being written unlinked. Return [] when nothing links. Warned once — the count is ' +\n 'counters.subjectLinkErrors.',\n );\n return null;\n }\n if (!out.length) {\n counters.subjectLinkMisses++;\n return null;\n }\n\n // Room is measured against what the record already declares, so a caller\n // that arrives at the cap loses its LINKS and keeps its own subjects — the\n // host's own refs are never displaced by a derived one.\n let room = Math.max(0, SUBJECT_MAX - have.length);\n let capped = 0;\n const add: SubjectRef[] = [];\n\n for (const s of out) {\n const ref = wellFormed(s);\n if (!ref) {\n counters.subjectLinkErrors++;\n warnOnce(\n 'entry',\n '[telemetry] subjectLinker returned an entry that is not { type, id } — dropped. ' +\n 'Warned once — the count is counters.subjectLinkErrors.',\n );\n continue;\n }\n // A ref the record already carries is never doubled, and the DECLARED one\n // survives whole — including its `role`, which the caller knew and the\n // linker is guessing at.\n const key = `${ref.type}:${ref.id}`;\n if (seen.has(key)) continue;\n\n // A linked type the registry does not declare is WRITTEN, and counted.\n //\n // Refusing it here was the obvious rule and it is the wrong one, because\n // `EventSpec.subjects` is a REQUIRED list — `model.ts` quarantines a\n // record missing any type declared there. So the only way to satisfy a\n // refusal is to make the type mandatory, and a linked type is mandatory\n // for nobody: linking exists precisely because SOME records resolve and\n // some do not. Declaring `user` on a desktop event to permit the link\n // would quarantine every record from a machine that has not been\n // activated yet — deleting the pre-activation funnel to describe the\n // post-activation one. A refusal that can only be satisfied by data loss\n // is not a rule, it is a dead feature: the type stays undeclared, every\n // link is dropped, and the hook does nothing at all.\n //\n // Undeclared is therefore a fact to REPORT, not to enforce. The registry\n // stays honest because the count says exactly which name is carrying\n // which extra type, and `deriveSuggestions` can turn that into \"declare\n // it\" advice on the day the link becomes total.\n if (!spec.subjects.includes(ref.type)) {\n counters.subjectLinkUndeclared++;\n }\n if (room <= 0) {\n capped++;\n continue;\n }\n seen.add(key);\n room--;\n add.push(ref);\n }\n\n counters.subjectLinkCapped += capped;\n // Nothing survived. Deliberately NOT counted as a miss: a miss is the host\n // saying no link exists, which is a different fact from a link it named and\n // the package refused.\n if (!add.length) return null;\n counters.subjectsLinked += add.length;\n return [...have, ...add];\n };\n}\n\n/** a ref the envelope can actually store, copied — or null */\nfunction wellFormed(s: unknown): SubjectRef | null {\n if (!s || typeof s !== 'object') return null;\n const { type, id, role } = s as SubjectRef;\n if (typeof type !== 'string' || !type) return null;\n if (typeof id !== 'string' || !id) return null;\n return typeof role === 'string' && role ? { type, id, role } : { type, id };\n}\n\nexport function createEmitter(ctx: EmitCtx) {\n const { registry, byKind, RollupModel, rejects, counters } = ctx;\n\n /** per-process token buckets — a storm cap, approximate on purpose, not an SLA */\n const burstBuckets = new Map<string, { n: number; resetAt: number }>();\n const burstAllow = (key: string, maxPerMinute: number): boolean => {\n const now = Date.now();\n let b = burstBuckets.get(key);\n if (!b || now >= b.resetAt) {\n if (burstBuckets.size > 10_000) burstBuckets.clear(); // storm of DISTINCT keys\n b = { n: 0, resetAt: now + 60_000 };\n burstBuckets.set(key, b);\n }\n return ++b.n <= maxPerMinute;\n };\n\n return async function emit(name: string, doc: EmitInput): Promise<EmitResult> {\n // minted up front so every return path — including the ones that store\n // nothing — can hand the caller an id to correlate on\n const id = newId();\n\n /** quarantine + count, without the document (nothing is hydrated yet) */\n const reject = (reason: string): EmitResult => {\n counters.rejected++;\n ctx.track(\n rejects().insertOne({ at: new Date(), name, reason, raw: plain(doc) }).catch(() => {}),\n );\n return { id, outcome: 'rejected' };\n };\n\n // '*' is the dashboard's cross-tenant READ scope; a row carrying it would\n // turn a tenant name into a privilege escalation. Quarantined rather than\n // thrown for the same reason everything else here is: hosts call emit()\n // fire-and-forget, and an unhandled rejection on attacker-shaped input is a\n // way to stop the process. The refusal is loud where it counts — counters,\n // quarantine, the System page — and nothing is written either way.\n if (isPlatformScope(doc.tenantId)) return reject(RESERVED_TENANT_MESSAGE);\n\n const spec = registry[name];\n // unregistered names quarantine rather than throw — the caller may be a\n // stale client; the operator finds it in rejects + counters\n if (!spec) return reject('unregistered event');\n\n const dedupeKey = doc.dedupeKey;\n if (dedupeKey !== undefined && (typeof dedupeKey !== 'string' || !dedupeKey || dedupeKey.length > 200)) {\n return reject('dedupeKey must be a non-empty string of at most 200 chars');\n }\n\n const kind = spec.kind;\n const baseRate = spec.sampleRate ?? SAMPLE_RATE[kind];\n\n // A span carrying money or an error must survive, or the usage→span join\n // dangles. A record with a dedupeKey must survive for a subtler reason: its\n // AGGREGATION is gated on its own insert (below), so sampling or capping the\n // evidence away would take the rollup with it — the aggregate would silently\n // lose the record instead of merely losing the row. dedupeKey therefore\n // implies forced: never sampled, never burst-capped.\n const forced =\n !!doc.forceKeep ||\n kind === TelemetryKind.Usage ||\n !!doc.error ||\n dedupeKey != null ||\n (doc.metrics as any)?.cost_usd != null;\n\n // per-call override beats the spec; usage is durable either way\n const durable = kind === TelemetryKind.Usage || (doc.durable ?? spec.durable ?? false);\n\n const Model = byKind[kind];\n // `durable` is a routing instruction, not data — destructured out the same\n // way forceKeep is, so it never lands on the document. `dedupeKey` is NOT:\n // it is a stored, indexed field and rides through in `rest`.\n const { forceKeep: _drop, durable: _durable, ...rest } = doc;\n\n // ── write-time subject linking ──\n // HERE, and not after hydration, because the merged subjects have to be on\n // the document before pre('validate') derives `subjectKeys` — and\n // subjectKeys is what recordRollup fans a `by:['subject']` family out over.\n // Link any later and the row carries a party its own milestone rollup has\n // never heard of, which is the read/write split this feature exists to\n // close.\n //\n // Bounded, guarded, and never fatal: see createSubjectLinking(). One\n // ordering consequence is worth stating rather than discovering — on the\n // insert-gated path below, the INSERT is the dedupe verdict, so a record\n // that turns out to be a redelivery has already asked the linker by the\n // time it learns nothing will be written. It writes nothing and aggregates\n // nothing, as before; the cost of the duplicate is one cached lookup.\n const linked = ctx.linkSubjects\n ? await ctx.linkSubjects(name, spec, doc.tenantId, doc.subjects)\n : null;\n\n // `...rest` FIRST. Spreading it last would let a caller override `forced`,\n // `sampleRate`, `name`, or `_id` — and a cost-bearing span passed\n // forced:false gets sampled away, dangling the usage→span join (ops rule 6).\n // Dotted keys sanitized HERE, not just in the hook — mongoose Map casting\n // rejects \".\" keys at assignment, which is before pre('validate') runs.\n const safe = (o?: Record<string, unknown>) =>\n new Map(Object.entries(o ?? {}).map(([k, v]) => [k.replace(/\\./g, '_'), v]));\n const payload = {\n ...rest,\n _id: id,\n name,\n // computed like everything below it, and absent when nothing linked, so a\n // host with no linker hands the model the exact object 0.4.0 did\n ...(linked ? { subjects: linked } : {}),\n sampleRate: forced ? 1 : baseRate,\n forced,\n attrs: safe(doc.attrs),\n metrics: safe(doc.metrics),\n };\n\n // Observed before hydration, because the hook below is where they die.\n noteUndeclaredAttrs(counters, name, spec, doc.attrs);\n\n const onFail = async (e: unknown) => {\n counters.rejected++;\n // plain() first — JSON.stringify(Map) is '{}' and would erase every subject\n await rejects()\n .insertOne({ at: new Date(), name, reason: String(e), raw: plain(doc) })\n .catch(() => {});\n };\n\n // Hydrate + validate ONCE, for every record — kept, sampled, or capped.\n // The pre('validate') hook derives subjectKeys, sanitizes dotted attr keys,\n // and runs the registry checks, so the aggregate plane below never sees an\n // invalid or under-derived record.\n const d = new Model(payload);\n try {\n await d.validate();\n } catch (e) {\n await onFail(e);\n if (kind === TelemetryKind.Usage) throw e; // caller must know\n return { id, outcome: 'rejected' };\n }\n\n /**\n * Fire the aggregate plane and HAND BACK the writes, so a `durable` emit can\n * await them (below). Still tracked either way — t.flush() drains them for\n * everyone else.\n *\n * A rollup failure stays a quarantine-and-count, never a throw, on every\n * path including durable: the row is already on disk by then, and turning a\n * failed aggregate into an exception would tell the caller nothing was\n * written when something was. Drops are reported through counters and the\n * rejects collection, as everywhere else.\n */\n const rollup = (): Promise<unknown>[] =>\n (spec.rollups ?? []).map((r) => {\n const p = recordRollup(RollupModel, d, name, r, counters).catch(onFail);\n ctx.track(p);\n return p;\n });\n\n // hook already ran; skip the re-validate on save\n const saveOpts = {\n validateBeforeSave: false,\n ...(durable ? { writeConcern: { w: 'majority', j: true } } : {}),\n } as any;\n\n // ── insert-gated: the write IS the dedupe, so it must precede the rollup ──\n // Usage (unique idempotencyKey) and any record with a dedupeKey. A\n // duplicate returns having aggregated NOTHING; that is the entire point.\n // The save is awaited here whether or not `durable` was asked for — gating\n // requires it — so the outcome is 'written', never 'queued'; `durable` adds\n // the write concern and the rethrow on top.\n if (kind === TelemetryKind.Usage || dedupeKey != null) {\n try {\n await d.save(saveOpts);\n } catch (e: any) {\n if (isDuplicateKey(e)) {\n counters.deduped++; // dedupe working — no row, no re-count\n return { id, outcome: 'deduped' };\n }\n await onFail(e);\n if (durable) throw e; // money, and anything else the caller chose to await\n return { id, outcome: 'rejected' };\n }\n // Aggregates awaited too, and NOT only when `durable` — because this\n // branch returns 'written', and that outcome has to mean one thing. A\n // gated write whose rollups were still in flight would be 'written' with\n // a weaker guarantee than the durable path's 'written', which is the\n // exact ambiguity Promise<void> had before EmitResult replaced it.\n //\n // The cost is one round trip per rollup family on a write that already\n // awaited its insert, and kind=usage — unconditionally durable, and the\n // case that matters most, since usage rollups are money — was paying it\n // regardless. Callers who do not want to wait have `queued`.\n await Promise.all(rollup());\n return { id, outcome: 'written' };\n }\n\n // ── aggregate plane: unconditional ──\n const aggregates = rollup();\n\n // ── evidence plane: sampling verdict, then burst cap ──\n if (!forced && !traceKeep(doc.traceId as string | undefined, baseRate)) {\n counters.sampled++;\n return { id, outcome: 'sampled' };\n }\n\n // Cost-bearing records are exempt from the cap — the usage→span join\n // outranks storm control, and money volume is bounded by spend anyway.\n const burst = spec.burst;\n if (burst && (doc.metrics as any)?.cost_usd == null) {\n const v = burst.key ? resolveDim(burst.key, d) : '';\n if (!burstAllow(`${doc.tenantId}|${name}|${v ?? ''}`, burst.maxPerMinute)) {\n counters.capped++;\n return { id, outcome: 'capped' };\n }\n }\n\n // Declared durable: await the row and rethrow, so a host whose cost ledger\n // is a span can await THIS write instead of t.flush(), which drains every\n // in-flight write globally and serializes a busy worker.\n //\n // The ROLLUPS are awaited here too. `durable` exists to remove the race\n // between \"the emit resolved\" and \"the data is readable\", and a host that\n // awaited the row and then read the aggregate could otherwise legitimately\n // see a stale one — the same race, one plane over.\n if (durable) {\n try {\n await d.save(saveOpts);\n } catch (e) {\n await onFail(e);\n throw e;\n }\n await Promise.all(aggregates);\n return { id, outcome: 'written' };\n }\n\n // Fire-and-forget, but never silent — failures quarantine, and t.flush()\n // awaits stragglers.\n ctx.track(d.save(saveOpts).catch(onFail));\n return { id, outcome: 'queued' };\n };\n}\n\nexport function isDuplicateKey(e: any): boolean {\n return e?.code === 11000 || e?.cause?.code === 11000;\n}\n","import { createHash } from 'node:crypto';\nimport type { Collection, Model } from 'mongoose';\nimport {\n TelemetryKind, PLATFORM_SCOPE, RESERVED_TENANT_MESSAGE, isPlatformScope, type EntityRef,\n} from './types.js';\n\n/**\n * Erasure, actually implemented (schema §4.7). Covers subjects, actor,\n * onBehalfOf, and client — every place an id can appear, because `data` is\n * registry-declared-or-unstored.\n *\n * DELETE only when the ref is the sole party on the row. Any row with\n * surviving subjects is REDACTED instead: forgetting a user must not destroy\n * the org's business record. Usage rows are always redacted (statutory\n * retention).\n */\n\nexport interface ForgetCtx {\n TelemetryModel: Model<any>;\n RollupModel: Model<any>;\n rejects: () => Collection;\n aliases: () => Collection;\n views: () => Collection;\n pepper: () => string;\n /**\n * The host asserting that a subject ref names the same party in every tenant.\n * The package cannot verify it, so it is declared rather than detected — and\n * it is what lets step 6 reach platform-scoped saved views. See the comment\n * there for why the default has to be off.\n */\n globalSubjectRefs: () => boolean;\n}\n\nexport interface ForgetResult {\n deleted: number;\n redacted: number;\n rollups: number;\n aliases: number;\n views: number;\n}\n\nexport function createForget(ctx: ForgetCtx) {\n /** keeps the `type:` prefix so subjectKeys stays re-derivable on any later save */\n const pseudoId = (ref: string) =>\n 'redacted_' + createHash('sha256').update(ref + ctx.pepper()).digest('hex').slice(0, 16);\n\n return async function forget(tenantId: string, ref: EntityRef): Promise<ForgetResult> {\n const { TelemetryModel, RollupModel } = ctx;\n // No '*' here, and deliberately NOT as \"erase across every tenant\": erasure\n // deletes and rewrites rows, so a scope that matched everything would make\n // one typo unbounded. A platform-wide erasure is N tenant-scoped calls, and\n // the caller has to name each one. Throws — forget() is always awaited.\n if (isPlatformScope(tenantId)) throw new Error(RESERVED_TENANT_MESSAGE);\n const [type, rawId] = ref.split(':') as [string, string];\n if (!type || !rawId) throw new Error(`telemetry: forget ref \"${ref}\" is not \"type:id\"`);\n const newId = pseudoId(ref);\n const newRef = `${type}:${newId}`;\n\n const match = { tenantId, $or: [{ subjectKeys: ref }, { otherPrincipals: ref }] };\n\n // 1. sole-party, non-financial rows: delete outright\n const del = await TelemetryModel.deleteMany({\n ...match,\n kind: { $ne: TelemetryKind.Usage },\n subjectKeys: { $eq: ref, $size: 1 }, // ref is the ONLY subject\n otherPrincipals: { $in: [[], null] },\n });\n\n // 2. everything else: keep the row, destroy the linkage.\n // Driver-level updateMany: mongoose 9 gates pipeline updates behind an\n // option that mongoose 7/8 don't know — the driver accepts them everywhere.\n const red = await TelemetryModel.collection.updateMany(match, [\n {\n $set: {\n subjects: {\n $map: {\n input: '$subjects',\n as: 's',\n in: {\n $cond: [\n { $eq: [{ $concat: ['$$s.type', ':', '$$s.id'] }, ref] },\n { $mergeObjects: ['$$s', { id: newId }] },\n '$$s',\n ],\n },\n },\n },\n subjectKeys: {\n $map: {\n input: '$subjectKeys',\n as: 'k',\n in: { $cond: [{ $eq: ['$$k', ref] }, newRef, '$$k'] },\n },\n },\n otherPrincipals: {\n $map: {\n input: { $ifNull: ['$otherPrincipals', []] },\n as: 'k',\n in: { $cond: [{ $eq: ['$$k', ref] }, newRef, '$$k'] },\n },\n },\n actor: { $cond: [{ $eq: ['$actor', ref] }, newRef, '$actor'] },\n onBehalfOf: { $cond: [{ $eq: ['$onBehalfOf', ref] }, newRef, '$onBehalfOf'] },\n client: '$$REMOVE',\n redactedAt: '$$NOW',\n },\n },\n ]);\n\n // 3. derived rollups — REKEY, never delete. Deleting a person's rollups\n // retroactively shrinks every cohort they were counted in, so funnel\n // denominators change under you. Aggregates survive; the person does\n // not. _id is immutable in Mongo, so insert-then-delete rather than $set.\n //\n // Only rollups carrying the ref as a DIMENSION are touched. A rollup\n // grouped on something else — an issue keyed on error.fingerprint —\n // never held the id, which is exactly why non-subject rollups are safe\n // to keep forever.\n const rolls = await RollupModel.find({ tenantId, dims: ref }).lean();\n let rollups = 0;\n if (rolls.length) {\n await RollupModel.bulkWrite(\n (rolls as any[]).map((r) => {\n const dims = r.dims.map((d: string) => (d === ref ? newRef : d));\n const bucketKey = r.bucketAt ? new Date(r.bucketAt).toISOString() : '';\n return {\n insertOne: {\n document: { ...r, _id: `${tenantId}|${r.as}|${dims.join('|')}|${bucketKey}`, dims },\n },\n };\n }),\n { ordered: false },\n ).catch((e: any) => {\n // re-running forget() for the same ref collides on _id — already erased, no-op\n const errs = e?.writeErrors ?? [];\n if (e?.code !== 11000 && !(errs.length && errs.every((w: any) => w.code === 11000))) throw e;\n });\n rollups = (await RollupModel.deleteMany({ tenantId, dims: ref })).deletedCount;\n }\n\n // 4. quarantine holds raw payloads — in scope for erasure too\n await ctx.rejects().deleteMany({\n 'raw.tenantId': tenantId,\n $or: [\n { 'raw.subjects': { $elemMatch: { type, id: rawId } } },\n { 'raw.actor': ref },\n { 'raw.onBehalfOf': ref },\n ],\n });\n\n // 5. aliases are pure linkage — anon→user. Either side matching is enough;\n // there is nothing to redact, only to delete.\n const aliases = (\n await ctx.aliases().deleteMany({ tenantId, $or: [{ anonRef: ref }, { userRef: ref }] })\n ).deletedCount;\n\n // 6. saved dashboard views: ownerRef is a person. Private views die with\n // them; shared ones stay useful to the tenant, so only the owner link\n // is redacted (dashboards §3 — same delete-vs-redact rule as rows).\n //\n // A person who used the cross-tenant dashboard owns views stored under\n // PLATFORM_SCOPE, which is not a tenant — so a tenant-scoped forget()\n // misses them and erasure is incomplete. Reaching them is only SAFE when\n // a ref names one party globally; if ids are per-tenant, 'user:u_1' is a\n // different person in each and one tenant's erasure would delete\n // another's views. The package cannot tell which world it is in, so the\n // host declares it and the default is the conservative one.\n //\n // Note the asymmetry with the guard at the top: that refuses '*' as the\n // ERASURE SCOPE (unbounded rewrite of every tenant's rows). This reaches\n // '*' rows owned by one named person. Bounded by the ref, not the tenant.\n const viewScope = ctx.globalSubjectRefs()\n ? { $in: [tenantId, PLATFORM_SCOPE] }\n : tenantId;\n const views =\n (await ctx.views().deleteMany({ tenantId: viewScope, ownerRef: ref, shared: { $ne: true } })).deletedCount +\n (await ctx.views().updateMany(\n { tenantId: viewScope, ownerRef: ref, shared: true },\n { $set: { ownerRef: newRef } },\n )).modifiedCount;\n\n return { deleted: del.deletedCount ?? 0, redacted: red.modifiedCount ?? 0, rollups, aliases, views };\n };\n}\n","import type { Model } from 'mongoose';\nimport type { Registry } from './registry.js';\nimport type { LinkSubjects } from './emit.js';\nimport { recordRollup } from './rollups.js';\nimport type { Logger, TelemetryCounters } from './types.js';\n\n/**\n * The backfill for write-time subject linking (0.5.0) — the operation a host\n * runs ONCE, on the day it configures a `subjectLinker`, to make the records it\n * already has answer the question the new ones can.\n *\n * `subjectLinker` links on the way to disk. That is not an implementation\n * detail, it is the whole reason the hook exists: a lifetime `by:['subject']`\n * rollup is keyed on the subject the record was written WITH, permanently, so a\n * read-time join can reach the raw rows and never the aggregates. Which means a\n * host that adopts linking on a Tuesday has two populations. Records after\n * Tuesday carry `user:u_1` on the row and in a `subjects:['user']` family.\n * Records before it carry `machine:m1` and nothing else, and the family has no\n * member for any of them — so a lifetime milestone is missing every one, and a\n * cohort funnel anchored on `user` reads ZERO for every stage those events\n * feed, while the events sit right there, real and correctly timestamped.\n *\n * Nothing at read time closes that. The aggregate is already written. The rows\n * have to be relinked and the affected rollups replayed, which is this file.\n *\n * Two properties carry the whole design:\n *\n * 1. It reuses `createSubjectLinking()` — the SAME merge `emit()` and\n * `ingest.ts` run. Dedupe on `type:id`, the declared ref winning whole,\n * `SUBJECT_MAX`, the timeout, the six counters. A backfill with its own\n * merge rules would be a second policy that quietly disagrees with the\n * write path about what a linked row looks like, and the disagreement\n * would show up as an aggregate nobody can reconcile.\n *\n * 2. It is idempotent BY CONSTRUCTION rather than by bookkeeping. A row that\n * already carries the linked subject offers it to the merge, the merge\n * dedupes it, and NOTHING is new — so nothing is written and nothing is\n * replayed. There is no watermark to corrupt and no marker field to\n * forget. That matters more here than anywhere else in the package,\n * because `recordRollup` `$add`s 1 per call: a replay that runs twice\n * inflates a historical `count` that no reader can distinguish from a real\n * one. An aggregate that is merely missing data announces itself. An\n * aggregate that is 1.3× too big does not.\n */\n\nexport interface RelinkOptions {\n /**\n * Restrict to these event names. Default: every stored record, whatever its\n * name — including names the registry no longer declares, which are counted\n * in `skipped` (see below) rather than quietly relinked.\n *\n * A name that is not in the registry THROWS, before any I/O. A typo that\n * silently relinks nothing is exactly the failure this package tests for\n * elsewhere: it looks like a clean run.\n */\n names?: string[];\n /** only records at/after this instant (`occurredAt`) */\n since?: Date;\n /**\n * Stop after this many records are EXAMINED — not linked. A cap on work, so\n * an operator can probe a huge collection cheaply; it says nothing about how\n * many rows changed. Default unbounded.\n */\n limit?: number;\n /**\n * Report what would change and write NOTHING. **Defaults to `true`.**\n *\n * This operation mutates historical aggregates, so the short call has to be\n * the safe one — `await t.relink()` tells you what it would do. Writing is\n * the thing you opt into, with `{ dryRun: false }`.\n *\n * A dry run still ASKS the host's linker (there is no other way to know what\n * would link), so `t.counters.subjectsLinked` and its five siblings move.\n * Nothing on disk does.\n */\n dryRun?: boolean;\n /** records fetched per batch, and the `onProgress` cadence. Default 500. */\n batchSize?: number;\n /**\n * Called after each batch with the CUMULATIVE result so far, for progress\n * output on a run that may take hours. Guarded: a printer that throws does\n * not kill the backfill.\n */\n onProgress?: (r: RelinkResult) => void;\n}\n\nexport interface RelinkResult {\n /** rows read */\n examined: number;\n /** rows that gained at least one subject */\n linked: number;\n /** subjects added in total — two links on one row count twice */\n subjects: number;\n /** rollup documents written (or, under `dryRun`, that would have been) */\n rollups: number;\n /**\n * Rows where the linker answered `[]`. Not a failure — \"no link exists\" is an\n * answer, and on a backfill it is the expected answer for most rows.\n */\n misses: number;\n /**\n * Rows where the linker threw, rejected, timed out, or answered with\n * something that is not a list of refs. Counted once per ROW, however many\n * ways it went wrong; `t.counters.subjectLinkErrors` / `subjectLinkTimeouts`\n * keep the finer split, including which of the four it was.\n */\n errors: number;\n /**\n * Rows the run declined to offer the linker at all, plus one standing for a\n * run that declined everything.\n *\n * Two things land here. A stored row whose `name` the registry no longer\n * declares: we cannot know which rollup families it once fed, so we cannot\n * replay them, and relinking the row without them would leave the row and its\n * aggregates disagreeing — which is the exact bug this operation exists to\n * fix, inverted. And a call with no `subjectLinker` configured, which returns\n * `skipped: 1` having read nothing: counting the rows it refused to read\n * would mean reading them.\n */\n skipped: number;\n}\n\n/** records fetched per batch, and how often `onProgress` fires */\nexport const RELINK_BATCH_SIZE = 500;\n\nexport interface RelinkCtx {\n registry: Registry;\n /** the BASE model — every kind is a discriminator on one collection */\n TelemetryModel: Model<any>;\n RollupModel: Model<any>;\n counters: TelemetryCounters;\n logger: Logger;\n /** the guarded 0.5.0 merge, or null when no `subjectLinker` is configured */\n linkSubjects: LinkSubjects | null;\n}\n\ntype SubjectRef = { type: string; id: string; role?: string };\n\nconst refKey = (s: { type: string; id: string }) => `${s.type}:${s.id}`;\n\nexport function createRelink(ctx: RelinkCtx) {\n const { registry, TelemetryModel, RollupModel, counters, logger, linkSubjects } = ctx;\n\n return async function relink(opts: RelinkOptions = {}): Promise<RelinkResult> {\n const dryRun = opts.dryRun !== false;\n const batchSize = opts.batchSize ?? RELINK_BATCH_SIZE;\n const result: RelinkResult = {\n examined: 0, linked: 0, subjects: 0, rollups: 0, misses: 0, errors: 0, skipped: 0,\n };\n\n if (opts.names) {\n const unknown = opts.names.filter((n) => !registry[n]);\n if (unknown.length) {\n throw new Error(\n `telemetry: relink() was given names this registry does not declare: ${unknown.join(', ')}. ` +\n 'A name with no spec has no rollup families to replay, so relinking it could only ' +\n 'desynchronize its rows from its aggregates. Omit `names` to sweep everything.',\n );\n }\n }\n\n // Nothing to do, and nothing worth throwing about: a host may call this\n // from a boot path or a cron that does not know how the instance was\n // configured, and \"you have no linker\" is a fact, not an exception.\n if (!linkSubjects) {\n logger.warn(\n '[telemetry] relink() has no subjectLinker to ask — nothing was read and nothing was ' +\n 'written. Configure createTelemetry({ subjectLinker }) first; relink() backfills what ' +\n 'that hook would have done, it does not replace it.',\n );\n result.skipped = 1;\n return result;\n }\n\n // Mongo reads `limit: 0` as NO LIMIT, so a caller asking for zero records\n // would get the entire collection — the one arithmetic mistake in this file\n // that could not be undone. Handled before the query is built.\n if (opts.limit != null && opts.limit <= 0) return result;\n\n const filter: Record<string, unknown> = {};\n if (opts.names) filter.name = { $in: opts.names };\n if (opts.since) filter.occurredAt = { $gte: opts.since };\n\n const query = TelemetryModel.find(filter)\n // Pinned to the `_id` index on purpose, and NOT sorted.\n //\n // This cursor updates the very documents it is walking. Left to the\n // planner, a filter on `name` invites an index that a relink MOVES the\n // document within — `{tenantId, subjectKeys, occurredAt}` is multikey on\n // the array we are adding to, so a row could be delivered a second time\n // under its new key. `_id` is the one key our writes never touch, so the\n // scan cannot re-deliver. (A re-delivery would be harmless — the merge\n // dedupes — but it would eat `limit` and inflate `examined`, and a\n // backfill whose progress numbers lie is a backfill nobody trusts.)\n //\n // A `sort({_id: 1})` would express the same thing and risk a blocking\n // in-memory sort on a collection too big for one, which is precisely the\n // collection this operation exists for.\n .hint({ _id: 1 })\n .batchSize(batchSize);\n if (opts.limit != null) query.limit(opts.limit);\n\n const progress = () => {\n if (!opts.onProgress) return;\n try {\n opts.onProgress({ ...result });\n } catch (e) {\n logger.warn(`[telemetry] relink() onProgress threw — ignored, the backfill continues: ${e}`);\n }\n };\n\n const cursor = query.cursor();\n let sinceProgress = 0;\n try {\n for await (const doc of cursor) {\n result.examined++;\n sinceProgress++;\n if (sinceProgress >= batchSize) {\n sinceProgress = 0;\n progress();\n }\n\n const spec = registry[doc.name];\n if (!spec) {\n result.skipped++;\n continue;\n }\n\n // The host is asked about PLAIN refs, not the mongoose subdocuments —\n // the same shape the write path hands it, so a linker cannot tell a\n // backfill from a live write and cannot behave differently on one.\n const declared: SubjectRef[] = (doc.subjects ?? []).map((s: any) =>\n (s.role ? { type: s.type, id: s.id, role: s.role } : { type: s.type, id: s.id }),\n );\n\n // Why the counters and not the return value: `LinkSubjects` answers\n // `null` for every outcome that changes nothing — a miss, a throw, a\n // timeout, garbage, and a link the merge deduped away. They are the\n // same value and they are not the same event, so the split is read off\n // the deltas the shared implementation already records. Errors are\n // folded to one per ROW here (a single row can produce several, one per\n // junk entry) because this result counts rows.\n const m0 = counters.subjectLinkMisses;\n const e0 = counters.subjectLinkErrors + counters.subjectLinkTimeouts;\n const merged = await linkSubjects(doc.name, spec, doc.tenantId, declared);\n result.misses += counters.subjectLinkMisses - m0;\n if (counters.subjectLinkErrors + counters.subjectLinkTimeouts > e0) result.errors++;\n\n if (!merged) continue;\n\n const had = new Set<string>(declared.map(refKey));\n const mergedKeys: string[] = [];\n const newKeys: string[] = [];\n for (const s of merged) {\n const key = refKey(s);\n if (mergedKeys.includes(key)) continue;\n mergedKeys.push(key);\n if (!had.has(key)) newKeys.push(key);\n }\n // The merge already guarantees this, and asserting it costs nothing: a\n // replay over zero new refs is the one thing that must never happen\n // twice.\n if (!newKeys.length) continue;\n\n result.linked++;\n result.subjects += newKeys.length;\n\n // ── the row FIRST, then its aggregates ──\n //\n // The order is the crash policy, and it is not symmetric. Replay first\n // and die before the row is updated, and the re-run finds a row that\n // still looks unlinked, links it again, and adds a SECOND 1 to every\n // count it already moved. Update the row first and die before the\n // replay, and the re-run finds the ref already present, adds nothing,\n // and one record is missing from one rollup.\n //\n // So the second one, always: this operation fails toward an aggregate\n // that is short, never one that is long. A short aggregate can be\n // spotted against the rows it came from. A long one cannot be spotted\n // at all.\n //\n // Written through `updateOne` rather than `doc.save()` deliberately —\n // saving would re-run `pre('validate')`, which re-parses `attrs` and\n // `data` against TODAY's registry. A registry that has tightened since\n // these rows were written would quarantine historical records that were\n // valid when they landed, and a backfill has no business deleting the\n // history it was asked to repair. `subjectKeys` is derived here by the\n // same rule that hook uses, because the rollup fan-out reads\n // `subjectKeys` and a row updated without it relinks and still\n // aggregates to nothing.\n if (!dryRun) {\n await TelemetryModel.updateOne(\n { _id: doc._id },\n { $set: { subjects: merged, subjectKeys: mergedKeys } },\n );\n }\n\n // In memory only, and never saved: the fan-out must see the NEW refs\n // and nothing else. `recordRollup` adds 1 per (document, subject) it is\n // handed, so handing it the merged list would re-count every subject\n // the original write already counted — the double that this whole file\n // is arranged to prevent.\n doc.subjectKeys = newKeys;\n\n for (const r of spec.rollups ?? []) {\n // A family that does not group by `subject` counted this record once\n // at write time and cannot gain a group from a new one — its dims are\n // attrs and fields that have not changed. Replaying it would be a\n // straight double. This one line is the exactly-once condition;\n // everything else follows from the merge.\n if (!r.by.includes('subject')) continue;\n // A `subjects` filter that does not admit any of the new refs leaves\n // recordRollup with an empty fan-out, which it declines. That is what\n // keeps a family the ORIGINAL subjects already satisfied untouched:\n // it is never handed those subjects again.\n result.rollups += await recordRollup(RollupModel, doc, doc.name, r, counters, { dryRun });\n }\n }\n } finally {\n await cursor.close().catch(() => {});\n }\n\n if (sinceProgress) progress();\n return result;\n };\n}\n","import type { Collection, Model } from 'mongoose';\nimport { REJECT_TTL_DAYS } from './types.js';\nimport type { Registry } from './registry.js';\n\n/**\n * Registry-driven payload indexes (schema §4.4) — replaces the wildcard. A\n * wildcard index cannot compound with tenantId (pre-Mongo 7.0), so any attr\n * query would scan across every tenant — both a perf problem and the exact\n * isolation hole scoped() exists to close. Attrs are bounded and declared, so\n * pay for targeted indexes instead of insert cost on everything.\n *\n * Every payload index is tenant-prefixed and time-sorted. The partial filter\n * pins `name`, so a query must include { name } to use it. Undeclared attrs\n * stay queryable via a $match on {tenantId, name, occurredAt} first — bounded,\n * no index needed, fine for ad-hoc at small-SaaS volume.\n */\n\n/** Mongo caps a collection at 64 indexes. Base + discriminators use ~10. Budget the rest. */\nexport const INDEX_BUDGET = 24;\n\nexport interface SyncCtx {\n registry: Registry;\n TelemetryModel: Model<any>;\n models: Model<any>[];\n rejects: () => Collection;\n}\n\nexport function createSyncIndexes(ctx: SyncCtx) {\n return async function syncIndexes(): Promise<void> {\n // Model.init() awaited before first write (traps #3): cold-DB writes racing\n // async index builds silently duplicate — the unique idempotency index and\n // deterministic rollup _ids depend on this.\n await Promise.all(ctx.models.map((m) => m.init()));\n\n // one generator, two payload maps — attrs (string equality) and metrics\n // (numeric range). Identical shape: tenant-prefixed, name-pinned, time-sorted.\n const plan = (name: string, kind: 'attr' | 'metric', key: string) => ({\n name: `${kind}_${name.replace(/\\./g, '_')}_${key}`,\n keys: {\n tenantId: 1,\n [`${kind === 'attr' ? 'attrs' : 'metrics'}.${key}`]: 1,\n occurredAt: -1,\n } as Record<string, 1 | -1>,\n partial: { name }, // keeps each index to just that event's rows\n });\n const planned = Object.entries(ctx.registry).flatMap(([name, spec]) => [\n ...(spec.indexedAttrs ?? []).map((k) => plan(name, 'attr', k)),\n ...(spec.indexedMetrics ?? []).map((k) => plan(name, 'metric', k)),\n ]);\n\n const coll = ctx.TelemetryModel.collection;\n const plannedNames = new Set(planned.map((p) => p.name));\n\n // Drop orphans FIRST. If the budget check ran first, removing an entry to\n // get back under the cap would still throw, and the stale index would never\n // be dropped — unrecoverable without manual intervention.\n for (const ix of await coll.indexes()) {\n if (\n (ix.name?.startsWith('attr_') || ix.name?.startsWith('metric_')) &&\n !plannedNames.has(ix.name)\n ) {\n await coll.dropIndex(ix.name);\n }\n }\n\n if (planned.length > INDEX_BUDGET) {\n throw new Error(`telemetry: ${planned.length} payload indexes exceeds budget ${INDEX_BUDGET}`);\n }\n\n for (const p of planned) {\n await coll.createIndex(p.keys, {\n name: p.name,\n partialFilterExpression: p.partial,\n background: true,\n });\n }\n\n // quarantined rejects expire on their own — nothing bounds them otherwise\n await ctx.rejects().createIndex({ at: 1 }, { expireAfterSeconds: REJECT_TTL_DAYS * 86400 });\n };\n}\n","import type { Connection } from 'mongoose';\nimport { TraceMap, originalPositionFor, sourceContentFor } from '@jridgewell/trace-mapping';\nimport type { Logger } from './types.js';\n\n/**\n * Sourcemaps — so an error recorded against a minified bundle reads as source.\n *\n * WHY READ TIME, NOT WRITE TIME. A record keeps the frames the client sent,\n * exactly. Translation happens when the dashboard reads it, against whatever\n * map is registered for that record's (tenant, service, release, file). So a\n * map registered AFTER the errors arrived still translates them, a wrong map\n * can be replaced without rewriting history, and ingest never pays to parse a\n * 2MB map on the hot path.\n *\n * WHY THE HOST REGISTERS, NOT THE BROWSER. A map is the application's source.\n * Serving it publicly so a translator can fetch it gives the source to anyone\n * who asks; registering it server-side lets the host stop serving it at all.\n * `register()` is a server API with no HTTP route — a host that builds its\n * bundle in the same image as its server (the common case) registers from its\n * own disk at boot, and never needs an upload credential.\n *\n * WHAT LEAVES. The dashboard gets an original `source`, `line`, `column`,\n * `name`, and the ONE source line the frame points at. Never the map, never\n * `sourcesContent` wholesale.\n */\n\n/** one map per (tenant, service, release, file) — `file` is the bundle's basename */\nexport interface SourcemapFile {\n /** the bundle's file name as a frame's `filename` ends with it: `chunk-vendors.f18c196e.js` */\n file: string;\n /** the map, as JSON text or a parsed object */\n map: string | Record<string, unknown>;\n}\n\nexport interface RegisterSourcemapsInput {\n tenantId: string;\n service: string;\n release: string;\n files: SourcemapFile[];\n}\n\nexport interface OriginalPosition {\n source: string;\n line: number;\n column: number;\n name?: string;\n /** the original source line, trimmed and capped — present when the map carries sourcesContent */\n context?: string;\n}\n\n/** a Mongo document is 16MB; a map over this is refused rather than half-stored */\nexport const SOURCEMAP_MAX_BYTES = 15 * 1024 * 1024;\n\n/** maps outlive the errors that need them by nothing — error retention is 90d */\nexport const SOURCEMAP_RETENTION_DAYS = 90;\n\nconst CACHE_SIZE = 8;\nconst CONTEXT_MAX = 200;\n\n/** `https://x.com/js/app.1a2b.js?v=3#x` → `app.1a2b.js` */\nexport const bundleFile = (filename: string | undefined): string =>\n String(filename ?? '').split(/[?#]/)[0]!.split(/[\\\\/]/).pop() ?? '';\n\nconst cleanSource = (source: string) =>\n // webpack:///src/x.ts, webpack://app/./src/x.ts → src/x.ts\n source.replace(/^webpack:\\/\\/[^/]*\\//, '').replace(/^\\.\\//, '');\n\nexport function createSourcemaps(opts: {\n connection: Connection;\n collection: string;\n logger: Logger;\n}) {\n const coll = () => opts.connection.db!.collection(opts.collection);\n // parsed maps are the expensive part (a vendor chunk is ~2MB of JSON); a\n // miss is remembered too, so a record with no map costs one query, not one\n // per frame per request\n const cache = new Map<string, TraceMap | null>();\n\n const remember = (key: string, value: TraceMap | null) => {\n cache.delete(key);\n cache.set(key, value);\n while (cache.size > CACHE_SIZE) cache.delete(cache.keys().next().value!);\n };\n\n const keyOf = (tenantId: string, service: string, release: string, file: string) =>\n `${tenantId}\u0000${service}\u0000${release}\u0000${file}`;\n\n async function load(tenantId: string, service: string, release: string, file: string) {\n const key = keyOf(tenantId, service, release, file);\n if (cache.has(key)) {\n const hit = cache.get(key)!;\n remember(key, hit);\n return hit;\n }\n let parsed: TraceMap | null = null;\n try {\n const doc = await coll().findOne({ tenantId, service, release, file }, { projection: { map: 1 } });\n if (doc?.map) parsed = new TraceMap(String(doc.map));\n } catch (e) {\n opts.logger.warn('[telemetry] sourcemap load failed', file, (e as Error)?.message);\n }\n remember(key, parsed);\n return parsed;\n }\n\n return {\n async ensureIndexes() {\n await coll().createIndex(\n { tenantId: 1, service: 1, release: 1, file: 1 },\n { unique: true, name: 'sourcemap_identity' },\n );\n await coll().createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0, name: 'sourcemap_ttl' });\n },\n\n /**\n * Store maps for one release. Idempotent: registering the same release\n * again replaces its maps and refreshes their retention, so a host can\n * simply call this on every boot.\n */\n async register(input: RegisterSourcemapsInput): Promise<{ stored: number; skipped: string[] }> {\n const { tenantId, service, release } = input;\n if (!tenantId || !service || !release) {\n throw new Error('telemetry: sourcemaps.register needs tenantId, service and release');\n }\n if (release === 'unknown') {\n // the SDK's placeholder for \"no release set\" — every build would share it\n // and translate against the wrong map\n throw new Error('telemetry: refusing to register sourcemaps for release \"unknown\" — set a real release on the client');\n }\n const now = new Date();\n const expiresAt = new Date(now.getTime() + SOURCEMAP_RETENTION_DAYS * 864e5);\n const skipped: string[] = [];\n let stored = 0;\n for (const f of input.files) {\n const file = bundleFile(f.file);\n const map = typeof f.map === 'string' ? f.map : JSON.stringify(f.map);\n if (!file || !map) { skipped.push(f.file); continue; }\n if (Buffer.byteLength(map) > SOURCEMAP_MAX_BYTES) {\n opts.logger.warn(`[telemetry] sourcemap ${file} exceeds ${SOURCEMAP_MAX_BYTES} bytes — skipped`);\n skipped.push(f.file);\n continue;\n }\n try {\n JSON.parse(map);\n } catch {\n skipped.push(f.file);\n continue;\n }\n await coll().updateOne(\n { tenantId, service, release, file },\n { $set: { map, bytes: Buffer.byteLength(map), registeredAt: now, expiresAt } },\n { upsert: true },\n );\n cache.delete(keyOf(tenantId, service, release, file));\n stored++;\n }\n return { stored, skipped };\n },\n\n /** translate one position; null when no map is registered or it has no mapping there */\n async resolve(\n where: { tenantId: string; service: string; release: string; filename: string },\n lineno: number,\n colno: number,\n ): Promise<OriginalPosition | null> {\n const file = bundleFile(where.filename);\n if (!file || !where.release || where.release === 'unknown') return null;\n if (!Number.isFinite(lineno) || !Number.isFinite(colno)) return null;\n const map = await load(where.tenantId, where.service, where.release, file);\n if (!map) return null;\n // stack traces are 1-based columns; trace-mapping wants 0-based\n const pos = originalPositionFor(map, { line: lineno, column: Math.max(0, colno - 1) });\n if (!pos.source || pos.line == null) return null;\n const out: OriginalPosition = {\n source: cleanSource(pos.source),\n line: pos.line,\n column: (pos.column ?? 0) + 1,\n };\n if (pos.name) out.name = pos.name;\n const content = sourceContentFor(map, pos.source);\n const text = content?.split('\\n')[pos.line - 1];\n if (text != null) out.context = text.trim().slice(0, CONTEXT_MAX);\n return out;\n },\n\n /**\n * A copy of an error record with `original` set on every frame a map\n * could translate. Anything else comes back unchanged — never throws.\n */\n async symbolicate<T extends Record<string, any>>(record: T): Promise<T> {\n const frames = record?.error?.frames;\n if (record?.kind !== 'error' || !Array.isArray(frames) || !frames.length) return record;\n try {\n const translated = await Promise.all(\n frames.map(async (f: any) => {\n const original = await this.resolve(\n {\n tenantId: record.tenantId,\n service: record.service,\n release: record.release,\n filename: f?.filename,\n },\n Number(f?.lineno),\n Number(f?.colno),\n );\n return original ? { ...f, original } : f;\n }),\n );\n return { ...record, error: { ...record.error, frames: translated } };\n } catch (e) {\n opts.logger.warn('[telemetry] symbolicate failed', (e as Error)?.message);\n return record;\n }\n },\n };\n}\n\nexport type Sourcemaps = ReturnType<typeof createSourcemaps>;\n","import { randomBytes, scryptSync, timingSafeEqual } from 'node:crypto';\nimport { Schema, type Connection, type Model } from 'mongoose';\nimport { TelemetryKind, RESERVED_TENANT_MESSAGE, isPlatformScope } from './types.js';\n\n/**\n * Keys — the key IS the configuration (instrumentation §2). Client init is\n * { key, url, release } and nothing else: service, env, tenant resolution,\n * kind allowlist, CORS, and rate limits all hang off the key server-side.\n *\n * Format:\n * pk_<label>_tk_<24hex> publishable — the id is the whole credential\n * sk_<label>_tk_<24hex>_<48hex> secret — id + secret half; only a hash is stored\n *\n * <label> is cosmetic ('live', 'test', …); the tk_ id is the lookup key.\n */\n\nexport const KeyKind = { Publishable: 'publishable', Secret: 'secret' } as const;\nexport type KeyKind = (typeof KeyKind)[keyof typeof KeyKind];\n\n/**\n * How tenantId resolves for records written with this key:\n * - fixed: the key carries it. Single-tenant apps, internal tools, CLI builds.\n * - session: the host resolves it from the request (contextAdapter).\n * - claimed: the payload asserts it. Secret keys only — enforced here.\n */\nexport const TenantMode = { Fixed: 'fixed', Session: 'session', Claimed: 'claimed' } as const;\nexport type TenantMode = (typeof TenantMode)[keyof typeof TenantMode];\n\nconst KEY_RE = /^(pk|sk)_([a-z0-9]+)_(tk_[a-f0-9]{24})(?:_([a-f0-9]{48}))?$/;\n\nexport interface ParsedKey {\n kind: KeyKind;\n label: string;\n id: string;\n secret?: string;\n}\n\nexport function parseKeyString(raw: string | undefined): ParsedKey | null {\n if (!raw) return null;\n const m = KEY_RE.exec(raw.trim());\n if (!m) return null;\n const [, prefix, label, id, secret] = m;\n if (prefix === 'sk' && !secret) return null;\n if (prefix === 'pk' && secret) return null;\n return { kind: prefix === 'pk' ? KeyKind.Publishable : KeyKind.Secret, label: label!, id: id!, secret };\n}\n\n// scrypt params picked once and versioned IN the hash string (open item §10\n// closed): a future param change bumps the prefix, old hashes keep verifying.\nconst SCRYPT_VERSION = 'scrypt1';\nconst SCRYPT = { N: 16384, r: 8, p: 1, keylen: 32 };\n\nexport function hashSecret(secret: string): string {\n const salt = randomBytes(16).toString('hex');\n const hash = scryptSync(secret, salt, SCRYPT.keylen, SCRYPT).toString('hex');\n return `${SCRYPT_VERSION}$${salt}$${hash}`;\n}\n\n/** constant-time — a key check must not leak how much of the secret matched */\nexport function verifySecret(secret: string, stored: string | undefined): boolean {\n if (!stored) return false;\n const [version, salt, hex] = stored.split('$');\n if (version !== SCRYPT_VERSION || !salt || !hex) return false;\n const expected = Buffer.from(hex, 'hex');\n const actual = scryptSync(secret, salt, SCRYPT.keylen, SCRYPT);\n return expected.length === actual.length && timingSafeEqual(expected, actual);\n}\n\nexport function buildKeyModel(connection: Connection, modelName: string, collection: string): Model<any> {\n const existing = connection.models?.[modelName];\n if (existing) return existing;\n const schema = new Schema(\n {\n /** the tk_ id embedded in the key string — lookup is a point read */\n _id: { type: String, required: true },\n kind: { type: String, required: true, enum: Object.values(KeyKind) },\n /** sk_ only — versioned scrypt hash of the secret half */\n secretHash: String,\n\n tenantMode: { type: String, required: true, enum: Object.values(TenantMode) },\n /** required iff tenantMode = fixed */\n tenantId: String,\n\n /** stamped onto every record — the client cannot lie about where it runs */\n service: { type: String, required: true },\n env: { type: String, required: true },\n\n /** CORS allowlist. pk_ only; empty = no browser origins accepted. */\n origins: { type: [String], default: [] },\n /** pk_ defaults to event/error/span; sk_ to all five */\n allowedKinds: { type: [String], required: true },\n /** optional narrowing to a subset of registry names */\n allowedNames: { type: [String], default: undefined },\n\n /** records/min across the key. Distinct from EventSpec.burst (per-group). */\n maxPerMinute: { type: Number, required: true, default: 600 },\n\n createdAt: { type: Date, required: true },\n revokedAt: Date,\n /** touched at most once/min, not per request */\n lastUsedAt: Date,\n },\n { collection, versionKey: false },\n );\n schema.index({ revokedAt: 1 });\n return connection.model(modelName, schema);\n}\n\nexport interface CreateKeyInput {\n kind: KeyKind;\n tenantMode: TenantMode;\n tenantId?: string;\n service: string;\n env: string;\n label?: string;\n origins?: string[];\n allowedKinds?: string[];\n allowedNames?: string[];\n maxPerMinute?: number;\n}\n\n/**\n * Mint a key. The full key string is returned ONCE and never reconstructable —\n * only the hash of an sk_ secret is stored. Boot-time trust assertions live\n * here so a misconfigured key cannot exist (instrumentation §2):\n * claimed ⇒ secret · fixed ⇒ tenantId · publishable ⇒ no usage, no claimed\n */\nexport async function createKey(KeyModel: Model<any>, input: CreateKeyInput): Promise<{ key: string; id: string }> {\n const {\n kind, tenantMode, tenantId, service, env,\n label = 'live', origins = [], allowedNames, maxPerMinute = 600,\n } = input;\n\n if (tenantMode === TenantMode.Claimed && kind !== KeyKind.Secret) {\n throw new Error('telemetry: tenantMode \"claimed\" requires a secret key');\n }\n if (tenantMode === TenantMode.Fixed && !tenantId) {\n throw new Error('telemetry: tenantMode \"fixed\" requires tenantId');\n }\n // A fixed key IS its tenantId — minting one on '*' would hand a wire\n // credential the dashboard's cross-tenant scope. The other two modes carry no\n // tenantId to check here; ingest guards them once the tenant has resolved.\n if (isPlatformScope(tenantId)) throw new Error(RESERVED_TENANT_MESSAGE);\n const allowedKinds =\n input.allowedKinds ??\n (kind === KeyKind.Publishable\n ? [TelemetryKind.Event, TelemetryKind.Error, TelemetryKind.Span]\n : Object.values(TelemetryKind));\n if (kind === KeyKind.Publishable && allowedKinds.includes(TelemetryKind.Usage)) {\n throw new Error('telemetry: a publishable key may never write usage');\n }\n\n const id = `tk_${randomBytes(12).toString('hex')}`;\n const secret = kind === KeyKind.Secret ? randomBytes(24).toString('hex') : undefined;\n\n await KeyModel.create({\n _id: id,\n kind,\n secretHash: secret ? hashSecret(secret) : undefined,\n tenantMode,\n tenantId,\n service,\n env,\n origins,\n allowedKinds,\n allowedNames,\n maxPerMinute,\n createdAt: new Date(),\n });\n\n const prefix = kind === KeyKind.Publishable ? 'pk' : 'sk';\n return { key: secret ? `${prefix}_${label}_${id}_${secret}` : `${prefix}_${label}_${id}`, id };\n}\n","import express from 'express';\nimport type { NextFunction, Request, Response, Router } from 'express';\nimport { TelemetryKind, RESERVED_TENANT_MESSAGE, isPlatformScope, plain } from './types.js';\nimport { KeyKind, TenantMode, parseKeyString, verifySecret } from './keys.js';\nimport { noteUndeclaredAttrs } from './emit.js';\nimport { recordRollup } from './rollups.js';\nimport type { Telemetry } from './index.js';\n\n/**\n * The wire ingest surface (instrumentation §3–4). One endpoint, batch-only.\n *\n * Trust in one line: a claim is not a fact. The handler's job is converting\n * key-derived facts and payload claims into one honest envelope — a browser\n * record claiming tenantId is not an attack to reject, it is a field to ignore.\n *\n * Error surface splits on key kind (traps §19): `pk_` NEVER 4xxes — telemetry\n * errors surfacing in browser consoles read as a broken page — so unknown\n * names, oversize, rate limits, revoked keys all drop, quarantine what's\n * parseable, count, and answer 202. `sk_` callers are programmers and get\n * honest 400/401/413/429.\n *\n * Delivery is at-least-once, so the plane order INVERTS from emit():\n * insert first (client-generated `_id`; duplicate ⇒ drop, NO rollup), then\n * aggregate. The plane order follows the delivery semantics (schema §4.6).\n */\n\nexport interface IngestContext {\n tenantId: string;\n subjects?: Array<{ type: string; id: string; role?: string }>;\n actor?: string;\n}\n\nexport interface ContextAdapter {\n /** INBOUND: who is making this request? Only consulted for tenantMode=session. */\n resolveContext(req: Request): IngestContext | null | Promise<IngestContext | null>;\n}\n\nexport interface CreateIngestOptions {\n telemetry: Telemetry;\n contextAdapter?: ContextAdapter;\n /** batch caps — the defaults are the wire contract */\n maxRecords?: number;\n bodyLimit?: string;\n /** key cache TTL ms (60s). Tests turn it down. */\n keyCacheMs?: number;\n}\n\nconst BATCH_MAX = 100;\n\ninterface CachedKey {\n doc: any | null;\n at: number;\n}\n\nexport function createIngest(opts: CreateIngestOptions): Router {\n const { telemetry: t, contextAdapter, maxRecords = BATCH_MAX, bodyLimit = '512kb', keyCacheMs = 60_000 } = opts;\n const KeyModel = t.models.keys;\n const registry = t.registry;\n const logger = t.logger;\n\n const keyCache = new Map<string, CachedKey>();\n const buckets = new Map<string, { n: number; resetAt: number }>();\n\n const takeRecords = (keyId: string, maxPerMinute: number, n: number): number => {\n const now = Date.now();\n let b = buckets.get(keyId);\n if (!b || now >= b.resetAt) {\n b = { n: 0, resetAt: now + 60_000 };\n buckets.set(keyId, b);\n }\n const room = Math.max(0, maxPerMinute - b.n);\n const taken = Math.min(room, n);\n b.n += taken;\n return taken;\n };\n\n const loadKey = async (id: string): Promise<any | null> => {\n const hit = keyCache.get(id);\n if (hit && Date.now() - hit.at < keyCacheMs) return hit.doc;\n const doc = await KeyModel.findById(id).lean();\n keyCache.set(id, { doc: doc ?? null, at: Date.now() }); // negative-cache junk ids too\n return doc ?? null;\n };\n\n const quarantine = (name: string, reason: string, raw: unknown) => {\n t.counters.rejected++;\n void t.collections.rejects()\n .insertOne({ at: new Date(), name, reason, raw: plain(raw) })\n .catch(() => {});\n };\n\n const router = express.Router();\n\n // Preflight cannot be key-scoped (the browser has not sent Authorization\n // yet) — reflect the origin and let the POST enforce the per-key allowlist.\n router.options('/', (req, res) => {\n const origin = req.headers.origin;\n if (origin) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Vary', 'Origin');\n res.setHeader('Access-Control-Allow-Methods', 'POST');\n res.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');\n res.setHeader('Access-Control-Max-Age', '600');\n }\n res.status(204).end();\n });\n\n // Auth resolves BEFORE the body parser so the error middleware knows which\n // error surface (pk drop / sk honest) applies to parse failures.\n router.post(\n '/',\n async (req: Request & { telemetryKey?: any }, res, next) => {\n const bearer = /^Bearer\\s+(.+)$/i.exec(String(req.headers.authorization ?? ''))?.[1];\n // sendBeacon cannot set headers — pk_ may ride the query string. sk_ may not.\n const fromQuery = typeof req.query.key === 'string' ? req.query.key : undefined;\n const parsed = parseKeyString(bearer) ?? (fromQuery?.startsWith('pk_') ? parseKeyString(fromQuery) : null);\n\n const drop = () => res.status(202).json({ accepted: 0, rejected: 0 });\n\n if (!parsed) {\n // no attributable caller: an sk_-shaped credential gets honesty, all\n // else is noise — 202 and gone\n if (bearer?.startsWith('sk_') || fromQuery?.startsWith('sk_')) {\n return res.status(401).json({ error: 'invalid_key' });\n }\n return drop();\n }\n\n const doc = await loadKey(parsed.id);\n const skFail = (status: number, error: string) => res.status(status).json({ error });\n if (!doc || doc.revokedAt) {\n return parsed.kind === KeyKind.Secret ? skFail(401, doc ? 'revoked_key' : 'invalid_key') : drop();\n }\n if (doc.kind !== parsed.kind) {\n return parsed.kind === KeyKind.Secret ? skFail(401, 'invalid_key') : drop();\n }\n if (parsed.kind === KeyKind.Secret && !verifySecret(parsed.secret!, doc.secretHash)) {\n return skFail(401, 'invalid_key');\n }\n\n // browser origin allowlist — pk_ only; no ACAO header means the browser\n // never lets the page read the response, and we drop the write too\n const origin = req.headers.origin;\n if (parsed.kind === KeyKind.Publishable && origin) {\n if (!doc.origins?.includes(origin)) return drop();\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Vary', 'Origin');\n }\n\n if (!doc.lastUsedAt || Date.now() - new Date(doc.lastUsedAt).getTime() > 60_000) {\n doc.lastUsedAt = new Date();\n void KeyModel.updateOne({ _id: doc._id }, { $set: { lastUsedAt: doc.lastUsedAt } }).catch(() => {});\n }\n\n req.telemetryKey = doc;\n next();\n },\n express.json({ limit: bodyLimit }),\n async (req: Request & { telemetryKey?: any }, res) => {\n const key = req.telemetryKey!;\n const pk = key.kind === KeyKind.Publishable;\n const receivedAt = new Date();\n const body = (req.body ?? {}) as Record<string, any>;\n\n let accepted = 0;\n let rejected = 0;\n const respond = () => res.status(202).json({ accepted, rejected });\n\n let records: any[] = Array.isArray(body.records) ? body.records : [];\n if (records.length > maxRecords) {\n if (!pk) return res.status(413).json({ error: 'batch_too_large', max: maxRecords });\n rejected += records.length - maxRecords;\n records = records.slice(0, maxRecords);\n }\n\n // per-key rate limit, counted in records — pk drops the overflow, sk is told\n const granted = takeRecords(key._id, key.maxPerMinute, records.length);\n if (granted < records.length) {\n if (!pk) return res.status(429).json({ error: 'rate_limited' });\n t.counters.capped += records.length - granted;\n rejected += records.length - granted;\n records = records.slice(0, granted);\n }\n\n // ── tenant resolution: the key's, the host's, or the payload's. No fourth path. ──\n let ctx: IngestContext | null = null;\n if (key.tenantMode === TenantMode.Fixed) {\n ctx = { tenantId: key.tenantId };\n } else if (key.tenantMode === TenantMode.Session) {\n if (!contextAdapter) {\n logger.warn('[telemetry] session-mode key but no contextAdapter configured');\n return pk ? respond() : res.status(500).json({ error: 'no_context_adapter' });\n }\n ctx = await contextAdapter.resolveContext(req);\n if (!ctx) {\n // pk: an unauthenticated browser is normal traffic, not an error\n rejected += records.length;\n return pk ? respond() : res.status(401).json({ error: 'no_session' });\n }\n } else {\n // claimed — sk_ only, asserted at key creation\n const claimed = body.context?.tenantId;\n if (typeof claimed !== 'string' || !claimed) {\n return res.status(400).json({ error: 'tenant_required' });\n }\n ctx = { tenantId: claimed };\n }\n const tenantId = ctx.tenantId;\n\n // ── the reserved token, checked ONCE, after resolution ──\n // Deliberately here and not in the `claimed` branch: all three paths mint\n // a tenantId from outside the package. `claimed` is the payload asserting\n // one, `session` is a host adapter that could compute one, and `fixed`\n // reads a key doc that may predate createKey()'s guard. A claim is not a\n // fact — and '*' is not even a tenant. pk_ never 4xxes (traps §19), so it\n // drops and counts; sk_ callers are programmers and are told why.\n if (isPlatformScope(tenantId)) {\n logger.warn(`[telemetry] ingest refused a batch: ${RESERVED_TENANT_MESSAGE}`);\n t.counters.rejected += records.length;\n rejected += records.length;\n return pk ? respond() : res.status(400).json({ error: 'reserved_tenant' });\n }\n\n // server computes the skew; client timestamps lie (schema §9 fix)\n const sentAt = body.sentAt ? Date.parse(body.sentAt) : NaN;\n const clockSkewMs = Number.isFinite(sentAt) ? sentAt - receivedAt.getTime() : 0;\n\n // defaults merge UNDER the claim — a batch that omits context details is\n // normal traffic, and platform/appVersion are envelope-required\n const batchClient = {\n platform: 'web',\n appVersion: String(body.release ?? 'unknown'),\n ...(body.client && typeof body.client === 'object' ? body.client : {}),\n clockSkewMs,\n };\n\n const subjectsOf = (raw: unknown): Array<{ type: string; id: string; role?: string }> =>\n Array.isArray(raw)\n ? raw\n .filter((s: any) => s && typeof s.type === 'string' && typeof s.id === 'string')\n .map((s: any) => ({ type: s.type, id: String(s.id), ...(s.role ? { role: String(s.role) } : {}) }))\n : [];\n\n // merge order, lowest to highest: batch claims < record subjects < host\n // context — the session cookie outranks the JS claim (instrumentation §4)\n const claimSubjects = subjectsOf(body.context?.subjects);\n const hostSubjects = subjectsOf(ctx.subjects);\n const mergeSubjects = (recordSubjects: unknown) => {\n const byType = new Map<string, Array<{ type: string; id: string; role?: string }>>();\n for (const layer of [claimSubjects, subjectsOf(recordSubjects), hostSubjects]) {\n const grouped = new Map<string, Array<{ type: string; id: string; role?: string }>>();\n for (const s of layer) {\n grouped.set(s.type, [...(grouped.get(s.type) ?? []), s]);\n }\n for (const [type, entries] of grouped) byType.set(type, entries);\n }\n return [...byType.values()].flat();\n };\n const batchActor = typeof body.context?.actor === 'string' ? body.context.actor : undefined;\n\n for (const rec of records) {\n const name = typeof rec?.name === 'string' ? rec.name : '';\n const fail = (reason: string) => {\n rejected++;\n quarantine(name || '(unnamed)', reason, rec);\n };\n\n // ── the identify control record: pure linkage, never stored as telemetry ──\n if (name === '$identify') {\n const anonRef = String(rec.anonRef ?? '');\n const userRef = String(rec.userRef ?? '');\n if (!/^.+:.+$/.test(anonRef) || !/^.+:.+$/.test(userRef)) {\n fail('malformed $identify');\n continue;\n }\n await t.collections.aliases().updateOne(\n { _id: `${tenantId}|${anonRef}` } as any,\n { $set: { tenantId, anonRef, userRef, linkedAt: receivedAt } },\n { upsert: true },\n );\n accepted++;\n continue;\n }\n\n const spec = registry[name];\n if (!spec) {\n fail('unregistered event');\n continue;\n }\n if (!key.allowedKinds.includes(spec.kind)) {\n fail(`kind ${spec.kind} not allowed for this key`);\n continue;\n }\n if (spec.origin === 'server' && pk) {\n // the CLIENT_MILESTONES guarantee: a browser may assert\n // wizard_started, never converted — server-origin names need sk_\n fail('server-origin name over a publishable key');\n continue;\n }\n if (key.allowedNames?.length && !key.allowedNames.includes(name)) {\n fail('name not allowed for this key');\n continue;\n }\n const id = typeof rec._id === 'string' && rec._id.length >= 16 && rec._id.length <= 64 ? rec._id : null;\n if (!id) {\n // without a client id there is no idempotency — the §3 contract\n fail('missing client _id');\n continue;\n }\n\n const occurredRaw = rec.occurredAt ? Date.parse(rec.occurredAt) : NaN;\n const occurredAt = Number.isFinite(occurredRaw)\n ? new Date(occurredRaw - clockSkewMs) // §3.3: corrected BEFORE rollups run\n : receivedAt;\n\n const safeMap = (o: unknown) =>\n o && typeof o === 'object'\n ? new Map(Object.entries(o as Record<string, unknown>).map(([k, v]) => [k.replace(/\\./g, '_'), v]))\n : new Map();\n\n // The wire is where a stale client's undeclared attr actually shows up\n // — a shipped desktop build sending a key the server's registry does\n // not know yet. Counted here for the same reason emit() counts it: the\n // strict parse below rejects the whole record, and the quarantine says\n // so one row at a time.\n noteUndeclaredAttrs(t.counters, name, spec, rec.attrs);\n\n // ── write-time subject linking, on the path that actually needs it ──\n // The desktop client knows its install and nothing else, so this — the\n // wire — is where `machine:<installId>` with no `user` arrives. Ingest\n // does not call emit() (at-least-once delivery inverts the plane order,\n // §4.6), so the hook is invoked HERE, from the same instance-wide\n // implementation emit() uses. Before construction, for the same reason\n // as there: pre('validate') derives `subjectKeys` and the rollups below\n // fan out over it.\n const subjects = mergeSubjects(rec.subjects);\n const linked = t.linkSubjects\n ? await t.linkSubjects(name, spec, tenantId, subjects)\n : null;\n\n const Model = t.models.byKind[spec.kind as TelemetryKind];\n const d = new Model({\n // facts the wire may not assert: tenant, service, env, origin, plane\n // fields (forced/sampleRate stripped by construction — only the\n // allowlisted fields below ever reach the document)\n _id: id,\n name,\n tenantId,\n occurredAt,\n severity: typeof rec.severity === 'string' ? rec.severity : undefined,\n subjects: linked ?? subjects,\n actor: ctx.actor ?? (typeof rec.actor === 'string' ? rec.actor : batchActor),\n onBehalfOf: typeof rec.onBehalfOf === 'string' ? rec.onBehalfOf : undefined,\n service: key.service,\n env: key.env,\n release: typeof body.release === 'string' ? body.release : undefined,\n origin: 'client',\n client: batchClient,\n traceId: typeof rec.traceId === 'string' ? rec.traceId : undefined,\n spanId: typeof rec.spanId === 'string' ? rec.spanId : undefined,\n parentId: typeof rec.parentId === 'string' ? rec.parentId : undefined,\n durationMs: typeof rec.durationMs === 'number' ? rec.durationMs : undefined,\n attrs: safeMap(rec.attrs),\n metrics: safeMap(rec.metrics),\n data: rec.data,\n body: typeof rec.body === 'string' ? rec.body : undefined,\n error: rec.error,\n state: rec.state,\n usage: rec.usage,\n });\n\n try {\n await d.validate();\n } catch (e) {\n fail(String(e));\n continue;\n }\n\n // ── insert-gated rollups: at-least-once transport, so the insert IS the dedupe ──\n try {\n await d.save({\n validateBeforeSave: false,\n ...(spec.kind === TelemetryKind.Usage ? { writeConcern: { w: 'majority', j: true } } : {}),\n } as any);\n } catch (e: any) {\n if (e?.code === 11000 || e?.cause?.code === 11000) {\n accepted++; // a retry of a record we already have — the contract working\n continue;\n }\n fail(String(e));\n continue;\n }\n for (const r of spec.rollups ?? []) {\n await recordRollup(t.models.rollups, d, name, r, t.counters).catch((e) =>\n quarantine(name, `rollup: ${e}`, rec),\n );\n }\n accepted++;\n }\n\n respond();\n },\n );\n\n // body-parser failures (bad JSON, over 512KB): pk_ swallows, sk_ hears the truth\n router.use((err: any, req: Request & { telemetryKey?: any }, res: Response, _next: NextFunction) => {\n if (req.telemetryKey?.kind === KeyKind.Secret) {\n const status = err?.type === 'entity.too.large' ? 413 : 400;\n return res.status(status).json({ error: err?.type ?? 'bad_request' });\n }\n t.counters.rejected++;\n res.status(202).json({ accepted: 0, rejected: 1 });\n });\n\n return router;\n}\n","import type { z } from 'zod';\nimport { BUILTIN_PLATFORMS } from './model.js';\nimport type { DimSource, Registry, RollupSpec } from './registry.js';\nimport {\n Env, LogLevel, Origin, RETENTION_DAYS, TELEMETRY_KINDS, TelemetryKind,\n} from './types.js';\n\n/**\n * The derived catalog (reports §3): everything a reader can ask this instance,\n * computed from the registry alone. Pure — no Mongo, no I/O — and built once at\n * createDashboard() / createTelemetryMcp(), boot-time like validateRegistry and\n * for the same reason: if the catalog cannot be built, the registry is wrong.\n *\n * It exists so that nothing is written twice. The registry already says which\n * events exist, which attrs and metrics they carry, which are indexed, and\n * which rollup families they feed; a page that names `cost_usd` is restating a\n * fact the package already knows. The rule this file installs is reports §11.1:\n * a page may not name a metric, an attr, or a family — it asks the catalog.\n */\n\nexport interface Catalog {\n events: Record<string, EventFacet>;\n families: Record<string, FamilyFacet>;\n /** name prefix before the first '.' → event names. An undotted name namespaces to itself. */\n namespaces: Record<string, string[]>;\n /** dims every record carries — filterable/groupable raw for every source */\n envelope: DimFacet[];\n /** every subject type named by any spec's `subjects` or any rollup's `subjects` */\n subjectTypes: string[];\n}\n\nexport interface EventFacet {\n kind: TelemetryKind;\n origin: Origin | 'any';\n subjects: string[];\n description: string;\n namespace: string;\n /** one per declared attr, typed, followed by this kind's own envelope fields */\n dims: DimFacet[];\n /** 'count' first, then per metric key: sum:, avg:, p50:, p95:, p99: */\n measures: MeasureFacet[];\n /** rollup family names this event feeds (its `as`, or its own name) */\n families: string[];\n indexedAttrs: string[];\n indexedMetrics: string[];\n /** the EFFECTIVE retention — the spec's override, else RETENTION_DAYS[kind] */\n retentionDays: number | null;\n}\n\nexport interface FamilyFacet {\n as: string;\n /** the grain, in declared order (pinned per family by validateRegistry) */\n by: DimSource[];\n /** rollups.ts `label(src)` per dim — the `x=` prefix written into `dims` */\n labels: string[];\n bucket: 'hour' | 'day' | 'week' | 'month' | null;\n /** a lifetime rollup has no bucket, and its `firstAt` IS the milestone */\n lifetime: boolean;\n /** the spec's `subjects` when `by` has a subject dim, else [] */\n subjectTypes: string[];\n sums: string[];\n /** labels of `capture` sources */\n capture: string[];\n /** event names declaring this family, registry order */\n feeders: string[];\n retentionDays: number | null;\n}\n\nexport interface DimFacet {\n /**\n * The DimSource form, so it passes straight through to a rollup `by`, to\n * `groupBy`, and to a filter term: 'attr:model' | 'field:client.platform' |\n * 'subjectType' | 'actorType'.\n */\n key: string;\n /** what rollups.ts writes before '=' — 'model', 'client.platform'; for the two pseudo-dims, the key itself */\n label: string;\n type: 'string' | 'enum' | 'number' | 'boolean' | 'date';\n /** closed domain when known: z.enum / z.literal values, envelope enums */\n values?: string[];\n optional: boolean;\n /** true when a real index exists — an `indexedAttrs` attr, or a base-indexed envelope field */\n indexed: boolean;\n}\n\nexport interface MeasureFacet {\n /** 'count' | 'sum:cost_usd' | 'avg:cost_usd' | 'p95:duration_ms' … */\n key: string;\n metric?: string;\n /** families whose `sum` carries this metric — exact answers. Only 'sum:' keys ever have one. */\n exactVia: string[];\n}\n\nexport interface DeriveCatalogOptions {\n /**\n * Host additions to `client.platform`, exactly as CreateTelemetryConfig\n * .platforms extends them — the catalog reports the same closed domain the\n * writer enforces, or it would offer a filter value no record can carry.\n */\n platforms?: readonly string[];\n}\n\n/** the projection the SPA has always booted on — names and shapes, never zod objects */\nexport interface RegistryProjectionEntry {\n kind: TelemetryKind;\n origin: Origin | 'any';\n subjects: string[];\n description: string;\n attrKeys: string[];\n metricKeys: string[];\n indexedAttrs: string[];\n indexedMetrics: string[];\n rollups: {\n as: string;\n by: DimSource[];\n bucket: RollupSpec['bucket'] | null;\n sum: string[];\n subjects: string[];\n }[];\n}\n\nexport type RegistryProjection = Record<string, RegistryProjectionEntry>;\n\n// ── dimension labels ────────────────────────────────────────────────────────\n\n/**\n * rollups.ts writes `${label(src)}=${value}` into `dims`, so the catalog has to\n * agree with it character for character or a groupBy would match nothing. The\n * bare `subject` source has no ':' and labels to itself, which is also what\n * that file's `slice(indexOf(':') + 1)` produces.\n */\nconst label = (src: DimSource): string => src.slice(src.indexOf(':') + 1);\n\n// ── the zod walk ────────────────────────────────────────────────────────────\n\n/**\n * zod 4 leaf `def.type` → the catalog's type. `z.coerce.*` is the base type\n * with `def.coerce` set, so it needs no case of its own; `z.int()` is a\n * ZodNumberFormat whose def.type is already 'number', and 'int' is listed\n * anyway so a future zod that names it does not silently degrade to 'string'.\n */\nconst LEAF_TYPES: Record<string, DimFacet['type']> = {\n string: 'string',\n number: 'number',\n int: 'number',\n bigint: 'number',\n boolean: 'boolean',\n date: 'date',\n};\n\ninterface WalkedAttr {\n type: DimFacet['type'];\n values?: string[];\n optional: boolean;\n}\n\n/**\n * Unwrap a declared attr schema to its leaf and read the leaf's type and, when\n * the domain is closed, its values.\n *\n * Deliberately NOT `z.toJSONSchema`: this needs five cases, and a JSON-schema\n * round trip would put a second vocabulary between the registry and the UI.\n * Anything the walker does not recognise is 'string', which is honest — attrs\n * are strings after Mongoose casting anyway (registry.ts).\n */\nfunction walkAttr(schema: unknown): WalkedAttr {\n let node: any = schema;\n let optional = false;\n\n // Bounded because a lazy or self-referential schema would otherwise hang\n // boot; twenty wrappers is already pathological.\n for (let depth = 0; node && depth < 20; depth++) {\n const def = node._zod?.def ?? node.def;\n if (!def?.type) break;\n\n switch (def.type) {\n // these three all mean \"the value may be absent from a stored record\",\n // which is the only thing `optional` claims\n case 'optional':\n case 'nullable':\n case 'default':\n optional = true;\n node = def.innerType;\n continue;\n\n case 'catch':\n case 'readonly':\n node = def.innerType;\n continue;\n\n // a pipe is `in -> out`; the INPUT side is what a caller may send and so\n // what a stored value was validated as. The output of a transform is\n // frequently a shape no filter could ever be written against.\n case 'pipe':\n node = def.in;\n continue;\n\n case 'enum': {\n // `.options` rather than Object.values(def.entries) because a numeric\n // TS enum's entries carry its reverse mapping too\n const options = Array.isArray(node.options) ? node.options : Object.values(def.entries ?? {});\n return { type: 'enum', values: options.map(String), optional };\n }\n\n case 'literal':\n return { type: 'enum', values: [...(def.values ?? [])].map(String), optional };\n\n default:\n return { type: LEAF_TYPES[def.type] ?? 'string', optional };\n }\n }\n\n return { type: 'string', optional };\n}\n\n// ── envelope dims ───────────────────────────────────────────────────────────\n\nconst dim = (\n key: string,\n type: DimFacet['type'],\n o: { values?: readonly string[]; optional?: boolean; indexed?: boolean } = {},\n): DimFacet => ({\n key,\n // the two pseudo-dims are derived at query time from subjectKeys / actor, so\n // they carry no `field:` prefix and label to themselves\n label: key.startsWith('field:') ? key.slice(6) : key,\n type,\n ...(o.values ? { values: [...o.values] } : {}),\n optional: o.optional ?? false,\n indexed: o.indexed ?? false,\n});\n\n/**\n * Fixed, not inferred. These are `field:` sources a rollup may already declare,\n * so the labels agree with what rollups.ts writes into `dims`. `indexed` is\n * true only where model.ts actually builds a base index over the field —\n * {tenantId, kind, name, occurredAt} and {tenantId, subjectKeys, occurredAt}.\n */\nconst envelopeDims = (platforms: readonly string[]): DimFacet[] => [\n dim('field:kind', 'enum', { values: TELEMETRY_KINDS, indexed: true }),\n dim('field:name', 'string', { indexed: true }),\n dim('field:severity', 'enum', { values: Object.values(LogLevel) }),\n dim('field:env', 'enum', { values: Object.values(Env) }),\n dim('field:service', 'string'),\n dim('field:release', 'string'),\n dim('field:origin', 'enum', { values: Object.values(Origin) }),\n // client context is absent on server-origin records, so both of its dims are optional\n dim('field:client.platform', 'enum', { values: platforms, optional: true }),\n dim('field:client.appVersion', 'string', { optional: true }),\n dim('subjectType', 'string', { optional: true, indexed: true }),\n dim('actorType', 'string', { optional: true }),\n];\n\n/**\n * The discriminator's own fields, offered only on events of that kind — a usage\n * event's dims include its meter, an event event's do not. `indexed` again\n * tracks the real discriminator indexes in model.ts, which is why\n * `error.type` is false while `state.key` is true: the error index is on\n * `error.fingerprint`.\n */\nconst kindDims = (kind: TelemetryKind): DimFacet[] => {\n switch (kind) {\n case TelemetryKind.Usage:\n return [\n dim('field:usage.meter', 'string', { indexed: true }),\n dim('field:usage.billedTo', 'string'),\n dim('field:usage.unit', 'string'),\n ];\n case TelemetryKind.State:\n return [\n dim('field:state.key', 'string', { indexed: true }),\n dim('field:state.to', 'string', { indexed: true }),\n ];\n case TelemetryKind.Error:\n return [dim('field:error.type', 'string'), dim('field:error.handled', 'boolean')];\n default:\n return [];\n }\n};\n\n// ── the derivation ──────────────────────────────────────────────────────────\n\n/** the three raw-only operators every metric gets beside its exact `sum:` */\nconst RAW_OPS = ['avg', 'p50', 'p95', 'p99'] as const;\n\nexport function deriveCatalog(registry: Registry, opts: DeriveCatalogOptions = {}): Catalog {\n // union, never replacement — a host adding 'watchos' keeps 'web' (model.ts)\n const platforms = [...new Set([...BUILTIN_PLATFORMS, ...(opts.platforms ?? [])])];\n\n // Families first: an EventFacet names the families it feeds and a family\n // names every event that feeds it, so the family pass has to see the whole\n // registry before any event facet can be finished.\n const families: Record<string, FamilyFacet> = {};\n for (const [name, spec] of Object.entries(registry)) {\n for (const r of spec.rollups ?? []) {\n const as = r.as ?? name;\n const seen = families[as];\n\n if (!seen) {\n families[as] = {\n as,\n by: [...r.by],\n labels: r.by.map(label),\n bucket: r.bucket ?? null,\n lifetime: !r.bucket,\n // `subjects` only means anything when there is a subject dim to\n // restrict; without one it selects nothing and claiming it would\n // offer a subject filter the family cannot answer\n subjectTypes: r.by.includes('subject') ? [...(r.subjects ?? [])] : [],\n sums: [...(r.sum ?? [])],\n capture: (r.capture ?? []).map(label),\n feeders: [name],\n retentionDays: r.retentionDays ?? null,\n };\n continue;\n }\n\n // `by`, `bucket` and `subjects` are pinned per family by validateRegistry\n // — two shapes under one `as` is a boot error — so the first feeder\n // settles the grain and later ones cannot disagree. `sum` and `capture`\n // are NOT pinned, because a second name may accumulate another metric\n // into the same docs, so they union in declaration order: that is what a\n // reader of the family can actually find in it. `retentionDays` is taken\n // from the first feeder; it is stamped per record by whichever spec\n // produced it, so a family fed by two different TTLs genuinely has two.\n for (const k of r.sum ?? []) if (!seen.sums.includes(k)) seen.sums.push(k);\n for (const c of r.capture ?? []) {\n const l = label(c);\n if (!seen.capture.includes(l)) seen.capture.push(l);\n }\n if (!seen.feeders.includes(name)) seen.feeders.push(name);\n }\n }\n\n const events: Record<string, EventFacet> = {};\n const namespaces: Record<string, string[]> = {};\n const subjectTypes: string[] = [];\n const noteSubject = (t: string) => {\n if (!subjectTypes.includes(t)) subjectTypes.push(t);\n };\n\n for (const [name, spec] of Object.entries(registry)) {\n const dot = name.indexOf('.');\n const namespace = dot === -1 ? name : name.slice(0, dot);\n (namespaces[namespace] ??= []).push(name);\n\n for (const s of spec.subjects) noteSubject(s);\n\n const indexedAttrs = [...(spec.indexedAttrs ?? [])];\n const dims: DimFacet[] = Object.entries((spec.attrs?.shape ?? {}) as Record<string, z.ZodType>).map(\n ([key, schema]) => {\n const walked = walkAttr(schema);\n return {\n key: `attr:${key}`,\n label: key,\n type: walked.type,\n ...(walked.values ? { values: walked.values } : {}),\n optional: walked.optional,\n indexed: indexedAttrs.includes(key),\n };\n },\n );\n dims.push(...kindDims(spec.kind));\n\n // this event's OWN declarations, per family. `exactVia` must not name a\n // family that sums the metric only because a DIFFERENT feeder said so —\n // this event's records would not be in that total.\n const eventFamilies: string[] = [];\n const ownSums = new Map<string, Set<string>>();\n for (const r of spec.rollups ?? []) {\n const as = r.as ?? name;\n if (!eventFamilies.includes(as)) eventFamilies.push(as);\n const set = ownSums.get(as) ?? new Set<string>();\n for (const k of r.sum ?? []) set.add(k);\n ownSums.set(as, set);\n for (const s of r.subjects ?? []) noteSubject(s);\n }\n\n const measures: MeasureFacet[] = [{ key: 'count', exactVia: [] }];\n for (const k of Object.keys(spec.metrics?.shape ?? {})) {\n measures.push({\n key: `sum:${k}`,\n metric: k,\n exactVia: eventFamilies.filter((as) => ownSums.get(as)?.has(k)),\n });\n for (const op of RAW_OPS) measures.push({ key: `${op}:${k}`, metric: k, exactVia: [] });\n }\n // durationMs lives on the envelope for kind=span rather than in `metrics`,\n // so it is a measure no registry can declare and every span has\n if (spec.kind === TelemetryKind.Span) {\n for (const op of RAW_OPS) {\n measures.push({ key: `${op}:durationMs`, metric: 'durationMs', exactVia: [] });\n }\n }\n\n events[name] = {\n kind: spec.kind,\n origin: spec.origin,\n subjects: [...spec.subjects],\n description: spec.description,\n namespace,\n dims,\n measures,\n families: eventFamilies,\n indexedAttrs,\n indexedMetrics: [...(spec.indexedMetrics ?? [])],\n // `hasOwnProperty` rather than `??`, exactly as model.ts stamps expiresAt:\n // an explicit `retentionDays: null` means immortal and must not fall\n // through to the per-kind default\n retentionDays: Object.prototype.hasOwnProperty.call(spec, 'retentionDays')\n ? spec.retentionDays ?? null\n : RETENTION_DAYS[spec.kind],\n };\n }\n\n return { events, families, namespaces, envelope: envelopeDims(platforms), subjectTypes };\n}\n\n/**\n * The catalog, narrowed back to the projection `/api/registry` and\n * `describe_telemetry` have always returned. It exists so that adding the\n * catalog costs the SPA nothing: the `registry` key keeps its exact shape while\n * `catalog` arrives beside it.\n *\n * One nuance the old per-event code did not have: `sum` is read off the FAMILY,\n * so two names feeding one family with different `sum` lists both report the\n * union. That is the more useful answer — it is what the family's docs actually\n * accumulate — and validateRegistry already forbids the mismatches that would\n * matter (`by`, `bucket`, `subjects`).\n */\nexport function projectRegistry(catalog: Catalog): RegistryProjection {\n return Object.fromEntries(\n Object.entries(catalog.events).map(([name, e]) => [\n name,\n {\n kind: e.kind,\n origin: e.origin,\n subjects: e.subjects,\n description: e.description,\n attrKeys: e.dims.filter((d) => d.key.startsWith('attr:')).map((d) => d.label),\n // every metric key gets exactly one `sum:` measure and nothing else does\n metricKeys: e.measures.filter((m) => m.key.startsWith('sum:')).map((m) => m.metric!),\n indexedAttrs: e.indexedAttrs,\n indexedMetrics: e.indexedMetrics,\n rollups: e.families.map((as) => {\n const f = catalog.families[as]!;\n return { as: f.as, by: f.by, bucket: f.bucket, sum: f.sums, subjects: f.subjectTypes };\n }),\n },\n ]),\n );\n}\n","import type { Catalog } from './catalog.js';\nimport { COUNTER_OVERFLOW_KEY, type TelemetryCounters } from './types.js';\n\n/**\n * The loop closed in the other direction (reports §9).\n *\n * Everywhere else in this package the registry tells the data what is allowed.\n * Here the data tells the registry what it is missing — and it can, because\n * nothing was ever dropped silently: `undeclaredAttrs` knows which attr key\n * keeps arriving undeclared, `rollupSkippedBy` knows which family keeps losing\n * which dim, and the quarantine knows which name nobody registered.\n *\n * Each of those is one registry line away from being fixed, so each suggestion\n * carries that line as `fix` — pasteable, not prose. Nothing here writes\n * anything: the host still edits the registry by hand. The package just stops\n * making it guess.\n *\n * Pure — no Mongo, no I/O — and unit-tested that way, like `deriveCatalog` and\n * `resolveReport`.\n */\n\nexport interface Suggestion {\n kind: 'undeclared_attr' | 'missing_dim_default' | 'unregistered_event';\n /** the registry entry to touch — an event name, or a rollup family name */\n target: string;\n /** attr key or dim label, when the suggestion is about one */\n key?: string;\n count: number;\n /** one sentence a human reads */\n message: string;\n /** the registry change, as code */\n fix: string;\n}\n\nexport interface DeriveSuggestionsInput {\n counters: TelemetryCounters;\n catalog: Catalog;\n /**\n * The quarantine rows the caller already fetched. `name` and `reason` are all\n * that is read; the index signature is there so a driver's `WithId<Document>`\n * passes straight in without a cast.\n */\n quarantine?: readonly { name?: unknown; reason?: unknown; [k: string]: unknown }[];\n}\n\n/**\n * emit.ts and ingest.ts both quarantine an unknown name with exactly this\n * reason, and model.ts's hook throws `telemetry: unregistered event \"x\"` for\n * the direct-model path — a substring test matches all three without matching\n * anything else.\n */\nconst UNREGISTERED_REASON = 'unregistered event';\n\n/** the returned list, capped. A System page is a thing a human reads. */\nexport const MAX_SUGGESTIONS = 50;\n\n/**\n * Quarantine names are client-controlled, and `fix` is rendered as code. Cap\n * the length and quote anything that is not plainly a bare name, so a hostile\n * event name cannot be dressed up as surrounding syntax.\n */\nconst NAME_MAX = 120;\nconst quote = (s: string) => (/^[A-Za-z0-9_.:$-]+$/.test(s) ? `'${s}'` : JSON.stringify(s));\n/** an object key that needs no quoting is written bare, the way a registry does */\nconst prop = (s: string) => (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(s) ? s : quote(s));\nconst times = (n: number) => `${n} time${n === 1 ? '' : 's'}`;\n\n/** split `${target}|${key}` on the FIRST '|' — the key half may contain more */\nconst split = (k: string): [string, string] => {\n const i = k.indexOf('|');\n return i === -1 ? [k, ''] : [k.slice(0, i), k.slice(i + 1)];\n};\n\nexport function deriveSuggestions(input: DeriveSuggestionsInput): Suggestion[] {\n const { counters, catalog, quarantine = [] } = input;\n const out: Suggestion[] = [];\n\n // ── undeclared attrs: the zod line that would let the record through ──\n for (const [k, count] of Object.entries(counters.undeclaredAttrs ?? {})) {\n // the fold-here bucket names no event and no key, so there is no line to\n // paste — it is a counter to look at, not a suggestion to act on\n if (k === COUNTER_OVERFLOW_KEY || !count) continue;\n const [name, key] = split(k);\n if (!name || !key) continue;\n\n const facet = catalog.events[name];\n const line = `${prop(key)}: z.string().max(64),`;\n // No attr dims at all means the spec declares no `attrs` object, and a bare\n // key line would have nothing to land in — so hand over the whole block.\n const hasAttrs = !!facet?.dims.some((d) => d.key.startsWith('attr:'));\n out.push({\n kind: 'undeclared_attr',\n target: name,\n key,\n count,\n message: `\\`${name}\\` has been sent with attr \\`${key}\\` ${times(count)} — not declared`,\n fix: hasAttrs ? line : `attrs: z.object({ ${prop(key)}: z.string().max(64) }),`,\n });\n }\n\n // ── skipped rollups: the dimDefault that would make the drop a group ──\n for (const [k, count] of Object.entries(counters.rollupSkippedBy ?? {})) {\n if (k === COUNTER_OVERFLOW_KEY || !count) continue;\n const [as, dim] = split(k);\n if (!as || !dim) continue;\n\n // Naming the feeders matters: `dimDefault` is declared per rollup on an\n // EVENT, not on the family, so \"add it to `screens_viewed`\" is not yet an\n // instruction — the catalog knows which specs to open.\n const feeders = catalog.families[as]?.feeders ?? [];\n const where = feeders.length\n ? `// on the \\`${as}\\` rollup of ${feeders.map((f) => `\\`${f}\\``).join(', ')}\\n`\n : '';\n out.push({\n kind: 'missing_dim_default',\n target: as,\n key: dim,\n count,\n message:\n `\\`${as}\\` skipped ${count} record${count === 1 ? '' : 's'} with no \\`${dim}\\` — ` +\n 'declare `dimDefault`',\n fix: `${where}dimDefault: 'unknown',`,\n });\n }\n\n // ── unregistered names: the stub that would stop the quarantine ──\n const unregistered = new Map<string, number>();\n for (const row of quarantine) {\n if (typeof row?.reason !== 'string' || !row.reason.includes(UNREGISTERED_REASON)) continue;\n const name = typeof row.name === 'string' ? row.name.slice(0, NAME_MAX) : '';\n if (!name || name === '(unnamed)') continue;\n unregistered.set(name, (unregistered.get(name) ?? 0) + 1);\n }\n for (const [name, count] of unregistered) {\n out.push({\n kind: 'unregistered_event',\n target: name,\n count,\n message: `\\`${name}\\` was rejected ${times(count)} — not in the registry`,\n // the minimum that boots: validateRegistry wants a kind, an origin, and\n // a subjects array, and nothing here can guess the rest\n fix: `${quote(name)}: { kind: 'event', origin: 'client', subjects: [], description: '' },`,\n });\n }\n\n // Loudest first. Ties break on target then key so the same counters always\n // produce the same page — a list that reshuffles between refreshes is one\n // nobody trusts.\n out.sort(\n (a, b) =>\n b.count - a.count ||\n a.target.localeCompare(b.target) ||\n (a.key ?? '').localeCompare(b.key ?? ''),\n );\n return out.slice(0, MAX_SUGGESTIONS);\n}\n","import type { Model } from 'mongoose';\nimport type { Registry, RollupSpec } from './registry.js';\nimport { truncate } from './rollups.js';\nimport type { TimeRange } from './query.js';\n\n/**\n * The sixth read primitive: cohort funnels over lifetime milestone rollups\n * (cohort-math §1). Every host that models milestones as lifetime rollups then\n * rewrites the same three things — stage ordering, the cohort window, and the\n * median time-to-step aggregation. This file is that code, once.\n *\n * The formulas are ported verbatim from maxed's `src/server/telemetry/funnel.ts`\n * (recon: plans/cohort-math.md). Names differ where maxed's were host-specific\n * or actively wrong; the mapping is exact and total:\n *\n * maxed here why\n * ─────────────────────────────────────────────────────────────────────────\n * accounts subjects the package counts subjects, not accounts\n * first first unchanged — |{s : stage 1 present}|\n * pctOfFirst pctOfFirst unchanged\n * pctOfPrevious pctOfPrevious unchanged\n * medianDaysFromSignup medianDaysFromAnchor the anchor milestone is configurable here\n * medianDaysFromPrevious medianDaysFromPrevious unchanged\n * StageSummary.stuckAccounts notReached reached k−1, not k (drop-off INTO k)\n * accountsStuckAt(k) stalledAt reached k, not k+1 (drop-off OUT OF k)\n *\n * The last two are the deliberate divergence. maxed ships both quantities under\n * the word \"stuck\", and its `accountsStuckAt` reports every CONVERTED subject as\n * stuck because the terminal stage has no k+1 to fail (cohort-math H3). Here the\n * two quantities have two names and `stalledAt` is **null** on the terminal\n * stage — \"how many stalled here\" has no answer when there is nowhere to go\n * next, and 0 would be as wrong as `subjects`.\n *\n * Interval convention: the package is half-open (`$gte`/`$lt`) everywhere and\n * stays that way. maxed's cohort window is closed on both ends (cohort-math R6),\n * so `cohort.endInclusive` exists to reproduce it — and is translated to a\n * half-open bound HERE (see `cohortWindow`) rather than leaking `$lte` into the\n * read layer.\n */\n\n// ── shapes ──────────────────────────────────────────────────────────────────\n\nexport interface FunnelStageSpec {\n /** the lifetime rollup family whose doc marks this stage — `firstAt` IS the timestamp */\n as: string;\n /** stable identifier in the response. Default: `as` */\n key?: string;\n label?: string;\n description?: string;\n}\n\nexport interface FunnelCohortWindow extends TimeRange {\n /**\n * Include `to` itself. Default FALSE — the package is half-open everywhere and\n * that is the correct convention. maxed's funnel is closed on both ends\n * (cohort-math R6), so a host migrating off it sets this to keep its numbers.\n */\n endInclusive?: boolean;\n}\n\nexport interface FunnelParams {\n /** ordered stages. A stage may be reached without its predecessor — see LITERAL below. */\n stages: readonly FunnelStageSpec[];\n /** the milestone that assigns cohort membership and anchors time-to-step. Default: `stages[0].as` */\n anchor?: string;\n /** the cohort window, applied to the ANCHOR family's `firstAt` */\n cohort: FunnelCohortWindow;\n /** exit families — counted, never staged (cohort-math §1.4) */\n exits?: readonly FunnelStageSpec[];\n /** restrict the cohort to one subject type ('account') */\n subjectType?: string;\n /** also slice the cohort by anchor date. UTC, Monday-start weeks — `truncate()` */\n interval?: 'day' | 'week' | 'month';\n /** cohort size cap. Clamped to `limits.funnel`; hitting it sets `truncated`. */\n limit?: number;\n}\n\nexport interface FunnelStageResult {\n /** 1-based position in `stages` */\n order: number;\n key: string;\n as: string;\n label: string;\n description?: string;\n /** subjects with this stage present. NOT monotonic — see LITERAL below. */\n subjects: number;\n /** 0–100, unrounded. null when stage 1's count is 0. */\n pctOfFirst: number | null;\n /** 0–100, unrounded. null on stage 1 and whenever the previous count is 0 — never 0, never Infinity. */\n pctOfPrevious: number | null;\n /** fractional days, unrounded. null on an empty sample. */\n medianDaysFromAnchor: number | null;\n /** fractional days, unrounded. null on stage 1 and on an empty sample. */\n medianDaysFromPrevious: number | null;\n /** reached the PREVIOUS stage and not this one — drop-off INTO this stage. 0 on stage 1. */\n notReached: number;\n /** reached this stage and not the NEXT — drop-off OUT OF it. null on the terminal stage. */\n stalledAt: number | null;\n}\n\nexport interface FunnelExitResult {\n key: string;\n as: string;\n label: string;\n subjects: number;\n}\n\nexport interface FunnelSlice {\n /** the truncated anchor date — UTC bucket start, not a \"2026-W31\" label */\n at: Date;\n subjects: number;\n stages: FunnelStageResult[];\n}\n\nexport interface FunnelResult {\n /** cohort size: subjects whose ANCHOR firstAt fell in the window */\n cohortSubjects: number;\n /** |{ s : stage 1 present }| — the `pctOfFirst` denominator. Equals cohortSubjects when the anchor IS stage 1. */\n first: number;\n stages: FunnelStageResult[];\n exits: FunnelExitResult[];\n /** present only when `interval` was asked for; ascending by `at` */\n slices: FunnelSlice[] | null;\n /** the cohort read hit its cap — every number below is an UNDERCOUNT (traps §18: no silent caps) */\n truncated: boolean;\n cohort: { from: Date; to: Date; endInclusive: boolean; anchor: string };\n dataSource: 'rollups';\n}\n\n/** one subject's assembled milestone index — the input `summarizeStages` reasons over */\nexport interface CohortSubject {\n ref: string;\n /** the anchor milestone's firstAt. Never null via `runFunnel`; the branch exists per cohort-math R9. */\n anchorAt: Date | null;\n /** stage key → first occurrence */\n stages: Record<string, Date>;\n /** exit key → first occurrence */\n exits: Record<string, Date>;\n}\n\ninterface ResolvedStage {\n order: number;\n key: string;\n as: string;\n label: string;\n description?: string;\n}\n\n// ── pure math ───────────────────────────────────────────────────────────────\n\nconst DAY_MS = 86_400_000;\n\n/**\n * Mean of the two middles on even counts — NOT the lower middle (cohort-math R1).\n * Empty set is null, never 0: \"nobody got here\" and \"everybody got here\n * instantly\" are different facts and a chart must be able to tell them apart.\n * No rounding anywhere; the caller formats.\n */\nexport function median(values: readonly number[]): number | null {\n if (values.length === 0) return null;\n const s = [...values].sort((a, b) => a - b);\n const mid = s.length >> 1;\n return s.length % 2 === 1 ? s[mid]! : (s[mid - 1]! + s[mid]!) / 2;\n}\n\n/**\n * The stage table. Pure — same input, same output, no Mongo — so the equivalence\n * test can pin it cell by cell.\n *\n * LITERAL, never backfilled (cohort-math R4): a subject counts at stage N only\n * if a stage-N doc exists for it. Reaching N+1 does not imply N. So stage counts\n * are NOT required to be non-increasing, `pctOfPrevious` may exceed 100%, and a\n * skipping subject contributes to `subjects` for the later stage but to nothing\n * else on that row — not `prevReached`, not the fromPrevious sample, not\n * `notReached`. That is a data fact, not a bug, and smoothing it would invent\n * subjects that never existed.\n */\nexport function summarizeStages(\n subjects: readonly CohortSubject[],\n stages: readonly ResolvedStage[],\n): FunnelStageResult[] {\n const firstKey = stages[0]?.key;\n const first = firstKey ? subjects.filter((s) => s.stages[firstKey]).length : 0;\n\n return stages.map((st, i) => {\n const prev = i > 0 ? stages[i - 1]! : null;\n const next = i < stages.length - 1 ? stages[i + 1]! : null;\n\n const reached: CohortSubject[] = [];\n const fromAnchor: number[] = [];\n for (const s of subjects) {\n const at = s.stages[st.key];\n if (!at) continue;\n reached.push(s);\n // a subject with no anchor is excluded from the SAMPLE but still counted\n // in `subjects` (cohort-math R9) — unreachable through runFunnel, kept\n // because summarizeStages is exported and can be fed from elsewhere\n if (s.anchorAt) fromAnchor.push((at.getTime() - s.anchorAt.getTime()) / DAY_MS);\n }\n\n let prevReached = 0;\n let notReached = 0;\n const fromPrevious: number[] = [];\n if (prev) {\n for (const s of subjects) {\n const p = s.stages[prev.key];\n if (!p) continue;\n prevReached += 1;\n const cur = s.stages[st.key];\n if (cur) fromPrevious.push((cur.getTime() - p.getTime()) / DAY_MS);\n else notReached += 1;\n }\n }\n\n // `pctOfPrevious` divides ALL subjects that reached this stage by only those\n // that reached the previous one — two independent counts, not a conversion\n // rate (cohort-math H4). Ported deliberately: changing it would silently\n // disagree with the funnel a migrating host is reading today.\n return {\n order: st.order,\n key: st.key,\n as: st.as,\n label: st.label,\n ...(st.description ? { description: st.description } : {}),\n subjects: reached.length,\n pctOfFirst: first > 0 ? (reached.length / first) * 100 : null,\n pctOfPrevious: prev ? (prevReached > 0 ? (reached.length / prevReached) * 100 : null) : null,\n medianDaysFromAnchor: median(fromAnchor),\n medianDaysFromPrevious: prev ? median(fromPrevious) : null,\n notReached,\n // the divergence: maxed's `!next` clause makes every subject that reached\n // the terminal stage \"stuck\" there. null says \"undefined\", which is true.\n stalledAt: next ? subjects.filter((s) => s.stages[st.key] && !s.stages[next.key]).length : null,\n };\n });\n}\n\n// ── registry lookup ─────────────────────────────────────────────────────────\n\n/** the first declaration of a rollup family — validateRegistry pins the shape, so it speaks for all */\nexport function findFamily(registry: Registry, as: string): { name: string; spec: RollupSpec } | null {\n for (const [name, s] of Object.entries(registry)) {\n for (const r of s.rollups ?? []) {\n if ((r.as ?? name) === as) return { name, spec: r };\n }\n }\n return null;\n}\n\n/**\n * A milestone family is a LIFETIME rollup keyed on exactly one subject dim. Any\n * other shape cannot answer \"when did this subject first reach this stage\" —\n * a bucketed family has one doc per period, and an extra dim has one doc per\n * (subject, value). Both would produce a plausible wrong number, so this throws\n * instead. A registry mistake must fail loudly; that is what this package is for.\n */\nexport function requireMilestoneFamily(registry: Registry, as: string, primitive: string): RollupSpec {\n const found = findFamily(registry, as);\n if (!found) {\n throw new Error(\n `telemetry: ${primitive} — no rollup family \"${as}\" is declared. Add a \\`rollups: [{ as: '${as}', ` +\n `by: ['subject'], subjects: [...] }]\\` block to the event that marks it.`,\n );\n }\n const { name, spec } = found;\n const shape = `by: [${spec.by.map((d) => `'${d}'`).join(', ')}]${spec.bucket ? `, bucket: '${spec.bucket}'` : ''}`;\n if (spec.bucket) {\n throw new Error(\n `telemetry: ${primitive} — rollup family \"${as}\" (declared on \"${name}\") is BUCKETED (${shape}). ` +\n `A milestone needs a lifetime family so \\`firstAt\\` is the one moment the subject reached it; ` +\n `a bucketed family has one doc per period and would count the same subject repeatedly.`,\n );\n }\n if (spec.by.length !== 1 || spec.by[0] !== 'subject') {\n throw new Error(\n `telemetry: ${primitive} — rollup family \"${as}\" (declared on \"${name}\") is keyed ${shape}, ` +\n `but a milestone must be keyed by exactly one subject dim (\\`by: ['subject']\\`). ` +\n `Extra dims split one subject across several docs, which would over-count every stage.`,\n );\n }\n return spec;\n}\n\n// ── the read ────────────────────────────────────────────────────────────────\n\nexport interface FunnelCtx {\n RollupModel: Model<any>;\n registry: Registry;\n /** cohort size cap — config, per traps §18 */\n cohortCap: number;\n /**\n * The tenancy term for a scope, INJECTED. This file computes cohort math; it\n * does not get to decide who may read across tenants, and hard-wiring\n * `{ tenantId }` here would put that policy in two places. query.ts owns it.\n */\n scopeMatch: (scope: string) => Record<string, unknown>;\n}\n\n/**\n * Closed → half-open, exactly. BSON dates are integer milliseconds, so\n * `{$lte: e}` and `{$lt: e + 1ms}` select identically — which is why\n * `endInclusive` can be honoured without a `$lte` ever reaching the query layer.\n */\nfunction cohortWindow(c: FunnelCohortWindow): { from: Date; to: Date; endInclusive: boolean } {\n const endInclusive = c.endInclusive === true;\n return { from: c.from, to: endInclusive ? new Date(c.to.getTime() + 1) : c.to, endInclusive };\n}\n\nexport async function runFunnel(\n ctx: FunnelCtx,\n scope: string,\n params: FunnelParams,\n): Promise<FunnelResult> {\n if (!params.stages?.length) throw new Error('telemetry: funnel() needs at least one stage');\n\n const stages: ResolvedStage[] = params.stages.map((s, i) => ({\n order: i + 1,\n key: s.key ?? s.as,\n as: s.as,\n label: s.label ?? s.key ?? s.as,\n ...(s.description ? { description: s.description } : {}),\n }));\n const exits: ResolvedStage[] = (params.exits ?? []).map((s, i) => ({\n order: i + 1,\n key: s.key ?? s.as,\n as: s.as,\n label: s.label ?? s.key ?? s.as,\n }));\n\n // ANCHOR, not first-event (cohort-math R5): a subject whose earliest record is\n // a page view three weeks before signup is still assigned by the signup. A\n // subject with no anchor doc in the window is absent from the cohort entirely\n // — every other milestone it has is invisible, counted at no stage.\n const anchor = params.anchor ?? stages[0]!.as;\n\n requireMilestoneFamily(ctx.registry, anchor, 'funnel()');\n for (const s of [...stages, ...exits]) requireMilestoneFamily(ctx.registry, s.as, 'funnel()');\n\n const { from, to, endInclusive } = cohortWindow(params.cohort);\n const cap = Math.min(Math.max(1, params.limit ?? ctx.cohortCap), ctx.cohortCap);\n\n const cohortMatch: Record<string, unknown> = {\n ...ctx.scopeMatch(scope),\n as: anchor,\n // AMBIGUOUS-2 (cohort-math): maxed's cohort read overwrites per row with no\n // ordering, so its `signupAt` is whichever row Mongo returned last —\n // nondeterministic. Unreachable here by construction: the rollup's `firstAt`\n // is a `$min` maintained on write, so the anchor timestamp is the EARLIEST\n // occurrence, always, matching the tie-break rule maxed uses everywhere else\n // (R12). We take min(at) and the storage enforces it.\n firstAt: { $gte: from, $lt: to },\n };\n if (params.subjectType) cohortMatch.subjectType = params.subjectType;\n\n // limit+1 so \"hit the cap\" is a fact, not an inference off an exact match\n const cohortRows = await ctx.RollupModel.find(cohortMatch)\n .sort({ firstAt: 1 })\n .limit(cap + 1)\n .lean();\n const truncated = cohortRows.length > cap;\n if (truncated) cohortRows.pop();\n\n // A subject ref is unique only WITHIN a tenant, so the index is keyed by\n // (tenant, ref). Under a cross-tenant scope two tenants' 'account:a1' are two\n // subjects; keying on the ref alone would braid their milestones into one\n // funnel and report a conversion that never happened.\n const keyOf = (r: any) => `${r.tenantId ?? ''}|${r.dims?.[0]}`;\n const index = new Map<string, CohortSubject>();\n const refs = new Set<string>();\n const tenants = new Set<string>();\n for (const r of cohortRows as any[]) {\n const ref = r.dims?.[0];\n if (!ref) continue;\n refs.add(ref);\n tenants.add(String(r.tenantId ?? ''));\n index.set(keyOf(r), { ref, anchorAt: r.firstAt, stages: {}, exits: {} });\n }\n\n if (refs.size) {\n const byAs = new Map<string, ResolvedStage[]>();\n for (const s of [...stages, ...exits]) {\n const list = byAs.get(s.as) ?? [];\n list.push(s);\n byAs.set(s.as, list);\n }\n // One read for every stage of every cohort member — the multi-subject gap\n // (cohort-math G3). N single-subject reads or an uncapped family scan were\n // the alternatives; the second truncates a large cohort silently.\n const stageRows = await ctx.RollupModel.find({\n ...ctx.scopeMatch(scope),\n as: { $in: [...byAs.keys()] },\n dims: { $in: [...refs] },\n // AMBIGUOUS-1 (cohort-math): maxed collects stages with `at >= cohortStart`\n // and no upper bound. We keep the lower bound — reading (a), as-written.\n // Reasons: (1) it is what maxed does, and an equivalence test against a\n // table computed under the other reading would prove nothing; (2) over\n // rollup storage the predicate reads \"first reached no earlier than the\n // cohort opened\", which is the only reading under which a cohort's funnel\n // is a function of its own window — drop the bound and a backfill dated\n // before the window silently adds stages to a report already published.\n // No UPPER bound, deliberately: a conversion landing months after the\n // window still belongs to its cohort (R7).\n firstAt: { $gte: from },\n })\n // The exact worst case of the query as written: a lifetime by:['subject']\n // family holds at most one doc per (tenant, subject), and `dims` matches\n // refs across every tenant in the cohort. Under a single-tenant scope that\n // is index.size × families. The bound cannot bite; it is here because §18\n // says every read carries its limit, not because we expect to reach it.\n .limit(refs.size * tenants.size * byAs.size + 1)\n .lean();\n\n for (const r of stageRows as any[]) {\n const subject = index.get(keyOf(r));\n if (!subject) continue;\n for (const s of byAs.get(r.as) ?? []) {\n const bag = exits.includes(s) ? subject.exits : subject.stages;\n const prevAt = bag[s.key];\n // earliest wins (R12) — belt and braces, `firstAt` is already a $min\n if (!prevAt || r.firstAt < prevAt) bag[s.key] = r.firstAt;\n }\n }\n }\n\n const subjects = [...index.values()];\n const summary = summarizeStages(subjects, stages);\n\n let slices: FunnelSlice[] | null = null;\n if (params.interval) {\n const groups = new Map<number, CohortSubject[]>();\n for (const s of subjects) {\n // subjects with no anchor date are dropped from the slices, matching\n // maxed (adminTelemetry.ts:660-666); unreachable via this path\n if (!s.anchorAt) continue;\n const at = truncate(s.anchorAt, params.interval)!;\n const k = at.getTime();\n groups.set(k, [...(groups.get(k) ?? []), s]);\n }\n slices = [...groups.entries()]\n .sort((a, b) => a[0] - b[0])\n .map(([k, members]) => ({\n at: new Date(k),\n subjects: members.length,\n stages: summarizeStages(members, stages),\n }));\n }\n\n return {\n cohortSubjects: subjects.length,\n first: stages[0] ? subjects.filter((s) => s.stages[stages[0]!.key]).length : 0,\n stages: summary,\n exits: exits.map((e) => ({\n key: e.key,\n as: e.as,\n label: e.label,\n subjects: subjects.filter((s) => s.exits[e.key]).length,\n })),\n slices,\n truncated,\n cohort: { from: params.cohort.from, to: params.cohort.to, endInclusive, anchor },\n dataSource: 'rollups' as const,\n };\n}\n","import type { Model } from 'mongoose';\nimport { isPlatformScope } from './types.js';\nimport type { Registry, RollupSpec } from './registry.js';\nimport { findFamily, runFunnel, type FunnelParams, type FunnelResult } from './funnel.js';\n\n/**\n * The six read primitives (dashboards §2). Everything the UI renders comes\n * through these — kind pages never touch Mongo, which is the seam that lets\n * span/event route to a columnar store later without touching a component.\n *\n * Traps §18 is law here, but per primitive rather than blanket. A time range is\n * REQUIRED by records, series, distribution, journey and distinctCount, and a\n * cohort window by funnel; `rollups()`'s range is OPTIONAL because a lifetime\n * family has no time axis to filter on; `trace()` takes NONE — it is pinned by\n * an indexed traceId and bounded by the trace itself.\n *\n * What is universal is the cap: every primitive carries its `$limit` INSIDE the\n * pipeline rather than applying it to a materialised result, the caps are\n * config, and the five that can cut an answer short — rollups, distribution,\n * distinctCount, funnel, breakdown — report `truncated` rather than\n * undercounting in silence. What each cap BOUNDS differs, and QueryLimits below\n * says which are output caps and which are scan caps: breakdown's, like\n * series', bounds the groups returned and never the rows read. The slow-query\n * counter is an adapter. Every response reports\n * `dataSource` (recon #2) so a spliced number can always say which store\n * answered.\n *\n * Tenancy: every primitive takes a SCOPE, not a tenant. A scope is a tenantId,\n * or PLATFORM_SCOPE ('*') for a cross-tenant read. `'*'` is only ever reachable\n * because a host's `viewerAdapter` put it on the Viewer — an authorization\n * decision the package does not make and cannot second-guess. The write side\n * treats '*' as reserved (types.ts), so no stored row can ever carry it and\n * \"omit the tenant term\" is unambiguous.\n *\n * Row-shaped primitives (records/rollups/trace/journey) already return the\n * stored `tenantId` on every row, which is what makes a cross-tenant number\n * attributable — do not project it away.\n */\n\n/**\n * Two kinds of cap live here and the difference is worth stating, because the\n * word \"limit\" hides it. An OUTPUT cap bounds what the response contains: its\n * `$limit` sits after the `$group`/sort or rides an indexed cursor, so the work\n * behind it is bounded by the range and the indexes, not by the number. A SCAN\n * cap bounds what the primitive reads, which means an answer past it is an\n * undercount — so every scan-capped primitive reports `truncated`.\n */\nexport interface QueryLimits {\n // ── output caps ──\n records: number;\n series: number;\n rollups: number;\n trace: number;\n journey: number;\n /**\n * Distinct GROUPS one breakdown() returns — the top N by measure, read as\n * cap+1 so truncation is observed. Never a bound on rows scanned: \"the top\n * models this quarter\" is exactly the question Mongo folds a million rows\n * into in one pass (reports §6).\n */\n breakdown: number;\n /**\n * Distinct VALUES one /values lookup returns — the top N by count, read as\n * cap+1 so truncation is observed. Never a bound on rows scanned: the\n * `$limit` sits after the `$group`, exactly as breakdown's does (reports §5).\n */\n values: number;\n\n // ── scan caps ──\n /** raw docs distribution will scan before it reports an undercount */\n distribution: number;\n /** rollup docs distinctCount will scan before it reports an undercount */\n distinct: number;\n /** subjects in one funnel cohort */\n funnel: number;\n}\n\nexport const DEFAULT_LIMITS: QueryLimits = {\n records: 200,\n series: 744, // a month of hourly buckets\n rollups: 500,\n trace: 500,\n journey: 500,\n breakdown: 50, // top groups — a starting point, to be measured on real hosts\n values: 200, // top values of one dimension — a picker, not a table\n distribution: 100_000,\n distinct: 100_000,\n funnel: 5_000,\n};\n\nexport interface RecordFilter {\n kind?: string;\n /**\n * One event name, or a SET of them as an `$in`. The set form exists because a\n * namespace or a rollup family is several names, and without it the only\n * honest read for one was \"every record of that kind in the range\" — a scan\n * sold as a filter (reports §6). An empty array is treated as absent, never\n * as a term that matches nothing.\n */\n name?: string | string[];\n severity?: string;\n env?: string;\n service?: string;\n release?: string;\n /** pin to one subject: 'user:u_1' */\n subject?: string;\n traceId?: string;\n /** equality on declared attrs */\n attrs?: Record<string, string>;\n /** range on declared metrics */\n metrics?: Record<string, { gte?: number; lte?: number }>;\n /** the customer toggle: exclude these actor TYPES ('admin', 'system') */\n excludeActorTypes?: string[];\n}\n\nexport interface TimeRange {\n from: Date;\n to: Date;\n}\n\n/** one group of a breakdown; `at` only when an `interval` was asked for */\nexport interface BreakdownRow {\n dims: (string | null)[];\n at?: Date;\n value: number;\n}\n\nexport interface BreakdownResult {\n rows: BreakdownRow[];\n /** distinct groups RETURNED — never more than the cap */\n groups: number;\n /** more groups existed than the cap; the ones kept are the top by measure */\n truncated: boolean;\n /**\n * The per-bucket pass hit ITS ceiling (`limits.series` buckets per returned\n * group), so some group is missing buckets. Always false without an\n * `interval`, and separate from `truncated` because they cut different axes:\n * one drops groups, the other drops periods of a group that IS shown.\n */\n bucketsTruncated: boolean;\n dataSource: 'raw';\n}\n\nconst esc = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** exported for values.ts — the raw step must match rows exactly as the primitives do */\nexport function buildMatch(scope: string, range: TimeRange, f: RecordFilter): Record<string, unknown> {\n const match: Record<string, any> = {\n // the ONLY place the tenant term is optional. Omitted under '*' — every\n // other term still applies, and the time range is still mandatory (§18).\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n occurredAt: { $gte: range.from, $lt: range.to },\n };\n for (const k of ['kind', 'name', 'severity', 'env', 'service', 'release', 'traceId'] as const) {\n const v = f[k];\n // only `name` is ever a set; an empty one is an absent term rather than an\n // `$in: []` that silently matches nothing\n if (Array.isArray(v)) {\n if (v.length) match[k] = { $in: v };\n } else if (v) match[k] = v;\n }\n if (f.subject) match.subjectKeys = f.subject;\n for (const [k, v] of Object.entries(f.attrs ?? {})) match[`attrs.${k}`] = v;\n for (const [k, r] of Object.entries(f.metrics ?? {})) {\n const term: Record<string, number> = {};\n if (r.gte != null) term.$gte = r.gte;\n if (r.lte != null) term.$lte = r.lte;\n if (Object.keys(term).length) match[`metrics.${k}`] = term;\n }\n if (f.excludeActorTypes?.length) {\n // a record with NO actor is a customer fact; only typed actors are excludable\n match.$and = [\n ...(match.$and ?? []),\n {\n $or: [\n { actor: { $exists: false } },\n { actor: { $not: new RegExp(`^(${f.excludeActorTypes.map(esc).join('|')}):`) } },\n ],\n },\n ];\n }\n return match;\n}\n\nexport type Interval = 'hour' | 'day' | 'week' | 'month';\n\nconst INTERVALS: readonly Interval[] = ['hour', 'day', 'week', 'month'];\n\n/** weeks start Monday, UTC — the same truncation everywhere it is asked for */\nconst truncTo = (path: string, unit: Interval) => ({\n $dateTrunc: { date: path, unit, ...(unit === 'week' ? { startOfWeek: 'monday' } : {}) },\n});\n\n/**\n * The measure grammar, in ONE place: `count` (default), `sum:<metric>`,\n * `avg:<metric>`. series() and breakdown() must agree on what a measure means\n * — two copies of this regex is two chances for \"sum:cost_usd\" to mean\n * different things on a chart and in the table beside it.\n *\n * `count` sums 1/sampleRate rather than counting documents, so it extrapolates\n * correctly the day a rate drops below 1 (§5.3).\n *\n * `durationMs` is the one metric name that is not in `metrics`: a span's\n * duration lives on the ENVELOPE, which is where distribution() has always read\n * it from. Resolving it to `$metrics.durationMs` here would have aggregated a\n * path no record carries and reported 0 — a number, confidently wrong — so the\n * branch is in the shared accumulator rather than in either caller.\n */\nfunction measureAccumulator(measure: string): Record<string, unknown> {\n const m = /^(sum|avg):(.+)$/.exec(measure);\n if (!m) return { $sum: { $divide: [1, { $ifNull: ['$sampleRate', 1] }] } };\n const path = m[2] === 'durationMs' ? '$durationMs' : `$metrics.${m[2]}`;\n return m[1] === 'sum' ? { $sum: path } : { $avg: path };\n}\n\nconst badRequest = (message: string) =>\n Object.assign(new Error(`telemetry: breakdown() — ${message}`), { status: 400 });\n\n/**\n * The envelope paths breakdown() will `$group` on. An ALLOWLIST, not a\n * passthrough: every one of these is either indexed or low-cardinality\n * enveloped metadata. `data.*` and `body` are deliberately absent — they are\n * free-form user content with no index behind them, and a `$group` over an\n * arbitrary path is an unbounded scan of exactly the payloads the rest of this\n * package works to keep out of aggregates.\n */\nconst BREAKDOWN_FIELDS: readonly string[] = [\n 'kind', 'name', 'severity', 'env', 'service', 'release', 'origin',\n 'client.platform', 'client.appVersion',\n 'usage.meter', 'usage.billedTo', 'usage.unit',\n 'state.key', 'state.to',\n 'error.type', 'error.handled',\n];\n\n/** 'user:u_1' → 'user'; null for an absent ref, never a thrown $split */\nconst typePrefix = (ref: unknown) => ({\n $let: {\n vars: { ref },\n in: {\n $cond: [\n { $eq: [{ $type: '$$ref' }, 'string'] },\n { $arrayElemAt: [{ $split: ['$$ref', ':'] }, 0] },\n null,\n ],\n },\n },\n});\n\n/**\n * One groupBy token → the aggregation expression it groups on. The syntax is\n * the catalog's and the rollup `by` syntax, so a dim key passes straight\n * through from one to the other.\n *\n * Every expression resolves an absent value to an explicit `null` rather than\n * leaving the field missing: a record with no `plan` is a group (\"none\"), not a\n * row to drop. That is the raw-side analogue of a family's `dimDefault`.\n */\nexport function dimExpression(dim: string): unknown {\n if (dim.startsWith('attr:')) {\n const key = dim.slice(5);\n if (!key) throw badRequest('`attr:` needs a key, e.g. \"attr:plan\"');\n return { $ifNull: [`$attrs.${key}`, null] };\n }\n if (dim.startsWith('field:')) {\n const path = dim.slice(6);\n if (!BREAKDOWN_FIELDS.includes(path)) {\n throw badRequest(\n `\"field:${path}\" is not groupable. Allowed paths: ${BREAKDOWN_FIELDS.join(', ')}. ` +\n 'Grouping by `data.*`, `body`, or an arbitrary path is refused — those are unindexed ' +\n 'free-form content, and a $group over them scans it all. Use `attr:<key>` for a declared attr.',\n );\n }\n return { $ifNull: [`$${path}`, null] };\n }\n if (dim === 'subjectType') return typePrefix({ $arrayElemAt: ['$subjectKeys', 0] });\n if (dim === 'actorType') return typePrefix('$actor');\n throw badRequest(\n `\"${dim}\" is not a dimension. Use \"attr:<key>\", \"field:<path>\", \"subjectType\" or \"actorType\".`,\n );\n}\n\n/** simple TTL cache with in-flight coalescing — proven shape in maxed.\n * Exported so values.ts memoizes on exactly these semantics rather than\n * keeping a second copy that could drift on eviction or error handling. */\nexport class QueryCache {\n private store = new Map<string, { at: number; value: Promise<unknown> }>();\n constructor(private ttlMs: number, private cap: number) {}\n get<T>(key: string, produce: () => Promise<T>): Promise<T> {\n const hit = this.store.get(key);\n if (hit && Date.now() - hit.at < this.ttlMs) return hit.value as Promise<T>;\n const value = produce();\n // a failed query must not be cached as the answer for ten minutes\n value.catch(() => this.store.delete(key));\n if (this.store.size >= this.cap) {\n const oldest = [...this.store.entries()].sort((a, b) => a[1].at - b[1].at)[0];\n if (oldest) this.store.delete(oldest[0]);\n }\n this.store.set(key, { at: Date.now(), value });\n return value;\n }\n}\n\nexport interface QueryCtx {\n TelemetryModel: Model<any>;\n RollupModel: Model<any>;\n registry: Registry;\n limits?: Partial<QueryLimits>;\n /** called with { op, ms, params } when a read exceeds slowMs (default 500) */\n onSlowQuery?: (info: { op: string; ms: number; params: unknown }) => void;\n slowMs?: number;\n cacheTtlMs?: number;\n cacheSize?: number;\n}\n\nexport function createQueries(ctx: QueryCtx) {\n const limits = { ...DEFAULT_LIMITS, ...ctx.limits };\n const slowMs = ctx.slowMs ?? 500;\n const cache = new QueryCache(ctx.cacheTtlMs ?? 10 * 60_000, ctx.cacheSize ?? 60);\n\n const timed = async <T>(op: string, params: unknown, run: () => Promise<T>): Promise<T> => {\n const t0 = Date.now();\n try {\n return await run();\n } finally {\n const ms = Date.now() - t0;\n if (ms > slowMs) ctx.onSlowQuery?.({ op, ms, params });\n }\n };\n\n return {\n /** cursor-paged raw envelope reads — tables, lists, detail drawers */\n async records(\n scope: string,\n range: TimeRange,\n filter: RecordFilter = {},\n opts: { limit?: number; cursor?: string } = {},\n ) {\n const limit = Math.min(Math.max(1, opts.limit ?? limits.records), limits.records);\n const match = buildMatch(scope, range, filter);\n if (opts.cursor) {\n // keyset on (occurredAt desc, _id desc) — never $skip\n const [atIso, id] = JSON.parse(Buffer.from(opts.cursor, 'base64url').toString());\n const at = new Date(atIso);\n match.$and = [\n ...((match.$and as unknown[]) ?? []),\n { $or: [{ occurredAt: { $lt: at } }, { occurredAt: at, _id: { $lt: id } }] },\n ];\n }\n return timed('records', { scope, filter }, async () => {\n const items = await ctx.TelemetryModel.find(match)\n .sort({ occurredAt: -1, _id: -1 })\n .limit(limit + 1)\n .lean();\n const more = items.length > limit;\n if (more) items.pop();\n const last: any = items[items.length - 1];\n return {\n items,\n nextCursor: more\n ? Buffer.from(JSON.stringify([new Date(last.occurredAt).toISOString(), last._id])).toString('base64url')\n : null,\n dataSource: 'raw' as const,\n };\n });\n },\n\n /** time-series at query time. count extrapolates by 1/sampleRate (§5.3) —\n * exact while rates sit at 1, still honest the day one drops.\n *\n * Under PLATFORM_SCOPE this aggregates ACROSS tenants into one bucket per\n * interval. That is the platform-wide chart, not a bug — the sum of every\n * tenant is the number a platform operator came for. A per-tenant\n * breakdown is a different question; ask it with rollups() or by scoping\n * to a tenant. Same for distribution() below. */\n series(\n scope: string,\n range: TimeRange,\n filter: RecordFilter,\n opts: { measure?: string; interval?: Interval } = {},\n ) {\n const { measure = 'count', interval = 'day' } = opts;\n const key = JSON.stringify(['series', scope, range.from, range.to, filter, measure, interval]);\n return cache.get(key, () =>\n timed('series', { scope, filter, measure, interval }, async () => {\n const buckets = await ctx.TelemetryModel.aggregate([\n { $match: buildMatch(scope, range, filter) },\n { $group: { _id: truncTo('$occurredAt', interval), value: measureAccumulator(measure) } },\n { $sort: { _id: 1 } },\n { $limit: limits.series },\n ] as any[]);\n return { buckets: buckets.map((b: any) => ({ at: b._id, value: b.value })), dataSource: 'raw' as const };\n }),\n );\n },\n\n /**\n * Top groups of a measure by one or two dimensions — \"which models cost the\n * most\", \"errors by release\", \"events by platform per week\". The primitive\n * that replaces a page's client-side grouping of whatever rows it happened\n * to have fetched, which answered \"this page\" while reading like it\n * answered the range (reports §6).\n *\n * THE CAP IS ON GROUPS RETURNED, NEVER ON ROWS SCANNED. Every `$limit`\n * below sits AFTER a `$group`, exactly as series() does: the scan is bounded\n * by buildMatch — tenant, range, filters, indexes — and nothing else, so a\n * quarter of a million records is one pass and 50 rows. Truncation\n * therefore keeps the TOP groups by measure, which is what a breakdown\n * table means; a cap on documents scanned would return an arbitrary prefix\n * and call it the top.\n *\n * With an `interval` this runs a SECOND aggregate restricted to the top\n * groups, rather than one pipeline that groups by (dims, bucket) and folds.\n * Two reasons: the ranking must be the measure over the WHOLE range (the\n * same number the no-interval call reports), and folding in one pass means\n * `$push`-ing every bucket of every group before the cap can apply — the\n * unbounded intermediate this primitive exists to avoid. The restriction is\n * an `$expr`/`$or` over the ≤ cap tuples because a dim can be a computed\n * expression (subjectType), which a plain `$in` on a path cannot address.\n *\n * Under PLATFORM_SCOPE it aggregates ACROSS tenants, like series() — one\n * set of groups with every tenant summed into it, which is the platform-wide\n * table a platform operator came for. Ask for a per-tenant split by scoping\n * to a tenant, or with rollups().\n */\n breakdown(\n scope: string,\n range: TimeRange,\n filter: RecordFilter,\n opts: {\n /** 1–2 of `attr:<key>` | `field:<path>` | `subjectType` | `actorType` */\n groupBy: string[];\n measure?: string;\n interval?: Interval;\n /** groups, clamped to limits.breakdown */\n limit?: number;\n },\n ) {\n const groupBy = opts.groupBy ?? [];\n if (groupBy.length < 1 || groupBy.length > 2) {\n // three dims is a pivot table nobody can read and a group count that\n // multiplies; zero is series() with extra steps\n throw badRequest(`groupBy takes 1 or 2 dimensions, got ${groupBy.length}`);\n }\n const measure = opts.measure ?? 'count';\n const interval = opts.interval;\n if (interval && !INTERVALS.includes(interval)) {\n throw badRequest(`interval must be one of ${INTERVALS.join(', ')}`);\n }\n // resolved (and refused) BEFORE the cache key is built — an invalid dim is\n // a 400 on every call, not a rejection remembered for ten minutes\n const dims = groupBy.map(dimExpression);\n const cap = Math.min(Math.max(1, opts.limit ?? limits.breakdown), limits.breakdown);\n const key = JSON.stringify([\n 'breakdown', scope, range.from, range.to, filter, groupBy, measure, interval ?? null, cap,\n ]);\n return cache.get(key, () =>\n timed('breakdown', { scope, filter, groupBy, measure, interval }, async (): Promise<BreakdownResult> => {\n const match = buildMatch(scope, range, filter);\n const dimId = Object.fromEntries(dims.map((expr, i) => [`d${i}`, expr]));\n // cap+1 so truncation is OBSERVED rather than inferred from an exact\n // match, the same read rollups() and distribution() do\n const top = await ctx.TelemetryModel.aggregate([\n { $match: match },\n { $group: { _id: dimId, value: measureAccumulator(measure) } },\n { $sort: { value: -1, _id: 1 } },\n { $limit: cap + 1 },\n ] as any[]);\n const truncated = top.length > cap;\n if (truncated) top.pop();\n const tuples: (string | null)[][] = top.map((g: any) =>\n groupBy.map((_, i) => g._id?.[`d${i}`] ?? null),\n );\n if (!interval) {\n return {\n rows: top.map((g: any, i: number) => ({ dims: tuples[i]!, value: g.value })),\n groups: top.length,\n truncated,\n bucketsTruncated: false,\n dataSource: 'raw' as const,\n };\n }\n if (!tuples.length) {\n return { rows: [], groups: 0, truncated, bucketsTruncated: false, dataSource: 'raw' as const };\n }\n const inTop = {\n $or: tuples.map((t) => ({ $and: dims.map((expr, i) => ({ $eq: [expr, t[i] ?? null] })) })),\n };\n // this pass has a ceiling of its own — buckets × groups — and it used\n // to be the one cap in the file that could cut an answer without\n // saying so. Read as cap+1, like every other one, and reported as\n // `bucketsTruncated`.\n const bucketCap = limits.series * top.length;\n const perBucket = await ctx.TelemetryModel.aggregate([\n { $match: { ...match, $expr: inTop } },\n { $group: { _id: { at: truncTo('$occurredAt', interval), ...dimId }, value: measureAccumulator(measure) } },\n // `at` is the first key of `_id`, so one BSON sort orders by bucket\n // then by dims — deterministic without a second sort key\n { $sort: { _id: 1 } },\n { $limit: bucketCap + 1 },\n ] as any[]);\n const bucketsTruncated = perBucket.length > bucketCap;\n if (bucketsTruncated) perBucket.pop();\n return {\n rows: perBucket.map((b: any) => ({\n dims: groupBy.map((_, i) => b._id?.[`d${i}`] ?? null) as (string | null)[],\n at: b._id.at as Date,\n value: b.value,\n })),\n groups: top.length,\n truncated,\n bucketsTruncated,\n dataSource: 'raw' as const,\n };\n }),\n );\n },\n\n /**\n * Percentiles + histogram off raw. Keep-all makes the SAMPLE complete —\n * no sampling stands between the match and the math (§5.3) — but the\n * computation is not exact and this comment used to claim it was:\n * `$percentile` runs `method: 'approximate'` (t-digest), and the scan stops\n * at `limits.distribution`.\n *\n * So the ceiling is read as cap+1 and `truncated` reports whether it was\n * actually reached, the same way rollups/distinctCount/funnel do. A match\n * wider than the ceiling is an undercount, and an undercount the response\n * does not mention is the silent cap this package refuses everywhere else.\n * Mongo 7+.\n */\n distribution(\n scope: string,\n range: TimeRange,\n filter: RecordFilter,\n opts: { measure?: string } = {},\n ) {\n const measure = opts.measure ?? 'durationMs';\n const path = measure === 'durationMs' ? '$durationMs' : `$metrics.${measure.replace(/^metric:/, '')}`;\n const key = JSON.stringify(['distribution', scope, range.from, range.to, filter, measure]);\n return cache.get(key, () =>\n timed('distribution', { scope, filter, measure }, async () => {\n const match = {\n ...buildMatch(scope, range, filter),\n [path.slice(1)]: { $exists: true },\n };\n // one scan ceiling, shared by both pipelines — and cap+1 so the\n // response can SAY it was truncated instead of quietly undercounting\n const cap = limits.distribution;\n const [summary] = await ctx.TelemetryModel.aggregate([\n { $match: match },\n { $limit: cap + 1 },\n {\n $group: {\n _id: null,\n p: { $percentile: { input: path, p: [0.5, 0.9, 0.95, 0.99], method: 'approximate' } },\n min: { $min: path },\n max: { $max: path },\n avg: { $avg: path },\n n: { $sum: 1 },\n },\n },\n ] as any[]);\n // `truncated` is always present, empty match included — a caller that\n // has to check whether the key exists before trusting it is back to\n // inferring the cap\n if (!summary) return { n: 0, truncated: false, dataSource: 'raw' as const };\n const [p50, p90, p95, p99] = summary.p;\n const histogram = await ctx.TelemetryModel.aggregate([\n { $match: match },\n { $limit: cap + 1 },\n { $bucketAuto: { groupBy: path, buckets: 20 } },\n ] as any[]);\n return {\n p50, p90, p95, p99,\n min: summary.min, max: summary.max, avg: summary.avg, n: summary.n,\n histogram: histogram.map((h: any) => ({ min: h._id.min, max: h._id.max, n: h.count })),\n truncated: summary.n > cap,\n dataSource: 'raw' as const,\n };\n }),\n );\n },\n\n /** rollup family reads — issues, spend, activity, milestones, funnels */\n rollups(\n scope: string,\n params: {\n as: string;\n /**\n * One dimension value, or several as an `$in`. The array form exists\n * because building an index for N subjects otherwise costs N queries or\n * an unfiltered family scan that the cap truncates — plausible, wrong,\n * and silent (cohort-math G3).\n */\n dims?: string | string[];\n subjectType?: string;\n /** the field `range` filters. Default: bucketAt when bucketed, lastAt otherwise. */\n on?: 'firstAt' | 'lastAt' | 'bucketAt';\n /**\n * Half-open (`$gte`/`$lt`), always. Applied to `on`.\n *\n * The default is today's behaviour and deliberately unchanged, but\n * `lastAt` is the MOST RECENT occurrence — cohort selection wants\n * `firstAt`, and on a once-per-subject milestone the two are equal only\n * until something re-emits it (cohort-math G1). `on: 'firstAt'` makes\n * that choice explicit rather than lucky; there is already an index for\n * it ({tenantId, as, subjectType, firstAt}).\n */\n range?: TimeRange;\n sort?: 'count' | 'lastAt' | 'firstAt' | 'bucketAt';\n limit?: number;\n },\n ) {\n const key = JSON.stringify(['rollups', scope, params]);\n return cache.get(key, () =>\n timed('rollups', { scope, params }, async () => {\n // family shape is pinned by validateRegistry, so the first declaration speaks for all\n let bucketed = false;\n outer: for (const [name, s] of Object.entries(ctx.registry)) {\n for (const r of s.rollups ?? []) {\n if ((r.as ?? name) === params.as) {\n bucketed = !!r.bucket;\n break outer;\n }\n }\n }\n // rollup rows carry their own tenantId, so a '*' read stays attributable\n const match: Record<string, any> = {\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n as: params.as,\n };\n if (params.dims) {\n match.dims = Array.isArray(params.dims) ? { $in: params.dims } : params.dims;\n }\n if (params.subjectType) match.subjectType = params.subjectType;\n if (params.range) {\n const on = params.on ?? (bucketed ? 'bucketAt' : 'lastAt');\n match[on] = { $gte: params.range.from, $lt: params.range.to };\n }\n const sortKey = params.sort ?? (bucketed ? 'bucketAt' : 'count');\n const limit = Math.min(Math.max(1, params.limit ?? limits.rollups), limits.rollups);\n // limit+1 so truncation is observed, not inferred from an exact match\n const rows = await ctx.RollupModel.find(match)\n .sort({ [sortKey]: sortKey === 'firstAt' || sortKey === 'bucketAt' ? 1 : -1 })\n .limit(limit + 1)\n .lean();\n const truncated = rows.length > limit;\n if (truncated) rows.pop();\n return { rows, bucketed, truncated, dataSource: 'rollups' as const };\n }),\n );\n },\n\n /** one trace, every kind, one time axis — the first join view */\n trace(scope: string, traceId: string) {\n return timed('trace', { scope, traceId }, async () => {\n const items = await ctx.TelemetryModel.find({\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n traceId,\n })\n .sort({ occurredAt: 1 })\n .limit(limits.trace)\n .lean();\n return { items, dataSource: 'raw' as const };\n });\n },\n\n /** one subject's whole story — records interleaved, milestones as markers */\n journey(scope: string, subjectRef: string, range: TimeRange, opts: { limit?: number } = {}) {\n return timed('journey', { scope, subjectRef }, async () => {\n const limit = Math.min(Math.max(1, opts.limit ?? limits.journey), limits.journey);\n // a subject ref is only unique WITHIN a tenant, so a '*' journey can\n // legitimately braid two tenants' 'user:u_1' together — every row and\n // milestone carries its tenantId, which is what keeps that readable\n const pin = isPlatformScope(scope) ? {} : { tenantId: scope };\n const [records, milestones] = await Promise.all([\n ctx.TelemetryModel.find({\n ...pin,\n subjectKeys: subjectRef,\n occurredAt: { $gte: range.from, $lt: range.to },\n })\n .sort({ occurredAt: -1 })\n .limit(limit)\n .lean(),\n // lifetime families only — bucketed activity rows would drown the markers\n ctx.RollupModel.find({ ...pin, dims: subjectRef, bucketAt: { $exists: false } })\n .sort({ firstAt: 1 })\n .limit(100)\n .lean(),\n ]);\n return { records, milestones, dataSource: 'raw+rollups' as const };\n });\n },\n\n /**\n * Distinct subjects per bucket, and over the whole range — DAU/MAU/WAU,\n * EXACTLY, with no sketch and no write-path change.\n *\n * The trick is that there is no trick. A family declared `by: ['subject']`\n * with a bucket already writes exactly ONE doc per (subject, bucket), which\n * is what the deterministic `_id` guarantees. So distinct-subjects-in-bucket\n * IS the doc count, and distinct-over-a-range is one `$group` on `dims`. An\n * HLL sketch would buy approximation we do not need and storage we would\n * have to maintain.\n *\n * `interval` may be COARSER than the family's own bucket (daily rows →\n * monthly MAU) — re-truncating bucket starts cannot split a bucket across\n * two periods, so the roll-up stays exact. Asking for finer than the family\n * writes cannot invent detail: it returns the family's own grain.\n */\n distinctCount(\n scope: string,\n params: {\n as: string;\n subjectType?: string;\n range: TimeRange;\n interval?: 'hour' | 'day' | 'week' | 'month';\n },\n ) {\n // A family with no subject dim or no bucket cannot answer this, and the\n // failure mode is a confident wrong number rather than an empty result —\n // so it throws, loudly, naming the family and the fix.\n const spec = requireDistinctFamily(ctx.registry, params.as);\n const interval = params.interval ?? spec.bucket!;\n const key = JSON.stringify(['distinctCount', scope, params]);\n return cache.get(key, () =>\n timed('distinctCount', { scope, params }, async () => {\n const match: Record<string, any> = {\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n as: params.as,\n bucketAt: { $gte: params.range.from, $lt: params.range.to },\n };\n if (params.subjectType) match.subjectType = params.subjectType;\n const cap = limits.distinct;\n const [out] = await ctx.RollupModel.aggregate([\n { $match: match },\n // one scan ceiling, shared by both branches — and cap+1 so the\n // response can SAY it was truncated instead of quietly undercounting\n { $limit: cap + 1 },\n {\n $facet: {\n buckets: [\n {\n $group: {\n _id: {\n at: { $dateTrunc: { date: '$bucketAt', unit: interval, ...(interval === 'week' ? { startOfWeek: 'monday' } : {}) } },\n dims: '$dims',\n },\n },\n },\n { $group: { _id: '$_id.at', value: { $sum: 1 } } },\n { $sort: { _id: 1 } },\n { $limit: limits.series },\n ],\n distinct: [{ $group: { _id: '$dims' } }, { $count: 'n' }],\n scanned: [{ $count: 'n' }],\n },\n },\n ] as any[]);\n const scanned = out?.scanned?.[0]?.n ?? 0;\n return {\n buckets: (out?.buckets ?? []).map((b: any) => ({ at: b._id, value: b.value })),\n /** distinct subjects across the WHOLE range — never the sum of the buckets */\n distinct: out?.distinct?.[0]?.n ?? 0,\n interval,\n truncated: scanned > cap,\n dataSource: 'rollups' as const,\n };\n }),\n );\n },\n\n /**\n * Cohort funnel over lifetime milestone families — stage counts, conversion,\n * and median time-to-step. See funnel.ts; the math lives there so it can be\n * unit-pinned without a database.\n */\n funnel(scope: string, params: FunnelParams): Promise<FunnelResult> {\n return timed('funnel', { scope, params }, () =>\n runFunnel(\n {\n RollupModel: ctx.RollupModel,\n registry: ctx.registry,\n cohortCap: limits.funnel,\n scopeMatch: (s) => (isPlatformScope(s) ? {} : { tenantId: s }),\n },\n scope,\n params,\n ),\n );\n },\n };\n}\n\n/**\n * distinctCount's precondition. The exactness argument rests entirely on the\n * family writing one doc per (subject, bucket), so each way of breaking that\n * gets its own message with its own fix — a registry mistake here would\n * otherwise surface as a number that looks like DAU and is not.\n */\nfunction requireDistinctFamily(registry: Registry, as: string): RollupSpec {\n const found = findFamily(registry, as);\n if (!found) {\n throw new Error(\n `telemetry: distinctCount() — no rollup family \"${as}\" is declared. Add ` +\n `\\`rollups: [{ as: '${as}', by: ['subject'], subjects: [...], bucket: 'day' }]\\` to the events that count as activity.`,\n );\n }\n const { name, spec } = found;\n const by = `by: [${spec.by.map((d) => `'${d}'`).join(', ')}]`;\n if (!spec.bucket) {\n throw new Error(\n `telemetry: distinctCount() — rollup family \"${as}\" (declared on \"${name}\") has no \\`bucket\\`. ` +\n `Distinct-per-period needs one doc per (subject, period); a lifetime family has one doc per subject ` +\n `forever, so every period would report the same number. Add \\`bucket: 'day'\\`, or ask this with rollups().`,\n );\n }\n if (!spec.by.includes('subject')) {\n throw new Error(\n `telemetry: distinctCount() — rollup family \"${as}\" (declared on \"${name}\") is keyed ${by} with no ` +\n `\\`subject\\` dim, so its docs count OCCURRENCES, not subjects. Add 'subject' to \\`by\\` (with \\`subjects: [...]\\`).`,\n );\n }\n if (spec.by.length !== 1) {\n throw new Error(\n `telemetry: distinctCount() — rollup family \"${as}\" (declared on \"${name}\") is keyed ${by}. Extra dims ` +\n `split one subject across several docs per period, so the count would exceed the true distinct total. ` +\n `Declare a second family with \\`by: ['subject']\\` for the distinct question.`,\n );\n }\n return spec;\n}\n\nexport type Queries = ReturnType<typeof createQueries>;\n","import type { Model } from 'mongoose';\nimport { isPlatformScope } from './types.js';\nimport type { Catalog, DimFacet } from './catalog.js';\nimport {\n DEFAULT_LIMITS, QueryCache, buildMatch, dimExpression,\n type QueryLimits, type TimeRange,\n} from './query.js';\n\n/**\n * `/values` — the observed domain of one dimension (reports §5).\n *\n * \"What values does this dimension actually take?\" is the question standing\n * between a report builder and every filter it offers. The answer has four\n * possible sources and they are tried cheapest first, with the response SAYING\n * which one answered — a picker built on a guess is a filter that silently\n * matches nothing:\n *\n * 1. `catalog` — the registry already declared a closed domain (a `z.enum`,\n * an envelope enum). Verbatim, in schema order, and NO read at all.\n * 2. `rollups` — some family is keyed by this dim, so every value that ever\n * hit an aggregate is one indexed `$group` away, with its count.\n * 3. `raw` — an indexed attr (or an envelope/pseudo dim) over a range.\n * 4. `none` — nothing can answer it. The UI offers free-text equality with\n * a *scan* badge, exactly as the FilterBar already does.\n *\n * This is NOT a tenth primitive. It is a lookup the report builder makes before\n * it names a value, which is why it lives beside the primitives rather than\n * inside `createQueries` — it reads the catalog, and the primitives deliberately\n * do not.\n *\n * The `none` path never throws, including when the raw step is the only\n * eligible one and no range was given. A caller that has to catch an exception\n * to learn \"you'll have to type it\" is a caller that will render an error page\n * over a working text box.\n */\n\nexport interface ValuesParams {\n /**\n * A `DimFacet.key`: `attr:model` | `field:client.platform` | `subjectType` |\n * `actorType`. The literal `'subject'` is also accepted, and is the only way\n * to ask a family for its subject refs — it is a rollup `by` source rather\n * than a catalog dim, so it can only ever be answered by step 2.\n */\n dim: string;\n /**\n * Restrict to these event names — a Report's source events. REQUIRED in\n * practice for the raw step (it decides whether the attr is indexed), and a\n * narrowing hint for the other two.\n */\n names?: string[];\n /** required by the raw step; ignored by the others */\n range?: TimeRange;\n /** values cap, default `limits.values` (200), clamped to it */\n limit?: number;\n}\n\nexport interface ValuesResult {\n /** catalog order for a declared enum, else by count desc then value asc */\n values: string[];\n /** parallel to `values` when the source can count — absent for 'catalog' */\n counts?: number[];\n source: 'catalog' | 'rollups' | 'raw' | 'none';\n /** the family that was read, when `source === 'rollups'` */\n via?: string;\n /** more values existed than the cap; the ones kept are the top by count */\n truncated: boolean;\n /** mirrors `source`, so a values response reads like every other one (recon #2) */\n dataSource: 'catalog' | 'rollups' | 'raw' | 'none';\n}\n\nexport interface ValuesCtx {\n catalog: Catalog;\n TelemetryModel: Model<any>;\n RollupModel: Model<any>;\n limits?: Partial<QueryLimits>;\n /** called with { op, ms, params } when a read exceeds slowMs (default 500) */\n onSlowQuery?: (info: { op: string; ms: number; params: unknown }) => void;\n slowMs?: number;\n cacheTtlMs?: number;\n cacheSize?: number;\n}\n\nconst empty = (source: ValuesResult['source']): ValuesResult => ({\n values: [], source, truncated: false, dataSource: source,\n});\n\n/** count the way series/breakdown do: 1/sampleRate, so a dropped rate still extrapolates */\nconst SAMPLED_COUNT = { $sum: { $divide: [1, { $ifNull: ['$sampleRate', 1] }] } };\n\nexport function createValues(ctx: ValuesCtx) {\n const limits = { ...DEFAULT_LIMITS, ...ctx.limits };\n const slowMs = ctx.slowMs ?? 500;\n const cache = new QueryCache(ctx.cacheTtlMs ?? 10 * 60_000, ctx.cacheSize ?? 60);\n const { catalog } = ctx;\n\n const timed = async <T>(op: string, params: unknown, run: () => Promise<T>): Promise<T> => {\n const t0 = Date.now();\n try {\n return await run();\n } finally {\n const ms = Date.now() - t0;\n if (ms > slowMs) ctx.onSlowQuery?.({ op, ms, params });\n }\n };\n\n /** the event facets a `names` restriction selects, in the order given; all of them otherwise */\n const eventNames = (names?: string[]): string[] =>\n names?.length ? names.filter((n) => catalog.events[n]) : Object.keys(catalog.events);\n\n /**\n * Step 1. Every DimFacet under this key that carries a closed domain, unioned\n * in first-seen order. Two events declaring different enums for one attr is\n * not a conflict — it is two closed domains, and their union is the set a\n * filter over both could ever match.\n */\n function fromCatalog(dim: string, names?: string[]): string[] {\n const facets: DimFacet[] = [];\n for (const d of catalog.envelope) if (d.key === dim) facets.push(d);\n for (const name of eventNames(names)) {\n for (const d of catalog.events[name]!.dims) if (d.key === dim) facets.push(d);\n }\n const out: string[] = [];\n for (const f of facets) for (const v of f.values ?? []) if (!out.includes(v)) out.push(v);\n return out;\n }\n\n /**\n * Step 2. The family whose `by` names this dim, fewest dims first — fewer\n * dims is fewer docs for the same domain, and the `by` comparison is literal\n * because a DimFacet.key IS a DimSource (catalog §3). `subjectType` and\n * `actorType` have no `by` equivalent — a family keyed by a subject writes\n * `'subject'`, whose values are refs, not types — so they fall through.\n */\n function pickFamily(dim: string, names?: string[]): { as: string; index: number; label: string } | null {\n if (dim === 'subjectType' || dim === 'actorType') return null;\n const matches = Object.values(catalog.families)\n .map((f) => ({ f, index: f.by.indexOf(dim as any) }))\n .filter(({ f, index }) =>\n index !== -1 && (!names?.length || f.feeders.some((n) => names.includes(n))))\n .sort((a, b) => a.f.by.length - b.f.by.length || a.f.as.localeCompare(b.f.as));\n const best = matches[0];\n return best ? { as: best.f.as, index: best.index, label: best.f.labels[best.index]! } : null;\n }\n\n /**\n * Step 3's precondition. `dimExpression` owns the vocabulary — a dim is\n * raw-readable exactly when the primitive that would group on it accepts it,\n * so there is no second allowlist to drift. On top of that an ATTR must be\n * genuinely indexed on one of the events in play: a `$group` over an\n * unindexed attr is the collection scan this package refuses to sell as a\n * lookup, and `none` (free text + a scan badge) is the honest answer.\n */\n function rawReadable(dim: string, names?: string[]): boolean {\n try {\n dimExpression(dim);\n } catch {\n return false;\n }\n if (!dim.startsWith('attr:')) return true;\n const key = dim.slice(5);\n return eventNames(names).some((n) => catalog.events[n]!.indexedAttrs.includes(key));\n }\n\n return async function values(scope: string, params: ValuesParams): Promise<ValuesResult> {\n const { dim, names, range } = params;\n if (!dim) return empty('none');\n const cap = Math.min(Math.max(1, params.limit ?? limits.values), limits.values);\n const key = JSON.stringify([\n 'values', scope, dim, names ?? null, range?.from ?? null, range?.to ?? null, cap,\n ]);\n\n return cache.get(key, () =>\n timed('values', { scope, dim, names }, async (): Promise<ValuesResult> => {\n // ── 1. the registry already said so ──\n const declared = fromCatalog(dim, names);\n if (declared.length) {\n return { values: declared, source: 'catalog', truncated: false, dataSource: 'catalog' };\n }\n\n // ── 2. what the aggregates have seen ──\n const family = pickFamily(dim, names);\n if (family) {\n // {tenantId, as, dims, bucketAt} answers the match on its prefix; the\n // $limit sits after the $group, so the cap bounds the ANSWER and the\n // scan stays bounded by the family\n const rows = await ctx.RollupModel.aggregate([\n {\n $match: {\n ...(isPlatformScope(scope) ? {} : { tenantId: scope }),\n as: family.as,\n },\n },\n { $project: { v: { $arrayElemAt: ['$dims', family.index] }, count: 1 } },\n { $match: { v: { $type: 'string' } } },\n { $group: { _id: '$v', count: { $sum: '$count' } } },\n { $sort: { count: -1, _id: 1 } },\n { $limit: cap + 1 },\n ] as any[]);\n const truncated = rows.length > cap;\n if (truncated) rows.pop();\n // rollups.ts writes `${label}=${value}` for every dim but the subject\n // one, which keeps its native `type:id` so erasure can match it — so\n // the prefix is stripped where it is actually present, never assumed\n const prefix = `${family.label}=`;\n return {\n values: rows.map((r: any) =>\n String(r._id).startsWith(prefix) ? String(r._id).slice(prefix.length) : String(r._id),\n ),\n counts: rows.map((r: any) => r.count),\n source: 'rollups',\n via: family.as,\n truncated,\n dataSource: 'rollups',\n };\n }\n\n // ── 3. the rows themselves, when an index answers them ──\n if (!rawReadable(dim, names)) return empty('none');\n // A missing range is not an error: the caller asked what it could offer\n // and the answer is \"nothing cheap\" — free text with a scan badge.\n if (!range) return empty('none');\n\n // `RecordFilter.name` takes the set directly, so the source events are\n // one indexed `$in` on {tenantId, kind, name, occurredAt} rather than a\n // restriction bolted onto the match afterwards\n const rows = await ctx.TelemetryModel.aggregate([\n { $match: buildMatch(scope, range, names?.length ? { name: names } : {}) },\n { $group: { _id: dimExpression(dim), count: SAMPLED_COUNT } },\n // a \"no value\" is not a value to pick — the null group is real\n // (breakdown reports it) but it is not something a filter can name\n { $match: { _id: { $ne: null } } },\n { $sort: { count: -1, _id: 1 } },\n { $limit: cap + 1 },\n ] as any[]);\n const truncated = rows.length > cap;\n if (truncated) rows.pop();\n return {\n values: rows.map((r: any) => String(r._id)),\n counts: rows.map((r: any) => r.count),\n source: 'raw',\n truncated,\n dataSource: 'raw',\n };\n }),\n );\n };\n}\n\nexport type Values = ReturnType<typeof createValues>;\n","import type { Catalog, DimFacet, FamilyFacet } from './catalog.js';\nimport type { Interval, QueryLimits, RecordFilter, TimeRange } from './query.js';\nimport type { TelemetryKind } from './types.js';\nimport type { ViewSpec } from './views.js';\n\n/**\n * The Report and its resolver (reports §4, §6). A Report is the one shape a\n * page renders, the explore UI builds, a saved view stores, a URL hash carries\n * and `run_report` executes. `resolveReport` is the pure function that turns\n * one into a Plan: the cheapest primitive that answers it EXACTLY, a raw plan\n * when nothing can, and a refusal with a reason when nothing at all can.\n *\n * Pure, like deriveCatalog and summarizeStages — no Mongo, no I/O, and\n * deterministic given `now`, so it is pinned by unit tests rather than by a\n * seeded database (reports §11.6). Nothing here executes anything — that is\n * execute.ts, which is the only file that needs a database to do its job.\n *\n * `Plan.args` is POSITIONAL and spreads straight into the named primitive:\n *\n * const plan = resolveReport(report, catalog);\n * if ('primitive' in plan) await q[plan.primitive](scope, ...plan.args);\n *\n * That is the entire contract between this file and query.ts, and it is why\n * nothing here imports a primitive — the resolver names one and hands over its\n * arguments, so adding a primitive costs a rule and no plumbing.\n */\n\n// ── the Report ──────────────────────────────────────────────────────────────\n\nexport type ReportSource =\n /** one registered name */\n | { event: string }\n /** every event under `library.*` */\n | { namespace: string }\n | { kind: TelemetryKind }\n /** read a rollup family directly */\n | { family: string };\n\n/** a shorthand from the UI's RANGES ('7d'), or an explicit half-open ISO pair */\nexport type ReportRange = string | { from: string; to: string };\n\nexport interface ReportFilter {\n /** a DimFacet.key: 'attr:model' | 'field:env' | 'subjectType' | 'field:name' … */\n dim: string;\n op: 'eq' | 'in' | 'gte' | 'lte';\n value: string | string[] | number;\n}\n\nexport interface Report {\n source: ReportSource;\n range: ReportRange;\n interval?: Interval;\n /** a MeasureFacet.key. Default 'count'; also 'distinct:<subjectType>' and 'funnel' */\n measure?: string;\n /** DimFacet.key[], at most two — three dims is a pivot nobody can read */\n groupBy?: string[];\n filters?: ReportFilter[];\n excludeActorTypes?: string[];\n /** a rendering hint carried with the Report; no primitive takes it today */\n sort?: 'value' | 'label' | 'time';\n limit?: number;\n /** same length, immediately before */\n compare?: 'previous';\n\n // ── funnel-only (`measure: 'funnel'`) ──\n /** lifetime `by: ['subject']` family names, in order */\n stages?: string[];\n anchor?: string;\n exits?: string[];\n subjectType?: string;\n}\n\n/**\n * The pre-Report `ViewSpec.query`. Every view saved before Reports existed is\n * this shape and must keep parsing, so it stays in the union and\n * `normalizeQuery()` lifts it.\n *\n * @deprecated write a {@link Report}. The `display` key this shape used to\n * carry is REMOVED (reports §8): the renderer decides from the Report itself,\n * and a chart/table toggle would be a UI preference rather than view state. A\n * stored view that still carries the key keeps parsing — `spec` is a Mixed\n * document — and the key is ignored.\n */\nexport interface LegacyQuery {\n range?: string;\n filters?: Record<string, unknown>;\n groupBy?: string;\n sort?: string;\n}\n\n// ── the Plan ────────────────────────────────────────────────────────────────\n\nexport type PlanPrimitive =\n | 'records' | 'series' | 'breakdown' | 'distribution'\n | 'rollups' | 'distinctCount' | 'funnel';\n\n/**\n * How the executor folds a `rollups` plan. `rollups()` has no server-side\n * groupBy — it returns the family's own docs, and the requested dims ARE that\n * family's dims, so the grouping is a fold over rows rather than a second read.\n * `labels[i]` is the `dims` prefix rollups.ts writes for `groupBy[i]`; a subject\n * dim labels to 'subject' and its stored value is the bare `type:id` ref.\n */\nexport interface PlanShape {\n groupBy: string[];\n labels: string[];\n measure: string;\n interval?: Interval;\n /** filters the fold applies, because rollups() can only pin whole dims */\n filters?: { dim: string; label: string; op: ReportFilter['op']; value: ReportFilter['value'] }[];\n}\n\nexport interface Plan {\n primitive: PlanPrimitive;\n /** positional args AFTER scope — the executor is literally `q[primitive](scope, ...args)` */\n args: unknown[];\n exactness: 'exact' | 'raw' | 'scan';\n /** the family that answers it, when one does */\n via?: string;\n /** human sentence — the UI badge and the MCP explanation */\n why: string;\n /** how to fold the rows a `rollups` plan returns */\n shape?: PlanShape;\n /** present when `compare: 'previous'` — same primitive, range shifted back by its own length */\n previous?: { args: unknown[] };\n}\n\nexport interface Unavailable {\n unavailable: true;\n why: string;\n}\n\n// ── ranges ──────────────────────────────────────────────────────────────────\n\n/** the UI's RANGES (util.js), which is the vocabulary a stored view speaks */\nconst RANGE_MS: Record<string, number> = {\n '1h': 36e5,\n '24h': 864e5,\n '7d': 7 * 864e5,\n '30d': 30 * 864e5,\n '90d': 90 * 864e5,\n};\n\nconst badRequest = (message: string) =>\n Object.assign(new Error(`telemetry: ${message}`), { status: 400 });\n\n/**\n * A ReportRange → the half-open pair every primitive takes. Shorthands end at\n * `now`, which is injectable so the resolver stays deterministic under test.\n *\n * An unrecognised shorthand THROWS rather than defaulting to 7d the way\n * util.js does: on the client a wrong default draws a chart, here it would\n * silently answer a different question than the one asked.\n */\nexport function rangeOf(range: ReportRange, now: Date = new Date()): TimeRange {\n if (typeof range === 'string') {\n const ms = RANGE_MS[range] ?? spanOf(range);\n if (ms == null) {\n throw badRequest(\n `range \"${range}\" is not a known shorthand — use one of ${Object.keys(RANGE_MS).join(', ')}, ` +\n 'an `<n>h`/`<n>d` form, or an explicit { from, to } ISO pair',\n );\n }\n return { from: new Date(now.getTime() - ms), to: now };\n }\n const from = new Date(range.from);\n const to = new Date(range.to);\n if (Number.isNaN(from.getTime()) || Number.isNaN(to.getTime()) || from >= to) {\n throw badRequest(\n `range { from: \"${range.from}\", to: \"${range.to}\" } is not valid — \\`from\\` must be a valid ` +\n 'ISO time strictly before `to` (the package is half-open everywhere)',\n );\n }\n return { from, to };\n}\n\n/** '14d' / '6h' — the generic form mcp.ts already accepts off a stored view */\nfunction spanOf(range: string): number | null {\n const m = /^(\\d+)([hd])$/.exec(range);\n if (!m) return null;\n return Number(m[1]) * (m[2] === 'h' ? 36e5 : 864e5);\n}\n\n/**\n * The interval that keeps a range under ~120 buckets — util.js `intervalFor`,\n * extended to explicit pairs by their span so a Report built from a date picker\n * lands on the same grain as one built from the range chips.\n */\nexport function intervalForRange(range: ReportRange, now: Date = new Date()): Interval {\n if (typeof range === 'string' && RANGE_MS[range] != null) {\n return range === '1h' || range === '24h' ? 'hour' : range === '90d' ? 'week' : 'day';\n }\n const { from, to } = rangeOf(range, now);\n const ms = to.getTime() - from.getTime();\n if (ms <= 864e5) return 'hour';\n if (ms < 90 * 864e5) return 'day';\n return 'week';\n}\n\n/** hour < day < week < month — a family may be FINER than the interval asked for, never coarser */\nconst INTERVAL_RANK: Record<Interval, number> = { hour: 0, day: 1, week: 2, month: 3 };\n\n/** the previous window of the same length, immediately before: [from - (to - from), from) */\nconst shift = (range: TimeRange): TimeRange => ({\n from: new Date(range.from.getTime() - (range.to.getTime() - range.from.getTime())),\n to: range.from,\n});\n\n// ── source expansion ────────────────────────────────────────────────────────\n\ninterface ResolvedSource {\n form: 'event' | 'namespace' | 'kind' | 'family';\n /** the event names this source expands to, registry order */\n events: string[];\n /** set only by `{ kind }`, where the kind term IS the source and is therefore complete */\n kind?: TelemetryKind;\n family?: FamilyFacet;\n}\n\nfunction expandSource(source: ReportSource, catalog: Catalog): ResolvedSource | Unavailable {\n if ('event' in source) {\n if (!catalog.events[source.event]) {\n return unavailable(\n `no event named \"${source.event}\" is registered — the catalog knows ${count(Object.keys(catalog.events).length, 'event')}, ` +\n 'so either the name is a typo or the registry never declared it',\n );\n }\n return { form: 'event', events: [source.event] };\n }\n if ('namespace' in source) {\n const events = catalog.namespaces[source.namespace];\n if (!events?.length) {\n return unavailable(\n `no event name starts with \"${source.namespace}.\" — the registered namespaces are ` +\n `${Object.keys(catalog.namespaces).join(', ')}`,\n );\n }\n return { form: 'namespace', events: [...events] };\n }\n if ('kind' in source) {\n const events = Object.keys(catalog.events).filter((n) => catalog.events[n]!.kind === source.kind);\n if (!events.length) {\n return unavailable(\n `no event is registered with kind \"${source.kind}\" — declare one, or pick a kind the registry uses`,\n );\n }\n return { form: 'kind', events, kind: source.kind };\n }\n const family = catalog.families[source.family];\n if (!family) {\n return unavailable(\n `no rollup family \"${source.family}\" is declared — add a \\`rollups: [{ as: '${source.family}', by: [...] }]\\` ` +\n 'block to the event that should feed it',\n );\n }\n return { form: 'family', events: [...family.feeders], family };\n}\n\n// ── dimensions ──────────────────────────────────────────────────────────────\n\n/**\n * Filter-only pseudo dims: they are RecordFilter keys with real indexes behind\n * them, but they are not groupable and so they are not in the catalog. A saved\n * view's `filters.subject` lifts to one of these.\n */\nconst FILTER_ONLY: Record<string, keyof RecordFilter> = {\n 'field:subject': 'subject',\n 'field:traceId': 'traceId',\n};\n\n/**\n * Every dim this source can offer: the envelope, plus each event's own attrs\n * and kind fields. A key several events declare is `indexed` only when ALL of\n * them index it — one unindexed feeder makes the whole read a scan, and\n * claiming otherwise sells a scan as a lookup (reports §11.3).\n */\nfunction dimsFor(catalog: Catalog, events: string[]): Map<string, DimFacet> {\n const out = new Map<string, DimFacet>();\n for (const d of catalog.envelope) out.set(d.key, d);\n for (const name of events) {\n for (const d of catalog.events[name]?.dims ?? []) {\n const seen = out.get(d.key);\n out.set(d.key, seen ? { ...seen, indexed: seen.indexed && d.indexed } : d);\n }\n }\n return out;\n}\n\n/** the measure keys this source declares — 'count', 'sum:cost_usd', 'p95:durationMs' … */\nconst measureDeclared = (catalog: Catalog, events: string[], key: string): boolean =>\n key === 'count' || events.some((n) => catalog.events[n]?.measures.some((m) => m.key === key));\n\nconst MEASURE_OP = /^(sum|avg|p50|p90|p95|p99):(.+)$/;\n\n// ── the resolver ────────────────────────────────────────────────────────────\n\nconst unavailable = (why: string): Unavailable => ({ unavailable: true, why });\n\nconst count = (n: number, noun: string) => `${n} ${noun}${n === 1 ? '' : 's'}`;\n\nexport interface ResolveOptions {\n /** injected so a plan is deterministic — shorthand ranges end here */\n now?: Date;\n limits?: Partial<QueryLimits>;\n}\n\n/**\n * Report → Plan, first match wins (reports §6). The order is a preference\n * order: an exact rollup read beats a raw scan, and a refusal beats a query\n * that 400s at the database.\n *\n * One deviation from the plan's table, because the table's rows overlap:\n * `records` is tried BEFORE `series`. A Report with no measure still has the\n * default measure 'count', so the series rule would match everything and the\n * records rule would be unreachable. Asking for a measure — `measure: 'count'`\n * explicitly — is what distinguishes \"chart this\" from \"show me the rows\".\n */\nexport function resolveReport(report: Report, catalog: Catalog, opts: ResolveOptions = {}): Plan | Unavailable {\n const now = opts.now ?? new Date();\n const limits = opts.limits ?? {};\n const src = expandSource(report.source, catalog);\n if ('unavailable' in src) return src;\n\n const measure = report.measure ?? 'count';\n const groupBy = report.groupBy ?? [];\n if (groupBy.length > 2) {\n return unavailable(\n `groupBy takes at most 2 dimensions, got ${groupBy.length} (${groupBy.join(', ')}) — three dims is a ` +\n 'pivot table nobody can read and a group count that multiplies',\n );\n }\n if (report.interval && INTERVAL_RANK[report.interval] == null) {\n return unavailable(`interval \"${report.interval}\" is not one of hour, day, week, month`);\n }\n\n // 1 — cohort funnels, over lifetime milestone families only\n if (measure === 'funnel') return planFunnel(report, catalog, now, limits);\n\n // 2 — distinct subjects per period, off a bucketed single-subject family\n if (measure.startsWith('distinct:')) return planDistinct(report, catalog, src, measure, now);\n\n const opMatch = MEASURE_OP.exec(measure);\n if (measure !== 'count' && !opMatch) {\n return unavailable(\n `measure \"${measure}\" is not a measure — use 'count', 'sum:<metric>', 'avg:<metric>', ` +\n \"'p50|p95|p99:<metric>', 'distinct:<subjectType>' or 'funnel'\",\n );\n }\n if (opMatch && !measureDeclared(catalog, src.events, measure)) {\n return unavailable(\n `\"${measure}\" names a metric no source event declares — add \\`${opMatch[2]}\\` to the \\`metrics\\` ` +\n `object of ${src.events.join(', ')}, or pick one of ${metricList(catalog, src.events)}`,\n );\n }\n\n // 3 — exact, via one indexed rollup read\n const exact = planRollups(report, catalog, src, measure, groupBy, now, limits);\n if (exact) return exact;\n\n // 4–7 — raw. One filter build, four dispatches.\n const filter = toRecordFilter(report, catalog, src);\n if ('unavailable' in filter) return filter;\n const range = rangeOf(report.range, now);\n const dims = dimsFor(catalog, src.events);\n const touched = [...groupBy, ...(report.filters ?? []).map((f) => f.dim)];\n const unindexed = touched.find((k) => !(dims.get(k)?.indexed ?? FILTER_ONLY[k] != null));\n // the source itself is always pinned by an indexed term now (a name, a name\n // set, or a kind), so the only thing left that can make a read a scan is a\n // dimension with no index behind it\n const scanWhy = unindexed\n ? ` — \"${unindexed}\" has no index behind it, so this is a collection scan bounded only by the range` +\n (unindexed.startsWith('attr:') ? `; add \"${unindexed.slice(5)}\" to \\`indexedAttrs\\` to make it a lookup` : '')\n : '';\n const exactness = unindexed != null ? 'scan' : 'raw';\n\n // 6 — percentiles come off the raw distribution, and only without a groupBy\n if (opMatch && opMatch[1] !== 'sum' && opMatch[1] !== 'avg') {\n if (groupBy.length) {\n return unavailable(\n `percentiles per group are not offered yet (reports §13) — \"${measure}\" with ` +\n `groupBy ${groupBy.join(', ')} would be one distribution() read per group. Drop the groupBy, ` +\n 'or filter to one group and ask again',\n );\n }\n return withCompare(report, {\n primitive: 'distribution',\n args: [range, filter, { measure: opMatch[2]! }],\n exactness,\n why:\n `${measure} is approximate by construction ($percentile t-digest over the matched records)` +\n `${scanWhy}`,\n });\n }\n\n // 4 — top groups by one or two dims\n if (groupBy.length) {\n const bad = groupBy.find((k) => !dims.has(k));\n if (bad) {\n return unavailable(\n `\"${bad}\" is not a dimension of ${describe(src)} — group by one of ${[...dims.keys()].join(', ')}`,\n );\n }\n return withCompare(report, {\n primitive: 'breakdown',\n args: [\n range,\n filter,\n {\n groupBy,\n measure,\n ...(report.interval ? { interval: report.interval } : {}),\n ...(report.limit ? { limit: capped(report.limit, limits.breakdown) } : {}),\n },\n ],\n exactness,\n why: `raw ${measure} by ${groupBy.join(' × ')} over the range${scanWhy}`,\n });\n }\n\n // 7 — no measure, no groupBy, no interval: the reader wants the rows\n if (!report.measure && !report.interval) {\n return withCompare(report, {\n primitive: 'records',\n args: [range, filter, report.limit ? { limit: capped(report.limit, limits.records) } : {}],\n exactness,\n why: `the matching records themselves, newest first${scanWhy}`,\n });\n }\n\n // 5 — one line over time\n const interval = report.interval ?? intervalForRange(report.range, now);\n return withCompare(report, {\n primitive: 'series',\n args: [range, filter, { measure, interval }],\n exactness,\n why: `raw ${measure} per ${interval} over the range${scanWhy}`,\n });\n}\n\nconst capped = (limit: number, cap: number | undefined) =>\n cap == null ? limit : Math.max(1, Math.min(limit, cap));\n\nconst describe = (src: ResolvedSource) =>\n src.form === 'family' ? `family \"${src.family!.as}\"` : src.events.join(', ');\n\nconst metricList = (catalog: Catalog, events: string[]) => {\n const keys = new Set<string>();\n for (const n of events) for (const m of catalog.events[n]?.measures ?? []) keys.add(m.key);\n return keys.size ? [...keys].join(', ') : 'nothing but count';\n};\n\n// ── rule 1: funnel ──────────────────────────────────────────────────────────\n\n/**\n * Every stage, the anchor and every exit must be a lifetime `by: ['subject']`\n * family. The predicate and the messages mirror funnel.ts `requireMilestoneFamily`\n * — that function takes a Registry and this file only ever sees a Catalog, so\n * the FamilyFacet carries the same three facts (`lifetime`, `by`, `feeders`)\n * and the refusals read the same. A resolver that refused for a different\n * reason than the primitive throws for would be worse than no check at all.\n */\nfunction planFunnel(\n report: Report,\n catalog: Catalog,\n now: Date,\n limits: Partial<QueryLimits>,\n): Plan | Unavailable {\n const stages = report.stages ?? [];\n if (!stages.length) {\n return unavailable(\n \"`measure: 'funnel'` needs `stages` — one or more lifetime `by: ['subject']` rollup family names, \" +\n 'in the order a subject reaches them',\n );\n }\n const anchor = report.anchor ?? stages[0]!;\n const exits = report.exits ?? [];\n for (const as of [...stages, anchor, ...exits]) {\n const refusal = milestoneRefusal(catalog, as);\n if (refusal) return unavailable(refusal);\n }\n\n // one funnel is one population: two stages restricted to different subject\n // types would report conversions between subjects that are not the same party\n const first = catalog.families[stages[0]!]!;\n for (const as of [...stages.slice(1), anchor]) {\n const f = catalog.families[as]!;\n if (!sameSet(f.subjectTypes, first.subjectTypes)) {\n return unavailable(\n `funnel stages must share one subject type: \"${stages[0]}\" is declared \\`subjects: [${first.subjectTypes.join(', ')}]\\` ` +\n `and \"${as}\" is \\`subjects: [${f.subjectTypes.join(', ')}]\\` — two populations cannot convert into each other`,\n );\n }\n }\n if (report.subjectType && !first.subjectTypes.includes(report.subjectType)) {\n return unavailable(\n `subjectType \"${report.subjectType}\" is not one of the stages' subjects (${first.subjectTypes.join(', ')}) — ` +\n 'the cohort would be empty',\n );\n }\n if (report.interval === 'hour') {\n return unavailable(\n 'funnel slices are day, week or month — an hourly cohort slice is not offered, because a cohort is ' +\n 'assembled from lifetime milestones with no hourly grain to slice on',\n );\n }\n\n const params: Record<string, unknown> = {\n stages: stages.map((as) => ({ as })),\n anchor,\n ...(exits.length ? { exits: exits.map((as) => ({ as })) } : {}),\n cohort: rangeOf(report.range, now),\n ...(report.subjectType ? { subjectType: report.subjectType } : {}),\n ...(report.interval ? { interval: report.interval } : {}),\n ...(report.limit ? { limit: capped(report.limit, limits.funnel) } : {}),\n };\n return withCompare(report, {\n primitive: 'funnel',\n args: [params],\n exactness: 'exact',\n via: anchor,\n why:\n `cohort funnel over ${count(stages.length, 'lifetime milestone family')}, anchored on \"${anchor}\" — ` +\n 'rollups only, no raw scan',\n });\n}\n\n/** the funnel.ts precondition, said against a FamilyFacet. null when the family qualifies. */\nfunction milestoneRefusal(catalog: Catalog, as: string): string | null {\n const f = catalog.families[as];\n if (!f) {\n return (\n `no rollup family \"${as}\" is declared. Add a \\`rollups: [{ as: '${as}', by: ['subject'], subjects: [...] }]\\` ` +\n 'block to the event that marks it'\n );\n }\n const shape = `by: [${f.by.map((d) => `'${d}'`).join(', ')}]${f.bucket ? `, bucket: '${f.bucket}'` : ''}`;\n if (!f.lifetime) {\n return (\n `rollup family \"${as}\" (declared on \"${f.feeders[0]}\") is BUCKETED (${shape}). A milestone needs a ` +\n 'lifetime family so `firstAt` is the one moment the subject reached it; a bucketed family has one doc ' +\n 'per period and would count the same subject repeatedly'\n );\n }\n if (f.by.length !== 1 || f.by[0] !== 'subject') {\n return (\n `rollup family \"${as}\" (declared on \"${f.feeders[0]}\") is keyed ${shape}, but a milestone must be keyed ` +\n \"by exactly one subject dim (`by: ['subject']`). Extra dims split one subject across several docs, \" +\n 'which would over-count every stage'\n );\n }\n return null;\n}\n\n// ── rule 2: distinct ────────────────────────────────────────────────────────\n\nfunction planDistinct(\n report: Report,\n catalog: Catalog,\n src: ResolvedSource,\n measure: string,\n now: Date,\n): Plan | Unavailable {\n const subjectType = measure.slice('distinct:'.length);\n if (!subjectType) {\n return unavailable(\n `\"${measure}\" needs a subject type — 'distinct:account', one of ${catalog.subjectTypes.join(', ')}`,\n );\n }\n if (!catalog.subjectTypes.includes(subjectType)) {\n return unavailable(\n `no event or rollup declares the subject type \"${subjectType}\" — the registry knows ` +\n `${catalog.subjectTypes.join(', ') || 'no subject types at all'}`,\n );\n }\n if (report.groupBy?.length) {\n return unavailable(\n `distinct counts take no groupBy: distinctCount() answers one series per family, and \"${report.groupBy.join(', ')}\" ` +\n \"would need a family keyed by those dims AND `by: ['subject']`, which cannot count subjects exactly\",\n );\n }\n\n // one doc per (subject, bucket) is the whole exactness argument — the same\n // predicate query.ts `requireDistinctFamily` enforces at read time\n const wanted = new Set(src.events);\n const fits = Object.values(catalog.families).filter(\n (f) =>\n f.bucket != null &&\n f.by.length === 1 &&\n f.by[0] === 'subject' &&\n f.subjectTypes.includes(subjectType) &&\n src.events.every((e) => f.feeders.includes(e)),\n );\n const family = fits.find((f) => sameSet(f.feeders, [...wanted])) ?? fits[0];\n if (!family) {\n return unavailable(\n `no bucketed \\`by: ['subject']\\` family covers ${src.events.join(', ')} for subject type \"${subjectType}\" — ` +\n `declare \\`rollups: [{ as: 'activity', by: ['subject'], subjects: ['${subjectType}'], bucket: 'day' }]\\` ` +\n 'on the events that count as activity',\n );\n }\n const superset = !sameSet(family.feeders, [...wanted]);\n return withCompare(report, {\n primitive: 'distinctCount',\n args: [\n {\n as: family.as,\n subjectType,\n range: rangeOf(report.range, now),\n ...(report.interval ? { interval: report.interval } : {}),\n },\n ],\n exactness: 'exact',\n via: family.as,\n why:\n `\"${family.as}\" writes exactly one doc per (subject, ${family.bucket}), so distinct subjects IS the doc ` +\n 'count — exact, no sketch' +\n (superset\n ? `. Its feeders (${family.feeders.join(', ')}) are a SUPERSET of the source (${src.events.join(', ')}), ` +\n 'so the count includes subjects who only did the others'\n : ''),\n });\n}\n\n// ── rule 3: exact via rollups ───────────────────────────────────────────────\n\n/** a family dim in groupBy/filter vocabulary — the subject dim is asked for as `subjectType` */\nconst famDims = (f: FamilyFacet) => f.by.map((b) => (b === 'subject' ? 'subjectType' : (b as string)));\n\n/**\n * The cheapest read in the package: a family whose docs ARE the answer. Every\n * condition below is a way the family could be a different question than the\n * one asked, and any one of them falling through to raw is correct — a raw plan\n * is slower, never wrong.\n *\n * Returns null (not Unavailable) when nothing matches, because \"no family\n * answers this exactly\" is not a refusal.\n */\nfunction planRollups(\n report: Report,\n catalog: Catalog,\n src: ResolvedSource,\n measure: string,\n groupBy: string[],\n now: Date,\n limits: Partial<QueryLimits>,\n): Plan | null {\n // an actor-type exclusion is a WRITE-time decision for a family (`actors`),\n // so a read-time one cannot be applied to rows already accumulated\n if (report.excludeActorTypes?.length) return null;\n\n const candidates = src.family\n ? [src.family]\n : Object.values(catalog.families).filter((f) => sameSet(f.feeders, src.events));\n\n const op = MEASURE_OP.exec(measure);\n const filters = report.filters ?? [];\n const fits = candidates.filter((f) => {\n const dims = famDims(f);\n if (!groupBy.every((k) => dims.includes(k))) return false;\n if (report.interval && (!f.bucket || INTERVAL_RANK[f.bucket] > INTERVAL_RANK[report.interval])) return false;\n if (op) {\n // `sum` is stored; `avg` is sums[k]/count, which is exact off the same doc\n if ((op[1] !== 'sum' && op[1] !== 'avg') || !f.sums.includes(op[2]!)) return false;\n }\n // a rollup `dims` entry is a STRING ('region=eu'), so a family dim answers\n // equality and set membership and nothing else — a numeric bound belongs to\n // the raw path, where it can read `metrics.<k>`\n return filters.every(\n (t) => (dims.includes(t.dim) && (t.op === 'eq' || t.op === 'in')) || nameFilterCovers(t, f),\n );\n });\n // fewest dims wins: the cheapest read and the tightest match, since a wider\n // family would have to be folded down to the same groups anyway\n const family = fits.sort((a, b) => a.by.length - b.by.length)[0];\n if (!family) return null;\n\n const dims = famDims(family);\n const range = rangeOf(report.range, now);\n const on = family.lifetime ? 'firstAt' : 'bucketAt';\n // a `field:name` term is already answered by the family's feeders; the rest\n // are dim equalities the executor applies while folding the rows\n const fold = filters.filter((t) => dims.includes(t.dim));\n return withCompare(report, {\n primitive: 'rollups',\n args: [\n {\n as: family.as,\n on,\n range,\n sort: family.lifetime ? 'count' : 'bucketAt',\n ...(report.limit ? { limit: capped(report.limit, limits.rollups) } : {}),\n },\n ],\n exactness: 'exact',\n via: family.as,\n shape: {\n groupBy,\n labels: groupBy.map((k) => family.labels[dims.indexOf(k)]!),\n measure,\n ...(report.interval ? { interval: report.interval } : {}),\n ...(fold.length\n ? { filters: fold.map((t) => ({ ...t, label: family.labels[dims.indexOf(t.dim)]! })) }\n : {}),\n },\n why:\n `family \"${family.as}\" is keyed by ${dims.join(', ') || 'nothing but its feeders'} and maintained on write, ` +\n `so this is one indexed rollup read over \\`${on}\\` instead of a raw scan` +\n (op?.[1] === 'avg'\n ? `. avg:${op[2]} is exact off a rollup: the executor divides sums.${op[2]} by count`\n : '') +\n (report.interval && family.bucket !== report.interval\n ? `. Its ${family.bucket} buckets roll up into ${report.interval} without splitting one`\n : ''),\n });\n}\n\n/**\n * A `field:name` filter is not a family dim — a rollup doc does not record which\n * event wrote it — but it costs nothing when the names it admits already cover\n * every feeder, because then it removes nothing the family holds.\n */\nfunction nameFilterCovers(t: ReportFilter, f: FamilyFacet): boolean {\n if (t.dim !== 'field:name') return false;\n const admitted = t.op === 'eq' ? [String(t.value)] : t.op === 'in' ? [...(t.value as string[])].map(String) : null;\n return admitted != null && f.feeders.every((n) => admitted.includes(n));\n}\n\n// ── the raw filter ──────────────────────────────────────────────────────────\n\n/** the RecordFilter keys a `field:` filter maps onto, equality only */\nconst FIELD_TERMS: Record<string, keyof RecordFilter> = {\n 'field:kind': 'kind',\n 'field:name': 'name',\n 'field:severity': 'severity',\n 'field:env': 'env',\n 'field:service': 'service',\n 'field:release': 'release',\n ...FILTER_ONLY,\n};\n\n/**\n * Report → RecordFilter, the shape every raw primitive takes. Deliberately\n * total over what RecordFilter can EXPRESS and refusing everything else: this\n * plan step is where \"the query layer is missing a parameter\" gets said out\n * loud (dashboards law 6) rather than papered over with a filter that reads\n * more records than the Report asked about.\n */\nfunction toRecordFilter(report: Report, catalog: Catalog, src: ResolvedSource): RecordFilter | Unavailable {\n const filter: RecordFilter = {};\n\n if (src.events.length === 1) {\n // one name pins the read exactly, whichever source form named it\n filter.name = src.events[0];\n } else if (src.kind) {\n // a kind term IS the source: `{ kind }` expanded to every event declaring\n // it, so one indexed equality covers exactly that set for less than an\n // `$in` over every name in it\n filter.kind = src.kind;\n } else {\n // a namespace or a family is several names, and `RecordFilter.name` takes\n // the set — so the read is the source, exactly, rather than \"every record\n // of that kind in the range\" with a note apologising for it\n filter.name = [...src.events];\n }\n\n for (const t of report.filters ?? []) {\n const term = FIELD_TERMS[t.dim];\n if (term) {\n if (t.op !== 'eq') {\n return unavailable(\n `\"${t.dim}\" supports equality only on the raw path — RecordFilter.${String(term)} is one string, ` +\n `and \"${t.op}\" would need a term query.ts does not build`,\n );\n }\n (filter as Record<string, unknown>)[term] = String(t.value);\n continue;\n }\n if (t.dim.startsWith('attr:')) {\n const key = t.dim.slice(5);\n if (t.op === 'eq') {\n (filter.attrs ??= {})[key] = String(t.value);\n continue;\n }\n if (t.op === 'gte' || t.op === 'lte') {\n // a numeric bound names a METRIC — `metrics.<k>` is the only ranged\n // term buildMatch writes, and attrs are strings after casting\n if (!measureDeclared(catalog, src.events, `sum:${key}`)) {\n return unavailable(\n `\"${t.dim} ${t.op}\" is a numeric bound, which only a declared metric can carry — add \\`${key}\\` to ` +\n `the \\`metrics\\` object of ${src.events.join(', ')}, or filter it as an equality`,\n );\n }\n const range = ((filter.metrics ??= {})[key] ??= {});\n range[t.op] = Number(t.value);\n continue;\n }\n return unavailable(\n `\"${t.dim}\" supports equality (or a gte/lte bound on a metric) — an \\`in\\` over attrs would need a ` +\n '`$in` term buildMatch does not write',\n );\n }\n if (t.dim === 'subjectType' || t.dim === 'actorType') {\n return unavailable(\n `\"${t.dim}\" is derived at query time from ${t.dim === 'subjectType' ? '`subjectKeys`' : '`actor`'} and ` +\n 'RecordFilter has no term for it — group by it instead, pin one subject with `field:subject`' +\n (t.dim === 'actorType' ? ', or use `excludeActorTypes`' : ''),\n );\n }\n return unavailable(\n `\"${t.dim}\" is not filterable on the raw path — RecordFilter carries ${Object.keys(FIELD_TERMS).join(', ')}, ` +\n '`attr:<key>` and metric bounds',\n );\n }\n\n if (report.excludeActorTypes?.length) filter.excludeActorTypes = [...report.excludeActorTypes];\n return filter;\n}\n\n// ── compare ─────────────────────────────────────────────────────────────────\n\n/**\n * `compare: 'previous'` is pure arithmetic on the Report: the same plan, its\n * range shifted back by its own length. No primitive changes, and the executor\n * runs the same call twice.\n *\n * Each primitive keeps its range in a different place, which is exactly why the\n * shift lives here rather than in seven call sites.\n */\nfunction withCompare(report: Report, plan: Plan): Plan {\n if (report.compare !== 'previous') return plan;\n const [first, ...rest] = plan.args;\n if (plan.primitive === 'rollups' || plan.primitive === 'distinctCount' || plan.primitive === 'funnel') {\n const params = first as Record<string, unknown>;\n const key = plan.primitive === 'funnel' ? 'cohort' : 'range';\n const window = params[key] as (TimeRange & { endInclusive?: boolean }) | undefined;\n if (!window) return plan;\n return { ...plan, previous: { args: [{ ...params, [key]: { ...window, ...shift(window) } }, ...rest] } };\n }\n return { ...plan, previous: { args: [shift(first as TimeRange), ...rest] } };\n}\n\nconst sameSet = (a: readonly string[], b: readonly string[]) =>\n a.length === b.length && a.every((x) => b.includes(x));\n\n// ── the URL form (reports §4, §11.4) ────────────────────────────────────────\n\n/**\n * A Report is a URL. These two are inverses — `parseReportQuery(reportToQuery(r))`\n * deep-equals `r` — and they are the ONLY encoding: `GET /api/report` reads it,\n * the explore hash carries it, and util.js implements the same grammar on the\n * client. A Report that needed state a URL cannot hold would mean the query\n * layer is missing a parameter (dashboards law 6), not that the encoder needs a\n * blob.\n *\n * source=event:llm.completion&range=7d&interval=day&measure=sum:cost_usd\n * &groupBy=attr:gen_ai_request_model&filter=attr:feature:eq:chat&compare=previous\n *\n * Everything is flat and human-typable. `filter` REPEATS (express parses repeats\n * into an array; one stays a string, and both are accepted), because a term's\n * value may contain a comma — an `in` list is exactly that.\n */\nconst FILTER_OPS = new Set<ReportFilter['op']>(['eq', 'in', 'gte', 'lte']);\nconst SORTS = new Set(['value', 'label', 'time']);\n\nexport function parseReportQuery(q: Record<string, unknown>): Report {\n /** a repeated param takes its first value; every param but `filter` is single */\n const str = (k: string): string | undefined => {\n const v = Array.isArray(q[k]) ? (q[k] as unknown[])[0] : q[k];\n return typeof v === 'string' && v ? v : undefined;\n };\n const list = (k: string): string[] =>\n (str(k) ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n\n const raw = str('source');\n if (!raw) {\n throw badRequest(\n '`source` is required — one of source=event:<name>, namespace:<ns>, kind:<kind>, family:<as>',\n );\n }\n const cut = raw.indexOf(':');\n const form = cut > 0 ? raw.slice(0, cut) : '';\n const named = cut > 0 ? raw.slice(cut + 1) : '';\n if (!named || !['event', 'namespace', 'kind', 'family'].includes(form)) {\n throw badRequest(\n `\\`source\\` must be \"event:<name>\", \"namespace:<ns>\", \"kind:<kind>\" or \"family:<as>\" — got \"${raw}\"`,\n );\n }\n const source: ReportSource =\n form === 'event'\n ? { event: named }\n : form === 'namespace'\n ? { namespace: named }\n : form === 'kind'\n ? { kind: named as TelemetryKind }\n : { family: named };\n\n // the shorthand wins when both are present: it is the Report's own param, and\n // the shell's from/to ride along on every URL the SPA builds\n const shorthand = str('range');\n const from = str('from');\n const to = str('to');\n if (!shorthand && !(from && to)) {\n throw badRequest('a range is required — either `range=7d` or both `from` and `to` as ISO times');\n }\n const range: ReportRange = shorthand ?? { from: from!, to: to! };\n\n const interval = str('interval');\n if (interval && INTERVAL_RANK[interval as Interval] == null) {\n throw badRequest(`\\`interval\\` must be one of hour, day, week, month — got \"${interval}\"`);\n }\n const sort = str('sort');\n if (sort && !SORTS.has(sort)) {\n throw badRequest(`\\`sort\\` must be one of value, label, time — got \"${sort}\"`);\n }\n const compare = str('compare');\n if (compare && compare !== 'previous') {\n throw badRequest(`\\`compare\\` takes only \"previous\" — got \"${compare}\"`);\n }\n const limitRaw = str('limit');\n const limit = limitRaw == null ? undefined : Number(limitRaw);\n if (limit != null && (!Number.isInteger(limit) || limit < 1)) {\n throw badRequest(`\\`limit\\` must be a positive integer — got \"${limitRaw}\"`);\n }\n\n const measure = str('measure');\n const groupBy = list('groupBy');\n const excludeActorTypes = list('excludeActors');\n const stages = list('stages');\n const exits = list('exits');\n const anchor = str('anchor');\n const subjectType = str('subjectType');\n const filters = (\n q.filter == null ? [] : Array.isArray(q.filter) ? q.filter.map(String) : [String(q.filter)]\n ).map(parseFilterTerm);\n\n return {\n source,\n range,\n ...(interval ? { interval: interval as Interval } : {}),\n ...(measure ? { measure } : {}),\n ...(groupBy.length ? { groupBy } : {}),\n ...(filters.length ? { filters } : {}),\n ...(excludeActorTypes.length ? { excludeActorTypes } : {}),\n ...(sort ? { sort: sort as Report['sort'] } : {}),\n ...(limit != null ? { limit } : {}),\n ...(compare ? { compare: 'previous' as const } : {}),\n ...(stages.length ? { stages } : {}),\n ...(anchor ? { anchor } : {}),\n ...(exits.length ? { exits } : {}),\n ...(subjectType ? { subjectType } : {}),\n };\n}\n\n/**\n * `<dim>:<op>:<value>`, where the DIM itself contains a colon (`attr:model`) and\n * so may the value (`field:subject:eq:user:u_1`). The op is therefore found\n * rather than positioned: the FIRST token that is one of the four operators\n * ends the dim and begins the value. A dim whose last segment is literally\n * \"eq\"/\"in\"/\"gte\"/\"lte\" would mis-split, which is the price of a grammar a\n * person can type; nothing in the catalog's vocabulary produces one.\n */\nfunction parseFilterTerm(term: string): ReportFilter {\n const parts = term.split(':');\n const i = parts.findIndex((p) => FILTER_OPS.has(p as ReportFilter['op']));\n const rest = i < 0 ? '' : parts.slice(i + 1).join(':');\n // an EMPTY value is refused with the rest: `field:env:eq:` reads as \"env is\n // the empty string\", which nothing stores — it is a half-typed URL, and\n // answering it would return zero rows that look like an answer\n if (i < 1 || !rest) {\n throw badRequest(\n `\\`filter\\` must be \"<dim>:<op>:<value>\" with op one of eq, in, gte, lte — got \"${term}\"`,\n );\n }\n const dim = parts.slice(0, i).join(':');\n const op = parts[i] as ReportFilter['op'];\n if (op === 'in') {\n const values = rest.split(',').map((s) => s.trim()).filter(Boolean);\n if (!values.length) throw badRequest(`\\`filter\\` \"${term}\" has an empty \\`in\\` list`);\n return { dim, op, value: values };\n }\n if (op === 'gte' || op === 'lte') {\n const n = Number(rest);\n if (Number.isNaN(n)) throw badRequest(`\\`filter\\` bound \"${term}\" is not a number`);\n return { dim, op, value: n };\n }\n return { dim, op, value: rest };\n}\n\n/**\n * The inverse. `filter` is the one key that can hold several values — one term\n * stays a string so the URL reads the way a person would write it, several\n * become the repeated-param array express parses back.\n */\nexport function reportToQuery(report: Report): Record<string, string | string[]> {\n const s = report.source;\n const q: Record<string, string | string[]> = {\n source:\n 'event' in s\n ? `event:${s.event}`\n : 'namespace' in s\n ? `namespace:${s.namespace}`\n : 'kind' in s\n ? `kind:${s.kind}`\n : `family:${s.family}`,\n };\n if (typeof report.range === 'string') q.range = report.range;\n else {\n q.from = report.range.from;\n q.to = report.range.to;\n }\n if (report.interval) q.interval = report.interval;\n if (report.measure) q.measure = report.measure;\n if (report.groupBy?.length) q.groupBy = report.groupBy.join(',');\n if (report.filters?.length) {\n const terms = report.filters.map(\n (f) => `${f.dim}:${f.op}:${Array.isArray(f.value) ? f.value.join(',') : String(f.value)}`,\n );\n q.filter = terms.length === 1 ? terms[0]! : terms;\n }\n if (report.excludeActorTypes?.length) q.excludeActors = report.excludeActorTypes.join(',');\n if (report.sort) q.sort = report.sort;\n if (report.limit != null) q.limit = String(report.limit);\n if (report.compare) q.compare = report.compare;\n if (report.stages?.length) q.stages = report.stages.join(',');\n if (report.anchor) q.anchor = report.anchor;\n if (report.exits?.length) q.exits = report.exits.join(',');\n if (report.subjectType) q.subjectType = report.subjectType;\n return q;\n}\n\n// ── the legacy lift ─────────────────────────────────────────────────────────\n\n/** legacy filter key → the DimFacet key its equality term becomes */\nconst LEGACY_DIMS: Record<string, string> = {\n kind: 'field:kind',\n name: 'field:name',\n severity: 'field:severity',\n env: 'field:env',\n service: 'field:service',\n release: 'field:release',\n subject: 'field:subject',\n traceId: 'field:traceId',\n};\n\n/**\n * The stored-view lift (reports §4). `ViewSpec.query` is a `Report` now — the\n * derived ones included — but every view saved before this shipped is\n * `{ range, filters, groupBy, sort }`, a Mixed document that must keep parsing.\n *\n * Returns null when nothing in the query identifies a source, because a legacy\n * query that names neither an event, a kind nor a family is not a Report — it\n * is a page's default, and the caller's own fallback is the honest answer.\n */\nexport function normalizeQuery(query: ViewSpec['query'] | null | undefined): Report | null {\n if (!query || typeof query !== 'object') return null;\n if ('source' in query && query.source) return query as Report;\n\n const q = query as LegacyQuery;\n const filters = (q.filters ?? {}) as Record<string, unknown>;\n const str = (v: unknown) => (typeof v === 'string' && v ? v : null);\n\n // a family read is more specific than a kind page, and a name more specific\n // than either — whichever is present wins in that order\n const name = str(filters.name);\n const family = str(filters.rollup);\n const kind = str(filters.kind);\n const source: ReportSource | null = name\n ? { event: name }\n : family\n ? { family }\n : kind\n ? { kind: kind as TelemetryKind }\n : null;\n if (!source) return null;\n\n const consumed = name ? 'name' : family ? 'rollup' : 'kind';\n const terms: ReportFilter[] = [];\n for (const [k, v] of Object.entries(filters)) {\n if (k === consumed || k === 'rollup') continue;\n if (k === 'excludeActorTypes') continue;\n if (k === 'attrs') {\n // the FilterBar's own encoding, both ways round: an object, or 'a:b,c:d'\n const entries =\n typeof v === 'string'\n ? v.split(',').map((pair) => pair.split(':').map((s) => s.trim()))\n : Object.entries((v ?? {}) as Record<string, unknown>).map(([a, b]) => [a, String(b)]);\n for (const [key, value] of entries) {\n if (key && value != null) terms.push({ dim: `attr:${key}`, op: 'eq', value: String(value) });\n }\n continue;\n }\n const dim = LEGACY_DIMS[k];\n const value = str(v);\n if (dim && value) terms.push({ dim, op: 'eq', value });\n }\n\n const groupBy = (q.groupBy ?? '')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n const sort = q.sort === 'value' || q.sort === 'label' || q.sort === 'time' ? q.sort : undefined;\n const actors = filters.excludeActorTypes;\n\n return {\n source,\n range: q.range ?? '7d',\n ...(terms.length ? { filters: terms } : {}),\n ...(groupBy.length ? { groupBy } : {}),\n ...(sort ? { sort } : {}),\n ...(Array.isArray(actors) && actors.length ? { excludeActorTypes: actors.map(String) } : {}),\n };\n}\n","import { truncate } from './rollups.js';\nimport { resolveReport, type Plan, type PlanShape, type Report } from './report.js';\nimport type { Catalog } from './catalog.js';\nimport type { BreakdownRow, Queries, QueryLimits } from './query.js';\n\n/**\n * The executor (reports §6). `resolveReport` picks a primitive and its\n * arguments; this runs them. One function, two doors — `GET /api/report` and\n * the `run_report` MCP tool — so a Report means the same thing over HTTP and to\n * an agent, and neither door invents a query of its own.\n *\n * It lives here rather than in report.ts because report.ts is PURE: type-only\n * imports, no Mongo, unit-pinned like deriveCatalog. Executing needs `Queries`,\n * which is the whole database. The seam between them is `Plan.args`:\n *\n * const result = await q[plan.primitive](scope, ...plan.args);\n *\n * That is the entire dispatch. There is no per-primitive adapter here, and the\n * moment one appears the plan shape is wrong.\n *\n * The one thing this file DOES translate is a `rollups` plan, and `foldRollups`\n * below says why: rollups() has no server-side groupBy, so the requested groups\n * are a fold over the docs it returns. The fold produces the same row shape\n * `breakdown()` does, so a renderer never learns which store answered — which\n * is the point of planning an exact read in the first place.\n */\n\nexport interface ExecuteOptions {\n /** injected so a plan is deterministic — shorthand ranges end here */\n now?: Date;\n /** forwarded to the resolver, which uses them to cap the plan's own limits */\n limits?: Partial<QueryLimits>;\n /**\n * Applied to a `records` plan's items before they leave. The dashboard has no\n * redactor (its viewer is already inside the tenant); mcp.ts passes its own,\n * because an agent reading raw `data` payloads is the exposure that tool\n * suite defaults against.\n */\n redact?: (items: any[]) => any[];\n}\n\nexport interface ReportResult {\n /** the Report as executed — after a legacy lift, so the caller can see what ran */\n report: Report;\n plan: Plan;\n /** the primitive's own result, EXCEPT a rollups plan, which arrives folded */\n result: unknown;\n /** present when `compare: 'previous'` — the same call, range shifted back */\n previous?: unknown;\n /** which store answered, read off the result rather than assumed */\n dataSource: 'raw' | 'rollups' | 'raw+rollups';\n}\n\n/**\n * Report → the answer. Refusals are 400s: `Unavailable` is not an exception in\n * the resolver (a refusal is an answer), but by the time someone has asked for\n * the DATA it is — the `why` is the message, verbatim, because it already names\n * the offending key and the registry change that would fix it.\n */\nexport async function executeReport(\n q: Queries,\n scope: string,\n report: Report,\n catalog: Catalog,\n opts: ExecuteOptions = {},\n): Promise<ReportResult> {\n const plan = resolveReport(report, catalog, { now: opts.now, limits: opts.limits });\n if ('unavailable' in plan) throw Object.assign(new Error(plan.why), { status: 400 });\n\n const run = async (args: unknown[]): Promise<unknown> => {\n // the contract, verbatim. `args` is positional and typed `unknown[]`, so the\n // cast is the one place the plan's promise is taken on trust — report.test.ts\n // pins the args shape per primitive, dashboard.test.ts executes all seven.\n const raw: any = await (q as any)[plan.primitive](scope, ...args);\n if (plan.primitive === 'rollups' && plan.shape) {\n return foldRollups(raw?.rows ?? [], plan.shape, !!raw?.truncated);\n }\n if (plan.primitive === 'records' && opts.redact) {\n return { ...raw, items: opts.redact(raw?.items ?? []) };\n }\n return raw;\n };\n\n const [result, previous] = await Promise.all([\n run(plan.args),\n plan.previous ? run(plan.previous.args) : Promise.resolve(undefined),\n ]);\n return {\n report,\n plan,\n result,\n ...(plan.previous ? { previous } : {}),\n dataSource: (result as any)?.dataSource ?? 'raw',\n };\n}\n\n// ── folding a rollups plan ──────────────────────────────────────────────────\n\n/** the fields the fold reads off a rollup doc — see rollups.ts for the full shape */\nexport interface RollupDoc {\n /** dimension values in the family's `by` order: 'region=eu', or a bare 'user:u_1' */\n dims: string[];\n bucketAt?: Date | string | null;\n count?: number;\n sums?: Record<string, number> | Map<string, number> | null;\n}\n\n/** what breakdown() returns, from the rollup store instead of the raw one */\nexport interface FoldedRollups {\n rows: BreakdownRow[];\n /** distinct group tuples, ignoring the time axis — the same count breakdown reports */\n groups: number;\n /** the rollup read hit its cap, so groups are missing */\n truncated: boolean;\n dataSource: 'rollups';\n}\n\nconst MEASURE_OP = /^(sum|avg):(.+)$/;\n\n/**\n * A family's docs ARE the groups: the requested dims are its own `by` dims, so\n * grouping is arithmetic over rows already read, not a second query. This folds\n * them into the shape `breakdown()` returns — `{ dims, at?, value }` sorted the\n * same way — so the two are interchangeable and a chart cannot tell which store\n * answered. dashboard.test.ts asserts exactly that, number for number, on one\n * seed.\n *\n * Pure: no Mongo, no clock. `truncated` is the primitive's own flag, passed\n * through rather than re-derived, because a fold cannot know what it never saw.\n */\nexport function foldRollups(\n rows: readonly RollupDoc[],\n shape: PlanShape,\n truncated = false,\n): FoldedRollups {\n const op = MEASURE_OP.exec(shape.measure);\n const groups = new Map<string, { dims: (string | null)[]; at?: Date; sum: number; count: number }>();\n\n for (const doc of rows) {\n const dims = doc?.dims ?? [];\n if (!(shape.filters ?? []).every((f) => admits(f, dimValue(dims, f.label)))) continue;\n const tuple = shape.labels.map((label) => dimValue(dims, label));\n // a family may bucket FINER than the interval asked for (day rows → weeks);\n // re-truncating a bucket start cannot split one, so the roll-up stays exact\n const at =\n shape.interval && doc.bucketAt ? truncate(new Date(doc.bucketAt as any), shape.interval) : undefined;\n const key = `${JSON.stringify(tuple)}|${at ? at.getTime() : ''}`;\n let g = groups.get(key);\n if (!g) groups.set(key, (g = { dims: tuple, ...(at ? { at } : {}), sum: 0, count: 0 }));\n g.count += typeof doc.count === 'number' ? doc.count : 0;\n if (op) g.sum += sumOf(doc.sums, op[2]!);\n }\n\n const rowsOut: BreakdownRow[] = [...groups.values()].map((g) => ({\n dims: g.dims,\n ...(g.at ? { at: g.at } : {}),\n // avg is sums[k]/count off the SAME doc, which is exact — not an average of\n // averages, which is what folding a per-bucket mean would have produced\n value: !op ? g.count : op[1] === 'sum' ? g.sum : g.count ? g.sum / g.count : 0,\n }));\n rowsOut.sort(\n shape.interval\n ? (a, b) => (a.at?.getTime() ?? 0) - (b.at?.getTime() ?? 0) || byDims(a, b)\n : (a, b) => b.value - a.value || byDims(a, b),\n );\n\n return {\n rows: rowsOut,\n groups: new Set([...groups.values()].map((g) => JSON.stringify(g.dims))).size,\n truncated,\n dataSource: 'rollups',\n };\n}\n\n/**\n * One dim value out of a doc's `dims`, by the label rollups.ts wrote in front of\n * it. A SUBJECT dim is the exception and keeps its native `type:id` ref with no\n * `label=` prefix — erasure matches those directly (rollups.ts) — so it is\n * found as the entry that carries no `=` at all, and returned whole. That is\n * also what `breakdown()` returns for `subjectType`'s sibling dims, so the two\n * row shapes stay comparable.\n */\nfunction dimValue(dims: readonly string[], label: string): string | null {\n const prefix = `${label}=`;\n for (const d of dims) if (d.startsWith(prefix)) return d.slice(prefix.length);\n for (const d of dims) if (!d.includes('=')) return d;\n return null;\n}\n\n/** the fold's half of a filter — rollups() can only pin whole dims (reports §6) */\nfunction admits(f: NonNullable<PlanShape['filters']>[number], value: string | null): boolean {\n if (f.op === 'in') return (f.value as unknown[]).map(String).includes(String(value));\n if (f.op === 'gte' || f.op === 'lte') {\n const n = Number(value);\n if (Number.isNaN(n)) return false;\n return f.op === 'gte' ? n >= Number(f.value) : n <= Number(f.value);\n }\n return String(value) === String(f.value);\n}\n\n/** lean() hands back a plain object; a hydrated doc hands back a Map. Read both. */\nfunction sumOf(sums: RollupDoc['sums'], key: string): number {\n if (!sums) return 0;\n const v = sums instanceof Map ? sums.get(key) : (sums as Record<string, number>)[key];\n return typeof v === 'number' ? v : 0;\n}\n\n/** breakdown sorts ties by its `_id` tuple; matching that keeps the two orders identical */\nfunction byDims(a: BreakdownRow, b: BreakdownRow): number {\n for (let i = 0; i < a.dims.length; i++) {\n const x = a.dims[i] ?? '';\n const y = b.dims[i] ?? '';\n if (x !== y) return x < y ? -1 : 1;\n }\n return 0;\n}\n","import { Schema, type Connection, type Model } from 'mongoose';\nimport { deriveCatalog, type Catalog } from './catalog.js';\nimport type { Registry } from './registry.js';\nimport { intervalForRange, type LegacyQuery, type Report } from './report.js';\nimport { newId } from './types.js';\n\n/**\n * Views — one shape, three producers (dashboards §3). A view is nothing but\n * named query state; derived views come from the registry for free, configured\n * ones ship in host code, saved ones live in `<collection>_views`. Name\n * collisions shadow saved → configured → derived, so a user can override a\n * default without editing anything.\n *\n * Tenancy: views scope on the LITERAL viewer scope, including PLATFORM_SCOPE.\n * '*' is an escape hatch for reading telemetry, not a master key to other\n * people's saved state, so it does NOT fan out here the way it does in the\n * query primitives. A platform viewer's views live in their own '*' namespace:\n * invisible to every tenant, and every tenant's views invisible to them. Both\n * directions fall out of the same literal match — in resolveViews below and in\n * the router's delete/ownership lookup, which must stay literal for the same\n * reason (a platform admin's `role: 'admin'` is admin OF the platform scope).\n *\n * Erasure across that boundary is opt-in. forget(tenantId, ref) is\n * tenant-scoped and '*' is not a tenant, so a person's PLATFORM-scoped views\n * are missed by default — set `globalSubjectRefs` on createTelemetry() and\n * forget() reaches them too. The flag is the host asserting that a ref names\n * one party globally; without that, `user:u_1` is a different person in every\n * tenant and one tenant's erasure would delete another's views. Bounded by the\n * named ref either way — never by the tenant, which is the escape hatch this\n * namespace exists to deny.\n */\n\nexport interface ViewSpec {\n name: string;\n icon?: string;\n page: 'errors' | 'traces' | 'events' | 'journeys' | 'usage' | 'overview' | 'system' | 'explore';\n /**\n * A Report (reports §4) — or the pre-Report shape, which every stored view\n * still carries and `normalizeQuery()` lifts. `spec` is a Mixed document, so\n * nothing has to migrate: a query with no `source` is read as legacy and a\n * query with one is read as a Report.\n */\n query: Report | LegacyQuery;\n}\n\nexport function buildViewModel(connection: Connection, modelName: string, collection: string): Model<any> {\n const existing = connection.models?.[modelName];\n if (existing) return existing;\n const schema = new Schema(\n {\n _id: { type: String, required: true },\n tenantId: { type: String, required: true },\n /** a person — forget() deletes private views, redacts this on shared ones */\n ownerRef: String,\n shared: { type: Boolean, default: false },\n spec: { type: Schema.Types.Mixed, required: true },\n createdAt: { type: Date, required: true },\n },\n { collection, versionKey: false },\n );\n schema.index({ tenantId: 1, shared: 1 });\n schema.index({ tenantId: 1, ownerRef: 1 });\n return connection.model(modelName, schema);\n}\n\nconst KIND_PAGE: Record<string, ViewSpec['page']> = {\n error: 'errors',\n span: 'traces',\n event: 'events',\n state: 'journeys',\n usage: 'usage',\n};\n\n/**\n * Derived views — generated from the registry at load, zero config, and every\n * one of them a {@link Report} (reports §8). They exist because the registry\n * already knows enough to write them, so five shapes fall out of it:\n *\n * | shape | name | what it answers |\n * |---|---|---|\n * | per event | `<name>` | that one name over a week |\n * | per family | `rollup: <as>` | the family's own docs — the cheapest read there is |\n * | per namespace | `namespace: <ns>` | `library.*` split by name over a month |\n * | per usage event | `spend: <name>` | its `*_usd` sum per day |\n * | per subject type | `funnel: <type>` | its lifetime milestones as a cohort funnel |\n *\n * The catalog is what makes the last three writable, and it is PURE — so this\n * function keeps its one-argument signature and derives one when a caller\n * (resolveViews, off a request) has none to hand. `createDashboard` and\n * `createTelemetryMcp` both built theirs at boot and pass it through.\n *\n * Determinism matters more than it looks: these names are the sidebar, and a\n * list that reshuffles between requests is one nobody can link into. Every loop\n * below walks the catalog in registry order.\n */\nexport function deriveViews(\n registry: Registry,\n catalog: Catalog = deriveCatalog(registry),\n): Array<ViewSpec & { origin: 'derived' }> {\n const views: Array<ViewSpec & { origin: 'derived' }> = [];\n const derived = (name: string, page: ViewSpec['page'], query: Report) =>\n views.push({ origin: 'derived', name, page, query });\n\n // ── one per event: the name, charted over a week ──\n for (const [name, e] of Object.entries(catalog.events)) {\n derived(name, KIND_PAGE[e.kind] ?? 'events', {\n source: { event: name },\n range: '7d',\n interval: intervalForRange('7d'),\n });\n }\n\n // ── one per rollup family: read the family itself, which is always exact ──\n for (const as of Object.keys(catalog.families)) {\n derived(`rollup: ${as}`, 'journeys', { source: { family: as }, range: '30d' });\n }\n\n // ── one per namespace: `library.*` broken out by name ──\n // A namespace of one event is that event's own view under a second name, so\n // it is skipped rather than duplicated into the sidebar.\n for (const [ns, names] of Object.entries(catalog.namespaces)) {\n if (names.length < 2) continue;\n derived(`namespace: ${ns}`, 'explore', {\n source: { namespace: ns },\n range: '30d',\n interval: 'day',\n groupBy: ['field:name'],\n });\n }\n\n // ── one per usage event that meters money ──\n // `*_usd` is a formatting CONVENTION (dashboards §4), which makes it the one\n // thing about a metric this file may read off a key. It never names one.\n for (const [name, e] of Object.entries(catalog.events)) {\n if (e.kind !== 'usage') continue;\n const money = e.measures.find((m) => m.key.startsWith('sum:') && m.key.endsWith('_usd'));\n if (!money) continue;\n derived(`spend: ${name}`, 'usage', {\n source: { event: name },\n range: '30d',\n interval: 'day',\n measure: money.key,\n });\n }\n\n // ── one funnel per subject type ──\n // Stages are the lifetime single-subject families of that type, in registry\n // order — the order the host typed them in, which is the only sequence a\n // registry can claim. The UI re-orders them by observed median `firstAt`\n // (reports §7); this default has no data to read.\n for (const subjectType of catalog.subjectTypes) {\n const stages = Object.values(catalog.families)\n .filter((f) => f.lifetime && f.by.length === 1 && f.by[0] === 'subject' && f.subjectTypes.includes(subjectType))\n .map((f) => f.as);\n // one stage is not a funnel — it is a count, and there is already a view for it\n if (stages.length < 2) continue;\n derived(`funnel: ${subjectType}`, 'journeys', {\n // any source expands; the family the funnel is anchored on is the honest one\n source: { family: stages[0]! },\n range: '30d',\n interval: 'week',\n measure: 'funnel',\n stages,\n anchor: stages[0]!,\n subjectType,\n });\n }\n\n return views;\n}\n\nexport interface ResolvedView extends ViewSpec {\n origin: 'derived' | 'configured' | 'saved';\n id?: string;\n ownerRef?: string;\n shared?: boolean;\n}\n\n/** merge the three producers; name collisions resolve saved → configured → derived */\nexport async function resolveViews(opts: {\n ViewModel: Model<any>;\n registry: Registry;\n /** the caller's boot-time catalog, so a request does not re-derive one */\n catalog?: Catalog;\n configured: ViewSpec[];\n /** the viewer's scope — a tenantId, or PLATFORM_SCOPE. Matched literally. */\n tenantId: string;\n viewerRef?: string;\n}): Promise<ResolvedView[]> {\n const byName = new Map<string, ResolvedView>();\n for (const v of deriveViews(opts.registry, opts.catalog)) byName.set(v.name, v);\n for (const v of opts.configured) byName.set(v.name, { ...v, origin: 'configured' });\n const saved = await opts.ViewModel.find({\n tenantId: opts.tenantId,\n $or: [{ shared: true }, ...(opts.viewerRef ? [{ ownerRef: opts.viewerRef }] : [])],\n })\n .sort({ createdAt: 1 })\n .limit(200)\n .lean();\n for (const doc of saved as any[]) {\n byName.set(doc.spec.name, {\n ...doc.spec,\n origin: 'saved',\n id: doc._id,\n ownerRef: doc.ownerRef,\n shared: doc.shared,\n });\n }\n return [...byName.values()];\n}\n\nexport async function saveView(opts: {\n ViewModel: Model<any>;\n tenantId: string;\n viewerRef?: string;\n spec: ViewSpec;\n shared: boolean;\n}): Promise<{ id: string }> {\n // a viewer without an identity cannot own a private view — share or nothing\n if (!opts.shared && !opts.viewerRef) {\n throw Object.assign(new Error('private views need a viewer identity'), { status: 400 });\n }\n const id = newId();\n await opts.ViewModel.create({\n _id: id,\n tenantId: opts.tenantId,\n ownerRef: opts.viewerRef,\n shared: opts.shared,\n spec: opts.spec,\n createdAt: new Date(),\n });\n return { id };\n}\n","import express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { NextFunction, Request, Response, Router } from 'express';\nimport { INDEX_BUDGET } from './indexes.js';\nimport { isPlatformScope } from './types.js';\nimport { deriveCatalog, projectRegistry } from './catalog.js';\nimport { deriveSuggestions } from './suggest.js';\nimport { createQueries, type QueryLimits, type RecordFilter, type TimeRange } from './query.js';\nimport { createValues } from './values.js';\nimport { parseReportQuery, resolveReport } from './report.js';\nimport { executeReport } from './execute.js';\nimport { buildViewModel, resolveViews, saveView, type ViewSpec } from './views.js';\nimport type { Telemetry } from './index.js';\n\n/**\n * The read surface (dashboards §2–§8): one express router serving /api/* for\n * the six query primitives plus views/system, and the built React SPA with\n * hashed assets and SPA fallback. Never an app, never a server — the host\n * mounts it.\n *\n * Access control is the named inbound adapter: viewerAdapter.resolveViewer.\n * The router refuses to CONSTRUCT without it — an unauthenticated telemetry\n * dashboard is a data leak with charts.\n */\n\nexport interface Viewer {\n /**\n * The read scope: a tenantId, or PLATFORM_SCOPE (`'*'`) for a cross-tenant\n * read — a support console, a platform-wide cost page.\n *\n * `'*'` is an authorization decision, and it is the HOST's to make. The\n * package never infers platform admin from a role, a header, or a config\n * flag; it only makes the escape hatch expressible, so that a host needing a\n * cross-tenant read says so through this adapter instead of reaching around\n * `scoped()` with a raw model. Return `'*'` only for viewers you have already\n * authorized. `'*'` is reserved on the write side, so no stored row carries\n * it and no tenant can ever be named it.\n */\n tenantId: string;\n /** 'admin' unlocks System writes (key revoke); anything else is read-only there */\n role: string;\n /** who this person is — owns saved views; e.g. 'user:u_1' */\n viewerRef?: string;\n}\n\nexport interface ViewerAdapter {\n resolveViewer(req: Request): Viewer | null | Promise<Viewer | null>;\n}\n\nexport interface SubjectAdapter {\n /** pretty labels for subject refs; absent refs render raw */\n describe(refs: string[]): Promise<Record<string, { label: string; href?: string }>>;\n}\n\nexport interface CreateDashboardOptions {\n telemetry: Telemetry;\n viewerAdapter: ViewerAdapter;\n subjectAdapter?: SubjectAdapter;\n /** configured views — versioned in host code (dashboards §3) */\n views?: ViewSpec[];\n queryLimits?: Partial<QueryLimits>;\n onSlowQuery?: (info: { op: string; ms: number; params: unknown }) => void;\n /** threshold onSlowQuery fires above, ms. Default 500. Forwarded to createQueries. */\n slowMs?: number;\n /** in-process query cache TTL, ms. Default 600_000. Forwarded to createQueries. */\n cacheTtlMs?: number;\n /** cached query results kept before eviction. Default 60. Forwarded to createQueries. */\n cacheSize?: number;\n /** where the browser sees this router mounted — MUST match (traps #8) */\n mountPath?: string;\n /** where the SPA calls /api — defaults to mountPath */\n apiBase?: string;\n title?: string;\n spaDir?: string;\n}\n\nconst here = path.dirname(fileURLToPath(import.meta.url));\n\n// Published builds run from dist/index.js, so the UI bundle sits alongside at\n// dist/ui; running from source it is two levels up. Pick whichever exists —\n// a build flag gets one of the two cases wrong (traps #7).\nconst SPA_DIR_CANDIDATES = ['./ui', '../../dist/ui'];\n\nexport function defaultSpaDir(): string {\n for (const candidate of SPA_DIR_CANDIDATES) {\n const dir = path.resolve(here, candidate);\n if (fs.existsSync(path.join(dir, 'index.html'))) return dir;\n }\n return path.resolve(here, SPA_DIR_CANDIDATES[SPA_DIR_CANDIDATES.length - 1]!);\n}\n\nfunction escapeJson(value: unknown): string {\n // `</script>` inside injected JSON would close the tag early — escape at `<`\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n}\n\nconst parseRange = (q: Record<string, unknown>): TimeRange => {\n const to = q.to ? new Date(String(q.to)) : new Date();\n const from = q.from\n ? new Date(String(q.from))\n : new Date(to.getTime() - 7 * 864e5);\n if (Number.isNaN(from.getTime()) || Number.isNaN(to.getTime()) || from >= to) {\n throw Object.assign(new Error('invalid time range'), { status: 400 });\n }\n return { from, to };\n};\n\nconst parseFilter = (q: Record<string, unknown>): RecordFilter => {\n const f: RecordFilter = {};\n for (const k of ['kind', 'name', 'severity', 'env', 'service', 'release', 'subject', 'traceId'] as const) {\n if (typeof q[k] === 'string' && q[k]) (f as any)[k] = q[k];\n }\n // `name=a,b` is the name-SET term — a namespace or a rollup family is several\n // event names, and reading them as one `$in` is what makes that read exact\n // instead of \"every record of that kind\". Names never contain a comma\n // (validateRegistry), so the split is unambiguous, and one name stays a\n // string so every URL that exists keeps its shape.\n if (typeof q.name === 'string' && q.name.includes(',')) {\n const names = q.name.split(',').map((s) => s.trim()).filter(Boolean);\n if (names.length) f.name = names.length === 1 ? names[0] : names;\n }\n if (typeof q.attrs === 'string' && q.attrs) {\n // attrs=format:pdf,route:/reports\n f.attrs = Object.fromEntries(\n String(q.attrs)\n .split(',')\n .map((p) => p.split(':'))\n .filter((p) => p.length >= 2)\n .map(([k, ...v]) => [k!, v.join(':')]),\n );\n }\n if (typeof q.metrics === 'string' && q.metrics) {\n // metrics=cost_usd>0.5,tokens_in<100\n f.metrics = {};\n for (const term of String(q.metrics).split(',')) {\n const m = /^([\\w.]+)([<>])(-?[\\d.]+)$/.exec(term);\n if (m) f.metrics[m[1]!] = m[2] === '>' ? { gte: Number(m[3]) } : { lte: Number(m[3]) };\n }\n }\n if (typeof q.excludeActors === 'string' && q.excludeActors) {\n f.excludeActorTypes = String(q.excludeActors).split(',').filter(Boolean);\n }\n return f;\n};\n\n/** the fields `rollups()` will range-filter on — an allowlist, not a passthrough */\nconst ROLLUP_ON = ['firstAt', 'lastAt', 'bucketAt'] as const;\n\n/** the fields `rollups()` will ORDER by — an allowlist for the same reason */\nconst ROLLUP_SORT = ['count', 'lastAt', 'firstAt', 'bucketAt'] as const;\n\n/** an `$in` from a URL is still a scan, so the repeated-param form is bounded */\nconst MAX_DIMS = 100;\n\n/**\n * `?dims=user:u_1&dims=user:u_2` — the repeated-param form express already\n * parses into an array — is the multi-subject read. One value stays a string,\n * so the single-dim URLs that exist keep working unchanged.\n *\n * Validated rather than coerced: more than MAX_DIMS values, or a nested value\n * where a string belongs (`?dims[0][k]=v` under the extended parser), is a 400\n * rather than a silently narrowed `$in`. Silently dropping half a cohort is the\n * failure the array form exists to prevent, so it must not be reintroduced by\n * the parser that reads it.\n */\nconst parseDims = (v: unknown): string | string[] | undefined => {\n if (typeof v === 'string') return v || undefined;\n if (!Array.isArray(v)) return undefined;\n if (v.length > MAX_DIMS) {\n throw Object.assign(new Error(`at most ${MAX_DIMS} dims values`), { status: 400 });\n }\n if (!v.every((d) => typeof d === 'string' && d)) {\n throw Object.assign(new Error('dims must be non-empty strings'), { status: 400 });\n }\n return v.length ? (v as string[]) : undefined;\n};\n\nexport function createDashboard(opts: CreateDashboardOptions): Router {\n const { telemetry: t, viewerAdapter, subjectAdapter, views: configured = [] } = opts;\n if (!viewerAdapter?.resolveViewer) {\n throw new Error(\n 'telemetry: createDashboard requires a viewerAdapter — an unauthenticated telemetry dashboard is a data leak with charts',\n );\n }\n\n const mountPath = opts.mountPath ?? '/telemetry';\n const apiBase = opts.apiBase ?? mountPath;\n const title = opts.title ?? 'Telemetry';\n const spaDir = opts.spaDir ?? defaultSpaDir();\n\n const conn = t.models.telemetry.db!;\n const ViewModel = buildViewModel(\n conn as any,\n `${t.models.telemetry.modelName}View`,\n `${t.models.telemetry.collection.collectionName}_views`,\n );\n\n const q = createQueries({\n TelemetryModel: t.models.telemetry,\n RollupModel: t.models.rollups,\n registry: t.registry,\n limits: opts.queryLimits,\n onSlowQuery: opts.onSlowQuery,\n // forwarded, not re-defaulted — an onSlowQuery pinned at the 500ms default\n // is a callback the host cannot aim\n slowMs: opts.slowMs,\n cacheTtlMs: opts.cacheTtlMs,\n cacheSize: opts.cacheSize,\n });\n\n // Derived once, here, for the same reason validateRegistry runs at boot: if\n // the catalog cannot be built the registry is wrong, and a request is the\n // wrong place to find that out. The `client.platform` enum is per instance\n // (CreateTelemetryConfig.platforms extends the builtin list) and the\n // Telemetry handle does not carry it, so it is read back off the compiled\n // schema — the same closed domain the writer enforces.\n const catalog = deriveCatalog(t.registry, {\n platforms: (t.models.telemetry.schema.path('client') as any)?.schema?.path('platform')?.enumValues,\n });\n const registry = projectRegistry(catalog);\n\n // the observed domain of a dimension (reports §5). Built here rather than\n // inside createQueries because it reads the CATALOG — it is the lookup the\n // report builder makes before it names a value, not a tenth primitive.\n const values = createValues({\n catalog,\n TelemetryModel: t.models.telemetry,\n RollupModel: t.models.rollups,\n limits: opts.queryLimits,\n onSlowQuery: opts.onSlowQuery,\n slowMs: opts.slowMs,\n cacheTtlMs: opts.cacheTtlMs,\n cacheSize: opts.cacheSize,\n });\n\n const api = express.Router();\n api.use(express.json({ limit: '64kb' }));\n\n // ── the gate ──\n api.use(async (req: Request & { viewer?: Viewer }, res, next) => {\n try {\n const viewer = await viewerAdapter.resolveViewer(req);\n if (!viewer?.tenantId) return res.status(401).json({ error: 'unauthenticated' });\n req.viewer = viewer;\n next();\n } catch (e) {\n next(e);\n }\n });\n\n const h =\n (fn: (req: Request & { viewer?: Viewer }, res: Response) => Promise<unknown>) =>\n (req: Request, res: Response, next: NextFunction) => {\n fn(req as any, res).then((body) => {\n if (!res.headersSent) res.json(body);\n }, next);\n };\n\n // the SPA's one boot call — it learns its scope here, because a cross-tenant\n // number that cannot say which tenant it came from is unusable\n api.get('/registry', h(async (req) => ({\n registry,\n catalog,\n kinds: ['event', 'error', 'span', 'state', 'usage'],\n role: req.viewer!.role,\n scope: req.viewer!.tenantId,\n platform: isPlatformScope(req.viewer!.tenantId),\n })));\n\n api.get('/records', h(async (req) => {\n const page = await q.records(req.viewer!.tenantId, parseRange(req.query), parseFilter(req.query), {\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n cursor: typeof req.query.cursor === 'string' ? req.query.cursor : undefined,\n });\n // Error frames are translated here, at read, against whatever map is\n // registered for the record's release — see sourcemaps.ts. A copy: the\n // query layer's cached page is never mutated.\n if (!t.sourcemaps || !page?.items?.some((r: any) => r?.kind === 'error')) return page;\n return { ...page, items: await Promise.all(page.items.map((r: any) => t.sourcemaps.symbolicate(r))) };\n }));\n\n api.get('/series', h(async (req) =>\n q.series(req.viewer!.tenantId, parseRange(req.query), parseFilter(req.query), {\n measure: typeof req.query.measure === 'string' ? req.query.measure : undefined,\n interval: (req.query.interval as any) || undefined,\n }),\n ));\n\n api.get('/distribution', h(async (req) =>\n q.distribution(req.viewer!.tenantId, parseRange(req.query), parseFilter(req.query), {\n measure: typeof req.query.measure === 'string' ? req.query.measure : undefined,\n }),\n ));\n\n /**\n * `?groupBy=attr:model,field:client.platform` — comma-separated so a\n * breakdown stays a URL, like the funnel's `stages`. The primitive owns the\n * vocabulary: an unknown dim, a refused path, three dims or a bad interval\n * all throw with `status: 400` and their own message, which the error\n * middleware surfaces verbatim rather than flattening into 'bad_request'.\n */\n api.get('/breakdown', h(async (req) =>\n q.breakdown(req.viewer!.tenantId, parseRange(req.query), parseFilter(req.query), {\n groupBy: String(req.query.groupBy ?? '').split(',').map((s) => s.trim()).filter(Boolean),\n measure: typeof req.query.measure === 'string' ? req.query.measure : undefined,\n interval: (req.query.interval as any) || undefined,\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n }),\n ));\n\n api.get('/rollups', h(async (req) => {\n if (typeof req.query.as !== 'string' || !req.query.as) {\n throw Object.assign(new Error('rollup family required'), { status: 400 });\n }\n // an unrecognised `on` would range-filter on a field that does not exist and\n // return an empty family — a 400 says so instead\n const on = req.query.on;\n if (on !== undefined && !ROLLUP_ON.includes(on as any)) {\n throw Object.assign(new Error(`on must be one of ${ROLLUP_ON.join(', ')}`), { status: 400 });\n }\n // `sort` reaches Mongo's .sort() — an unvalidated passthrough lets a caller\n // order by an unindexed field and turn a bounded read into a blocking\n // in-memory sort. Same hole `on` had, same allowlist.\n const sort = req.query.sort;\n if (sort !== undefined && !ROLLUP_SORT.includes(sort as any)) {\n throw Object.assign(new Error(`sort must be one of ${ROLLUP_SORT.join(', ')}`), { status: 400 });\n }\n return q.rollups(req.viewer!.tenantId, {\n as: req.query.as,\n dims: parseDims(req.query.dims),\n subjectType: typeof req.query.subjectType === 'string' ? req.query.subjectType : undefined,\n // cohort selection wants firstAt; the default is still bucketAt when\n // bucketed, lastAt otherwise — see query.ts\n on: on as (typeof ROLLUP_ON)[number] | undefined,\n range: req.query.from || req.query.to ? parseRange(req.query) : undefined,\n sort: sort as (typeof ROLLUP_SORT)[number] | undefined,\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n });\n }));\n\n api.get('/trace/:traceId', h(async (req) => q.trace(req.viewer!.tenantId, String(req.params.traceId))));\n\n api.get('/journey/:ref', h(async (req) =>\n q.journey(req.viewer!.tenantId, String(req.params.ref), parseRange(req.query), {\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n }),\n ));\n\n /**\n * A cohort primitive throws when the named family cannot answer the question\n * asked of it — a registry mistake, which is a 400 with the explanation, not\n * a 500 that hides it. `status` already set (parseRange's 400) is respected.\n */\n const badRequest = async <T>(run: () => Promise<T>): Promise<T> => {\n try {\n return await run();\n } catch (e: any) {\n throw Object.assign(e, { status: e?.status ?? 400 });\n }\n };\n\n // ── the two cohort primitives (cohort-math S6/S8) ──\n // Stages arrive as a comma-separated family list so a funnel stays a URL —\n // `?stages=signed_up,activated,converted`. A view is a named URL (dashboards\n // §11.6); a funnel that needed a POST body could not be one.\n api.get('/funnel', h(async (req) => {\n const parseStages = (v: unknown) =>\n String(v ?? '').split(',').map((s) => s.trim()).filter(Boolean).map((as) => ({ as }));\n const stages = parseStages(req.query.stages);\n if (!stages.length) {\n throw Object.assign(new Error('funnel needs `stages` — a comma-separated list of rollup families'), { status: 400 });\n }\n // a registry mistake is the caller's to fix, not a 500 — the validator's\n // message names the family and the change, so surface it verbatim\n return badRequest(() => q.funnel(req.viewer!.tenantId, {\n stages,\n exits: parseStages(req.query.exits),\n anchor: typeof req.query.anchor === 'string' ? req.query.anchor : undefined,\n // the cohort window is the shell's own range, half-open like everything else\n cohort: { ...parseRange(req.query), endInclusive: req.query.endInclusive === 'true' },\n subjectType: typeof req.query.subjectType === 'string' ? req.query.subjectType : undefined,\n interval: (req.query.interval as any) || undefined,\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n }));\n }));\n\n api.get('/distinct', h(async (req) => {\n if (typeof req.query.as !== 'string' || !req.query.as) {\n throw Object.assign(new Error('rollup family required'), { status: 400 });\n }\n return badRequest(() => q.distinctCount(req.viewer!.tenantId, {\n as: req.query.as as string,\n subjectType: typeof req.query.subjectType === 'string' ? req.query.subjectType : undefined,\n range: parseRange(req.query),\n interval: (req.query.interval as any) || undefined,\n }));\n }));\n\n /**\n * The observed domain of one dimension — what turns the FilterBar's\n * `window.prompt` into a picker (reports §5). `names` is the Report's source\n * events, comma-separated so this stays a URL like everything else.\n *\n * The range is OPTIONAL here, unlike every raw-reading route: a dim the\n * catalog or the rollups can answer needs no window, and a dim that would\n * need one answers `source: 'none'` rather than 400 — the caller's fallback\n * is a text box, not an error.\n */\n api.get('/values', h(async (req) => {\n const dim = typeof req.query.dim === 'string' ? req.query.dim.trim() : '';\n if (!dim) {\n throw Object.assign(new Error('dim required'), { status: 400 });\n }\n const names = String(req.query.names ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n return values(req.viewer!.tenantId, {\n dim,\n names: names.length ? names : undefined,\n range: req.query.from || req.query.to ? parseRange(req.query) : undefined,\n limit: req.query.limit ? Number(req.query.limit) : undefined,\n });\n }));\n\n api.get('/subjects/describe', h(async (req) => {\n const refs = String(req.query.refs ?? '').split(',').filter(Boolean).slice(0, 100);\n if (!subjectAdapter) return { refs: {} }; // refs render raw — the documented fallback\n return { refs: await subjectAdapter.describe(refs) };\n }));\n\n /**\n * ── the Report, over HTTP (reports §4, §6) ──\n *\n * A Report IS this URL: `?source=event:llm.completion&range=7d&measure=sum:cost_usd\n * &groupBy=attr:gen_ai_request_model&filter=attr:feature:eq:chat`. One route\n * behind every chart, because the resolver picks the primitive — so the SPA\n * stops choosing an endpoint per page and asks the question instead.\n * `parseReportQuery`/`reportToQuery` are inverses and util.js speaks the same\n * grammar, which is what keeps a shared link and a saved view the same thing.\n */\n api.get('/report', h(async (req) =>\n badRequest(() =>\n executeReport(q, req.viewer!.tenantId, parseReportQuery(req.query as Record<string, unknown>), catalog),\n ),\n ));\n\n /**\n * The dry run. Same URL, no read: it answers `Plan | Unavailable` with a 200,\n * because a refusal is an ANSWER here — the UI greys the option and shows the\n * `why`, and an agent learns the cost of a question before paying it. (An\n * Unavailable on `/report` itself IS a 400: by then the caller asked for\n * data.) A malformed URL is still a 400 either way.\n */\n api.get('/report/plan', h(async (req) =>\n badRequest(async () =>\n resolveReport(parseReportQuery(req.query as Record<string, unknown>), catalog),\n ),\n ));\n\n // ── views: one shape, three producers ──\n api.get('/views', h(async (req) => ({\n views: await resolveViews({\n ViewModel,\n registry: t.registry,\n catalog,\n configured,\n tenantId: req.viewer!.tenantId,\n viewerRef: req.viewer!.viewerRef,\n }),\n })));\n\n api.post('/views', h(async (req) => {\n const { spec, shared = false } = (req.body ?? {}) as { spec?: ViewSpec; shared?: boolean };\n if (!spec?.name || !spec?.page || typeof spec.query !== 'object') {\n throw Object.assign(new Error('view spec required'), { status: 400 });\n }\n return saveView({\n ViewModel,\n tenantId: req.viewer!.tenantId,\n viewerRef: req.viewer!.viewerRef,\n spec,\n shared: !!shared,\n });\n }));\n\n api.delete('/views/:id', h(async (req, res) => {\n // LITERAL scope match, '*' included — see views.ts. The platform scope\n // reads telemetry across tenants; it does not own other people's saved\n // views, and `role: 'admin'` below is admin OF this scope. A view outside\n // the caller's scope reports removed:0 rather than 403: whether that id\n // exists elsewhere is not this viewer's business either.\n const doc = await ViewModel.findOne({ _id: req.params.id, tenantId: req.viewer!.tenantId }).lean() as any;\n if (!doc) return { removed: 0 };\n const mine = doc.ownerRef && doc.ownerRef === req.viewer!.viewerRef;\n if (!mine && req.viewer!.role !== 'admin') {\n res.status(403).json({ error: 'forbidden' });\n return undefined as never;\n }\n await ViewModel.deleteOne({ _id: doc._id });\n return { removed: 1 };\n }));\n\n // ── System — where \"never drop silently\" becomes visible. Not optional. ──\n api.get('/system', h(async (req) => {\n // Quarantined rejects hold RAW payloads — subjects, attrs, the lot. An\n // unfiltered find() here handed every tenant's failed writes to any\n // authenticated viewer, which is the same leak the query primitives are\n // scoped to prevent, reached by a route that never went through them.\n // Scoped like everything else; '*' still sees all, by authorization.\n const quarantine = await t.collections.rejects()\n .find(\n isPlatformScope(req.viewer!.tenantId) ? {} : { 'raw.tenantId': req.viewer!.tenantId },\n { sort: { at: -1 }, limit: 50 } as any,\n )\n .toArray()\n .catch(() => []);\n const indexes = await t.models.telemetry.collection.indexes().catch(() => []);\n const keys = req.viewer!.role === 'admin'\n ? await t.models.keys.find({}, { secretHash: 0 }).sort({ createdAt: -1 }).limit(100).lean()\n : [];\n return {\n counters: t.counters,\n quarantine,\n indexCount: indexes.length,\n indexBudget: INDEX_BUDGET,\n keys,\n role: req.viewer!.role,\n // The same three sources, read the other way round: what the data says\n // the registry is missing, each with the line that would fix it. Derived\n // from the counters and the quarantine ALREADY fetched above, so the\n // page costs no extra read. Nothing is written — the host still edits\n // the registry by hand (reports §9).\n suggestions: deriveSuggestions({ counters: t.counters, catalog, quarantine }),\n };\n }));\n\n api.post('/system/keys/:id/revoke', h(async (req, res) => {\n if (req.viewer!.role !== 'admin') {\n res.status(403).json({ error: 'forbidden' });\n return undefined as never;\n }\n const r = await t.models.keys.updateOne(\n { _id: req.params.id, revokedAt: null },\n { $set: { revokedAt: new Date() } },\n );\n return { revoked: r.modifiedCount ?? 0 };\n }));\n\n // JSON errors, never an HTML stack page — the template's smoke contract\n api.use((err: any, _req: Request, res: Response, _next: NextFunction) => {\n const status = err?.status ?? 500;\n if (status >= 500) t.logger.error('[telemetry:dashboard]', err);\n res.status(status).json({ error: status >= 500 ? 'internal_error' : String(err?.message ?? 'bad_request') });\n });\n\n // ── the router: /api/* + SPA with hashed assets + fallback ──\n const router = express.Router();\n router.use('/api', api);\n\n router.use('/_assets', express.static(path.join(spaDir, '_assets'), {\n maxAge: '1y',\n immutable: true,\n index: false,\n }));\n\n const base = `${mountPath.replace(/\\/$/, '')}/`;\n router.get(/.*/, (_req, res) => {\n let html: string;\n try {\n html = fs.readFileSync(path.join(spaDir, 'index.html'), 'utf8');\n } catch {\n return res.status(503).type('text/plain').send(\n 'telemetry: UI bundle not found. Run `npm run build` in the package, or pass an explicit `spaDir`.',\n );\n }\n const config = escapeJson({ apiBase: `${apiBase.replace(/\\/$/, '')}/api`, mountPath, title });\n // the shell must never cache — a heuristically-cached index.html keeps\n // referencing dead hashed assets across deploys. Assets cache hard instead.\n res.setHeader('Cache-Control', 'no-store');\n res.type('html').send(\n html.replace(\n '<!--telemetry-config-->',\n `<base href=\"${base}\" />\\n <script>window.__TELEMETRY__=${config}</script>`,\n ),\n );\n });\n\n return router;\n}\n","import type { Collection, Connection } from 'mongoose';\nimport { RETENTION_DAYS, newCounters, noopLogger, type EntityRef, type Logger } from './types.js';\nimport { validateRegistry, type Registry } from './registry.js';\nimport { buildTelemetryModels } from './model.js';\nimport { buildRollupModel } from './rollups.js';\nimport { buildCheckpointModel, createCheckpointFactory } from './checkpoint.js';\nimport { createEmitter, createSubjectLinking, type EmitInput, type SubjectLinker } from './emit.js';\nimport { createForget } from './forget.js';\nimport { createRelink } from './relink.js';\nimport { createSyncIndexes } from './indexes.js';\nimport { createSourcemaps } from './sourcemaps.js';\nimport { buildKeyModel, createKey, type CreateKeyInput } from './keys.js';\n\nexport { defineRegistry, boundedMeta, validateRegistry } from './registry.js';\nexport type { Registry, EventSpec, RollupSpec, DimSource } from './registry.js';\nexport {\n TelemetryKind, LogLevel, Env, Origin,\n BODY_MAX_CHARS, COUNTER_MAP_MAX, COUNTER_OVERFLOW_KEY, PLATFORM_SCOPE, RETENTION_DAYS,\n SAMPLE_RATE, SCHEMA_VERSION,\n isPlatformScope, newId, traceKeep, plain,\n} from './types.js';\nexport type { TelemetryCounters, Logger, EntityRef, ValidationPolicy } from './types.js';\nimport type { ValidationPolicy } from './types.js';\nexport { INDEX_BUDGET } from './indexes.js';\nexport { truncate, resolveDim } from './rollups.js';\nexport type { ForgetResult } from './forget.js';\nexport { RELINK_BATCH_SIZE } from './relink.js';\nexport type { RelinkOptions, RelinkResult } from './relink.js';\nexport type { Checkpoint } from './checkpoint.js';\nexport { SUBJECT_MAX, SUBJECT_LINK_TIMEOUT_MS } from './emit.js';\nexport type { EmitInput, EmitResult, LinkSubjects, SubjectLinker } from './emit.js';\nexport { KeyKind, TenantMode, parseKeyString, hashSecret, verifySecret, createKey } from './keys.js';\nexport type { CreateKeyInput, ParsedKey } from './keys.js';\nexport { createIngest } from './ingest.js';\nexport type { ContextAdapter, CreateIngestOptions, IngestContext } from './ingest.js';\nexport { createDashboard, defaultSpaDir } from './dashboard.js';\nexport type {\n CreateDashboardOptions, SubjectAdapter, Viewer, ViewerAdapter,\n} from './dashboard.js';\nexport { deriveCatalog, projectRegistry } from './catalog.js';\nexport type {\n Catalog, DeriveCatalogOptions, DimFacet, EventFacet, FamilyFacet, MeasureFacet,\n RegistryProjection, RegistryProjectionEntry,\n} from './catalog.js';\nexport { deriveSuggestions, MAX_SUGGESTIONS } from './suggest.js';\nexport type { DeriveSuggestionsInput, Suggestion } from './suggest.js';\nexport { createQueries, DEFAULT_LIMITS } from './query.js';\nexport type { Queries, QueryLimits, RecordFilter, TimeRange } from './query.js';\nexport { createValues } from './values.js';\nexport type { Values, ValuesCtx, ValuesParams, ValuesResult } from './values.js';\nexport { median, summarizeStages, findFamily, requireMilestoneFamily } from './funnel.js';\nexport type {\n CohortSubject, FunnelCohortWindow, FunnelExitResult, FunnelParams,\n FunnelResult, FunnelSlice, FunnelStageResult, FunnelStageSpec,\n} from './funnel.js';\nexport { deriveViews } from './views.js';\nexport type { ResolvedView, ViewSpec } from './views.js';\nexport {\n intervalForRange, normalizeQuery, parseReportQuery, rangeOf, reportToQuery, resolveReport,\n} from './report.js';\nexport type {\n LegacyQuery, Plan, PlanPrimitive, PlanShape, Report, ReportFilter, ReportRange,\n ReportSource, ResolveOptions, Unavailable,\n} from './report.js';\nexport { executeReport, foldRollups } from './execute.js';\nexport type { ExecuteOptions, FoldedRollups, ReportResult, RollupDoc } from './execute.js';\n\nexport interface CreateTelemetryConfig {\n /** the host-owned event registry — see defineRegistry() */\n registry: Registry;\n /** a mongoose Connection, or the mongoose module itself (its default connection is used) */\n connection: Connection | { connection: Connection };\n /** base collection name; six siblings derive from it: `<collection>_rollups`,\n * `_rejects`, `_aliases`, `_checkpoints`, `_keys`, `_views` */\n collection?: string;\n /**\n * Mongoose model name. Set it when two instances share one connection —\n * a reused name silently reuses the FIRST instance's registry (traps #2).\n */\n modelName?: string;\n /** secret pepper for forget()'s pseudonymous rekeying. Falls back to TELEMETRY_PEPPER. */\n pepper?: string;\n /**\n * Host additions to `client.platform`. EXTENDS the builtin list\n * ['web','electron','ios','android','server','cli'] — a host adding 'watchos'\n * keeps 'web'.\n */\n platforms?: readonly string[];\n /** override BODY_MAX_CHARS for this instance */\n bodyMax?: number;\n /**\n * What a vocabulary mismatch costs. Default `'lenient'`: an attr or metric\n * the registry does not accept is stripped, counted by name in\n * `counters.attrsDropped` / `counters.metricsDropped`, and the record is\n * written. `'strict'` restores the pre-0.7.0 behaviour of quarantining the\n * whole record. See ValidationPolicy in types.ts for why the default moved.\n */\n validation?: ValidationPolicy;\n /**\n * Declares that a subject ref (`type:id`) names the same party in EVERY\n * tenant. The package cannot verify that, so it is asserted rather than\n * detected. Only effect today: forget() also erases the person's\n * platform-scoped saved views, which a tenant-scoped call otherwise misses.\n * Leave it off when ids are minted per tenant — there, `user:u_1` is a\n * different person in each and one tenant's erasure would reach another's.\n */\n globalSubjectRefs?: boolean;\n /**\n * Attach additional subjects to a record AT WRITE TIME — the desktop\n * `machine:<installId>` that the host can resolve to a `user`, joined once,\n * onto the row and its rollups, instead of at every read that ever wants it.\n *\n * See SubjectLinker in emit.ts for what it must not do. In one line: it must\n * be cached, because it runs once per record on the ingest path, and it can\n * never fail a write — a slow or broken linker costs records their link, not\n * their existence.\n */\n subjectLinker?: SubjectLinker;\n /**\n * What `subjectLinker.link()` gets per record before the write proceeds\n * UNLINKED and counts a timeout. Default 50ms. Raise it only if you have\n * measured the resolver; the default is chosen so a host outage degrades\n * telemetry rather than stalling ingest behind it.\n */\n subjectLinkTimeoutMs?: number;\n logger?: Logger;\n}\n\n/**\n * The package factory. Returns the write path, erasure, tenant-scoped reads,\n * and the checkpoint primitive. Routers (ingest, dashboard) are separate\n * factories that take this instance — they never build their own storage.\n *\n * const t = createTelemetry({ registry, connection: mongoose })\n * await t.syncIndexes() // boot: indexes + TTLs, awaited before first write\n * await t.emit('user.signed_up', { tenantId, subjects: [...], attrs: {...} })\n */\nexport function createTelemetry(config: CreateTelemetryConfig) {\n const {\n registry,\n collection = 'telemetry',\n modelName = 'Telemetry',\n logger = noopLogger,\n } = config;\n\n // boot-time contract checks — misconfiguration fails deploy, not dashboards\n validateRegistry(registry);\n\n // A spec declaring `data` and no retentionDays inherits RETENTION_DAYS[kind],\n // so evidence a host went out of its way to declare gets a fuse nobody chose\n // — and `expiresAt` is stamped per row at WRITE time, so it is unrecoverable\n // after the fact. Warn once at boot. An explicit retentionDays (including\n // `null` for immortal) is a choice and silences this; the warning is about\n // the host not having made one.\n for (const [name, spec] of Object.entries(registry)) {\n if (!spec.data) continue;\n if (Object.prototype.hasOwnProperty.call(spec, 'retentionDays')) continue;\n const days = RETENTION_DAYS[spec.kind];\n if (days == null) continue;\n logger.warn(\n `[telemetry] \"${name}\" declares \\`data\\` but inherits retentionDays=${days} from kind=${spec.kind} — ` +\n `its payloads are stamped to expire in ${days} days, and that cannot be undone after the write. ` +\n `Set an explicit retentionDays (null = immortal) to choose, and to silence this.`,\n );\n }\n\n const conn: Connection =\n (config.connection as { connection: Connection }).connection ??\n (config.connection as Connection);\n\n const counters = newCounters();\n const { TelemetryModel, byKind } = buildTelemetryModels({\n connection: conn, registry, counters, modelName, collection,\n platforms: config.platforms, bodyMax: config.bodyMax, validation: config.validation,\n });\n const RollupModel = buildRollupModel(conn, `${modelName}Rollup`, `${collection}_rollups`);\n const CheckpointModel = buildCheckpointModel(conn, `${modelName}Checkpoint`, `${collection}_checkpoints`);\n const KeyModel = buildKeyModel(conn, `${modelName}Key`, `${collection}_keys`);\n\n const rejects = () => conn.db!.collection(`${collection}_rejects`);\n const aliases = () => conn.db!.collection(`${collection}_aliases`);\n const views = () => conn.db!.collection(`${collection}_views`);\n\n // fire-and-forget writes are tracked so flush() can await stragglers —\n // tests and SIGTERM handlers both need \"everything emitted is queryable\"\n const inFlight = new Set<Promise<unknown>>();\n const track = (p: Promise<unknown>) => {\n inFlight.add(p);\n void p.finally(() => inFlight.delete(p));\n };\n\n // Resolved ONCE, and shared with the ingest router below rather than built\n // twice: the linker is a policy (dedupe, the declared-type refusal, the cap,\n // the timeout), and a policy that exists in two places is two policies.\n const linkSubjects = createSubjectLinking({\n linker: config.subjectLinker,\n timeoutMs: config.subjectLinkTimeoutMs,\n counters,\n logger,\n });\n\n const emit = createEmitter({\n registry, byKind, RollupModel, rejects, counters, logger, track, linkSubjects,\n });\n\n const forget = createForget({\n TelemetryModel,\n RollupModel,\n rejects: rejects as () => Collection,\n aliases: aliases as () => Collection,\n views: views as () => Collection,\n pepper: () => {\n const p = config.pepper ?? process.env.TELEMETRY_PEPPER;\n if (!p) {\n throw new Error(\n 'telemetry: forget() needs a pepper — pass `pepper` to createTelemetry() or set TELEMETRY_PEPPER',\n );\n }\n return p;\n },\n globalSubjectRefs: () => config.globalSubjectRefs === true,\n });\n\n // The BACKFILL half of subject linking, and it takes the same `linkSubjects`\n // the write path uses rather than a merge of its own — see relink.ts for why\n // a second copy of those rules would be unreconcilable rather than merely\n // duplicated.\n const relink = createRelink({\n registry, TelemetryModel, RollupModel, counters, logger, linkSubjects,\n });\n\n const syncModelIndexes = createSyncIndexes({\n registry,\n TelemetryModel,\n models: [TelemetryModel, ...Object.values(byKind), RollupModel, CheckpointModel, KeyModel],\n rejects: rejects as () => Collection,\n });\n\n const sourcemaps = createSourcemaps({ connection: conn, collection: `${collection}_sourcemaps`, logger });\n\n const syncIndexes: typeof syncModelIndexes = async (...args) => {\n const result = await syncModelIndexes(...args);\n await sourcemaps.ensureIndexes();\n return result;\n };\n\n return {\n /** write — the only write */\n emit,\n /** erasure: delete sole-party rows, redact shared ones, rekey rollups, drop aliases */\n forget,\n /**\n * Backfill: re-ask the `subjectLinker` about records ALREADY on disk, and\n * replay the rollups the new subjects reach.\n *\n * Linking happens at write time, so configuring it fixes the future and\n * nothing else — a lifetime `by:['subject']` family is keyed on the subject\n * the record was written with, and a read-time join cannot reach back into\n * it. This is how a host catches up the backlog it adopted the hook with.\n *\n * DRY RUN BY DEFAULT: it rewrites historical aggregates, so the short call\n * reports and the writing call says `{ dryRun: false }`. Idempotent by\n * construction — a row that already carries the linked subject yields\n * nothing new, so a second run is a no-op.\n */\n relink,\n /**\n * Tenant scope is not optional — force every read through here. The five\n * dashboard query primitives (records/series/distribution/rollups/journey)\n * build on these in the read layer.\n *\n * scoped() does NOT know about PLATFORM_SCOPE, and the omission is\n * deliberate. This is the host-facing isolation primitive, and its\n * guarantee is worth more unconditional: whatever string goes in, only rows\n * carrying that string come out. `scoped('*')` therefore scopes to the\n * literal '*' — and since '*' is reserved on the write side, it matches\n * nothing. The cross-tenant escape hatch lives one layer up, in the query\n * primitives behind viewerAdapter, where an authorization decision has\n * actually been made about who is asking.\n */\n scoped(tenantId: string) {\n // the pin spreads LAST — `{ tenantId, ...q }` would let a caller-supplied\n // tenantId in q override the scope, the exact hole scoped() exists to close\n return {\n find: (q: Record<string, unknown> = {}) => TelemetryModel.find({ ...q, tenantId }),\n aggregate: (stages: Record<string, unknown>[]) =>\n TelemetryModel.aggregate([{ $match: { tenantId } }, ...stages] as any[]),\n rollups: (q: Record<string, unknown> = {}) => RollupModel.find({ ...q, tenantId }),\n rollupAggregate: (stages: Record<string, unknown>[]) =>\n RollupModel.aggregate([{ $match: { tenantId } }, ...stages] as any[]),\n };\n },\n /** pull-importer watermark — advisory; downstream writers must be idempotent */\n checkpoint: createCheckpointFactory(CheckpointModel, logger),\n /** boot: build declared + registry-driven indexes, await before first write */\n syncIndexes,\n /** await in-flight fire-and-forget writes (tests, graceful shutdown) */\n async flush() {\n while (inFlight.size) await Promise.allSettled([...inFlight]);\n },\n /** drop/default/cap counts — surface on /metrics so drops are never silent */\n counters,\n /** the registry, exposed for the router factories — hosts should import their own */\n registry,\n /**\n * Write-time subject linking, exposed for the router factories. `null` when\n * no `subjectLinker` is configured.\n *\n * The wire path does not go through emit() — createIngest() builds its\n * record itself, because at-least-once delivery inverts the plane order\n * (insert first, THEN aggregate). So it reaches the linker the same way it\n * reaches the registry and the models: off the instance, running the one\n * implementation, rather than growing a second copy of the rules.\n */\n linkSubjects,\n logger,\n /**\n * Sourcemaps for minified clients. `register()` stores a release's maps\n * (server-side only — there is no HTTP route); the dashboard translates\n * error frames against them at read time, so errors recorded before the\n * maps were registered are translated too. See sourcemaps.ts.\n */\n sourcemaps,\n /** mint an ingest key; the full key string is returned once, never again */\n createKey: (input: CreateKeyInput) => createKey(KeyModel, input),\n /** the models, exposed for hosts and the router factories */\n models: {\n telemetry: TelemetryModel,\n byKind,\n rollups: RollupModel,\n checkpoints: CheckpointModel,\n keys: KeyModel,\n },\n /** side collections (rejects/aliases live outside mongoose models) */\n collections: { rejects, aliases },\n };\n}\n\nexport type Telemetry = ReturnType<typeof createTelemetry>;\n"]}
|