@datasynx/agentic-ai-cartography 2.3.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -390,14 +390,22 @@ interface DriftAlert {
390
390
  /** ISO-8601 UTC generation time. */
391
391
  generatedAt: string;
392
392
  }
393
- /** One configured drift sink. `url` is required when `type === 'webhook'`. */
393
+ /** One configured drift sink. `url` is required for every type except `stdout`. */
394
394
  interface DriftSinkConfig {
395
- type: 'stdout' | 'webhook';
396
- /** Required when type === 'webhook'. */
395
+ type: 'stdout' | 'webhook' | 'slack' | 'pagerduty' | 'jira';
396
+ /** Required for `webhook`/`slack`/`jira`; optional for `pagerduty` (defaults to the Events API). */
397
397
  url?: string;
398
- /** Optional bearer token; falls back to CARTOGRAPHY_DRIFT_TOKEN. */
398
+ /** Bearer token (`webhook`) / Jira API token (`jira`); falls back to CARTOGRAPHY_DRIFT_TOKEN. */
399
399
  token?: string;
400
400
  timeoutMs?: number;
401
+ /** PagerDuty Events API v2 routing key (rides in the body). Falls back to `token`/CARTOGRAPHY_DRIFT_TOKEN. */
402
+ routingKey?: string;
403
+ /** Jira account email (basic-auth user). */
404
+ email?: string;
405
+ /** Jira target project key, e.g. "OPS". */
406
+ project?: string;
407
+ /** Jira issue type name (default "Task"). */
408
+ issueType?: string;
401
409
  }
402
410
  /**
403
411
  * Opt-in drift-alerting block on {@link CartographyConfig}. Absent → the runner
@@ -420,10 +428,17 @@ declare const DriftConfigSchema: z.ZodObject<{
420
428
  type: z.ZodEnum<{
421
429
  stdout: "stdout";
422
430
  webhook: "webhook";
431
+ slack: "slack";
432
+ pagerduty: "pagerduty";
433
+ jira: "jira";
423
434
  }>;
424
435
  url: z.ZodOptional<z.ZodString>;
425
436
  token: z.ZodOptional<z.ZodString>;
426
437
  timeoutMs: z.ZodOptional<z.ZodNumber>;
438
+ routingKey: z.ZodOptional<z.ZodString>;
439
+ email: z.ZodOptional<z.ZodString>;
440
+ project: z.ZodOptional<z.ZodString>;
441
+ issueType: z.ZodOptional<z.ZodString>;
427
442
  }, z.core.$strip>>>;
428
443
  }, z.core.$strip>;
429
444
  /** Machine-readable result formats shared by `discover` (#67) and `schedule`. */
@@ -866,6 +881,99 @@ declare const ComplianceReportSchema: z.ZodObject<{
866
881
  }, z.core.$strip>;
867
882
  type ComplianceReport = z.infer<typeof ComplianceReportSchema>;
868
883
 
884
+ /**
885
+ * RBAC identity types (4.5). A bearer credential resolves to a {@link Principal}
886
+ * `{ subject, tenant, role }`; the HTTP surfaces (MCP transport + REST/GraphQL API)
887
+ * enforce a deny-by-default `can(role, action)` matrix and pin every read to the
888
+ * principal's tenant. Kept dependency-light and free of any import from `db.ts`/
889
+ * `server.ts` so it can be reused by both transports without a cycle.
890
+ */
891
+
892
+ /** Roles, least → most privileged. `admin ⊇ operator ⊇ viewer` (rank-ordered). */
893
+ declare const ROLES: readonly ["viewer", "operator", "admin"];
894
+ type Role = typeof ROLES[number];
895
+ declare const RoleSchema: z.ZodEnum<{
896
+ viewer: "viewer";
897
+ operator: "operator";
898
+ admin: "admin";
899
+ }>;
900
+ /**
901
+ * Gated action classes:
902
+ * - `read` — any read-only query/resource (viewer+).
903
+ * - `discovery` — trigger a scan that mutates the catalog, e.g. `run_discovery` (operator+).
904
+ * - `admin` — manage credentials / admin-only surfaces (admin only).
905
+ */
906
+ declare const ACTIONS: readonly ["read", "discovery", "admin"];
907
+ type Action = typeof ACTIONS[number];
908
+ declare const ActionSchema: z.ZodEnum<{
909
+ read: "read";
910
+ admin: "admin";
911
+ discovery: "discovery";
912
+ }>;
913
+ /** The authenticated caller, bound to exactly one tenant. */
914
+ interface Principal {
915
+ /** Stable identity (token label / username / OIDC `sub`). */
916
+ subject: string;
917
+ /** Org-scope this principal may read/act within. */
918
+ tenant: string;
919
+ role: Role;
920
+ }
921
+ declare const PrincipalSchema: z.ZodObject<{
922
+ subject: z.ZodString;
923
+ tenant: z.ZodString;
924
+ role: z.ZodEnum<{
925
+ viewer: "viewer";
926
+ operator: "operator";
927
+ admin: "admin";
928
+ }>;
929
+ }, z.core.$strip>;
930
+ /** A seeded credential (config-supplied). The token is hashed before storage; never persisted raw. */
931
+ declare const CredentialConfigSchema: z.ZodObject<{
932
+ token: z.ZodString;
933
+ subject: z.ZodString;
934
+ tenant: z.ZodOptional<z.ZodString>;
935
+ role: z.ZodDefault<z.ZodEnum<{
936
+ viewer: "viewer";
937
+ operator: "operator";
938
+ admin: "admin";
939
+ }>>;
940
+ }, z.core.$strip>;
941
+ type CredentialConfig = z.infer<typeof CredentialConfigSchema>;
942
+ /**
943
+ * Opt-in auth block on {@link CartographyConfig}. Absent → today's behavior exactly
944
+ * (loopback no-token → implicit admin; a configured shared token → one implicit admin).
945
+ * When `credentials` are present (here or in the SQLite store), the server runs in RBAC
946
+ * mode: only a known token resolves to a principal, everything else is 401.
947
+ */
948
+ declare const AuthConfigSchema: z.ZodObject<{
949
+ credentials: z.ZodOptional<z.ZodArray<z.ZodObject<{
950
+ token: z.ZodString;
951
+ subject: z.ZodString;
952
+ tenant: z.ZodOptional<z.ZodString>;
953
+ role: z.ZodDefault<z.ZodEnum<{
954
+ viewer: "viewer";
955
+ operator: "operator";
956
+ admin: "admin";
957
+ }>>;
958
+ }, z.core.$strip>>>;
959
+ required: z.ZodOptional<z.ZodBoolean>;
960
+ }, z.core.$strip>;
961
+ type AuthConfig = z.infer<typeof AuthConfigSchema>;
962
+ /** A stored credential record (token already hashed). */
963
+ interface CredentialRecord {
964
+ tokenHash: string;
965
+ subject: string;
966
+ tenant: string;
967
+ role: Role;
968
+ createdAt: string;
969
+ }
970
+ /** Resolves a stored credential by its token hash. Implemented over SQLite (and, later, OIDC). */
971
+ interface CredentialStore {
972
+ /** Number of stored credentials — `0` means "no RBAC configured" (fall back to shared/loopback). */
973
+ count(): number;
974
+ findByHash(tokenHash: string): CredentialRecord | undefined;
975
+ }
976
+
869
977
  /** Attribution applied by an enrichment pass (3.3). `null` clears the field; `undefined` leaves it unchanged. */
