@jeffjassky/telemetry 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +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/indexes.ts","../src/server/keys.ts","../src/server/ingest.ts","../src/server/funnel.ts","../src/server/query.ts","../src/server/views.ts","../src/server/dashboard.ts","../src/server/index.ts"],"names":["label","Schema","newId","express","path"],"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\nexport const newCounters = (): TelemetryCounters => ({\n rejected: 0, defaulted: 0, sampled: 0, capped: 0, rollupSkipped: 0,\n deduped: 0, truncated: 0,\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,\n type TelemetryCounters,\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 },\n) {\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 const check = (label: string, m: Map<string, unknown> | undefined, zschema?: any) => {\n const obj = Object.fromEntries(m ?? []);\n if (!zschema) {\n if (Object.keys(obj).length) throw new Error(`telemetry: \"${this.name}\" declares no ${label}`);\n return;\n }\n const s = zschema.strict?.() ?? zschema;\n const r = s.safeParse(obj);\n if (!r.success) throw new Error(`telemetry: ${label} invalid for \"${this.name}\": ${r.error.message}`);\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}): 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, { platforms, bodyMax });\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 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/**\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 */\nexport async function recordRollup(\n RollupModel: Model<any>,\n doc: any,\n name: string,\n spec: RollupSpec,\n counters: TelemetryCounters,\n): Promise<void> {\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;\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 counters.rollupSkipped++;\n return;\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;\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 await RollupModel.bulkWrite(\n 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 { ordered: false },\n );\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, RESERVED_TENANT_MESSAGE, SAMPLE_RATE, isPlatformScope, newId, traceKeep, plain,\n type TelemetryCounters, type Logger,\n} from './types.js';\nimport type { 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}\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\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 // `...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 sampleRate: forced ? 1 : baseRate,\n forced,\n attrs: safe(doc.attrs),\n metrics: safe(doc.metrics),\n };\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 { 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 { 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 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: mergeSubjects(rec.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 { 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 four that can cut an answer short — rollups, distribution,\n * distinctCount, funnel — report `truncated` rather than undercounting in\n * silence. The slow-query 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\nexport interface QueryLimits {\n records: number;\n series: number;\n rollups: number;\n trace: number;\n journey: number;\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 distribution: 100_000,\n distinct: 100_000,\n funnel: 5_000,\n};\n\nexport interface RecordFilter {\n kind?: string;\n name?: 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\nconst esc = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nfunction 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 if (f[k]) match[k] = f[k];\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\n/** simple TTL cache with in-flight coalescing — proven shape in maxed */\nclass 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?: 'hour' | 'day' | 'week' | 'month' } = {},\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 m = /^(sum|avg):(.+)$/.exec(measure);\n const value = !m\n ? { $sum: { $divide: [1, { $ifNull: ['$sampleRate', 1] }] } }\n : m[1] === 'sum'\n ? { $sum: `$metrics.${m[2]}` }\n : { $avg: `$metrics.${m[2]}` };\n const buckets = await ctx.TelemetryModel.aggregate([\n { $match: buildMatch(scope, range, filter) },\n {\n $group: {\n _id: { $dateTrunc: { date: '$occurredAt', unit: interval, ...(interval === 'week' ? { startOfWeek: 'monday' } : {}) } },\n value,\n },\n },\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 * 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 { Schema, type Connection, type Model } from 'mongoose';\nimport type { Registry } from './registry.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';\n query: {\n range?: string;\n filters?: Record<string, unknown>;\n groupBy?: string;\n sort?: string;\n display?: 'table' | 'series' | 'breakdown' | 'stream';\n };\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. One per\n * event name (a pre-filtered page), one per rollup family (a RollupExplorer\n * preset). They exist because the registry already knows enough to write them.\n */\nexport function deriveViews(registry: Registry): Array<ViewSpec & { origin: 'derived' }> {\n const views: Array<ViewSpec & { origin: 'derived' }> = [];\n const families = new Set<string>();\n for (const [name, spec] of Object.entries(registry)) {\n views.push({\n origin: 'derived',\n name,\n page: KIND_PAGE[spec.kind] ?? 'events',\n query: { range: '7d', filters: { name }, display: spec.kind === 'event' ? 'series' : 'table' },\n });\n for (const r of spec.rollups ?? []) families.add(r.as ?? name);\n }\n for (const as of families) {\n views.push({\n origin: 'derived',\n name: `rollup: ${as}`,\n page: 'journeys',\n query: { range: '30d', filters: { rollup: as }, display: 'breakdown' },\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 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)) 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 { createQueries, type QueryLimits, type RecordFilter, type TimeRange } from './query.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 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\n/** the registry, projected for the UI — names and shapes, never zod objects */\nfunction registryProjection(t: Telemetry) {\n return Object.fromEntries(\n Object.entries(t.registry).map(([name, spec]) => [\n name,\n {\n kind: spec.kind,\n origin: spec.origin,\n subjects: spec.subjects,\n description: spec.description,\n attrKeys: spec.attrs ? Object.keys(spec.attrs.shape) : [],\n metricKeys: spec.metrics ? Object.keys(spec.metrics.shape) : [],\n indexedAttrs: spec.indexedAttrs ?? [],\n indexedMetrics: spec.indexedMetrics ?? [],\n rollups: (spec.rollups ?? []).map((r) => ({\n as: r.as ?? name,\n by: r.by,\n bucket: r.bucket ?? null,\n sum: r.sum ?? [],\n subjects: r.subjects ?? [],\n })),\n },\n ]),\n );\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 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: registryProjection(t),\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 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 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 // ── views: one shape, three producers ──\n api.get('/views', h(async (req) => ({\n views: await resolveViews({\n ViewModel,\n registry: t.registry,\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 };\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, type EmitInput } from './emit.js';\nimport { createForget } from './forget.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, PLATFORM_SCOPE, RETENTION_DAYS, SAMPLE_RATE, SCHEMA_VERSION,\n isPlatformScope, newId, traceKeep, plain,\n} from './types.js';\nexport type { TelemetryCounters, Logger, EntityRef } from './types.js';\nexport { INDEX_BUDGET } from './indexes.js';\nexport { truncate, resolveDim } from './rollups.js';\nexport type { ForgetResult } from './forget.js';\nexport type { Checkpoint } from './checkpoint.js';\nexport type { EmitInput, EmitResult } 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 { createQueries, DEFAULT_LIMITS } from './query.js';\nexport type { Queries, QueryLimits, RecordFilter, TimeRange } from './query.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';\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 * 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 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,\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 const emit = createEmitter({ registry, byKind, RollupModel, rejects, counters, logger, track });\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 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 * 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 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"]}