@datasynx/agentic-ai-cartography 2.4.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.js CHANGED
@@ -2815,7 +2815,10 @@ CREATE TABLE IF NOT EXISTS activity_events (
2815
2815
  duration_ms INTEGER,
2816
2816
  command TEXT,
2817
2817
  result_bytes INTEGER,
2818
- tenant TEXT NOT NULL DEFAULT 'local'
2818
+ tenant TEXT NOT NULL DEFAULT 'local',
2819
+ actor_subject TEXT,
2820
+ actor_role TEXT,
2821
+ actor_tenant TEXT
2819
2822
  );
2820
2823
 
2821
2824
  CREATE TABLE IF NOT EXISTS tasks (
@@ -2924,6 +2927,16 @@ CREATE INDEX IF NOT EXISTS idx_nodes_tenant_content ON nodes(tenant, content_has
2924
2927
  CREATE INDEX IF NOT EXISTS idx_contrib_org ON node_contributors(organization, global_id);
2925
2928
  CREATE INDEX IF NOT EXISTS idx_nodes_owner ON nodes(session_id, owner);
2926
2929
  `;
2930
+ var AUTH_SCHEMA = `
2931
+ CREATE TABLE IF NOT EXISTS auth_credentials (
2932
+ token_hash TEXT PRIMARY KEY,
2933
+ subject TEXT NOT NULL,
2934
+ tenant TEXT NOT NULL DEFAULT 'local',
2935
+ role TEXT NOT NULL,
2936
+ created_at TEXT NOT NULL
2937
+ );
2938
+ CREATE INDEX IF NOT EXISTS idx_auth_subject ON auth_credentials(subject);
2939
+ `;
2927
2940
  var CartographyDB = class {
2928
2941
  db;
2929
2942
  /** 3.6 anomaly settings; defaults apply when no `anomaly` config is supplied. */
@@ -2943,7 +2956,8 @@ var CartographyDB = class {
2943
2956
  const version = this.db.pragma("user_version", { simple: true });
2944
2957
  if (version === 0) {
2945
2958
  this.db.exec(SCHEMA);
2946
- this.db.pragma("user_version = 14");
2959
+ this.db.exec(AUTH_SCHEMA);
2960
+ this.db.pragma("user_version = 15");
2947
2961
  return;
2948
2962
  } else if (version === 1) {
2949
2963
  const cols = this.db.prepare("PRAGMA table_info(nodes)").all().map((c) => c.name);
@@ -3129,6 +3143,18 @@ var CartographyDB = class {
3129
3143
  }
3130
3144
  this.db.pragma("user_version = 14");
3131
3145
  }
3146
+ const v14 = this.db.pragma("user_version", { simple: true });
3147
+ if (v14 < 15) {
3148
+ this.db.exec(AUTH_SCHEMA);
3149
+ const ev = this.db.prepare("PRAGMA table_info(activity_events)").all();
3150
+ if (ev.length > 0) {
3151
+ const cols = ev.map((c) => c.name);
3152
+ if (!cols.includes("actor_subject")) this.db.exec("ALTER TABLE activity_events ADD COLUMN actor_subject TEXT");
3153
+ if (!cols.includes("actor_role")) this.db.exec("ALTER TABLE activity_events ADD COLUMN actor_role TEXT");
3154
+ if (!cols.includes("actor_tenant")) this.db.exec("ALTER TABLE activity_events ADD COLUMN actor_tenant TEXT");
3155
+ }
3156
+ this.db.pragma("user_version = 15");
3157
+ }
3132
3158
  }
3133
3159
  close() {
3134
3160
  this.db.pragma("optimize");
@@ -3559,13 +3585,13 @@ var CartographyDB = class {
3559
3585
  });
3560
3586
  }
3561
3587
  // ── Events ──────────────────────────────
3562
- insertEvent(sessionId, event, taskId) {
3588
+ insertEvent(sessionId, event, taskId, actor) {
3563
3589
  const id = crypto.randomUUID();
3564
3590
  const tenant = this.tenantOf(sessionId);
3565
3591
  this.db.prepare(`
3566
3592
  INSERT INTO activity_events
3567
- (id, session_id, task_id, timestamp, event_type, process, pid, target, target_type, port, command, result_bytes, tenant)
3568
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3593
+ (id, session_id, task_id, timestamp, event_type, process, pid, target, target_type, port, command, result_bytes, tenant, actor_subject, actor_role, actor_tenant)
3594
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3569
3595
  `).run(
3570
3596
  id,
3571
3597
  sessionId,
@@ -3579,9 +3605,52 @@ var CartographyDB = class {
3579
3605
  event.port ?? null,
3580
3606
  event.command ?? null,
3581
3607
  event.resultBytes ?? null,
3582
- tenant
3608
+ tenant,
3609
+ actor?.subject ?? null,
3610
+ actor?.role ?? null,
3611
+ actor?.tenant ?? null
3583
3612
  );
3584
3613
  }
3614
+ // ── RBAC credential store (4.5) ─────────────
3615
+ /** Number of stored credentials. `0` ⇒ no RBAC configured (fall back to shared/loopback). */
3616
+ countCredentials() {
3617
+ return this.db.prepare("SELECT COUNT(*) AS n FROM auth_credentials").get().n;
3618
+ }
3619
+ /** Look up a credential by its sha256 token hash. */
3620
+ findCredentialByHash(tokenHash) {
3621
+ const r = this.db.prepare("SELECT * FROM auth_credentials WHERE token_hash = ?").get(tokenHash);
3622
+ if (!r) return void 0;
3623
+ return {
3624
+ tokenHash: r["token_hash"],
3625
+ subject: r["subject"],
3626
+ tenant: r["tenant"],
3627
+ role: r["role"],
3628
+ createdAt: r["created_at"]
3629
+ };
3630
+ }
3631
+ /** Upsert a credential (idempotent on the token hash). Stores only the hash, never the raw token. */
3632
+ addCredential(rec) {
3633
+ this.db.prepare(`
3634
+ INSERT INTO auth_credentials (token_hash, subject, tenant, role, created_at)
3635
+ VALUES (?, ?, ?, ?, ?)
3636
+ ON CONFLICT(token_hash) DO UPDATE SET subject = excluded.subject, tenant = excluded.tenant, role = excluded.role
3637
+ `).run(rec.tokenHash, rec.subject, rec.tenant, rec.role, (/* @__PURE__ */ new Date()).toISOString());
3638
+ }
3639
+ /** List all credentials (token hashes only — the raw token is unrecoverable). */
3640
+ listCredentials() {
3641
+ const rows = this.db.prepare("SELECT * FROM auth_credentials ORDER BY created_at").all();
3642
+ return rows.map((r) => ({
3643
+ tokenHash: r["token_hash"],
3644
+ subject: r["subject"],
3645
+ tenant: r["tenant"],
3646
+ role: r["role"],
3647
+ createdAt: r["created_at"]
3648
+ }));
3649
+ }
3650
+ /** Revoke every credential for a subject. Returns the number removed. */
3651
+ revokeCredentialsBySubject(subject) {
3652
+ return this.db.prepare("DELETE FROM auth_credentials WHERE subject = ?").run(subject).changes;
3653
+ }
3585
3654
  getEvents(sessionId, since) {
3586
3655
  const rows = since ? this.db.prepare("SELECT * FROM activity_events WHERE session_id = ? AND timestamp > ? ORDER BY timestamp").all(sessionId, since) : this.db.prepare("SELECT * FROM activity_events WHERE session_id = ? ORDER BY timestamp").all(sessionId);
3587
3656
  return rows.map((r) => {
@@ -5260,6 +5329,36 @@ async function runDrift(db, config, opts = {}) {
5260
5329
  return alert;
5261
5330
  }
5262
5331
 
5332
+ // src/auth/rbac.ts
5333
+ var ROLE_RANK = { viewer: 1, operator: 2, admin: 3 };
5334
+ var ACTION_MIN_ROLE = { read: "viewer", discovery: "operator", admin: "admin" };
5335
+ function can(role, action) {
5336
+ return ROLE_RANK[role] >= ROLE_RANK[ACTION_MIN_ROLE[action]];
5337
+ }
5338
+ var AuthorizationError = class extends Error {
5339
+ constructor(action, role) {
5340
+ super(`forbidden: role '${role}' may not perform '${action}'`);
5341
+ this.action = action;
5342
+ this.role = role;
5343
+ this.name = "AuthorizationError";
5344
+ }
5345
+ };
5346
+ function authorize(principal, action) {
5347
+ if (!can(principal.role, action)) throw new AuthorizationError(action, principal.role);
5348
+ }
5349
+ var TenantMismatchError = class extends Error {
5350
+ constructor() {
5351
+ super("forbidden: principal is not scoped to the requested tenant");
5352
+ this.name = "TenantMismatchError";
5353
+ }
5354
+ };
5355
+ function scopeReads(principal) {
5356
+ return principal.tenant;
5357
+ }
5358
+ function assertSameTenant(principal, requestedTenant) {
5359
+ if (requestedTenant !== principal.tenant) throw new TenantMismatchError();
5360
+ }
5361
+
5263
5362
  // src/compliance/rulesets/baseline.ts
5264
5363
  var baseline = RulesetSchema.parse({
5265
5364
  name: "baseline",
@@ -5547,7 +5646,7 @@ async function resolveNlQuery(db, sessionId, search, raw, opts) {
5547
5646
 
5548
5647
  // src/mcp/server.ts
5549
5648
  var SERVER_NAME = "cartography";
5550
- var SERVER_VERSION = "2.4.0";
5649
+ var SERVER_VERSION = "2.5.0";
5551
5650
  var SERVICE_TYPES = NODE_TYPE_GROUPS.web;
5552
5651
  var DATA_TYPES = NODE_TYPE_GROUPS.data;
5553
5652
  var lexicalSearch = async (db, sessionId, query, opts) => db.searchNodes(sessionId, query, { types: opts.types, limit: opts.limit }).map((node) => ({ node }));
@@ -5949,6 +6048,14 @@ function createMcpServer(opts = {}) {
5949
6048
  annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true }
5950
6049
  },
5951
6050
  async (args) => {
6051
+ if (opts.principal) {
6052
+ try {
6053
+ authorize(opts.principal, "discovery");
6054
+ } catch (err) {
6055
+ if (err instanceof AuthorizationError) return json({ error: `forbidden: role '${opts.principal.role}' may not run discovery (operator required)` });
6056
+ throw err;
6057
+ }
6058
+ }
5952
6059
  let sid = resolveSession();
5953
6060
  if (args.update) {
5954
6061
  if (!sid) return json({ error: "No session to update; run discovery first." });
@@ -6091,7 +6198,41 @@ function defaultAllowedHosts(host2, port) {
6091
6198
  return [`${host2}:${port}`, `localhost:${port}`, `127.0.0.1:${port}`];
6092
6199
  }
6093
6200
 
6201
+ // src/auth/identity.ts
6202
+ import { createHash as createHash2 } from "crypto";
6203
+ function hashToken(token) {
6204
+ return createHash2("sha256").update(token, "utf8").digest("hex");
6205
+ }
6206
+ var SqliteCredentialStore = class {
6207
+ constructor(db) {
6208
+ this.db = db;
6209
+ }
6210
+ count() {
6211
+ return this.db.countCredentials();
6212
+ }
6213
+ findByHash(tokenHash) {
6214
+ return this.db.findCredentialByHash(tokenHash);
6215
+ }
6216
+ };
6217
+ function resolvePrincipal(presentedToken, opts) {
6218
+ const tenant = opts.defaultTenant ?? DEFAULT_TENANT;
6219
+ if (opts.store && opts.store.count() > 0) {
6220
+ if (!presentedToken) return void 0;
6221
+ const rec = opts.store.findByHash(hashToken(presentedToken));
6222
+ return rec ? { subject: rec.subject, tenant: rec.tenant, role: rec.role } : void 0;
6223
+ }
6224
+ if (opts.sharedToken) {
6225
+ if (!presentedToken || !timingSafeEqual(presentedToken, opts.sharedToken)) return void 0;
6226
+ return { subject: "shared-token", tenant, role: "admin" };
6227
+ }
6228
+ if (opts.required) return void 0;
6229
+ return { subject: "anonymous", tenant, role: "admin" };
6230
+ }
6231
+
6094
6232
  // src/mcp/transports.ts
6233
+ function samePrincipal(a, b) {
6234
+ return a.subject === b.subject && a.tenant === b.tenant && a.role === b.role;
6235
+ }
6095
6236
  async function runStdio(server) {
6096
6237
  const transport = new StdioServerTransport();
6097
6238
  await server.connect(transport);
@@ -6136,6 +6277,14 @@ async function runHttp(factory, opts = {}) {
6136
6277
  assertSafeBind({ host: host2, port, ...opts.allowedHosts ? { allowedHosts: opts.allowedHosts } : {}, ...opts.token ? { token: opts.token } : {} });
6137
6278
  const allowedHosts = opts.allowedHosts ?? defaultAllowedHosts(host2, port);
6138
6279
  const token = opts.token;
6280
+ const authStore = opts.auth?.store;
6281
+ const defaultTenant = opts.defaultTenant;
6282
+ const resolveAuth = (header) => resolvePrincipal(bearerToken(header), {
6283
+ ...authStore ? { store: authStore } : {},
6284
+ ...token ? { sharedToken: token } : {},
6285
+ ...defaultTenant ? { defaultTenant } : {},
6286
+ ...opts.auth?.required ? { required: true } : {}
6287
+ });
6139
6288
  const transports = /* @__PURE__ */ new Map();
6140
6289
  const httpServer = http.createServer(async (req, res) => {
6141
6290
  try {
@@ -6145,7 +6294,8 @@ async function runHttp(factory, opts = {}) {
6145
6294
  res.writeHead(404, { "content-type": "application/json" }).end('{"error":"not found"}');
6146
6295
  return;
6147
6296
  }
6148
- if (!checkBearer(req.headers["authorization"], token)) {
6297
+ const principal = resolveAuth(req.headers["authorization"]);
6298
+ if (!principal) {
6149
6299
  res.writeHead(401, { "content-type": "application/json", "www-authenticate": "Bearer" }).end('{"error":"unauthorized"}');
6150
6300
  return;
6151
6301
  }
@@ -6172,8 +6322,12 @@ async function runHttp(factory, opts = {}) {
6172
6322
  const sessionId = req.headers["mcp-session-id"];
6173
6323
  const existing = sessionId ? transports.get(sessionId) : void 0;
6174
6324
  if (existing) {
6325
+ if (!samePrincipal(existing.principal, principal)) {
6326
+ res.writeHead(403, { "content-type": "application/json" }).end('{"error":"session belongs to a different principal"}');
6327
+ return;
6328
+ }
6175
6329
  const body2 = req.method === "POST" ? await readJsonBody(req) : void 0;
6176
- await existing.handleRequest(req, res, body2);
6330
+ await existing.transport.handleRequest(req, res, body2);
6177
6331
  return;
6178
6332
  }
6179
6333
  if (req.method !== "POST") {
@@ -6187,13 +6341,13 @@ async function runHttp(factory, opts = {}) {
6187
6341
  allowedHosts,
6188
6342
  ...opts.allowedOrigins ? { allowedOrigins: opts.allowedOrigins } : {},
6189
6343
  onsessioninitialized: (id) => {
6190
- transports.set(id, transport);
6344
+ transports.set(id, { transport, principal });
6191
6345
  }
6192
6346
  });
6193
6347
  transport.onclose = () => {
6194
6348
  if (transport.sessionId) transports.delete(transport.sessionId);
6195
6349
  };
6196
- await factory().connect(transport);
6350
+ await factory(principal).connect(transport);
6197
6351
  await transport.handleRequest(req, res, body);
6198
6352
  } catch (err) {
6199
6353
  process.stderr.write(`[cartography-mcp] HTTP request failed: ${err instanceof Error ? err.message : String(err)}
@@ -7820,6 +7974,8 @@ async function runApi(opts) {
7820
7974
  const token = opts.token;
7821
7975
  const graphqlEnabled = opts.graphql !== false;
7822
7976
  const defaultTenant = opts.tenant?.defaultTenant ?? DEFAULT_TENANT;
7977
+ const authStore = opts.auth?.store;
7978
+ const rbacMode = !!(authStore && authStore.count() > 0);
7823
7979
  const log2 = opts.log ?? (() => {
7824
7980
  });
7825
7981
  const restDeps = { backend: opts.backend, version: opts.version };
@@ -7878,23 +8034,44 @@ async function runApi(opts) {
7878
8034
  finish(r.status);
7879
8035
  return;
7880
8036
  }
7881
- if (!checkBearer(req.headers["authorization"], token)) {
8037
+ const principal = resolvePrincipal(bearerToken(req.headers["authorization"]), {
8038
+ ...authStore ? { store: authStore } : {},
8039
+ ...token ? { sharedToken: token } : {},
8040
+ defaultTenant,
8041
+ ...opts.auth?.required ? { required: true } : {}
8042
+ });
8043
+ if (!principal) {
7882
8044
  send(res, 401, { error: "unauthorized" }, { "www-authenticate": "Bearer", ...cors });
7883
8045
  finish(401);
7884
8046
  return;
7885
8047
  }
7886
- let ctx;
7887
8048
  try {
7888
- ctx = resolveTenant(req, url, opts.tenant ?? {});
7889
- tenantLabel = ctx.tenant;
8049
+ authorize(principal, "read");
7890
8050
  } catch (err) {
7891
- if (err instanceof InvalidTenantError) {
7892
- send(res, 400, { error: "invalid tenant" }, cors);
7893
- finish(400);
8051
+ if (err instanceof AuthorizationError) {
8052
+ send(res, 403, { error: "forbidden" }, cors);
8053
+ finish(403);
7894
8054
  return;
7895
8055
  }
7896
8056
  throw err;
7897
8057
  }
8058
+ let ctx;
8059
+ if (rbacMode) {
8060
+ ctx = { tenant: principal.tenant };
8061
+ tenantLabel = principal.tenant;
8062
+ } else {
8063
+ try {
8064
+ ctx = resolveTenant(req, url, opts.tenant ?? {});
8065
+ tenantLabel = ctx.tenant;
8066
+ } catch (err) {
8067
+ if (err instanceof InvalidTenantError) {
8068
+ send(res, 400, { error: "invalid tenant" }, cors);
8069
+ finish(400);
8070
+ return;
8071
+ }
8072
+ throw err;
8073
+ }
8074
+ }
7898
8075
  if (graphqlEnabled && path === "/graphql") {
7899
8076
  if (req.method === "GET") {
7900
8077
  const g = handleGraphqlGet();
@@ -7964,6 +8141,30 @@ function dispatchRest(ctx, path, url, deps) {
7964
8141
  }
7965
8142
  }
7966
8143
 
8144
+ // src/auth/types.ts
8145
+ import { z as z9 } from "zod";
8146
+ var ROLES = ["viewer", "operator", "admin"];
8147
+ var RoleSchema = z9.enum(ROLES);
8148
+ var ACTIONS = ["read", "discovery", "admin"];
8149
+ var ActionSchema = z9.enum(ACTIONS);
8150
+ var PrincipalSchema = z9.object({
8151
+ subject: z9.string().min(1),
8152
+ tenant: z9.string().min(1),
8153
+ role: RoleSchema
8154
+ });
8155
+ var CredentialConfigSchema = z9.object({
8156
+ token: z9.string().min(1),
8157
+ subject: z9.string().min(1),
8158
+ tenant: z9.string().optional(),
8159
+ role: RoleSchema.default("viewer")
8160
+ });
8161
+ var AuthConfigSchema = z9.object({
8162
+ /** Seed credentials (merged into the SQLite store on startup). */
8163
+ credentials: z9.array(CredentialConfigSchema).optional(),
8164
+ /** Reject unauthenticated requests even on loopback (default: loopback dev stays open). */
8165
+ required: z9.boolean().optional()
8166
+ });
8167
+
7967
8168
  // src/api/start.ts
7968
8169
  import { readFileSync as readFileSync4 } from "fs";
7969
8170
  import { dirname as dirname3, resolve } from "path";
@@ -7990,6 +8191,7 @@ function parseApiArgs(argv) {
7990
8191
  else if (a === "--db") opts.dbPath = argv[++i];
7991
8192
  else if (a === "--session") opts.session = argv[++i];
7992
8193
  else if (a === "--tenant" || a === "--org") opts.tenant = argv[++i];
8194
+ else if (a === "--auth-required") opts.authRequired = true;
7993
8195
  else if (a === "--help" || a === "-h") opts.help = true;
7994
8196
  }
7995
8197
  return opts;
@@ -8005,11 +8207,13 @@ async function startApi(opts = {}) {
8005
8207
  const host2 = opts.host ?? "127.0.0.1";
8006
8208
  const port = opts.port ?? 3737;
8007
8209
  const version = readVersion();
8210
+ const authStore = new SqliteCredentialStore(db);
8008
8211
  const server = await runApi({
8009
8212
  host: host2,
8010
8213
  port,
8011
8214
  backend,
8012
8215
  version,
8216
+ auth: { store: authStore, ...opts.authRequired ? { required: true } : {} },
8013
8217
  ...opts.allowedHosts ? { allowedHosts: opts.allowedHosts } : {},
8014
8218
  ...opts.allowedOrigins ? { allowedOrigins: opts.allowedOrigins } : {},
8015
8219
  ...token ? { token } : {},
@@ -8504,13 +8708,13 @@ function createClaudeProvider() {
8504
8708
  }
8505
8709
 
8506
8710
  // src/providers/shell.ts
8507
- import { z as z9 } from "zod";
8711
+ import { z as z10 } from "zod";
8508
8712
  function createBashTool() {
8509
8713
  const shell = IS_WIN ? "powershell" : "posix";
8510
8714
  return {
8511
8715
  name: "Bash",
8512
8716
  description: "Run a read-only shell command (inspect ports, processes, config). Mutating or destructive commands are blocked by the read-only allowlist.",
8513
- inputShape: { command: z9.string().describe("The read-only shell command to run") },
8717
+ inputShape: { command: z10.string().describe("The read-only shell command to run") },
8514
8718
  annotations: { readOnlyHint: true, openWorldHint: true },
8515
8719
  handler: async (args) => {
8516
8720
  const command = String(args["command"] ?? "").trim();
@@ -11022,9 +11226,9 @@ async function runOnce(cfg, db) {
11022
11226
  }
11023
11227
 
11024
11228
  // src/sync/hash.ts
11025
- import { createHash as createHash2 } from "crypto";
11229
+ import { createHash as createHash3 } from "crypto";
11026
11230
  function shareHash(kind, payload) {
11027
- return createHash2("sha256").update(stableStringify({ kind, payload })).digest("hex");
11231
+ return createHash3("sha256").update(stableStringify({ kind, payload })).digest("hex");
11028
11232
  }
11029
11233
 
11030
11234
  // src/sync/classify.ts
@@ -11068,7 +11272,7 @@ function classify2(input) {
11068
11272
  }
11069
11273
 
11070
11274
  // src/sync/push.ts
11071
- import { createHash as createHash3 } from "crypto";
11275
+ import { createHash as createHash4 } from "crypto";
11072
11276
  var PUSH_SCHEMA_VERSION = 1;
11073
11277
  var DEFAULT_BATCH = 100;
11074
11278
  var DEFAULT_RETRIES = 4;
@@ -11082,7 +11286,7 @@ function defaultSleep(ms) {
11082
11286
  }
11083
11287
  function batchKey(items) {
11084
11288
  const hashes = items.map((i) => i.contentHash).sort();
11085
- return createHash3("sha256").update(stableStringify(hashes)).digest("hex");
11289
+ return createHash4("sha256").update(stableStringify(hashes)).digest("hex");
11086
11290
  }
11087
11291
  async function pushDeltas(config, items, opts = {}) {
11088
11292
  const central = config.centralDb;
@@ -11287,6 +11491,10 @@ function checkClaudePrerequisites() {
11287
11491
  }
11288
11492
  }
11289
11493
  export {
11494
+ ACTIONS,
11495
+ ActionSchema,
11496
+ AuthConfigSchema,
11497
+ AuthorizationError,
11290
11498
  CLIENTS,
11291
11499
  CONFIDENCE,
11292
11500
  CartographyDB,
@@ -11295,6 +11503,7 @@ export {
11295
11503
  ConditionSchema,
11296
11504
  ConfigError,
11297
11505
  ControlResultSchema,
11506
+ CredentialConfigSchema,
11298
11507
  CsvCostSource,
11299
11508
  DEFAULT_ANOMALY_THRESHOLDS,
11300
11509
  DEFAULT_SERVER_NAME,
@@ -11314,8 +11523,11 @@ export {
11314
11523
  PRIVATE_IP,
11315
11524
  PUSH_SCHEMA_VERSION,
11316
11525
  PagerDutySink,
11526
+ PrincipalSchema,
11317
11527
  ProviderRegistry,
11318
11528
  RELATION_TO_DIRECTION,
11529
+ ROLES,
11530
+ RoleSchema,
11319
11531
  RuleCheckSchema,
11320
11532
  RulesetSchema,
11321
11533
  SCAN_ARG_PATTERNS,
@@ -11326,10 +11538,12 @@ export {
11326
11538
  ScannerShape,
11327
11539
  SharingLevelSchema,
11328
11540
  SlackSink,
11541
+ SqliteCredentialStore,
11329
11542
  SqliteQueryBackend,
11330
11543
  SqliteStoreBackend,
11331
11544
  StdoutSink,
11332
11545
  TENANT_HEADER,
11546
+ TenantMismatchError,
11333
11547
  VectorStore,
11334
11548
  WebhookSink,
11335
11549
  applyInstall,
@@ -11337,7 +11551,9 @@ export {
11337
11551
  assertReadOnly,
11338
11552
  assertSafeBind,
11339
11553
  assertSafeScanArg,
11554
+ assertSameTenant,
11340
11555
  assignColors,
11556
+ authorize,
11341
11557
  bearerToken,
11342
11558
  bookmarksScanner,
11343
11559
  buildCartographyToolHandlers,
@@ -11345,6 +11561,7 @@ export {
11345
11561
  buildOpenApiDocument,
11346
11562
  buildReport,
11347
11563
  buildSinks,
11564
+ can,
11348
11565
  centralDbFromEnv,
11349
11566
  checkBearer,
11350
11567
  checkPrerequisites,
@@ -11421,6 +11638,7 @@ export {
11421
11638
  globalId,
11422
11639
  groupByDomain,
11423
11640
  handleGraphqlGet,
11641
+ hashToken,
11424
11642
  hexCorners,
11425
11643
  hexDistance,
11426
11644
  hexNeighbors,
@@ -11487,6 +11705,7 @@ export {
11487
11705
  renderDiff,
11488
11706
  resolveEffectiveLevel,
11489
11707
  resolveNlQuery,
11708
+ resolvePrincipal,
11490
11709
  resolveSharingLevel,
11491
11710
  resolveTenant,
11492
11711
  revalidateAnonymized,
@@ -11506,6 +11725,7 @@ export {
11506
11725
  safetyHook,
11507
11726
  sanitizeUntrusted,
11508
11727
  sanitizeValue,
11728
+ scopeReads,
11509
11729
  scoreTopology,
11510
11730
  securityRelevantChange,
11511
11731
  serializeConfig,