870
978
  interface NodeAttribution {
871
979
  owner?: string | null;
@@ -1143,7 +1251,28 @@ declare class CartographyDB {
1143
1251
  limit?: number;
1144
1252
  offset?: number;
1145
1253
  }): EdgeRow[];
1146
- insertEvent(sessionId: string, event: Pick<EventRow, 'eventType' | 'process' | 'pid' | 'target' | 'targetType' | 'port'> & Partial<Pick<EventRow, 'command' | 'resultBytes'>>, taskId?: string): void;
1254
+ insertEvent(sessionId: string, event: Pick<EventRow, 'eventType' | 'process' | 'pid' | 'target' | 'targetType' | 'port'> & Partial<Pick<EventRow, 'command' | 'resultBytes'>>, taskId?: string,
1255
+ /** Authenticated actor (4.5 RBAC) — stamped into the audit trail when present. */
1256
+ actor?: {
1257
+ subject: string;
1258
+ role: string;
1259
+ tenant: string;
1260
+ }): void;
1261
+ /** Number of stored credentials. `0` ⇒ no RBAC configured (fall back to shared/loopback). */
1262
+ countCredentials(): number;
1263
+ /** Look up a credential by its sha256 token hash. */
1264
+ findCredentialByHash(tokenHash: string): CredentialRecord | undefined;
1265
+ /** Upsert a credential (idempotent on the token hash). Stores only the hash, never the raw token. */
1266
+ addCredential(rec: {
1267
+ tokenHash: string;
1268
+ subject: string;
1269
+ tenant: string;
1270
+ role: string;
1271
+ }): void;
1272
+ /** List all credentials (token hashes only — the raw token is unrecoverable). */
1273
+ listCredentials(): Array<CredentialRecord>;
1274
+ /** Revoke every credential for a subject. Returns the number removed. */
1275
+ revokeCredentialsBySubject(subject: string): number;
1147
1276
  getEvents(sessionId: string, since?: string): EventRow[];
1148
1277
  startTask(sessionId: string, description?: string): string;
1149
1278
  endCurrentTask(sessionId: string): void;
@@ -2005,6 +2134,13 @@ interface CreateMcpServerOptions {
2005
2134
  * behaviour exactly. The org is normalized to a tenant.
2006
2135
  */
2007
2136
  org?: string;
2137
+ /**
2138
+ * The authenticated principal (4.5 RBAC). When set, mutating tools (`run_discovery`)
2139
+ * are gated by role: a `viewer` is refused with a forbidden error. Read tools are
2140
+ * unaffected (any principal is at least `viewer`). Unset → no role gating (the
2141
+ * transport already handled 401, or it's an in-process/stdio caller).
2142
+ */
2143
+ principal?: Principal;
2008
2144
  }
2009
2145
  /**
2010
2146
  * Build a fully-configured Cartography MCP server. Call `.connect(transport)` to run it.
@@ -2045,12 +2181,25 @@ interface HttpOptions {
2045
2181
  status: number;
2046
2182
  body: unknown;
2047
2183
  };
2184
+ /**
2185
+ * RBAC (4.5). When `store` holds credentials, the transport runs in RBAC mode: a
2186
+ * request's bearer token must resolve to a {@link Principal} (else 401), and the
2187
+ * principal is passed to `factory(principal)` so the per-session server is pinned to
2188
+ * the principal's tenant and gates mutating tools by role. Without a populated store
2189
+ * the legacy shared-token / open-loopback behavior is preserved.
2190
+ */
2191
+ auth?: {
2192
+ store?: CredentialStore;
2193
+ required?: boolean;
2194
+ };
2195
+ /** Tenant assigned to implicit (shared/loopback) admin principals. */
2196
+ defaultTenant?: string;
2048
2197
  }
