@obsunified/collector 2.0.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +1 -1
- package/dist/{chunk-UGWDOGGH.js → chunk-KMEZKGSO.js} +22 -10
- package/dist/chunk-KMEZKGSO.js.map +1 -0
- package/dist/{chunk-XKQTVIRE.js → chunk-ZSF5XP3B.js} +8 -2
- package/dist/chunk-ZSF5XP3B.js.map +1 -0
- package/dist/index.d.ts +630 -27
- package/dist/index.js +5819 -853
- package/dist/index.js.map +1 -1
- package/dist/{ingest-auth-HFVO1zIp.d.ts → ingest-auth-C5-8Mly5.d.ts} +9 -0
- package/dist/{openai-FJYOQ7WO.js → openai-GSJZGFGL.js} +2 -2
- package/package.json +5 -5
- package/src/__tests__/autosre-closed-loop.test.ts +1275 -0
- package/src/analyses/derive.ts +26 -25
- package/src/analyses/investigations.ts +8 -8
- package/src/analyses/tier0.ts +22 -22
- package/src/auth/dashboard-auth.test.ts +791 -0
- package/src/auth/dashboard-auth.ts +187 -38
- package/src/auth/login-rate-limit.test.ts +129 -0
- package/src/auth/login-rate-limit.ts +143 -0
- package/src/framework/body-limit.test.ts +165 -0
- package/src/framework/collector.ts +355 -115
- package/src/framework/env.ts +9 -0
- package/src/framework/limits.ts +31 -0
- package/src/framework/scheduled-handlers.test.ts +342 -0
- package/src/index.ts +59 -1
- package/src/lib/action-retention.test.ts +472 -0
- package/src/lib/action-retention.ts +420 -0
- package/src/lib/actions-store.ts +6 -12
- package/src/lib/ai-store/calls.ts +2 -2
- package/src/lib/ai-store/sessions.ts +3 -3
- package/src/lib/ai-store/spans.ts +1 -1
- package/src/lib/ai-store/types.ts +2 -1
- package/src/lib/alerts-store.test.ts +153 -0
- package/src/lib/alerts-store.ts +122 -21
- package/src/lib/analyses-runner.test.ts +75 -0
- package/src/lib/analyses-runner.ts +69 -3
- package/src/lib/analyses-store-latest.test.ts +61 -0
- package/src/lib/analyses-store.ts +17 -10
- package/src/lib/autosre-change-correlation.ts +780 -0
- package/src/lib/autosre-findings.ts +725 -0
- package/src/lib/autosre-ontology.ts +914 -0
- package/src/lib/autosre-remediation-gate.ts +1663 -0
- package/src/lib/blob-store.ts +1 -1
- package/src/lib/eval-cases-store.ts +63 -1
- package/src/lib/evidence-references.ts +6 -0
- package/src/lib/housekeeping.test.ts +153 -0
- package/src/lib/housekeeping.ts +193 -0
- package/src/lib/identity-index/action-lookups.ts +6 -6
- package/src/lib/identity-index/key-lookups.ts +2 -2
- package/src/lib/identity-index/user-lookup.ts +8 -5
- package/src/lib/identity-index.test.ts +2 -3
- package/src/lib/metrics-store-series.test.ts +99 -0
- package/src/lib/metrics-store.test.ts +23 -0
- package/src/lib/metrics-store.ts +27 -3
- package/src/lib/projects-store.test.ts +25 -0
- package/src/lib/projects-store.ts +4 -3
- package/src/lib/sql-db-dialect.test.ts +12 -3
- package/src/lib/sql-db-postgres.integration.test.ts +1225 -0
- package/src/lib/sql-db-postgres.test.ts +314 -0
- package/src/lib/sql-db-postgres.ts +392 -54
- package/src/lib/sql-db-sqlite-time-windows.test.ts +194 -0
- package/src/lib/sql-db.ts +40 -6
- package/src/lib/store/ingest.ts +94 -6
- package/src/lib/test-utils/action-graph-fixtures.ts +307 -0
- package/src/lib/test-utils/node-sqlite-db.ts +188 -0
- package/src/lib/webhook-url.test.ts +122 -0
- package/src/lib/webhook-url.ts +155 -0
- package/src/migrations/041_ingest_key_hash_text.sql +5 -0
- package/src/migrations/042_session_replay_project_composite_pk.sql +52 -0
- package/src/migrations/043_metric_exemplars_text_timestamps.sql +5 -0
- package/src/migrations/044_actions_started_at_index.sql +10 -0
- package/src/migrations/045_user_profiles_project_composite_pk.sql +40 -0
- package/src/migrations/046_action_graph_project_composite_pk.sql +255 -0
- package/src/migrations/047_ai_span_payloads_project_composite_pk.sql +61 -0
- package/src/migrations/048_telemetry_spans_project_composite_pk.sql +92 -0
- package/src/migrations/049_alert_state_notified.sql +17 -0
- package/src/migrations/050_autosre_causal_ontology.sql +216 -0
- package/src/migrations/alert-state-notified.test.ts +111 -0
- package/src/migrations/parity.test.ts +68 -0
- package/src/migrations/project-scoped-keys.test.ts +432 -0
- package/src/migrations-postgres/009_projects_and_keys.sql +4 -4
- package/src/migrations-postgres/026_obs_dashboard_project_seed.sql +1 -1
- package/src/migrations-postgres/035_metric_exemplars.sql +5 -2
- package/src/migrations-postgres/041_ingest_key_hash_text.sql +32 -0
- package/src/migrations-postgres/042_session_replay_project_composite_pk.sql +16 -0
- package/src/migrations-postgres/043_metric_exemplars_text_timestamps.sql +47 -0
- package/src/migrations-postgres/044_actions_started_at_index.sql +8 -0
- package/src/migrations-postgres/045_user_profiles_project_composite_pk.sql +33 -0
- package/src/migrations-postgres/046_action_graph_project_composite_pk.sql +39 -0
- package/src/migrations-postgres/047_ai_span_payloads_project_composite_pk.sql +30 -0
- package/src/migrations-postgres/048_telemetry_spans_project_composite_pk.sql +37 -0
- package/src/migrations-postgres/049_alert_state_notified.sql +10 -0
- package/src/migrations-postgres/050_autosre_causal_ontology.sql +216 -0
- package/src/migrations-postgres/README.md +58 -5
- package/src/otlp/decode/body.test.ts +76 -0
- package/src/otlp/decode/body.ts +67 -6
- package/src/plugins/_json.ts +21 -0
- package/src/plugins/action-graph-processor.ts +6 -12
- package/src/plugins/ai-receiver.ts +5 -12
- package/src/plugins/ai-span-payloads-processor.ts +1 -2
- package/src/plugins/alerts-evaluator-retention.test.ts +170 -0
- package/src/plugins/alerts-evaluator.test.ts +464 -3
- package/src/plugins/alerts-evaluator.ts +181 -41
- package/src/plugins/alerts-routes.ts +10 -6
- package/src/plugins/ask-routes.ts +4 -5
- package/src/plugins/autosre-routes.ts +1019 -0
- package/src/plugins/connected-routes/manifest.ts +13 -1
- package/src/plugins/connected-routes.test.ts +106 -0
- package/src/plugins/connected-routes.ts +285 -5
- package/src/plugins/dashboard-routes.test.ts +120 -0
- package/src/plugins/dashboard-routes.ts +11 -2
- package/src/plugins/default-span-enrichment.ts +13 -1
- package/src/plugins/eval-cases-routes.ts +65 -19
- package/src/plugins/evidence-retrieval-routes.ts +300 -4
- package/src/plugins/identity-receiver.ts +9 -11
- package/src/plugins/json-body.test.ts +91 -0
- package/src/plugins/onboarding-routes.test.ts +105 -0
- package/src/plugins/onboarding-routes.ts +26 -11
- package/src/plugins/projects-routes.ts +2 -1
- package/src/plugins/replay-isolation.test.ts +922 -0
- package/src/plugins/replay-receiver.ts +8 -8
- package/src/plugins/usage-receiver.ts +3 -6
- package/dist/chunk-UGWDOGGH.js.map +0 -1
- package/dist/chunk-XKQTVIRE.js.map +0 -1
- /package/dist/{openai-FJYOQ7WO.js.map → openai-GSJZGFGL.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as hono from 'hono';
|
|
2
|
-
import { MiddlewareHandler, Hono } from 'hono';
|
|
2
|
+
import { MiddlewareHandler, Hono, Context } from 'hono';
|
|
3
3
|
import * as hono_types from 'hono/types';
|
|
4
4
|
import * as _obsunified_types from '@obsunified/types';
|
|
5
|
-
import { StoredSpan, TelemetryOverviewOptions, TelemetryOverviewResponse, TelemetryTraceDetailResponse, TelemetryInstrumentationGapsResponse, TelemetryIssueOptions, TelemetryIssueOverviewResponse, TelemetryIssueDetailResponse, UsageEventRecord, UsageOverviewOptions, UsageOverviewResponse, UsageSessionDetailResponse, UsageSessionSummary, AlertRuleInput, AlertRule, AlertStateRow, AlertState, AlertEvaluationsListResponse, AlertComparison, JsonValue, EvidenceReference, EvidenceReferenceContract, Project, IngestKey, IngestKeyWithPlaintext } from '@obsunified/types';
|
|
6
|
-
import { b as CollectorEnv,
|
|
7
|
-
export { a as CollectorApp, d as consoleLogger, e as createIngestAuth } from './ingest-auth-
|
|
5
|
+
import { StoredSpan, TelemetryOverviewOptions, TelemetryOverviewResponse, TelemetryTraceDetailResponse, TelemetryInstrumentationGapsResponse, TelemetryIssueOptions, TelemetryIssueOverviewResponse, TelemetryIssueDetailResponse, UsageEventRecord, UsageOverviewOptions, UsageOverviewResponse, UsageSessionDetailResponse, UsageSessionSummary, AlertRuleInput, AlertRule, AlertStateRow, AlertState, AlertEvaluationsListResponse, AlertComparison, ChangeBlastRadiusResult, ContentionCandidate, ChangeEvent, ChangeEventInput, InvestigationFinding, InvestigationFindingInput, OntologyNode, OntologyEdge, CanonicalNodeIdentity, OntologyGraphResponse, RelationshipCertainty, CausalTriple, IncidentInvestigation, RemediationProposal, EvidenceEntityKind, RemediationProposalInput, JsonValue, EvidenceReference, EvidenceReferenceContract, Project, IngestKey, IngestKeyWithPlaintext } from '@obsunified/types';
|
|
6
|
+
import { b as CollectorEnv, L as Logger, C as ChildSpanRunner, c as CollectorRouteContext } from './ingest-auth-C5-8Mly5.js';
|
|
7
|
+
export { a as CollectorApp, d as consoleLogger, e as createIngestAuth } from './ingest-auth-C5-8Mly5.js';
|
|
8
8
|
import { ActionConfidence } from '@obsunified/types/constants';
|
|
9
9
|
import { Pool } from 'pg';
|
|
10
10
|
|
|
@@ -81,6 +81,83 @@ declare class D1Adapter implements SqlDb {
|
|
|
81
81
|
}>>;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* RFC 0002 Stage 1 — runner that executes SQL-only Analyses on the existing
|
|
86
|
+
* scheduled handler.
|
|
87
|
+
*
|
|
88
|
+
* runSqlAnalysis — execute one definition's `sql` against D1 and shape the
|
|
89
|
+
* row(s) into an AnalysisResult.
|
|
90
|
+
* runAllDueAnalyses — orchestrator: refresh the in-process registry into
|
|
91
|
+
* analysis_definitions, find which ones are due, run them,
|
|
92
|
+
* persist the results. Per-analysis errors are isolated
|
|
93
|
+
* via Promise.allSettled so one bad SQL doesn't kill the
|
|
94
|
+
* batch.
|
|
95
|
+
*
|
|
96
|
+
* Result shape convention: an Analysis SQL is expected to return a single
|
|
97
|
+
* row with the columns:
|
|
98
|
+
*
|
|
99
|
+
* status TEXT | NULL -- 'ok' | 'warn' | 'critical' | 'unknown'
|
|
100
|
+
* primary_value REAL | NULL
|
|
101
|
+
* baseline_value REAL | NULL
|
|
102
|
+
* payload TEXT | NULL -- JSON-serialized object, optional
|
|
103
|
+
*
|
|
104
|
+
* If `status` is NULL we derive it from the magnitude of delta_pct
|
|
105
|
+
* (>=25% → critical, >=10% → warn, else ok). delta_pct itself is computed
|
|
106
|
+
* here from primary/baseline so individual SQL queries don't have to.
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Orchestrator. Refreshes the analysis_definitions registry from the
|
|
111
|
+
* in-process registry (so newly-derived Tier 1 analyses become visible
|
|
112
|
+
* to the dashboard within one tick), then runs whatever's due.
|
|
113
|
+
*
|
|
114
|
+
* Runs once per project in the `projects` table (falling back to the
|
|
115
|
+
* `default` project when the table is empty or unreadable), so analyses and
|
|
116
|
+
* the alert rules bound to them refresh for every tenant, not just the
|
|
117
|
+
* first one.
|
|
118
|
+
*/
|
|
119
|
+
declare function runAllDueAnalyses(ctx: {
|
|
120
|
+
env: CollectorEnv;
|
|
121
|
+
retentionHours: number;
|
|
122
|
+
logger?: Logger;
|
|
123
|
+
tracer?: ChildSpanRunner;
|
|
124
|
+
}, _runtime?: unknown): Promise<{
|
|
125
|
+
ran: number;
|
|
126
|
+
failed: number;
|
|
127
|
+
refreshed: number;
|
|
128
|
+
narrated: number;
|
|
129
|
+
skipped?: number;
|
|
130
|
+
}>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Retention for the secondary tables the hourly sweep did not cover. Each
|
|
134
|
+
* rule is tied to an existing contract rather than a new policy:
|
|
135
|
+
*
|
|
136
|
+
* - `alert_evaluations`: `/internal/alerts/evaluations` accepts at most a
|
|
137
|
+
* 720-hour window, so rows older than that are unreachable through the API.
|
|
138
|
+
* - `ask_evidence_events`: feeds `getTopAskedAnalyses`, whose trailing window
|
|
139
|
+
* is 7 days; rows older than 30 days cannot influence it.
|
|
140
|
+
* - `metric_series`: identity rows whose points have all expired and that
|
|
141
|
+
* were created before the retention window. They hold no data; the next
|
|
142
|
+
* ingest of that identity recreates the row.
|
|
143
|
+
* - `evidence_retrieval_refs`: rows carry their own `expires_at` (copied from
|
|
144
|
+
* the signal they reference); expansions follow their ref.
|
|
145
|
+
*/
|
|
146
|
+
|
|
147
|
+
interface HousekeepingSummary {
|
|
148
|
+
alert_evaluations: number;
|
|
149
|
+
ask_evidence_events: number;
|
|
150
|
+
metric_series: number;
|
|
151
|
+
evidence_refs: number;
|
|
152
|
+
evidence_ref_expansions: number;
|
|
153
|
+
ontology_edges?: number;
|
|
154
|
+
ontology_nodes?: number;
|
|
155
|
+
change_events?: number;
|
|
156
|
+
incident_investigations?: number;
|
|
157
|
+
investigation_findings?: number;
|
|
158
|
+
remediation_proposals?: number;
|
|
159
|
+
}
|
|
160
|
+
|
|
84
161
|
interface ServiceMapOptions {
|
|
85
162
|
projectId: string;
|
|
86
163
|
hours: number;
|
|
@@ -298,6 +375,18 @@ interface CollectorConfig {
|
|
|
298
375
|
* a tracing layer at the storage seam.
|
|
299
376
|
*/
|
|
300
377
|
sqlDb?: SqlDbFactory;
|
|
378
|
+
/**
|
|
379
|
+
* Raw request body cap for `/v1/*` and `/internal/*` in bytes. Defaults
|
|
380
|
+
* to `MAX_BODY_BYTES` from the environment, then 10 MiB. Oversized
|
|
381
|
+
* requests get a 413 before any handler buffers the body.
|
|
382
|
+
*/
|
|
383
|
+
maxBodyBytes?: number;
|
|
384
|
+
/**
|
|
385
|
+
* Body cap for the unauthenticated `/auth/*` routes (login/check/logout).
|
|
386
|
+
* Defaults to 16 KiB and is independent of `maxBodyBytes`, so an anonymous
|
|
387
|
+
* client can never make the host buffer an ingest-sized body.
|
|
388
|
+
*/
|
|
389
|
+
maxAuthBodyBytes?: number;
|
|
301
390
|
}
|
|
302
391
|
declare class CollectorRuntime implements CollectorPluginContext {
|
|
303
392
|
private readonly spanProcessors;
|
|
@@ -327,30 +416,56 @@ declare const createTelemetryCollectorApp: (pluginsOrConfig: CollectorPlugin[] |
|
|
|
327
416
|
Bindings: CollectorEnv;
|
|
328
417
|
}>;
|
|
329
418
|
/**
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
419
|
+
* Runtime-neutral entry point for a background maintenance task.
|
|
420
|
+
*
|
|
421
|
+
* `run(env)` does the work and needs nothing but a `CollectorEnv`, so any
|
|
422
|
+
* host (Cloudflare cron, a Node `setInterval`, a Kubernetes CronJob hitting
|
|
423
|
+
* a one-shot script) can drive it. `scheduled(event, env, ctx)` is the thin
|
|
424
|
+
* Cloudflare Workers adapter over `run` — the event and context are accepted
|
|
425
|
+
* for signature compatibility with `ExportedHandler.scheduled` but are never
|
|
426
|
+
* consulted, so non-Workers hosts should call `run` directly rather than
|
|
427
|
+
* fabricating placeholder event objects.
|
|
333
428
|
*/
|
|
429
|
+
interface ScheduledTaskHandler<TSummary = void> {
|
|
430
|
+
run(env: CollectorEnv): Promise<TSummary>;
|
|
431
|
+
scheduled(event: ScheduledEvent, env: CollectorEnv, ctx: ExecutionContext): Promise<void>;
|
|
432
|
+
}
|
|
433
|
+
/** Per-table purge counts reported by the retention cleanup task. */
|
|
434
|
+
interface RetentionCleanupSummary {
|
|
435
|
+
spans: number;
|
|
436
|
+
usage: number;
|
|
437
|
+
logs: number;
|
|
438
|
+
ai_calls: number;
|
|
439
|
+
metric_points: number;
|
|
440
|
+
analysis_results: number;
|
|
441
|
+
profile_blobs: number;
|
|
442
|
+
/** RFC 0010 action spine rows removed (trees older than RETENTION_HOURS). */
|
|
443
|
+
actions: number;
|
|
444
|
+
/** Leaf rows removed with their actions: agent_runs, tool_calls,
|
|
445
|
+
* retrieval_events, eval_results and artifacts. */
|
|
446
|
+
action_leaves: number;
|
|
447
|
+
/** Secondary tables (see lib/housekeeping.ts); zeros when that step failed. */
|
|
448
|
+
housekeeping: HousekeepingSummary;
|
|
449
|
+
}
|
|
334
450
|
declare const createRetentionCleanupHandler: (options?: {
|
|
335
451
|
logger?: Logger;
|
|
336
|
-
}) =>
|
|
337
|
-
scheduled(_event: ScheduledEvent, env: CollectorEnv, _ctx: ExecutionContext): Promise<void>;
|
|
338
|
-
};
|
|
452
|
+
}) => ScheduledTaskHandler<RetentionCleanupSummary>;
|
|
339
453
|
/**
|
|
340
454
|
* RFC 0002 Stage 1 — run any due Analyses. Cheap to call frequently because
|
|
341
455
|
* `runAllDueAnalyses` filters by `last_run + refreshSeconds < now` before
|
|
342
456
|
* touching D1.
|
|
343
457
|
*
|
|
344
|
-
* Wire to a per-minute trigger in wrangler.toml: `crons = ["* * * * *"]
|
|
345
|
-
*
|
|
346
|
-
* retention table every
|
|
458
|
+
* Wire to a per-minute trigger in wrangler.toml: `crons = ["* * * * *"]`,
|
|
459
|
+
* or call `.run(env)` from a non-Workers host scheduler. Kept distinct from
|
|
460
|
+
* retention so the per-minute tick doesn't sweep every retention table every
|
|
461
|
+
* cycle.
|
|
347
462
|
*/
|
|
348
463
|
declare const createAnalysesRunHandler: (options?: {
|
|
349
464
|
logger?: Logger;
|
|
350
465
|
tracer?: ChildSpanRunner;
|
|
351
|
-
}) =>
|
|
352
|
-
|
|
353
|
-
|
|
466
|
+
}) => ScheduledTaskHandler<AnalysesRunSummary | undefined>;
|
|
467
|
+
/** Shape returned by `runAllDueAnalyses` and surfaced via the run handler. */
|
|
468
|
+
type AnalysesRunSummary = Awaited<ReturnType<typeof runAllDueAnalyses>>;
|
|
354
469
|
|
|
355
470
|
declare const actionRoutesPlugin: CollectorPlugin;
|
|
356
471
|
|
|
@@ -371,15 +486,20 @@ declare const aiReceiverPlugin: CollectorPlugin;
|
|
|
371
486
|
|
|
372
487
|
declare const aiSpanPayloadsProcessorPlugin: CollectorPlugin;
|
|
373
488
|
|
|
489
|
+
/** Resolve a hostname to its addresses (e.g. `dns.lookup(host, { all: true })`). */
|
|
490
|
+
type HostLookup = (hostname: string) => Promise<string[]>;
|
|
491
|
+
|
|
374
492
|
declare function evaluateAllRules(env: CollectorEnv, options?: {
|
|
375
493
|
logger?: Logger;
|
|
376
494
|
tracer?: ChildSpanRunner;
|
|
377
495
|
concurrency?: number;
|
|
378
496
|
ruleTimeoutMs?: number;
|
|
497
|
+
hostLookup?: HostLookup;
|
|
379
498
|
}): Promise<{
|
|
380
499
|
evaluated: number;
|
|
381
500
|
fired: number;
|
|
382
501
|
resolved: number;
|
|
502
|
+
redelivered: number;
|
|
383
503
|
}>;
|
|
384
504
|
/**
|
|
385
505
|
* Scheduled handler suitable for wrangler cron triggers. Dispatches on the
|
|
@@ -429,6 +549,8 @@ declare const analysesRoutesPlugin: CollectorPlugin;
|
|
|
429
549
|
|
|
430
550
|
declare const askRoutesPlugin: CollectorPlugin;
|
|
431
551
|
|
|
552
|
+
declare const autosreRoutesPlugin: CollectorPlugin;
|
|
553
|
+
|
|
432
554
|
declare const botFilterPlugin: CollectorPlugin;
|
|
433
555
|
|
|
434
556
|
type CausalConfidence = ActionConfidence;
|
|
@@ -666,18 +788,61 @@ declare const usersQueryRoutesPlugin: CollectorPlugin;
|
|
|
666
788
|
declare const utmEnrichmentPlugin: CollectorPlugin;
|
|
667
789
|
|
|
668
790
|
/**
|
|
669
|
-
*
|
|
791
|
+
* Fixed-window failure limiter for `POST /auth/login`. Only failed attempts
|
|
792
|
+
* count; a successful login clears the client's bucket. State is in-memory,
|
|
793
|
+
* so on Cloudflare Workers it is per isolate and on Node per process — it
|
|
794
|
+
* slows a single-origin brute force without any shared storage, and it can
|
|
795
|
+
* never lock an operator out for longer than one window.
|
|
796
|
+
*/
|
|
797
|
+
interface LoginRateLimitOptions {
|
|
798
|
+
/** Failed attempts allowed per window before 429. Default 10. */
|
|
799
|
+
maxFailures?: number;
|
|
800
|
+
/** Window length in milliseconds. Default 15 minutes. */
|
|
801
|
+
windowMs?: number;
|
|
802
|
+
/** Upper bound on tracked clients; the oldest bucket is evicted past it. */
|
|
803
|
+
maxClients?: number;
|
|
804
|
+
/** Clock override for tests. */
|
|
805
|
+
now?: () => number;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
interface DashboardAuthConfig {
|
|
809
|
+
password?: string;
|
|
810
|
+
token?: string;
|
|
811
|
+
/**
|
|
812
|
+
* Failed-login limiter for POST /auth/login (see login-rate-limit.ts).
|
|
813
|
+
* Pass `false` to disable; defaults to 10 failures per 15 minutes.
|
|
814
|
+
* `clientAddress` lets the host supply the connection's peer address;
|
|
815
|
+
* `trustProxyHeaders` honours forwarding headers from a trusted proxy.
|
|
816
|
+
* Without either, Workers use the edge-set client IP and every other
|
|
817
|
+
* runtime has no trustworthy identity: limiting is then skipped (never a
|
|
818
|
+
* shared bucket, which would let one client lock everyone out) and a
|
|
819
|
+
* warning is logged once via `warn` (default `console.warn`).
|
|
820
|
+
*/
|
|
821
|
+
loginRateLimit?: (LoginRateLimitOptions & {
|
|
822
|
+
clientAddress?: (c: Context<{
|
|
823
|
+
Bindings: CollectorEnv;
|
|
824
|
+
}>) => string | undefined;
|
|
825
|
+
trustProxyHeaders?: boolean;
|
|
826
|
+
/** Sink for the one-time "limiter inactive" warning. */
|
|
827
|
+
warn?: (message: string) => void;
|
|
828
|
+
}) | false;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Creates auth routes and middleware for dashboard password login and
|
|
832
|
+
* programmatic read/admin bearer token authentication.
|
|
670
833
|
*
|
|
671
834
|
* Routes added:
|
|
672
835
|
* POST /auth/login — accepts { password }, sets session cookie
|
|
673
|
-
* GET /auth/check — returns { authenticated: true/false }
|
|
836
|
+
* GET /auth/check — returns { authenticated: true/false } (supports cookie and Bearer token)
|
|
674
837
|
* POST /auth/logout — clears session cookie
|
|
675
838
|
*
|
|
676
|
-
* The returned middleware validates
|
|
839
|
+
* The returned middleware validates either:
|
|
840
|
+
* 1. Authorization: Bearer <token> (programmatic read/admin token for MCP/API)
|
|
841
|
+
* 2. obs_session cookie (human dashboard user session)
|
|
842
|
+
*
|
|
843
|
+
* Ingest keys are rejected on dashboard/internal routes — they are write-only.
|
|
677
844
|
*/
|
|
678
|
-
declare function createDashboardAuth(config: {
|
|
679
|
-
password: string;
|
|
680
|
-
}): {
|
|
845
|
+
declare function createDashboardAuth(config?: DashboardAuthConfig): {
|
|
681
846
|
middleware: MiddlewareHandler<{
|
|
682
847
|
Bindings: CollectorEnv;
|
|
683
848
|
Variables: {
|
|
@@ -718,6 +883,107 @@ declare class TailHub {
|
|
|
718
883
|
private broadcast;
|
|
719
884
|
}
|
|
720
885
|
|
|
886
|
+
/**
|
|
887
|
+
* Retention for the RFC 0010 action graph (`actions` spine plus the
|
|
888
|
+
* `agent_runs`, `tool_calls`, `retrieval_events`, `eval_results` and
|
|
889
|
+
* `artifacts` leaves).
|
|
890
|
+
*
|
|
891
|
+
* Unlike the telemetry tables these rows carry no `expires_at`; the sweep
|
|
892
|
+
* derives expiry from `actions.started_at` and the configured
|
|
893
|
+
* `RETENTION_HOURS`. The unit of deletion is the causal tree
|
|
894
|
+
* (`project_id`, `root_action_id`): a tree is selected, rechecked and
|
|
895
|
+
* removed as a whole inside one `SqlDb.batch` (a D1 batch or a Postgres
|
|
896
|
+
* transaction), never action by action. A tree is kept whole while any of
|
|
897
|
+
* its actions:
|
|
898
|
+
*
|
|
899
|
+
* - started inside the retention window,
|
|
900
|
+
* - is still in progress (`ended_at IS NULL`),
|
|
901
|
+
* - belongs to an `agent_runs` row whose `status` is `running`,
|
|
902
|
+
* - is referenced by an `eval_cases` row in the same project via
|
|
903
|
+
* `source_action_id`, `source_agent_run_id`, or (through a `tool_calls`
|
|
904
|
+
* row) `source_tool_call_id`.
|
|
905
|
+
*
|
|
906
|
+
* Work is bounded per invocation: each batch packs whole trees up to
|
|
907
|
+
* `maxActionsPerBatch` actions and `maxTreesPerBatch` trees, and the sweep
|
|
908
|
+
* stops after `maxBatches`. A tree with more than `maxActionsPerBatch`
|
|
909
|
+
* actions can never be deleted atomically within those bounds, so it is
|
|
910
|
+
* retained intact and reported as `oversized_trees` (and logged by the
|
|
911
|
+
* handler) instead of being deleted in pieces. Raise `maxActionsPerBatch`
|
|
912
|
+
* to reclaim such trees.
|
|
913
|
+
*
|
|
914
|
+
* Concurrency: every DELETE repeats the eligibility predicate, so a tree
|
|
915
|
+
* that gained a fresh or unfinished action, a `running` run, or an eval
|
|
916
|
+
* case between selection and deletion is left alone. On D1 the batch is a
|
|
917
|
+
* single serialized SQLite transaction, so that recheck is airtight. On
|
|
918
|
+
* Postgres (READ COMMITTED) each statement sees writes committed before it
|
|
919
|
+
* started, so a commit landing between the leaf deletes and the final spine
|
|
920
|
+
* delete of the same tree could leave that tree's spine without its leaves.
|
|
921
|
+
* That needs an ingest for a tree whose newest action is already older than
|
|
922
|
+
* the retention window, inside a sub-second window; it is documented rather
|
|
923
|
+
* than locked against because `SqlDb` has no row-locking primitive.
|
|
924
|
+
*
|
|
925
|
+
* Intentionally **not** deleted here:
|
|
926
|
+
*
|
|
927
|
+
* - `artifacts.storage_ref` blobs — only the metadata row goes; the blob
|
|
928
|
+
* store is not consulted (the collector never wrote those blobs).
|
|
929
|
+
* - `agent_runs` rows whose `id` is not an action in the tree — nothing
|
|
930
|
+
* proves when they started.
|
|
931
|
+
* - `ai_span_payloads.action_id` and `evidence_retrieval_refs` anchors —
|
|
932
|
+
* those tables have their own `expires_at` retention.
|
|
933
|
+
* - `eval_cases`, `eval_runs`, `eval_case_results` — curated fixtures,
|
|
934
|
+
* never retention-bound.
|
|
935
|
+
*/
|
|
936
|
+
|
|
937
|
+
interface ActionGraphRetentionOptions {
|
|
938
|
+
/** Retention window; trees whose newest action is older than this expire. */
|
|
939
|
+
retentionHours: number;
|
|
940
|
+
/** Clock override for tests. Defaults to `Date.now`. */
|
|
941
|
+
now?: () => number;
|
|
942
|
+
/**
|
|
943
|
+
* Upper bound on actions deleted per batch/transaction. Also the largest
|
|
944
|
+
* tree the sweep will delete; bigger trees are retained and reported.
|
|
945
|
+
* Defaults to 500.
|
|
946
|
+
*/
|
|
947
|
+
maxActionsPerBatch?: number;
|
|
948
|
+
/** Upper bound on trees per batch (bounds statements per transaction). Defaults to 25. */
|
|
949
|
+
maxTreesPerBatch?: number;
|
|
950
|
+
/** Upper bound on batches per invocation. Defaults to 10. */
|
|
951
|
+
maxBatches?: number;
|
|
952
|
+
}
|
|
953
|
+
/** Per-table delete counts for one `purgeExpiredActionGraph` call. */
|
|
954
|
+
interface ActionGraphPurgeSummary {
|
|
955
|
+
actions: number;
|
|
956
|
+
agent_runs: number;
|
|
957
|
+
tool_calls: number;
|
|
958
|
+
retrieval_events: number;
|
|
959
|
+
eval_results: number;
|
|
960
|
+
artifacts: number;
|
|
961
|
+
/** Whole trees deleted. */
|
|
962
|
+
trees: number;
|
|
963
|
+
/** Batches (transactions) executed. */
|
|
964
|
+
batches: number;
|
|
965
|
+
/** `true` when `maxBatches` was hit while deletable trees remained. */
|
|
966
|
+
truncated: boolean;
|
|
967
|
+
/**
|
|
968
|
+
* Expired, otherwise eligible trees retained because they hold more than
|
|
969
|
+
* `maxActionsPerBatch` actions. Capped at `OVERSIZED_REPORT_LIMIT`.
|
|
970
|
+
*/
|
|
971
|
+
oversized_trees: number;
|
|
972
|
+
/** Identities of the reported oversized trees, for operators. */
|
|
973
|
+
oversized: Array<{
|
|
974
|
+
project_id: string;
|
|
975
|
+
root_action_id: string;
|
|
976
|
+
actions: number;
|
|
977
|
+
}>;
|
|
978
|
+
}
|
|
979
|
+
/** Cutoff as the same ISO text shape the collector writes to `started_at`. */
|
|
980
|
+
declare const actionRetentionCutoff: (retentionHours: number, nowMs?: number) => string;
|
|
981
|
+
/**
|
|
982
|
+
* Purge expired action trees. Safe to call repeatedly: a second call right
|
|
983
|
+
* after the first finds no deletable trees and changes nothing.
|
|
984
|
+
*/
|
|
985
|
+
declare function purgeExpiredActionGraph(db: SqlDb, options: ActionGraphRetentionOptions): Promise<ActionGraphPurgeSummary>;
|
|
986
|
+
|
|
721
987
|
type ActionRecord = Omit<ActionRef, "projectId"> & {
|
|
722
988
|
projectId: string;
|
|
723
989
|
};
|
|
@@ -756,10 +1022,15 @@ declare class ActionStore {
|
|
|
756
1022
|
listArtifactsByAction(projectId: string, actionId: string, limit?: number): Promise<ArtifactRef[]>;
|
|
757
1023
|
}
|
|
758
1024
|
|
|
1025
|
+
interface AlertsStoreOptions {
|
|
1026
|
+
/** Permit webhook targets on loopback / private / link-local hosts. */
|
|
1027
|
+
allowPrivateWebhookTargets?: boolean;
|
|
1028
|
+
}
|
|
759
1029
|
declare function compareValue(value: number, threshold: number, comparison: AlertComparison): boolean;
|
|
760
1030
|
declare class AlertsStore {
|
|
761
1031
|
private readonly db;
|
|
762
|
-
|
|
1032
|
+
private readonly options;
|
|
1033
|
+
constructor(db: SqlDb, options?: AlertsStoreOptions);
|
|
763
1034
|
validateInput(input: AlertRuleInput): void;
|
|
764
1035
|
listRules(projectId: string): Promise<AlertRule[]>;
|
|
765
1036
|
getRule(id: string, projectId: string): Promise<AlertRule | null>;
|
|
@@ -767,8 +1038,24 @@ declare class AlertsStore {
|
|
|
767
1038
|
updateRule(id: string, projectId: string, patch: Partial<AlertRuleInput>): Promise<AlertRule | null>;
|
|
768
1039
|
deleteRule(id: string, projectId: string): Promise<boolean>;
|
|
769
1040
|
listEnabledRules(): Promise<AlertRule[]>;
|
|
770
|
-
getState(ruleId: string): Promise<AlertStateRow | null>;
|
|
1041
|
+
getState(ruleId: string, projectId: string): Promise<AlertStateRow | null>;
|
|
1042
|
+
/**
|
|
1043
|
+
* Record a state transition with its notification still outstanding
|
|
1044
|
+
* (`notified = 0`); `markNotified` flips it once a channel accepts the
|
|
1045
|
+
* alert. On a database that has not applied migration 049 the column is
|
|
1046
|
+
* missing: the transition is still written (legacy statement) so alerting
|
|
1047
|
+
* keeps working through a rolling deploy, and the evaluator treats a row
|
|
1048
|
+
* without the column as delivered.
|
|
1049
|
+
*/
|
|
771
1050
|
transitionState(ruleId: string, projectId: string, newState: AlertState, now: string): Promise<void>;
|
|
1051
|
+
/**
|
|
1052
|
+
* Mark the transition `(state, lastStateChange)` as delivered. Scoped to
|
|
1053
|
+
* the exact transition the caller notified for: if the rule changed state
|
|
1054
|
+
* again while the webhook was in flight, the newer transition keeps its
|
|
1055
|
+
* own outstanding flag. Returns false when nothing matched (stale or
|
|
1056
|
+
* already marked). On a pre-049 schema there is nothing to mark.
|
|
1057
|
+
*/
|
|
1058
|
+
markNotified(ruleId: string, projectId: string, state: AlertState, lastStateChange: string): Promise<boolean>;
|
|
772
1059
|
recordEvaluation(ruleId: string, projectId: string, value: number, state: AlertState, notified: boolean): Promise<void>;
|
|
773
1060
|
listEvaluations(params: {
|
|
774
1061
|
ruleId: string;
|
|
@@ -793,6 +1080,289 @@ declare class AlertsStore {
|
|
|
793
1080
|
private evaluateAIRule;
|
|
794
1081
|
}
|
|
795
1082
|
|
|
1083
|
+
declare function recordChangeEvent(db: SqlDb, projectId: string, input: ChangeEventInput): Promise<ChangeEvent>;
|
|
1084
|
+
declare function listChangeEvents(db: SqlDb, options: {
|
|
1085
|
+
projectId: string;
|
|
1086
|
+
environment?: string;
|
|
1087
|
+
serviceName?: string;
|
|
1088
|
+
targetNodeId?: string;
|
|
1089
|
+
kind?: string;
|
|
1090
|
+
since?: string;
|
|
1091
|
+
limit?: number;
|
|
1092
|
+
}): Promise<ChangeEvent[]>;
|
|
1093
|
+
declare function getChangeEvent(db: SqlDb, projectId: string, changeId: string, environment?: string): Promise<ChangeEvent | null>;
|
|
1094
|
+
/**
|
|
1095
|
+
* Indexed cross-trace contention lookup (RFC 0013 § 4.B).
|
|
1096
|
+
* Uses `idx_spans_contention_lookup` (`project_id, environment, target_node_id, start_time, end_time`).
|
|
1097
|
+
* Enforces P1 #5: if the target node is unscoped (`is_scoped_identity = 0`), caps
|
|
1098
|
+
* `relationshipCertainty` at `"inferred"`.
|
|
1099
|
+
*/
|
|
1100
|
+
declare function findCrossTraceContention(db: SqlDb, options: {
|
|
1101
|
+
projectId: string;
|
|
1102
|
+
environment: string;
|
|
1103
|
+
targetNodeId: string;
|
|
1104
|
+
excludeTraceId: string;
|
|
1105
|
+
startTime: string;
|
|
1106
|
+
endTime: string;
|
|
1107
|
+
limit?: number;
|
|
1108
|
+
}): Promise<ContentionCandidate[]>;
|
|
1109
|
+
/**
|
|
1110
|
+
* Computes traffic-normalized cohort rate lift, minimum sample gates, shared-degradation
|
|
1111
|
+
* noisy-neighbor contention checks, and code-path overlap for a `change_event`
|
|
1112
|
+
* (RFC 0013 § 4.A, P1 #1, P1 #2).
|
|
1113
|
+
*/
|
|
1114
|
+
declare function computeChangeBlastRadius(db: SqlDb, projectId: string, changeId: string, options?: {
|
|
1115
|
+
environment?: string;
|
|
1116
|
+
minComparableSample?: number;
|
|
1117
|
+
}): Promise<ChangeBlastRadiusResult | null>;
|
|
1118
|
+
|
|
1119
|
+
declare function recordInvestigationFinding(db: SqlDb, projectId: string, input: InvestigationFindingInput): Promise<InvestigationFinding>;
|
|
1120
|
+
declare function getInvestigationFinding(db: SqlDb, projectId: string, findingId: string, environment?: string): Promise<InvestigationFinding | null>;
|
|
1121
|
+
declare function searchInvestigationFindings(db: SqlDb, options: {
|
|
1122
|
+
projectId: string;
|
|
1123
|
+
environment?: string;
|
|
1124
|
+
fingerprint?: string;
|
|
1125
|
+
symptomEntityId?: string;
|
|
1126
|
+
rootCauseEntityId?: string;
|
|
1127
|
+
causalVerificationStatus?: string;
|
|
1128
|
+
incidentId?: string;
|
|
1129
|
+
limit?: number;
|
|
1130
|
+
}): Promise<InvestigationFinding[]>;
|
|
1131
|
+
declare class CounterfactualVerificationError extends Error {
|
|
1132
|
+
constructor(message: string);
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* Verifies a PairedCounterfactualProof in SQL against `eval_runs` and `eval_case_results`
|
|
1136
|
+
* (RFC 0013 § 5.A & P1 #3).
|
|
1137
|
+
*
|
|
1138
|
+
* Requires:
|
|
1139
|
+
* 1. `failingRunId` and all `passingRunIds` belong to `projectId` and ran against `evalCaseId`
|
|
1140
|
+
* with the identical non-null `input_payload_hash`.
|
|
1141
|
+
* 2. `failingRunId` failed (`passed = 0`) and its `failure_fingerprint` matches `finding.fingerprint`.
|
|
1142
|
+
* 3. All `passingRunIds` passed (`passed = 1`) and `passingRunIds.length >= requiredTrials`.
|
|
1143
|
+
* 4. Failing and passing runs have distinct recorded version/commit/prompt lineage.
|
|
1144
|
+
*/
|
|
1145
|
+
declare function verifyPairedCounterfactualProof(db: SqlDb, projectId: string, findingId: string, input: {
|
|
1146
|
+
environment?: string;
|
|
1147
|
+
evalCaseId: string;
|
|
1148
|
+
failingRunId: string;
|
|
1149
|
+
passingRunIds: string[];
|
|
1150
|
+
requiredTrials?: number;
|
|
1151
|
+
}): Promise<InvestigationFinding>;
|
|
1152
|
+
|
|
1153
|
+
interface ExtractedSpanLineage {
|
|
1154
|
+
environment: string;
|
|
1155
|
+
namespace: string;
|
|
1156
|
+
serviceName: string | null;
|
|
1157
|
+
serviceVersion: string | null;
|
|
1158
|
+
commitSha: string | null;
|
|
1159
|
+
configDigest: string | null;
|
|
1160
|
+
sourceNode: CanonicalNodeIdentity | null;
|
|
1161
|
+
targetNode: CanonicalNodeIdentity | null;
|
|
1162
|
+
edgePredicate: string | null;
|
|
1163
|
+
errorSignature: string | null;
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Extracts runtime lineage (`environment`, `serviceVersion`, `commitSha`, `configDigest`),
|
|
1167
|
+
* canonical source/target `OntologyNode` identities, and `errorSignature` from a span.
|
|
1168
|
+
*/
|
|
1169
|
+
declare function extractSpanLineageAndTopology(span: StoredSpan): ExtractedSpanLineage;
|
|
1170
|
+
/**
|
|
1171
|
+
* Upserts environment-scoped `ontology_nodes`, `ontology_edges`, and inferred version-transition
|
|
1172
|
+
* `change_events` from ingested spans.
|
|
1173
|
+
*/
|
|
1174
|
+
declare function upsertOntologyFromSpans(db: SqlDb, spans: StoredSpan[], options?: {
|
|
1175
|
+
bypassCache?: boolean;
|
|
1176
|
+
}): Promise<void>;
|
|
1177
|
+
/**
|
|
1178
|
+
* Tarjan's O(V + E) Strongly Connected Components (SCC) condensation algorithm
|
|
1179
|
+
* (RFC 0013 § 1.B & P2 #6). Ensures cyclic service/queue topologies never cause
|
|
1180
|
+
* infinite loops during dependency traversal.
|
|
1181
|
+
*/
|
|
1182
|
+
declare function computeTarjanScc(nodes: OntologyNode[], edges: OntologyEdge[]): {
|
|
1183
|
+
annotatedNodes: OntologyNode[];
|
|
1184
|
+
components: Array<{
|
|
1185
|
+
sccId: string;
|
|
1186
|
+
nodeIds: string[];
|
|
1187
|
+
isCyclic: boolean;
|
|
1188
|
+
}>;
|
|
1189
|
+
};
|
|
1190
|
+
interface TraceSpanLocusInput {
|
|
1191
|
+
span_id: string;
|
|
1192
|
+
parent_span_id: string | null;
|
|
1193
|
+
service_name: string | null;
|
|
1194
|
+
span_name: string;
|
|
1195
|
+
span_kind: number;
|
|
1196
|
+
status_code: number;
|
|
1197
|
+
status_message: string | null;
|
|
1198
|
+
start_time: string;
|
|
1199
|
+
end_time: string;
|
|
1200
|
+
duration_ms: number;
|
|
1201
|
+
environment?: string | null;
|
|
1202
|
+
target_node_id?: string | null;
|
|
1203
|
+
error_signature?: string | null;
|
|
1204
|
+
}
|
|
1205
|
+
interface TraceFaultLocusResult {
|
|
1206
|
+
faultLocusSpan: TraceSpanLocusInput | null;
|
|
1207
|
+
faultLocusNodeId: string | null;
|
|
1208
|
+
relationshipCertainty: RelationshipCertainty;
|
|
1209
|
+
causalProofTier: "unverified_locus";
|
|
1210
|
+
causalTriples: CausalTriple[];
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Per-trace cycle-guarded DFS fault locus detector (RFC 0013 § 1.B & P1 #1).
|
|
1214
|
+
* Identifies where an error surfaced (`originated_fault_in_span`) while keeping
|
|
1215
|
+
* `causalProofTier: "unverified_locus"` separate from `relationshipCertainty: "exact"`.
|
|
1216
|
+
*/
|
|
1217
|
+
declare function localizeTraceFaultLocus(traceId: string, spans: TraceSpanLocusInput[]): TraceFaultLocusResult;
|
|
1218
|
+
/**
|
|
1219
|
+
* Queries `telemetry_spans` for a trace and computes its fault locus.
|
|
1220
|
+
*/
|
|
1221
|
+
declare function loadTraceFaultLocusFromDb(db: SqlDb, projectId: string, traceId: string): Promise<TraceFaultLocusResult>;
|
|
1222
|
+
/**
|
|
1223
|
+
* Loads the environment-scoped operational ontology graph with Tarjan SCC
|
|
1224
|
+
* cycle metadata and dependency blackout indicators.
|
|
1225
|
+
*/
|
|
1226
|
+
declare function getOntologyGraph(db: SqlDb, options: {
|
|
1227
|
+
projectId: string;
|
|
1228
|
+
environment?: string;
|
|
1229
|
+
}): Promise<OntologyGraphResponse>;
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* Opens or deduplicates an active `incident_investigation` (RFC 0013 § 6.A & P2 #7).
|
|
1233
|
+
* Multiple firing alerts or webhook retries for the same `(project_id, environment, target_node_id, symptom_category)`
|
|
1234
|
+
* coalesce into a single active incident.
|
|
1235
|
+
*/
|
|
1236
|
+
declare function openOrDeduplicateIncident(db: SqlDb, projectId: string, input: {
|
|
1237
|
+
id?: string;
|
|
1238
|
+
environment?: string;
|
|
1239
|
+
targetNodeId: string;
|
|
1240
|
+
symptomCategory?: string;
|
|
1241
|
+
symptomAnchorKind: EvidenceEntityKind;
|
|
1242
|
+
symptomAnchorId: string;
|
|
1243
|
+
symptomFingerprint?: string | null;
|
|
1244
|
+
latestBundle?: Record<string, unknown> | null;
|
|
1245
|
+
}): Promise<{
|
|
1246
|
+
incident: IncidentInvestigation;
|
|
1247
|
+
deduplicated: boolean;
|
|
1248
|
+
}>;
|
|
1249
|
+
declare function getIncidentInvestigation(db: SqlDb, projectId: string, incidentId: string, environment?: string): Promise<IncidentInvestigation | null>;
|
|
1250
|
+
declare function listIncidentInvestigations(db: SqlDb, options: {
|
|
1251
|
+
projectId: string;
|
|
1252
|
+
environment?: string;
|
|
1253
|
+
status?: string;
|
|
1254
|
+
limit?: number;
|
|
1255
|
+
}): Promise<IncidentInvestigation[]>;
|
|
1256
|
+
/**
|
|
1257
|
+
* Exclusive runner lease acquisition / renewal (RFC 0013 § 6.B & P2 #7).
|
|
1258
|
+
* Prevents competing AutoSRE runners from investigating or remediating the same
|
|
1259
|
+
* incident simultaneously.
|
|
1260
|
+
*/
|
|
1261
|
+
declare function acquireIncidentLease(db: SqlDb, projectId: string, incidentId: string, input: {
|
|
1262
|
+
environment?: string;
|
|
1263
|
+
runnerId: string;
|
|
1264
|
+
leaseDurationSeconds?: number;
|
|
1265
|
+
nowIso?: string;
|
|
1266
|
+
}): Promise<{
|
|
1267
|
+
acquired: true;
|
|
1268
|
+
incident: IncidentInvestigation;
|
|
1269
|
+
} | {
|
|
1270
|
+
acquired: false;
|
|
1271
|
+
reason: string;
|
|
1272
|
+
conflictOwnerId: string | null;
|
|
1273
|
+
leaseExpiresAt: string | null;
|
|
1274
|
+
}>;
|
|
1275
|
+
/**
|
|
1276
|
+
* SSRF-safe, HMAC-SHA256 signed AutoSRE incident webhook outbox delivery
|
|
1277
|
+
* (RFC 0013 § 6.A).
|
|
1278
|
+
*/
|
|
1279
|
+
declare function dispatchIncidentWebhook(db: SqlDb, projectId: string, incidentId: string, webhook: {
|
|
1280
|
+
url: string;
|
|
1281
|
+
secret?: string;
|
|
1282
|
+
allowPrivateNetworks?: boolean;
|
|
1283
|
+
fetchImpl?: typeof fetch;
|
|
1284
|
+
}): Promise<{
|
|
1285
|
+
delivered: boolean;
|
|
1286
|
+
status?: number;
|
|
1287
|
+
error?: string;
|
|
1288
|
+
}>;
|
|
1289
|
+
declare class RemediationGateError extends Error {
|
|
1290
|
+
readonly statusCode: number;
|
|
1291
|
+
constructor(message: string, statusCode?: number);
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Pre-execution remediation proposal gate (RFC 0013 § 6.B & P1 #4).
|
|
1295
|
+
*/
|
|
1296
|
+
declare function proposeRemediationAction(db: SqlDb, projectId: string, input: RemediationProposalInput): Promise<RemediationProposal>;
|
|
1297
|
+
declare function getRemediationProposal(db: SqlDb, projectId: string, proposalId: string, environment?: string): Promise<RemediationProposal | null>;
|
|
1298
|
+
declare function listRemediationProposals(db: SqlDb, options: {
|
|
1299
|
+
projectId: string;
|
|
1300
|
+
environment?: string;
|
|
1301
|
+
status?: string;
|
|
1302
|
+
incidentId?: string;
|
|
1303
|
+
findingId?: string;
|
|
1304
|
+
limit?: number;
|
|
1305
|
+
}): Promise<RemediationProposal[]>;
|
|
1306
|
+
/**
|
|
1307
|
+
* Human dashboard session approval for `pending_human_approval` proposals
|
|
1308
|
+
* (RFC 0013 § 6.B & P1 #4). Mints a single-use `grantToken`.
|
|
1309
|
+
*/
|
|
1310
|
+
declare function approveRemediationProposal(db: SqlDb, projectId: string, proposalId: string, options: {
|
|
1311
|
+
environment?: string;
|
|
1312
|
+
approvedByUserId: string;
|
|
1313
|
+
}): Promise<RemediationProposal>;
|
|
1314
|
+
declare function rejectRemediationProposal(db: SqlDb, projectId: string, proposalId: string, options: {
|
|
1315
|
+
environment?: string;
|
|
1316
|
+
rejectedByUserId: string;
|
|
1317
|
+
reason?: string;
|
|
1318
|
+
}): Promise<RemediationProposal>;
|
|
1319
|
+
/**
|
|
1320
|
+
* Single-use grant redemption with optimistic `expectedCurrentState` verification
|
|
1321
|
+
* against `ontology_nodes` (RFC 0013 § 6.B & P1 #4).
|
|
1322
|
+
*/
|
|
1323
|
+
declare function claimRemediationGrant(db: SqlDb, projectId: string, proposalId: string, options: {
|
|
1324
|
+
environment?: string;
|
|
1325
|
+
grantToken: string;
|
|
1326
|
+
runnerId?: string;
|
|
1327
|
+
nowIso?: string;
|
|
1328
|
+
}): Promise<RemediationProposal>;
|
|
1329
|
+
/**
|
|
1330
|
+
* Records remediation completion, updates `ontology_nodes` to desired state,
|
|
1331
|
+
* and arms the +2m/+5m/+15m post-remediation watchdog on the finding.
|
|
1332
|
+
*/
|
|
1333
|
+
declare function completeRemediationProposal(db: SqlDb, projectId: string, proposalId: string, options: {
|
|
1334
|
+
environment?: string;
|
|
1335
|
+
resultingChangeId?: string | null;
|
|
1336
|
+
remediationAgentRunId?: string | null;
|
|
1337
|
+
baselineRequestRatePerMin?: number | null;
|
|
1338
|
+
nowIso?: string;
|
|
1339
|
+
}): Promise<RemediationProposal>;
|
|
1340
|
+
declare function failRemediationProposal(db: SqlDb, projectId: string, proposalId: string, options: {
|
|
1341
|
+
environment?: string;
|
|
1342
|
+
failureReason: string;
|
|
1343
|
+
nowIso?: string;
|
|
1344
|
+
}): Promise<RemediationProposal>;
|
|
1345
|
+
interface WatchdogEvaluationSummary {
|
|
1346
|
+
evaluated: number;
|
|
1347
|
+
recovered: number;
|
|
1348
|
+
inconclusiveLowTraffic: number;
|
|
1349
|
+
stillDegraded: number;
|
|
1350
|
+
timedOutClaims: number;
|
|
1351
|
+
expiredGrants: number;
|
|
1352
|
+
}
|
|
1353
|
+
/**
|
|
1354
|
+
* Post-Remediation Watchdog & Lease/Claim Timeout Evaluator (RFC 0013 § 5.B, § 6.B & P1 #3).
|
|
1355
|
+
*
|
|
1356
|
+
* Strictly separates:
|
|
1357
|
+
* - `recovery_status`: whether the service recovered under comparable traffic (`N >= minComparableRequests`)
|
|
1358
|
+
* - `causal_verification_status`: `"operationally_corroborated"` (never promoted to `"counterfactual_verified"`
|
|
1359
|
+
* by telemetry recovery alone!).
|
|
1360
|
+
*/
|
|
1361
|
+
declare function evaluateRemediationWatchdogs(db: SqlDb, options?: {
|
|
1362
|
+
nowIso?: string;
|
|
1363
|
+
minComparableRequests?: number;
|
|
1364
|
+
}): Promise<WatchdogEvaluationSummary>;
|
|
1365
|
+
|
|
796
1366
|
/**
|
|
797
1367
|
* Storage seam for opaque blob payloads — replay rrweb chunks and
|
|
798
1368
|
* pprof profiles.
|
|
@@ -801,7 +1371,7 @@ declare class AlertsStore {
|
|
|
801
1371
|
* - `R2BlobStore` — Cloudflare R2 binding (default on Workers).
|
|
802
1372
|
* - `S3BlobStore` (sibling file) — AWS S3 / MinIO / any S3-compatible.
|
|
803
1373
|
*
|
|
804
|
-
* Replay chunks live under `replays/<session_id>/<chunk_id>`; pprof
|
|
1374
|
+
* Replay chunks live under `replays/<project_id>/<session_id>/<chunk_id>`; pprof
|
|
805
1375
|
* profiles live under `profiles/<service>/<trace_id>/<span_id>`. The
|
|
806
1376
|
* adapter never sees these paths — they're constructed by the callers
|
|
807
1377
|
* (`replay-receiver`, `profile-routes`).
|
|
@@ -976,6 +1546,10 @@ interface EvalRunCandidate {
|
|
|
976
1546
|
modelProvider: string | null;
|
|
977
1547
|
model: string | null;
|
|
978
1548
|
modelVersion: string | null;
|
|
1549
|
+
environment?: string | null;
|
|
1550
|
+
serviceVersion?: string | null;
|
|
1551
|
+
commitSha?: string | null;
|
|
1552
|
+
configDigest?: string | null;
|
|
979
1553
|
}
|
|
980
1554
|
interface EvalRunSourceCase {
|
|
981
1555
|
id: string;
|
|
@@ -997,6 +1571,12 @@ interface EvalRun {
|
|
|
997
1571
|
evalCaseId: string | null;
|
|
998
1572
|
status: EvalRunStatus;
|
|
999
1573
|
candidate: EvalRunCandidate;
|
|
1574
|
+
environment?: string;
|
|
1575
|
+
serviceVersion?: string | null;
|
|
1576
|
+
commitSha?: string | null;
|
|
1577
|
+
configDigest?: string | null;
|
|
1578
|
+
inputPayloadHash?: string | null;
|
|
1579
|
+
failureFingerprint?: string | null;
|
|
1000
1580
|
startedAt: string | null;
|
|
1001
1581
|
endedAt: string | null;
|
|
1002
1582
|
totalCount: number;
|
|
@@ -1014,6 +1594,12 @@ interface EvalRunInput {
|
|
|
1014
1594
|
evalCaseId?: string | null;
|
|
1015
1595
|
status?: EvalRunStatus;
|
|
1016
1596
|
candidate?: Partial<EvalRunCandidate>;
|
|
1597
|
+
environment?: string | null;
|
|
1598
|
+
serviceVersion?: string | null;
|
|
1599
|
+
commitSha?: string | null;
|
|
1600
|
+
configDigest?: string | null;
|
|
1601
|
+
inputPayloadHash?: string | null;
|
|
1602
|
+
failureFingerprint?: string | null;
|
|
1017
1603
|
startedAt?: string | null;
|
|
1018
1604
|
endedAt?: string | null;
|
|
1019
1605
|
totalCount?: number;
|
|
@@ -1152,7 +1738,7 @@ declare class ProjectsStore {
|
|
|
1152
1738
|
ensureDefaultProject(): Promise<void>;
|
|
1153
1739
|
listKeys(projectId: string): Promise<IngestKey[]>;
|
|
1154
1740
|
createKey(projectId: string, name: string): Promise<IngestKeyWithPlaintext>;
|
|
1155
|
-
revokeKey(keyId: string): Promise<boolean>;
|
|
1741
|
+
revokeKey(keyId: string, projectId: string): Promise<boolean>;
|
|
1156
1742
|
findByKeyHash(keyHash: string): Promise<{
|
|
1157
1743
|
projectId: string;
|
|
1158
1744
|
keyId: string;
|
|
@@ -1184,6 +1770,23 @@ declare class PostgresAdapter implements SqlDb {
|
|
|
1184
1770
|
};
|
|
1185
1771
|
}>>;
|
|
1186
1772
|
}
|
|
1773
|
+
/**
|
|
1774
|
+
* Install `pg` result-type parsers so Postgres rows match the shape D1
|
|
1775
|
+
* returns and the shared stores keep working unchanged:
|
|
1776
|
+
*
|
|
1777
|
+
* - BOOLEAN → 0 / 1 (D1 stores flags as INTEGER; stores compare `=== 1`)
|
|
1778
|
+
* - BIGINT → number (`COUNT(*)`, `SUM(bigint)` would otherwise be strings;
|
|
1779
|
+
* integral values above MAX_SAFE_INTEGER throw)
|
|
1780
|
+
* - NUMERIC → number (`SUM`, `EXTRACT(EPOCH …)`; same overflow rule)
|
|
1781
|
+
* - JSON/JSONB → raw text (stores `JSON.parse` the column themselves)
|
|
1782
|
+
*
|
|
1783
|
+
* Call once per process before issuing queries, e.g.
|
|
1784
|
+
* `configurePostgresTypeParsers(pg.types)` in the Node entrypoint.
|
|
1785
|
+
*/
|
|
1786
|
+
interface PostgresTypeParserRegistry {
|
|
1787
|
+
setTypeParser(oid: number, parser: (value: string) => unknown): void;
|
|
1788
|
+
}
|
|
1789
|
+
declare const configurePostgresTypeParsers: (types: PostgresTypeParserRegistry) => void;
|
|
1187
1790
|
|
|
1188
1791
|
/** All built-in plugins in recommended registration order */
|
|
1189
1792
|
declare const allPlugins: CollectorPlugin[];
|
|
@@ -1194,4 +1797,4 @@ declare const _default: hono.Hono<{
|
|
|
1194
1797
|
Bindings: CollectorEnv;
|
|
1195
1798
|
}, hono_types.BlankSchema, "/">;
|
|
1196
1799
|
|
|
1197
|
-
export { type ActionRecord, ActionStore, type AgentRunRecord, AlertsStore, type ArtifactRecord, type BlobListOptions, type BlobListResult, type BlobObject, type BlobPutOptions, type BlobStore, BlobStoreToR2Adapter, type CollectorAuthConfig, type CollectorConfig, CollectorEnv, type CollectorPlugin, CollectorRouteContext, CollectorRuntime, D1Adapter, type EvalCase, type EvalCaseInput, type EvalCaseListOptions, type EvalCaseSourceLinks, EvalCaseSourceNotFoundError, type EvalCaseSourceType, EvalCasesStore, type EvalResultRecord, type EvalRun, type EvalRunCandidate, type EvalRunInput, type EvalRunSourceCase, type EvalRunStatus, type EvalRunsListOptions, Logger, MetricsStore, PostgresAdapter, type PostgresAdapterOptions, ProjectsStore, R2BlobStore, type RetrievalEventRecord, S3BlobStore, type S3BlobStoreOptions, type SpanProcessorPlugin, type SqlDb, type SqlDbFactory, type SqlStatement, type TailEvent, TailHub, type TailKind, type ToolCallRecord, type UsageEventProcessorPlugin, actionRoutesPlugin, aiReceiverPlugin, aiSpanPayloadsProcessorPlugin, alertsRoutesPlugin, allPlugins, analysesRoutesPlugin, askRoutesPlugin, botFilterPlugin, compareValue, connectedRoutesPlugin, createAlertEvaluatorHandler, createAnalysesRunHandler, createDashboardAuth, createDefaultCollectorApp, createRetentionCleanupHandler, createTelemetryCollectorApp, dashboardRoutesPlugin, _default as default, defaultSpanEnrichmentPlugin, evalCasesRoutesPlugin, evaluateAllRules, evidenceRetrievalRoutesPlugin, genAiNormalizerPlugin, identityReceiverPlugin, isEvalCaseSourceType, isEvalRunStatus, issueEnrichmentPlugin, issueInsightsPlugin, logsReceiverPlugin, metricsReceiverPlugin, onboardingRoutesPlugin, otlpReceiverPlugin, platformRoutesPlugin, profileRoutesPlugin, projectsRoutesPlugin, queryRoutesPlugin, redactionProcessorPlugin, replayQueryRoutesPlugin, replayReceiverPlugin, tailRoutesPlugin, timelineRoutesPlugin, uaEnrichmentPlugin, usageNormalizationPlugin, usagePrivacyPlugin, usageQueryRoutesPlugin, usageReceiverPlugin, usersQueryRoutesPlugin, utmEnrichmentPlugin };
|
|
1800
|
+
export { type ActionGraphPurgeSummary, type ActionGraphRetentionOptions, type ActionRecord, ActionStore, type AgentRunRecord, AlertsStore, type AnalysesRunSummary, type ArtifactRecord, type BlobListOptions, type BlobListResult, type BlobObject, type BlobPutOptions, type BlobStore, BlobStoreToR2Adapter, type CollectorAuthConfig, type CollectorConfig, CollectorEnv, type CollectorPlugin, CollectorRouteContext, CollectorRuntime, CounterfactualVerificationError, D1Adapter, type DashboardAuthConfig, type EvalCase, type EvalCaseInput, type EvalCaseListOptions, type EvalCaseSourceLinks, EvalCaseSourceNotFoundError, type EvalCaseSourceType, EvalCasesStore, type EvalResultRecord, type EvalRun, type EvalRunCandidate, type EvalRunInput, type EvalRunSourceCase, type EvalRunStatus, type EvalRunsListOptions, type HostLookup, Logger, MetricsStore, PostgresAdapter, type PostgresAdapterOptions, type PostgresTypeParserRegistry, ProjectsStore, R2BlobStore, RemediationGateError, type RetentionCleanupSummary, type RetrievalEventRecord, S3BlobStore, type S3BlobStoreOptions, type ScheduledTaskHandler, type SpanProcessorPlugin, type SqlDb, type SqlDbFactory, type SqlStatement, type TailEvent, TailHub, type TailKind, type ToolCallRecord, type UsageEventProcessorPlugin, type WatchdogEvaluationSummary, acquireIncidentLease, actionRetentionCutoff, actionRoutesPlugin, aiReceiverPlugin, aiSpanPayloadsProcessorPlugin, alertsRoutesPlugin, allPlugins, analysesRoutesPlugin, approveRemediationProposal, askRoutesPlugin, autosreRoutesPlugin, botFilterPlugin, claimRemediationGrant, compareValue, completeRemediationProposal, computeChangeBlastRadius, computeTarjanScc, configurePostgresTypeParsers, connectedRoutesPlugin, createAlertEvaluatorHandler, createAnalysesRunHandler, createDashboardAuth, createDefaultCollectorApp, createRetentionCleanupHandler, createTelemetryCollectorApp, dashboardRoutesPlugin, _default as default, defaultSpanEnrichmentPlugin, dispatchIncidentWebhook, evalCasesRoutesPlugin, evaluateAllRules, evaluateRemediationWatchdogs, evidenceRetrievalRoutesPlugin, extractSpanLineageAndTopology, failRemediationProposal, findCrossTraceContention, genAiNormalizerPlugin, getChangeEvent, getIncidentInvestigation, getInvestigationFinding, getOntologyGraph, getRemediationProposal, identityReceiverPlugin, isEvalCaseSourceType, isEvalRunStatus, issueEnrichmentPlugin, issueInsightsPlugin, listChangeEvents, listIncidentInvestigations, listRemediationProposals, loadTraceFaultLocusFromDb, localizeTraceFaultLocus, logsReceiverPlugin, metricsReceiverPlugin, onboardingRoutesPlugin, openOrDeduplicateIncident, otlpReceiverPlugin, platformRoutesPlugin, profileRoutesPlugin, projectsRoutesPlugin, proposeRemediationAction, purgeExpiredActionGraph, queryRoutesPlugin, recordChangeEvent, recordInvestigationFinding, redactionProcessorPlugin, rejectRemediationProposal, replayQueryRoutesPlugin, replayReceiverPlugin, searchInvestigationFindings, tailRoutesPlugin, timelineRoutesPlugin, uaEnrichmentPlugin, upsertOntologyFromSpans, usageNormalizationPlugin, usagePrivacyPlugin, usageQueryRoutesPlugin, usageReceiverPlugin, usersQueryRoutesPlugin, utmEnrichmentPlugin, verifyPairedCounterfactualProof };
|