@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/api-bin.js +2 -2
- package/dist/{chunk-X5JA2UDT.js → chunk-GA4427LB.js} +134 -14
- package/dist/chunk-GA4427LB.js.map +1 -0
- package/dist/{chunk-L4OSL7I6.js → chunk-NQXZUWOI.js} +41 -11
- package/dist/chunk-NQXZUWOI.js.map +1 -0
- package/dist/{chunk-B4QWX7CP.js → chunk-RYQ4KQCK.js} +55 -11
- package/dist/chunk-RYQ4KQCK.js.map +1 -0
- package/dist/cli.js +87 -8
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +262 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +223 -3
- package/dist/index.d.ts +223 -3
- package/dist/index.js +244 -24
- package/dist/index.js.map +1 -1
- package/dist/mcp-bin.js +2 -2
- package/package.json +1 -1
- package/server.json +2 -2
- package/dist/chunk-B4QWX7CP.js.map +0 -1
- package/dist/chunk-L4OSL7I6.js.map +0 -1
- package/dist/chunk-X5JA2UDT.js.map +0 -1
package/dist/api-bin.js
CHANGED
|
@@ -1774,7 +1774,10 @@ CREATE TABLE IF NOT EXISTS activity_events (
|
|
|
1774
1774
|
duration_ms INTEGER,
|
|
1775
1775
|
command TEXT,
|
|
1776
1776
|
result_bytes INTEGER,
|
|
1777
|
-
tenant TEXT NOT NULL DEFAULT 'local'
|
|
1777
|
+
tenant TEXT NOT NULL DEFAULT 'local',
|
|
1778
|
+
actor_subject TEXT,
|
|
1779
|
+
actor_role TEXT,
|
|
1780
|
+
actor_tenant TEXT
|
|
1778
1781
|
);
|
|
1779
1782
|
|
|
1780
1783
|
CREATE TABLE IF NOT EXISTS tasks (
|
|
@@ -1883,6 +1886,16 @@ CREATE INDEX IF NOT EXISTS idx_nodes_tenant_content ON nodes(tenant, content_has
|
|
|
1883
1886
|
CREATE INDEX IF NOT EXISTS idx_contrib_org ON node_contributors(organization, global_id);
|
|
1884
1887
|
CREATE INDEX IF NOT EXISTS idx_nodes_owner ON nodes(session_id, owner);
|
|
1885
1888
|
`;
|
|
1889
|
+
var AUTH_SCHEMA = `
|
|
1890
|
+
CREATE TABLE IF NOT EXISTS auth_credentials (
|
|
1891
|
+
token_hash TEXT PRIMARY KEY,
|
|
1892
|
+
subject TEXT NOT NULL,
|
|
1893
|
+
tenant TEXT NOT NULL DEFAULT 'local',
|
|
1894
|
+
role TEXT NOT NULL,
|
|
1895
|
+
created_at TEXT NOT NULL
|
|
1896
|
+
);
|
|
1897
|
+
CREATE INDEX IF NOT EXISTS idx_auth_subject ON auth_credentials(subject);
|
|
1898
|
+
`;
|
|
1886
1899
|
var CartographyDB = class {
|
|
1887
1900
|
db;
|
|
1888
1901
|
/** 3.6 anomaly settings; defaults apply when no `anomaly` config is supplied. */
|
|
@@ -1902,7 +1915,8 @@ var CartographyDB = class {
|
|
|
1902
1915
|
const version = this.db.pragma("user_version", { simple: true });
|
|
1903
1916
|
if (version === 0) {
|
|
1904
1917
|
this.db.exec(SCHEMA);
|
|
1905
|
-
this.db.
|
|
1918
|
+
this.db.exec(AUTH_SCHEMA);
|
|
1919
|
+
this.db.pragma("user_version = 15");
|
|
1906
1920
|
return;
|
|
1907
1921
|
} else if (version === 1) {
|
|
1908
1922
|
const cols = this.db.prepare("PRAGMA table_info(nodes)").all().map((c) => c.name);
|
|
@@ -2088,6 +2102,18 @@ var CartographyDB = class {
|
|
|
2088
2102
|
}
|
|
2089
2103
|
this.db.pragma("user_version = 14");
|
|
2090
2104
|
}
|
|
2105
|
+
const v14 = this.db.pragma("user_version", { simple: true });
|
|
2106
|
+
if (v14 < 15) {
|
|
2107
|
+
this.db.exec(AUTH_SCHEMA);
|
|
2108
|
+
const ev = this.db.prepare("PRAGMA table_info(activity_events)").all();
|
|
2109
|
+
if (ev.length > 0) {
|
|
2110
|
+
const cols = ev.map((c) => c.name);
|
|
2111
|
+
if (!cols.includes("actor_subject")) this.db.exec("ALTER TABLE activity_events ADD COLUMN actor_subject TEXT");
|
|
2112
|
+
if (!cols.includes("actor_role")) this.db.exec("ALTER TABLE activity_events ADD COLUMN actor_role TEXT");
|
|
2113
|
+
if (!cols.includes("actor_tenant")) this.db.exec("ALTER TABLE activity_events ADD COLUMN actor_tenant TEXT");
|
|
2114
|
+
}
|
|
2115
|
+
this.db.pragma("user_version = 15");
|
|
2116
|
+
}
|
|
2091
2117
|
}
|
|
2092
2118
|
close() {
|
|
2093
2119
|
this.db.pragma("optimize");
|
|
@@ -2518,13 +2544,13 @@ var CartographyDB = class {
|
|
|
2518
2544
|
});
|
|
2519
2545
|
}
|
|
2520
2546
|
// ── Events ──────────────────────────────
|
|
2521
|
-
insertEvent(sessionId, event, taskId) {
|
|
2547
|
+
insertEvent(sessionId, event, taskId, actor) {
|
|
2522
2548
|
const id = crypto.randomUUID();
|
|
2523
2549
|
const tenant = this.tenantOf(sessionId);
|
|
2524
2550
|
this.db.prepare(`
|
|
2525
2551
|
INSERT INTO activity_events
|
|
2526
|
-
(id, session_id, task_id, timestamp, event_type, process, pid, target, target_type, port, command, result_bytes, tenant)
|
|
2527
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2552
|
+
(id, session_id, task_id, timestamp, event_type, process, pid, target, target_type, port, command, result_bytes, tenant, actor_subject, actor_role, actor_tenant)
|
|
2553
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2528
2554
|
`).run(
|
|
2529
2555
|
id,
|
|
2530
2556
|
sessionId,
|
|
@@ -2538,9 +2564,52 @@ var CartographyDB = class {
|
|
|
2538
2564
|
event.port ?? null,
|
|
2539
2565
|
event.command ?? null,
|
|
2540
2566
|
event.resultBytes ?? null,
|
|
2541
|
-
tenant
|
|
2567
|
+
tenant,
|
|
2568
|
+
actor?.subject ?? null,
|
|
2569
|
+
actor?.role ?? null,
|
|
2570
|
+
actor?.tenant ?? null
|
|
2542
2571
|
);
|
|
2543
2572
|
}
|
|
2573
|
+
// ── RBAC credential store (4.5) ─────────────
|
|
2574
|
+
/** Number of stored credentials. `0` ⇒ no RBAC configured (fall back to shared/loopback). */
|
|
2575
|
+
countCredentials() {
|
|
2576
|
+
return this.db.prepare("SELECT COUNT(*) AS n FROM auth_credentials").get().n;
|
|
2577
|
+
}
|
|
2578
|
+
/** Look up a credential by its sha256 token hash. */
|
|
2579
|
+
findCredentialByHash(tokenHash) {
|
|
2580
|
+
const r = this.db.prepare("SELECT * FROM auth_credentials WHERE token_hash = ?").get(tokenHash);
|
|
2581
|
+
if (!r) return void 0;
|
|
2582
|
+
return {
|
|
2583
|
+
tokenHash: r["token_hash"],
|
|
2584
|
+
subject: r["subject"],
|
|
2585
|
+
tenant: r["tenant"],
|
|
2586
|
+
role: r["role"],
|
|
2587
|
+
createdAt: r["created_at"]
|
|
2588
|
+
};
|
|
2589
|
+
}
|
|
2590
|
+
/** Upsert a credential (idempotent on the token hash). Stores only the hash, never the raw token. */
|
|
2591
|
+
addCredential(rec) {
|
|
2592
|
+
this.db.prepare(`
|
|
2593
|
+
INSERT INTO auth_credentials (token_hash, subject, tenant, role, created_at)
|
|
2594
|
+
VALUES (?, ?, ?, ?, ?)
|
|
2595
|
+
ON CONFLICT(token_hash) DO UPDATE SET subject = excluded.subject, tenant = excluded.tenant, role = excluded.role
|
|
2596
|
+
`).run(rec.tokenHash, rec.subject, rec.tenant, rec.role, (/* @__PURE__ */ new Date()).toISOString());
|
|
2597
|
+
}
|
|
2598
|
+
/** List all credentials (token hashes only — the raw token is unrecoverable). */
|
|
2599
|
+
listCredentials() {
|
|
2600
|
+
const rows = this.db.prepare("SELECT * FROM auth_credentials ORDER BY created_at").all();
|
|
2601
|
+
return rows.map((r) => ({
|
|
2602
|
+
tokenHash: r["token_hash"],
|
|
2603
|
+
subject: r["subject"],
|
|
2604
|
+
tenant: r["tenant"],
|
|
2605
|
+
role: r["role"],
|
|
2606
|
+
createdAt: r["created_at"]
|
|
2607
|
+
}));
|
|
2608
|
+
}
|
|
2609
|
+
/** Revoke every credential for a subject. Returns the number removed. */
|
|
2610
|
+
revokeCredentialsBySubject(subject) {
|
|
2611
|
+
return this.db.prepare("DELETE FROM auth_credentials WHERE subject = ?").run(subject).changes;
|
|
2612
|
+
}
|
|
2544
2613
|
getEvents(sessionId, since) {
|
|
2545
2614
|
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);
|
|
2546
2615
|
return rows.map((r) => {
|
|
@@ -3217,6 +3286,9 @@ var CartographyDB = class {
|
|
|
3217
3286
|
}
|
|
3218
3287
|
};
|
|
3219
3288
|
|
|
3289
|
+
// src/auth/identity.ts
|
|
3290
|
+
import { createHash as createHash2 } from "crypto";
|
|
3291
|
+
|
|
3220
3292
|
// src/api/auth.ts
|
|
3221
3293
|
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
|
|
3222
3294
|
function isLoopbackHost(host) {
|
|
@@ -3237,11 +3309,6 @@ function bearerToken(header) {
|
|
|
3237
3309
|
const token = rest.trimStart();
|
|
3238
3310
|
return token.length > 0 ? token : void 0;
|
|
3239
3311
|
}
|
|
3240
|
-
function checkBearer(authorizationHeader, token) {
|
|
3241
|
-
if (!token) return true;
|
|
3242
|
-
const provided = bearerToken(authorizationHeader);
|
|
3243
|
-
return provided !== void 0 && timingSafeEqual(provided, token);
|
|
3244
|
-
}
|
|
3245
3312
|
function assertSafeBind(opts) {
|
|
3246
3313
|
if (isLoopbackHost(opts.host)) return;
|
|
3247
3314
|
if (opts.allowedHosts === void 0) {
|
|
@@ -3259,6 +3326,54 @@ function defaultAllowedHosts(host, port) {
|
|
|
3259
3326
|
return [`${host}:${port}`, `localhost:${port}`, `127.0.0.1:${port}`];
|
|
3260
3327
|
}
|
|
3261
3328
|
|
|
3329
|
+
// src/auth/identity.ts
|
|
3330
|
+
function hashToken(token) {
|
|
3331
|
+
return createHash2("sha256").update(token, "utf8").digest("hex");
|
|
3332
|
+
}
|
|
3333
|
+
var SqliteCredentialStore = class {
|
|
3334
|
+
constructor(db) {
|
|
3335
|
+
this.db = db;
|
|
3336
|
+
}
|
|
3337
|
+
count() {
|
|
3338
|
+
return this.db.countCredentials();
|
|
3339
|
+
}
|
|
3340
|
+
findByHash(tokenHash) {
|
|
3341
|
+
return this.db.findCredentialByHash(tokenHash);
|
|
3342
|
+
}
|
|
3343
|
+
};
|
|
3344
|
+
function resolvePrincipal(presentedToken, opts) {
|
|
3345
|
+
const tenant = opts.defaultTenant ?? DEFAULT_TENANT;
|
|
3346
|
+
if (opts.store && opts.store.count() > 0) {
|
|
3347
|
+
if (!presentedToken) return void 0;
|
|
3348
|
+
const rec = opts.store.findByHash(hashToken(presentedToken));
|
|
3349
|
+
return rec ? { subject: rec.subject, tenant: rec.tenant, role: rec.role } : void 0;
|
|
3350
|
+
}
|
|
3351
|
+
if (opts.sharedToken) {
|
|
3352
|
+
if (!presentedToken || !timingSafeEqual(presentedToken, opts.sharedToken)) return void 0;
|
|
3353
|
+
return { subject: "shared-token", tenant, role: "admin" };
|
|
3354
|
+
}
|
|
3355
|
+
if (opts.required) return void 0;
|
|
3356
|
+
return { subject: "anonymous", tenant, role: "admin" };
|
|
3357
|
+
}
|
|
3358
|
+
|
|
3359
|
+
// src/auth/rbac.ts
|
|
3360
|
+
var ROLE_RANK = { viewer: 1, operator: 2, admin: 3 };
|
|
3361
|
+
var ACTION_MIN_ROLE = { read: "viewer", discovery: "operator", admin: "admin" };
|
|
3362
|
+
function can(role, action) {
|
|
3363
|
+
return ROLE_RANK[role] >= ROLE_RANK[ACTION_MIN_ROLE[action]];
|
|
3364
|
+
}
|
|
3365
|
+
var AuthorizationError = class extends Error {
|
|
3366
|
+
constructor(action, role) {
|
|
3367
|
+
super(`forbidden: role '${role}' may not perform '${action}'`);
|
|
3368
|
+
this.action = action;
|
|
3369
|
+
this.role = role;
|
|
3370
|
+
this.name = "AuthorizationError";
|
|
3371
|
+
}
|
|
3372
|
+
};
|
|
3373
|
+
function authorize(principal, action) {
|
|
3374
|
+
if (!can(principal.role, action)) throw new AuthorizationError(action, principal.role);
|
|
3375
|
+
}
|
|
3376
|
+
|
|
3262
3377
|
export {
|
|
3263
3378
|
sanitizeUntrusted,
|
|
3264
3379
|
cloudAwsScanner,
|
|
@@ -3280,8 +3395,13 @@ export {
|
|
|
3280
3395
|
globalId,
|
|
3281
3396
|
deriveSessionName,
|
|
3282
3397
|
CartographyDB,
|
|
3283
|
-
|
|
3398
|
+
bearerToken,
|
|
3284
3399
|
assertSafeBind,
|
|
3285
|
-
defaultAllowedHosts
|
|
3400
|
+
defaultAllowedHosts,
|
|
3401
|
+
hashToken,
|
|
3402
|
+
SqliteCredentialStore,
|
|
3403
|
+
resolvePrincipal,
|
|
3404
|
+
AuthorizationError,
|
|
3405
|
+
authorize
|
|
3286
3406
|
};
|
|
3287
|
-
//# sourceMappingURL=chunk-
|
|
3407
|
+
//# sourceMappingURL=chunk-GA4427LB.js.map
|