2049
2198
  /**
2050
2199
  * Start a Streamable HTTP server. A fresh MCP server instance is created per
2051
2200
  * session via `factory`, so multiple clients can connect concurrently.
2052
2201
  */
2053
- declare function runHttp(factory: () => McpServer, opts?: HttpOptions): Promise<http.Server>;
2202
+ declare function runHttp(factory: (principal?: Principal) => McpServer, opts?: HttpOptions): Promise<http.Server>;
2054
2203
 
2055
2204
  /**
2056
2205
  * Shared HTTP auth + bind-hardening primitives.
@@ -2151,6 +2300,18 @@ interface ApiServerOptions extends BindGuardOptions {
2151
2300
  tenant?: TenantOptions;
2152
2301
  /** Expose `/graphql` (default true). */
2153
2302
  graphql?: boolean;
2303
+ /**
2304
+ * RBAC (4.5). When `store` holds credentials, the API runs in RBAC mode: a request's
2305
+ * bearer token must resolve to a {@link Principal} (else 401), the principal's role must
2306
+ * permit `read` (else 403), and reads are **pinned to the principal's tenant** (any
2307
+ * caller-supplied tenant header/param is ignored). Without a populated store the legacy
2308
+ * behavior is preserved: the configured shared `token` (or open loopback) is one implicit
2309
+ * admin that may still select a tenant via header/param.
2310
+ */
2311
+ auth?: {
2312
+ store?: CredentialStore;
2313
+ required?: boolean;
2314
+ };
2154
2315
  /** Access logger (stderr). */
2155
2316
  log?: (msg: string) => void;
2156
2317
  }
@@ -2212,6 +2373,78 @@ declare function handleGraphqlGet(): {
2212
2373
  body: string;
2213
2374
  };
2214
2375
 
2376
+ /**
2377
+ * The RBAC decision core (4.5): a pure, deny-by-default `can(role, action)` matrix
2378
+ * and the `authorize`/`assertSameTenant` guards the transports call. No I/O, no DB —
2379
+ * trivially unit-testable and identical for the MCP transport and the REST/GraphQL API.
2380
+ */
2381
+
2382
+ /** True iff `role` is at least the minimum role required for `action`. */
2383
+ declare function can(role: Role, action: Action): boolean;
2384
+ /** Thrown when an authenticated principal lacks the role for an action → HTTP 403. */
2385
+ declare class AuthorizationError extends Error {
2386
+ readonly action: Action;
2387
+ readonly role: Role;
2388
+ constructor(action: Action, role: Role);
2389
+ }
2390
+ /** Throw {@link AuthorizationError} unless `principal` may perform `action`. */
2391
+ declare function authorize(principal: Principal, action: Action): void;
2392
+ /** Thrown when a principal references a tenant other than its own → HTTP 403. */
2393
+ declare class TenantMismatchError extends Error {
2394
+ constructor();
2395
+ }
2396
+ /**
2397
+ * The tenant a principal's reads are pinned to. Callers MUST use this rather than any
2398
+ * caller-supplied tenant header/param, so a principal can never read another tenant by
2399
+ * spoofing the request — isolation is structural, not advisory.
2400
+ */
2401
+ declare function scopeReads(principal: Principal): string;
2402
+ /** Throw {@link TenantMismatchError} if `requestedTenant` differs from the principal's tenant. */
2403
+ declare function assertSameTenant(principal: Principal, requestedTenant: string): void;
2404
+
2405
+ /**
2406
+ * Identity resolution (4.5): turn a presented bearer token into a {@link Principal},
2407
+ * or `undefined` (→ 401). Three modes, in precedence order:
2408
+ * 1. **RBAC** — a populated SQLite {@link CredentialStore} is the source of truth; the
2409
+ * token is sha256-hashed and looked up (tokens are never stored or compared raw).
2410
+ * 2. **Shared token** — a single configured token resolves to one implicit `admin`
2411
+ * (today's behavior; constant-time compare).
2412
+ * 3. **Open/loopback dev** — no token configured → implicit `admin`, unless `required`.
2413
+ *
2414
+ * The hash-and-store design means a DB leak never exposes a usable credential, and the
2415
+ * OIDC seam is just another {@link CredentialStore}/resolver behind this one function.
2416
+ */
2417
+
2418
+ /** Stable sha256 hex of a token — the only form ever persisted or compared in the store. */
2419
+ declare function hashToken(token: string): string;
2420
+ /** Minimal DB surface the SQLite credential store needs (CartographyDB satisfies it structurally). */
2421
+ interface CredentialDb {
2422
+ countCredentials(): number;
2423
+ findCredentialByHash(tokenHash: string): CredentialRecord | undefined;
2424
+ }
2425
+ /** {@link CredentialStore} backed by `CartographyDB`'s `auth_credentials` table. */
2426
+ declare class SqliteCredentialStore implements CredentialStore {
2427
+ private readonly db;
2428
+ constructor(db: CredentialDb);
2429
+ count(): number;
2430
+ findByHash(tokenHash: string): CredentialRecord | undefined;
2431
+ }
2432
+ interface ResolveOptions {
2433
+ /** Populated → RBAC mode (source of truth). */
2434
+ store?: CredentialStore;
2435
+ /** Single shared token (one implicit admin) when no store credentials exist. */
2436
+ sharedToken?: string;
2437
+ /** Tenant assigned to implicit (shared/loopback) admin principals. */
2438
+ defaultTenant?: string;
2439
+ /** Reject unauthenticated requests even when neither store nor shared token is set. */
2440
+ required?: boolean;
2441
+ }
2442
+ /**
2443
+ * Resolve an already-parsed bearer token to a {@link Principal}, or `undefined` (→ 401).
2444
+ * `presentedToken` is the value from `bearerToken(authorizationHeader)` (may be undefined).
2445
+ */
2446
+ declare function resolvePrincipal(presentedToken: string | undefined, opts: ResolveOptions): Principal | undefined;
2447
+
2215
2448
  /**
2216
2449
  * Shared entry logic for the read-only API server (4.2), used by both the dedicated
2217
2450
  * `cartography-api` binary and the `api` CLI sub-command. Mirrors `src/mcp/start.ts`:
@@ -2232,6 +2465,8 @@ interface StartApiOptions {
2232
2465
  graphql?: boolean;
2233
2466
  /** Default tenant served when a request names none. */
2234
2467
  tenant?: string;
2468
+ /** Reject unauthenticated requests even on loopback (RBAC `required` mode). */
2469
+ authRequired?: boolean;
2235
2470
  log?: (msg: string) => void;
2236
2471
  }
2237
2472
  interface ParsedApiArgs extends StartApiOptions {
@@ -2840,7 +3075,12 @@ declare const SCAN_ARG_PATTERNS: {
2840
3075
  type ScanArgKind = keyof typeof SCAN_ARG_PATTERNS;
2841
3076
  /** Throw if `value` fails the strict pattern for `kind`; otherwise return it. */
2842
3077
  declare function assertSafeScanArg(kind: ScanArgKind, value: string): string;
2843
- /** Redact `user:password@` credentials embedded in any URL/DSN-like string. */
3078
+ /**
3079
+ * Redact `user:password@` credentials embedded in any URL/DSN-like string. The
3080
+ * quantifiers are length-bounded (schemes <64, userinfo/password <256 chars — far
3081
+ * beyond any real DSN) so the pattern is linear and cannot polynomially backtrack
3082
+ * (ReDoS) on adversarial input like `aaaa…` with no `://`.
3083
+ */
2844
3084
  declare function redactSecrets(value: string): string;
2845
3085
  /** Recursively redact secrets from arbitrary metadata before persistence. */
2846
3086
  declare function redactValue(value: unknown): unknown;
@@ -3269,6 +3509,42 @@ interface WebhookSinkOptions {
3269
3509
  token?: string;
3270
3510
  timeoutMs?: number;
3271
3511
  }
3512
+ /** Injectable fetch (defaults to the global) — lets tests deliver without a socket. */
3513
+ type FetchLike = (url: string, init: RequestInit) => Promise<{
3514
+ ok: boolean;
3515
+ status: number;
3516
+ }>;
3517
+ interface PostJsonOptions {
3518
+ url: string;
3519
+ body: unknown;
3520
+ /** Extra request headers (e.g. provider auth). `content-type: application/json` is always set. */
3521
+ headers?: Record<string, string>;
3522
+ timeoutMs?: number;
3523
+ /** Sink name for structured logs (never logs the url/token/body). */
3524
+ sinkName: string;
3525
+ /** Injected fetch for tests; defaults to the global. */
3526
+ fetchImpl?: FetchLike;
3527
+ }
3528
+ /**
3529
+ * Shared outbound JSON POST carrying the load-bearing sink hardening, reused by
3530
+ * {@link WebhookSink} and the Slack/PagerDuty/Jira provider sinks so there is exactly
3531
+ * one egress code path:
3532
+ * - refuses a non-`https:` / non-loopback target ({@link isSecureWebhookUrl}, SSRF/plaintext guard);
3533
+ * - `AbortSignal.timeout` bounded;
3534
+ * - **never throws** for a transient failure (logs and resolves so the runner continues);
3535
+ * - logs only `stripSensitive(url)` (host:port) — never the full url, headers, token, or body.
3536
+ * The body must already be redaction-safe (callers pass `redactValue(...)` output or a
3537
+ * provider payload derived from it).
3538
+ */
3539
+ declare function postJson(opts: PostJsonOptions): Promise<void>;
3540
+ /**
3541
+ * True if `url` is safe to POST to: `https:`, or `http:` only to a loopback host,
3542
+ * or any scheme when the documented `CARTOGRAPHY_ALLOW_INSECURE_SYNC=1` escape
3543
+ * hatch (test-only) is set. An unparseable URL is treated as insecure. Mirrors the
3544
+ * 2.11 `pushDeltas` guard so the drift feature never silently exfiltrates over the
3545
+ * wire in plaintext.
3546
+ */
3547
+ declare function isSecureWebhookUrl(url: string, env?: NodeJS.ProcessEnv): boolean;
3272
3548
  /**
3273
3549
  * Outbound sink: POSTs the alert as JSON to an operator-configured endpoint. The
3274
3550
  * first and only outbound network surface of the drift feature — off by default
@@ -3290,11 +3566,114 @@ declare class WebhookSink implements DriftSink {
3290
3566
  emit(alert: DriftAlert): Promise<void>;
3291
3567
  }
3292
3568
 
3569
+ /**
3570
+ * Provider drift sinks (4.4): Slack / PagerDuty / Jira. Each is a thin {@link DriftSink}
3571
+ * that (1) redacts the alert (`redactValue`), (2) maps it to the provider payload via the
3572
+ * pure adapters in `providers.ts`, and (3) delivers it through the shared {@link postJson}
3573
+ * helper — inheriting the *exact* `WebhookSink` hardening (https-or-loopback SSRF guard,
3574
+ * bounded timeout, never-throw, `stripSensitive` log-only). They differ only in where the
3575
+ * provider places its secret: Slack in the URL, PagerDuty as a `routing_key` in the body,
3576
+ * Jira as an `Authorization: Basic` header.
3577
+ */
3578
+
3579
+ /** Default PagerDuty Events API v2 ingest endpoint. */
3580
+ declare const PAGERDUTY_ENQUEUE_URL = "https://events.pagerduty.com/v2/enqueue";
3581
+ interface BaseSinkOptions {
3582
+ url: string;
3583
+ timeoutMs?: number;
3584
+ /** Injected fetch for tests; defaults to the global. */
3585
+ fetchImpl?: FetchLike;
3586
+ }
3587
+ /** Slack incoming webhook. The configured `url` is the secret; no auth header is sent. */
3588
+ declare class SlackSink implements DriftSink {
3589
+ private readonly opts;
3590
+ readonly name = "slack";
3591
+ constructor(opts: BaseSinkOptions);
3592
+ emit(alert: DriftAlert): Promise<void>;
3593
+ }
3594
+ interface PagerDutySinkOptions extends BaseSinkOptions {
3595
+ /** Events API v2 routing key (rides in the body, PagerDuty's auth model). */
3596
+ routingKey: string;
3597
+ }
3598
+ /** PagerDuty Events API v2 `trigger`. `url` defaults to {@link PAGERDUTY_ENQUEUE_URL}. */
3599
+ declare class PagerDutySink implements DriftSink {
3600
+ private readonly opts;
3601
+ readonly name = "pagerduty";
3602
+ constructor(opts: PagerDutySinkOptions);
3603
+ emit(alert: DriftAlert): Promise<void>;
3604
+ }
3605
+ interface JiraSinkOptions extends BaseSinkOptions {
3606
+ /** Jira account email (basic-auth user). */
3607
+ email: string;
3608
+ /** Jira API token (basic-auth pass). */
3609
+ token: string;
3610
+ /** Target project key (e.g. "OPS"). */
3611
+ project: string;
3612
+ /** Issue type name (default "Task"). */
3613
+ issueType?: string;
3614
+ }
3615
+ /** Jira REST API v2 create-issue, authenticated with `Authorization: Basic base64(email:token)`. */
3616
+ declare class JiraSink implements DriftSink {
3617
+ private readonly opts;
3618
+ readonly name = "jira";
3619
+ constructor(opts: JiraSinkOptions);
3620
+ emit(alert: DriftAlert): Promise<void>;
3621
+ }
3622
+
3623
+ /**
3624
+ * Pure provider payload mappers (4.4): a classified {@link DriftAlert} → the JSON
3625
+ * shape Slack / PagerDuty / Jira each expect. Deterministic, no I/O, no secrets —
3626
+ * they operate on the **already-`redactValue`'d** alert the sinks pass in, and read
3627
+ * only structured fields (severity/counts/item refs), never raw node metadata. The
3628
+ * delivery + auth + SSRF hardening lives in `provider-sink.ts`/`webhook.ts`; these
3629
+ * are just shape transforms, so they are trivially snapshot-testable.
3630
+ */
3631
+
3632
+ interface SlackMessage {
3633
+ text: string;
3634
+ blocks: unknown[];
3635
+ }
3636
+ /** Map an alert to a Slack incoming-webhook message (Block Kit). The webhook URL is the secret. */
3637
+ declare function formatSlack(alert: DriftAlert): SlackMessage;
3638
+ interface PagerDutyEvent {
3639
+ routing_key: string;
3640
+ event_action: 'trigger';
3641
+ dedup_key: string;
3642
+ payload: {
3643
+ summary: string;
3644
+ source: string;
3645
+ severity: 'info' | 'warning' | 'critical';
3646
+ timestamp: string;
3647
+ custom_details: Record<string, unknown>;
3648
+ };
3649
+ }
3650
+ /** Map an alert to a PagerDuty Events API v2 `trigger`. `routingKey` rides in the body (PD's auth model). */
3651
+ declare function formatPagerDuty(alert: DriftAlert, routingKey: string): PagerDutyEvent;
3652
+ interface JiraIssue {
3653
+ fields: {
3654
+ project: {
3655
+ key: string;
3656
+ };
3657
+ issuetype: {
3658
+ name: string;
3659
+ };
3660
+ summary: string;
3661
+ description: string;
3662
+ };
3663
+ }
3664
+ interface JiraOptions {
3665
+ project: string;
3666
+ issueType?: string;
3667
+ }
3668
+ /** Map an alert to a Jira create-issue body. Auth (Basic email:token) is applied by the sink, not here. */
3669
+ declare function formatJira(alert: DriftAlert, opts: JiraOptions): JiraIssue;
3670
+
3293
3671
  /**
3294
3672
  * Construct sinks from config. Absent/empty config → `[new StdoutSink()]` (the
3295
- * local default). A webhook sink's token falls back to `CARTOGRAPHY_DRIFT_TOKEN`
3296
- * when not given explicitly (mirroring `CARTOGRAPHY_HTTP_TOKEN`). A webhook entry
3297
- * without a url is skipped defensively (the schema already rejects it).
3673
+ * local default). Secrets (webhook `token`, Jira token, PagerDuty routing key) fall
3674
+ * back to `CARTOGRAPHY_DRIFT_TOKEN` when not given explicitly (mirroring
3675
+ * `CARTOGRAPHY_HTTP_TOKEN`). A provider entry missing a required field is skipped
3676
+ * with a warning rather than aborting the others — graceful degradation.
3298
3677
  */
3299
3678
  declare function buildSinks(drift?: DriftConfig): DriftSink[];
3300
3679
 
@@ -3710,4 +4089,4 @@ declare function logInfo(message: string, context?: Record<string, unknown>): vo
3710
4089
  declare function logWarn(message: string, context?: Record<string, unknown>): void;
3711
4090
  declare function logError(message: string, context?: Record<string, unknown>): void;
3712
4091
 
3713
- export { ANOMALY_KINDS, ANOMALY_SEVERITIES, type AgentProvider, type AgentRunContext, type AgentTool, type Anomaly, type AnomalyConfig, type AnomalyKind, type AnomalySeverity, type AnomalyThresholds, type AnonViolation, type AnonymizationLevel, type ApiServerOptions, type AskUserFn, type BindGuardOptions, CLIENTS, CONFIDENCE, COST_PERIODS, type CartographyConfig, CartographyDB, type CartographyMapData, type CentralDbConfig, CentralDbConfigSchema, type ClassifiedItem, type ClassifyInput, type ClassifyResult, type ClientSpec, type Cluster, ClusterSchema, type ComplianceInput, type ComplianceReport, ComplianceReportSchema, type ComplianceRule, ComplianceRuleSchema, type Condition, ConditionSchema, ConfigError, type ConfigFile, ConfigFileSchema, type ConfigFormat, type Connection, ConnectionSchema, type Contributor, type ControlResult, ControlResultSchema, type CostEntry, CostEntrySchema, type CostPeriod, type CostRecord, type CostSource, type CreateMcpServerOptions, type CronFields, CsvCostSource, type CsvCostSourceOptions, DEFAULT_ANOMALY_THRESHOLDS, DEFAULT_FAST_MODEL, DEFAULT_LEAD_MODEL, DEFAULT_SERVER_NAME, DEFAULT_TENANT, DOMAIN_COLORS, DOMAIN_PALETTE, DRIFT_FIELDS, type DataAsset, DataAssetSchema, type DependencyQuery, type DiscoveryEdge, type DiscoveryEvent, type DiscoveryFn, type DiscoveryNode, type DriftAlert, type DriftAlertItem, type DriftConfig, DriftConfigSchema, type DriftField, type DriftItemKind, type DriftRunRow, type DriftSink, type DriftSinkConfig, EDGE_RELATIONSHIPS, type EdgeRelationship, type EdgeRow, EdgeSchema, type EmbeddingProvider, type EnrichResult, type EntryOptions, type EstablishedConn, type EvidenceKind, type FragmentKind, type GraphSummary, type HealthResult, type HttpOptions, INGEST_SCHEMA_VERSION, type IngestEnvelope, IngestEnvelopeSchema, type IngestHandler, type IngestOptions, type IngestResponse, type IngestResult, type InstallPlan, InvalidTenantError, LOOPBACK_HOSTS, type LocalDiscoveryOptions, type LocalDiscoveryResult, type LogEntry, type LogLevel, MCP_BIN, type MatchStrategy, NODE_TYPES, NODE_TYPE_GROUPS, type NlIntent, type NlQueryOptions, type NlQueryResult, type NlRelation, type NodeAttribution, type NodeChange, type NodeIdentity, type NodeQuery, type NodeRow, NodeSchema, type NodeType, type NodesResult, NotFoundError, OUTPUT_FORMATS, type OrgKeyOptions, type OrgSummary, type OsKind, type OutputFormat, PACKAGE_NAME, PENDING_STATUSES, PERSONAL, PORT_MAP, PRIVATE_IP, PUSH_SCHEMA_VERSION, type ParsedApiArgs, type PendingShareRow, type PendingStatus, type PlanOptions, type PolicyResult, type ProviderFactory, type ProviderName, ProviderRegistry, type PushItem, type PushOptions, type PushResult, type QueryBackend, RELATION_TO_DIRECTION, type ResolveContext, type RuleCheck, RuleCheckSchema, type RuleScope, type Ruleset, RulesetSchema, type RunDriftOptions, SCAN_ARG_PATTERNS, SDL, SECURITY_METADATA_KEYS, SEVERITIES, SEVERITY_WEIGHT, SHARING_LEVELS, type ScanArgKind, type ScanContext, type ScanHintParams, type ScanResult, type Scanner, type ScannerPlugin, type ScannerPluginApi, ScannerRegistry, ScannerShape, type ScheduleConfig, ScheduleConfigSchema, type ScheduledRunResult, type Scope, type SearchFn, type SemanticSearchOptions, type ServerEntry, type SessionRow, type Severity, type SharePreview, type SharePreviewEntry, type SharingLevel, SharingLevelSchema, type SharingPolicy, type ShellKind, SqliteQueryBackend, SqliteStoreBackend, type StartApiOptions, StdoutSink, type StoreBackend, type SyncClassifyOptions, type SyncClassifyResult, TENANT_HEADER, type TenantContext, type TenantOptions, type ToolResult, type TopologyDelta, type TopologyDiff, type TopologyInput, type TraversalResult, VectorStore, WebhookSink, type WebhookSinkOptions, applyInstall, applySharingLevel, assertReadOnly, assertSafeBind, assertSafeScanArg, assignColors, bearerToken, bookmarksScanner, buildCartographyToolHandlers, buildMapData, buildOpenApiDocument, buildReport, buildSinks, centralDbFromEnv, checkBearer, checkPrerequisites, checkReadOnly, clampText, classify, classifyDrift, cleanupTempFiles, cloudAwsScanner, cloudAzureScanner, cloudGcpScanner, codeAddMcpCommand, computeCentroid, computeClusterBounds, computeIdentity, connectionsScanner, contentHash, createBashTool, createCartographyTools, createClaudeProvider, createDefaultRegistry, createHashEmbedder, createIngestHandler, createLocalEmbedder, createMcpServer, createOllamaProvider, createOpenAIProvider, createScanRunner, createSemanticSearch, createSqliteQueryBackend, currentOs, cursorDeeplink, databasesScanner, deepMerge, defaultAllowedHosts, defaultConfig, defaultContext, defaultProviderRegistry, defaultRegistry, defaultServerEntry, definePlugin, deriveSessionName, detectAnomalies, detectOrphans, detectShadowIt, diffTopology, edgesToConnections, enrichCosts, evaluateCheck, evaluateRule, evidenceLine, executeGraphql, executeNlQuery, exportAll, exportBackstageYAML, exportComplianceReport, exportCostCSV, exportCostSummary, exportDiscoveryApp, exportJGF, exportJSON, extractListeningPorts, filterBySeverity, findAnonViolations, formatComplianceText, generateDependencyMermaid, generateDiffMermaid, generateTopologyMermaid, getClient, getRuleset, globalId, groupByDomain, handleGraphqlGet, hexCorners, hexDistance, hexNeighbors, hexRing, hexSpiral, hexToPixel, hmacKey, hostname, ingestEnvelope, installedAppsScanner, isLoopbackHost, isPersonalHost, isReadOnlyCommand, isRemembered, k8sScanner, keyMetaOf, layoutClusters, listClients, listRulesets, loadConfig, loadOrgKey, loadPlugins, loadRuleset, localDiscoveryFn, log, logDebug, logError, logInfo, logWarn, machineId, maxSeverity, mcpServerObject, newAnomalies, nextRun, nodesToAssets, normalizeId, normalizeTenant, orgKeyPath, osUser, parseApiArgs, parseComposeDeps, parseConfig, parseConnectionString, parseCostCsv, parseCron, parseEstablished, parseNginxUpstreams, parseNlQuery, parseScanHint, pixelToHex, planInstall, portsScanner, previewShare, pseudonymize, pseudonymizeFragment, pseudonymizeString, pushDeltas, readConfigFile, redactConnectionString, redactSecrets, redactValue, renderDiff, resolveEffectiveLevel, resolveNlQuery, resolveSharingLevel, resolveTenant, revalidateAnonymized, reversalKey, reversePseudonym, rotateOrgKey, runApi, runDiscovery, runDrift, runHttp, runLocalDiscovery, runOnce, runStdio, runSyncClassify, safeEnv, safeJson, safetyHook, sanitizeUntrusted, sanitizeValue, scoreTopology, securityRelevantChange, serializeConfig, serviceConfigScanner, setVerbose, shadeVariant, shapeToJsonSchema, shareHash, splitSegments, stableStringify, startApi, stripSensitive, timingSafeEqual, validateScanner, vscodeDeeplink, zodToJsonSchema };
4092
+ export { ACTIONS, ANOMALY_KINDS, ANOMALY_SEVERITIES, type Action, ActionSchema, type AgentProvider, type AgentRunContext, type AgentTool, type Anomaly, type AnomalyConfig, type AnomalyKind, type AnomalySeverity, type AnomalyThresholds, type AnonViolation, type AnonymizationLevel, type ApiServerOptions, type AskUserFn, type AuthConfig, AuthConfigSchema, AuthorizationError, type BindGuardOptions, CLIENTS, CONFIDENCE, COST_PERIODS, type CartographyConfig, CartographyDB, type CartographyMapData, type CentralDbConfig, CentralDbConfigSchema, type ClassifiedItem, type ClassifyInput, type ClassifyResult, type ClientSpec, type Cluster, ClusterSchema, type ComplianceInput, type ComplianceReport, ComplianceReportSchema, type ComplianceRule, ComplianceRuleSchema, type Condition, ConditionSchema, ConfigError, type ConfigFile, ConfigFileSchema, type ConfigFormat, type Connection, ConnectionSchema, type Contributor, type ControlResult, ControlResultSchema, type CostEntry, CostEntrySchema, type CostPeriod, type CostRecord, type CostSource, type CreateMcpServerOptions, type CredentialConfig, CredentialConfigSchema, type CredentialDb, type CredentialRecord, type CredentialStore, type CronFields, CsvCostSource, type CsvCostSourceOptions, DEFAULT_ANOMALY_THRESHOLDS, DEFAULT_FAST_MODEL, DEFAULT_LEAD_MODEL, DEFAULT_SERVER_NAME, DEFAULT_TENANT, DOMAIN_COLORS, DOMAIN_PALETTE, DRIFT_FIELDS, type DataAsset, DataAssetSchema, type DependencyQuery, type DiscoveryEdge, type DiscoveryEvent, type DiscoveryFn, type DiscoveryNode, type DriftAlert, type DriftAlertItem, type DriftConfig, DriftConfigSchema, type DriftField, type DriftItemKind, type DriftRunRow, type DriftSink, type DriftSinkConfig, EDGE_RELATIONSHIPS, type EdgeRelationship, type EdgeRow, EdgeSchema, type EmbeddingProvider, type EnrichResult, type EntryOptions, type EstablishedConn, type EvidenceKind, type FetchLike, type FragmentKind, type GraphSummary, type HealthResult, type HttpOptions, INGEST_SCHEMA_VERSION, type IngestEnvelope, IngestEnvelopeSchema, type IngestHandler, type IngestOptions, type IngestResponse, type IngestResult, type InstallPlan, InvalidTenantError, type JiraIssue, type JiraOptions, JiraSink, type JiraSinkOptions, LOOPBACK_HOSTS, type LocalDiscoveryOptions, type LocalDiscoveryResult, type LogEntry, type LogLevel, MCP_BIN, type MatchStrategy, NODE_TYPES, NODE_TYPE_GROUPS, type NlIntent, type NlQueryOptions, type NlQueryResult, type NlRelation, type NodeAttribution, type NodeChange, type NodeIdentity, type NodeQuery, type NodeRow, NodeSchema, type NodeType, type NodesResult, NotFoundError, OUTPUT_FORMATS, type OrgKeyOptions, type OrgSummary, type OsKind, type OutputFormat, PACKAGE_NAME, PAGERDUTY_ENQUEUE_URL, PENDING_STATUSES, PERSONAL, PORT_MAP, PRIVATE_IP, PUSH_SCHEMA_VERSION, type PagerDutyEvent, PagerDutySink, type PagerDutySinkOptions, type ParsedApiArgs, type PendingShareRow, type PendingStatus, type PlanOptions, type PolicyResult, type PostJsonOptions, type Principal, PrincipalSchema, type ProviderFactory, type ProviderName, ProviderRegistry, type PushItem, type PushOptions, type PushResult, type QueryBackend, RELATION_TO_DIRECTION, ROLES, type ResolveContext, type ResolveOptions, type Role, RoleSchema, type RuleCheck, RuleCheckSchema, type RuleScope, type Ruleset, RulesetSchema, type RunDriftOptions, SCAN_ARG_PATTERNS, SDL, SECURITY_METADATA_KEYS, SEVERITIES, SEVERITY_WEIGHT, SHARING_LEVELS, type ScanArgKind, type ScanContext, type ScanHintParams, type ScanResult, type Scanner, type ScannerPlugin, type ScannerPluginApi, ScannerRegistry, ScannerShape, type ScheduleConfig, ScheduleConfigSchema, type ScheduledRunResult, type Scope, type SearchFn, type SemanticSearchOptions, type ServerEntry, type SessionRow, type Severity, type SharePreview, type SharePreviewEntry, type SharingLevel, SharingLevelSchema, type SharingPolicy, type ShellKind, type SlackMessage, SlackSink, SqliteCredentialStore, SqliteQueryBackend, SqliteStoreBackend, type StartApiOptions, StdoutSink, type StoreBackend, type SyncClassifyOptions, type SyncClassifyResult, TENANT_HEADER, type TenantContext, TenantMismatchError, type TenantOptions, type ToolResult, type TopologyDelta, type TopologyDiff, type TopologyInput, type TraversalResult, VectorStore, WebhookSink, type WebhookSinkOptions, applyInstall, applySharingLevel, assertReadOnly, assertSafeBind, assertSafeScanArg, assertSameTenant, assignColors, authorize, bearerToken, bookmarksScanner, buildCartographyToolHandlers, buildMapData, buildOpenApiDocument, buildReport, buildSinks, can, centralDbFromEnv, checkBearer, checkPrerequisites, checkReadOnly, clampText, classify, classifyDrift, cleanupTempFiles, cloudAwsScanner, cloudAzureScanner, cloudGcpScanner, codeAddMcpCommand, computeCentroid, computeClusterBounds, computeIdentity, connectionsScanner, contentHash, createBashTool, createCartographyTools, createClaudeProvider, createDefaultRegistry, createHashEmbedder, createIngestHandler, createLocalEmbedder, createMcpServer, createOllamaProvider, createOpenAIProvider, createScanRunner, createSemanticSearch, createSqliteQueryBackend, currentOs, cursorDeeplink, databasesScanner, deepMerge, defaultAllowedHosts, defaultConfig, defaultContext, defaultProviderRegistry, defaultRegistry, defaultServerEntry, definePlugin, deriveSessionName, detectAnomalies, detectOrphans, detectShadowIt, diffTopology, edgesToConnections, enrichCosts, evaluateCheck, evaluateRule, evidenceLine, executeGraphql, executeNlQuery, exportAll, exportBackstageYAML, exportComplianceReport, exportCostCSV, exportCostSummary, exportDiscoveryApp, exportJGF, exportJSON, extractListeningPorts, filterBySeverity, findAnonViolations, formatComplianceText, formatJira, formatPagerDuty, formatSlack, generateDependencyMermaid, generateDiffMermaid, generateTopologyMermaid, getClient, getRuleset, globalId, groupByDomain, handleGraphqlGet, hashToken, hexCorners, hexDistance, hexNeighbors, hexRing, hexSpiral, hexToPixel, hmacKey, hostname, ingestEnvelope, installedAppsScanner, isLoopbackHost, isPersonalHost, isReadOnlyCommand, isRemembered, isSecureWebhookUrl, k8sScanner, keyMetaOf, layoutClusters, listClients, listRulesets, loadConfig, loadOrgKey, loadPlugins, loadRuleset, localDiscoveryFn, log, logDebug, logError, logInfo, logWarn, machineId, maxSeverity, mcpServerObject, newAnomalies, nextRun, nodesToAssets, normalizeId, normalizeTenant, orgKeyPath, osUser, parseApiArgs, parseComposeDeps, parseConfig, parseConnectionString, parseCostCsv, parseCron, parseEstablished, parseNginxUpstreams, parseNlQuery, parseScanHint, pixelToHex, planInstall, portsScanner, postJson, previewShare, pseudonymize, pseudonymizeFragment, pseudonymizeString, pushDeltas, readConfigFile, redactConnectionString, redactSecrets, redactValue, renderDiff, resolveEffectiveLevel, resolveNlQuery, resolvePrincipal, resolveSharingLevel, resolveTenant, revalidateAnonymized, reversalKey, reversePseudonym, rotateOrgKey, runApi, runDiscovery, runDrift, runHttp, runLocalDiscovery, runOnce, runStdio, runSyncClassify, safeEnv, safeJson, safetyHook, sanitizeUntrusted, sanitizeValue, scopeReads, scoreTopology, securityRelevantChange, serializeConfig, serviceConfigScanner, setVerbose, shadeVariant, shapeToJsonSchema, shareHash, splitSegments, stableStringify, startApi, stripSensitive, timingSafeEqual, validateScanner, vscodeDeeplink, zodToJsonSchema };