@op0ai/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +38 -0
- package/README.md +28 -0
- package/dist/agent.d.ts +23 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +72 -0
- package/dist/agent.js.map +1 -0
- package/dist/agui.d.ts +87 -0
- package/dist/agui.d.ts.map +1 -0
- package/dist/agui.js +22 -0
- package/dist/agui.js.map +1 -0
- package/dist/config.d.ts +76 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/data.d.ts +168 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +211 -0
- package/dist/data.js.map +1 -0
- package/dist/define.d.ts +30 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +87 -0
- package/dist/define.js.map +1 -0
- package/dist/distill.d.ts +68 -0
- package/dist/distill.d.ts.map +1 -0
- package/dist/distill.js +113 -0
- package/dist/distill.js.map +1 -0
- package/dist/events.d.ts +39 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +25 -0
- package/dist/events.js.map +1 -0
- package/dist/evlog.d.ts +71 -0
- package/dist/evlog.d.ts.map +1 -0
- package/dist/evlog.js +124 -0
- package/dist/evlog.js.map +1 -0
- package/dist/guards.d.ts +61 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +88 -0
- package/dist/guards.js.map +1 -0
- package/dist/hash.d.ts +6 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +18 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +120 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +175 -0
- package/dist/index.js.map +1 -0
- package/dist/platform.d.ts +97 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +10 -0
- package/dist/platform.js.map +1 -0
- package/dist/session.d.ts +47 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +88 -0
- package/dist/session.js.map +1 -0
- package/dist/source.d.ts +65 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +96 -0
- package/dist/source.js.map +1 -0
- package/dist/tool.d.ts +43 -0
- package/dist/tool.d.ts.map +1 -0
- package/dist/tool.js +16 -0
- package/dist/tool.js.map +1 -0
- package/dist/usectx.d.ts +93 -0
- package/dist/usectx.d.ts.map +1 -0
- package/dist/usectx.js +220 -0
- package/dist/usectx.js.map +1 -0
- package/dist/vault.d.ts +21 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +25 -0
- package/dist/vault.js.map +1 -0
- package/package.json +75 -0
package/dist/evlog.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { WideEvent, AuditEntry } from "./guards.ts";
|
|
2
|
+
/** The minimal durable host evlog needs: the DO's `this.sql`. (DurableHost in define.ts structurally satisfies it.) */
|
|
3
|
+
export interface SqlHost {
|
|
4
|
+
sql: (strings: TemplateStringsArray, ...values: unknown[]) => unknown[];
|
|
5
|
+
}
|
|
6
|
+
/** Structural match for the bound AnalyticsEngineDataset (env.EVLOG) — lets us test with a fake + degrade to no-op. */
|
|
7
|
+
export interface AnalyticsSink {
|
|
8
|
+
writeDataPoint(point: {
|
|
9
|
+
indexes?: (string | null)[];
|
|
10
|
+
doubles?: number[];
|
|
11
|
+
blobs?: (string | null)[];
|
|
12
|
+
}): void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Map a WideEvent → an Analytics Engine data point with a STABLE, positional column order (AE's SQL schema is
|
|
16
|
+
* positional: blobN / doubleN / indexN). Keep this in lockstep with the documented query columns:
|
|
17
|
+
* index1 = cordId (the sampling / GROUP BY key)
|
|
18
|
+
* blob1=runId blob2=kind blob3=name blob4=tenantId blob5=cordId blob6=scope blob7=errCode blob8=errWhy
|
|
19
|
+
* double1 = durationMs double2 = ok (1|0)
|
|
20
|
+
*/
|
|
21
|
+
export declare function wideEventToDataPoint(e: WideEvent): {
|
|
22
|
+
indexes: (string | null)[];
|
|
23
|
+
blobs: (string | null)[];
|
|
24
|
+
doubles: number[];
|
|
25
|
+
};
|
|
26
|
+
/** Best-effort Analytics Engine writer — NEVER throws (telemetry must not break a run); logs failures to evlog. */
|
|
27
|
+
export declare function analyticsEvlog(sink: AnalyticsSink | undefined): (e: WideEvent) => void;
|
|
28
|
+
export interface AuditStore {
|
|
29
|
+
/** Append a hash-chained entry (commits to the prior entry's hash). Never throws; returns null on failure. */
|
|
30
|
+
append(e: {
|
|
31
|
+
actor: string;
|
|
32
|
+
action: string;
|
|
33
|
+
scopeId: string;
|
|
34
|
+
payload: unknown;
|
|
35
|
+
}): AuditEntry | null;
|
|
36
|
+
list(): AuditEntry[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* DO-backed audit chain on `this.sql`: each entry's hash commits to the previous (prevHash), so editing any
|
|
40
|
+
* earlier row breaks the chain (detect via {@link verifyAuditChain}). Durable → survives reload; spans the DO's
|
|
41
|
+
* whole lifetime (genesis → …), unlike an in-memory chain. Same AuditEntry shape as guards.ts (companion 23 §2).
|
|
42
|
+
*/
|
|
43
|
+
export declare function auditStore(host: SqlHost): AuditStore;
|
|
44
|
+
/** Recompute the chain and confirm every entry's hash + prevHash linkage. `ok:false` + `brokenAt` on tamper. */
|
|
45
|
+
export declare function verifyAuditChain(entries: readonly AuditEntry[]): {
|
|
46
|
+
ok: boolean;
|
|
47
|
+
brokenAt?: number;
|
|
48
|
+
};
|
|
49
|
+
/** What a call site emits — the semantic wide-event minus the identity/time the observer stamps. */
|
|
50
|
+
export type WidePartial = Omit<WideEvent, "runId" | "ts" | "cordId" | "tenantId">;
|
|
51
|
+
/** The governance seam a tool (or the runtime) calls to record a unit of work. */
|
|
52
|
+
export type WideSink = (e: WidePartial) => void;
|
|
53
|
+
export interface CordObserver {
|
|
54
|
+
readonly runId: string;
|
|
55
|
+
/** evlog lane: stamp identity+ts, write the Analytics Engine data point, AND append a tamper-evident audit entry. */
|
|
56
|
+
wide: WideSink;
|
|
57
|
+
audit: AuditStore;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Tie the evlog lane to one run: every `wide(...)` call writes an Analytics Engine row AND a hash-chained audit
|
|
61
|
+
* entry, both stamped with this run's identity (runId/cordId/tenantId). Pair with the AG-UI emitter (same runId)
|
|
62
|
+
* so the UI timeline, the analytics row, and the audit entry all correlate.
|
|
63
|
+
*/
|
|
64
|
+
export declare function cordObserver(opts: {
|
|
65
|
+
runId: string;
|
|
66
|
+
cordId: string;
|
|
67
|
+
tenantId: string;
|
|
68
|
+
host: SqlHost;
|
|
69
|
+
analytics?: AnalyticsSink;
|
|
70
|
+
}): CordObserver;
|
|
71
|
+
//# sourceMappingURL=evlog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evlog.d.ts","sourceRoot":"","sources":["../src/evlog.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzD,uHAAuH;AACvH,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC;CACzE;AAID,uHAAuH;AACvH,MAAM,WAAW,aAAa;IAC5B,cAAc,CAAC,KAAK,EAAE;QAAE,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;CAC7G;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,SAAS,GAAG;IAAE,OAAO,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAAC,KAAK,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAM9H;AAED,mHAAmH;AACnH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,GAAG,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAStF;AAWD,MAAM,WAAW,UAAU;IACzB,8GAA8G;IAC9G,MAAM,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,UAAU,GAAG,IAAI,CAAC;IACnG,IAAI,IAAI,UAAU,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAsCpD;AAED,gHAAgH;AAChH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAUnG;AAID,oGAAoG;AACpG,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,GAAG,QAAQ,GAAG,UAAU,CAAC,CAAC;AAClF,kFAAkF;AAClF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qHAAqH;IACrH,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,UAAU,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B,GAAG,YAAY,CAiBf"}
|
package/dist/evlog.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// evlog.ts — the cord's evlog lane: governance-grade observability that runs ALONGSIDE the AG-UI timeline.
|
|
2
|
+
// Where agui.ts is the cord↔UI wire (one CordEvent per step, persisted + broadcast for the live "stack trace"),
|
|
3
|
+
// evlog is the OPS + AUDIT wire: one WideEvent per unit of work (companion 23 §2 — "one fat event, many
|
|
4
|
+
// dimensions") written to Workers Analytics Engine, PLUS a tamper-evident, DO-persisted hash-chained audit.
|
|
5
|
+
// The two lanes share ONE runId, so a timeline step, an analytics row, and an audit entry all JOIN on it.
|
|
6
|
+
import { hashHex } from "./hash.js";
|
|
7
|
+
/**
|
|
8
|
+
* Map a WideEvent → an Analytics Engine data point with a STABLE, positional column order (AE's SQL schema is
|
|
9
|
+
* positional: blobN / doubleN / indexN). Keep this in lockstep with the documented query columns:
|
|
10
|
+
* index1 = cordId (the sampling / GROUP BY key)
|
|
11
|
+
* blob1=runId blob2=kind blob3=name blob4=tenantId blob5=cordId blob6=scope blob7=errCode blob8=errWhy
|
|
12
|
+
* double1 = durationMs double2 = ok (1|0)
|
|
13
|
+
*/
|
|
14
|
+
export function wideEventToDataPoint(e) {
|
|
15
|
+
return {
|
|
16
|
+
indexes: [e.cordId],
|
|
17
|
+
blobs: [e.runId, e.kind, e.name, e.tenantId, e.cordId, e.scope ?? "", e.error?.code ?? "", e.error?.why ?? ""],
|
|
18
|
+
doubles: [e.durationMs, e.ok ? 1 : 0],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Best-effort Analytics Engine writer — NEVER throws (telemetry must not break a run); logs failures to evlog. */
|
|
22
|
+
export function analyticsEvlog(sink) {
|
|
23
|
+
return (e) => {
|
|
24
|
+
if (!sink)
|
|
25
|
+
return;
|
|
26
|
+
try {
|
|
27
|
+
sink.writeDataPoint(wideEventToDataPoint(e));
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
console.log(JSON.stringify({ evlog: "evlog.write", error: err instanceof Error ? err.message : String(err) }));
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// ---------- tamper-evident, DO-persisted audit chain ----------
|
|
35
|
+
const auditEntryHash = (x) => hashHex([x.seq, x.ts, x.actor, x.action, x.scopeId, x.payloadHash, x.prevHash].join("|"));
|
|
36
|
+
// Hoisted from inside auditStore (captures nothing — pure formatting of its own params).
|
|
37
|
+
const log = (where, e) => console.log(JSON.stringify({ evlog: `cord_audit.${where}`, error: e instanceof Error ? e.message : String(e) }));
|
|
38
|
+
/**
|
|
39
|
+
* DO-backed audit chain on `this.sql`: each entry's hash commits to the previous (prevHash), so editing any
|
|
40
|
+
* earlier row breaks the chain (detect via {@link verifyAuditChain}). Durable → survives reload; spans the DO's
|
|
41
|
+
* whole lifetime (genesis → …), unlike an in-memory chain. Same AuditEntry shape as guards.ts (companion 23 §2).
|
|
42
|
+
*/
|
|
43
|
+
export function auditStore(host) {
|
|
44
|
+
let ready = false;
|
|
45
|
+
try {
|
|
46
|
+
void host.sql `CREATE TABLE IF NOT EXISTS cord_audit (seq INTEGER PRIMARY KEY, ts TEXT, actor TEXT, action TEXT, scopeId TEXT, payloadHash TEXT, prevHash TEXT, hash TEXT)`;
|
|
47
|
+
ready = true;
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
log("init", e);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
append({ actor, action, scopeId, payload }) {
|
|
54
|
+
if (!ready)
|
|
55
|
+
return null;
|
|
56
|
+
try {
|
|
57
|
+
const last = host.sql `SELECT seq, hash FROM cord_audit ORDER BY seq DESC LIMIT 1`;
|
|
58
|
+
const prev = last[0];
|
|
59
|
+
const seq = prev ? Number(prev.seq) + 1 : 0;
|
|
60
|
+
const prevHash = prev ? prev.hash : "GENESIS";
|
|
61
|
+
const ts = new Date().toISOString();
|
|
62
|
+
const payloadHash = hashHex(JSON.stringify(payload ?? null));
|
|
63
|
+
const base = { seq, ts, actor, action, scopeId, payloadHash, prevHash };
|
|
64
|
+
const hash = auditEntryHash(base);
|
|
65
|
+
void host.sql `INSERT INTO cord_audit (seq, ts, actor, action, scopeId, payloadHash, prevHash, hash) VALUES (${seq}, ${ts}, ${actor}, ${action}, ${scopeId}, ${payloadHash}, ${prevHash}, ${hash})`;
|
|
66
|
+
return { ...base, hash };
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
log("append", e);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
list() {
|
|
74
|
+
if (!ready)
|
|
75
|
+
return [];
|
|
76
|
+
try {
|
|
77
|
+
const rows = host.sql `SELECT seq, ts, actor, action, scopeId, payloadHash, prevHash, hash FROM cord_audit ORDER BY seq`;
|
|
78
|
+
return rows.map((r) => Object.assign(r, { seq: Number(r.seq) }));
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
log("list", e);
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Recompute the chain and confirm every entry's hash + prevHash linkage. `ok:false` + `brokenAt` on tamper. */
|
|
88
|
+
export function verifyAuditChain(entries) {
|
|
89
|
+
let prevHash = "GENESIS";
|
|
90
|
+
for (let i = 0; i < entries.length; i++) {
|
|
91
|
+
const entry = entries[i];
|
|
92
|
+
if (!entry)
|
|
93
|
+
return { ok: false, brokenAt: i };
|
|
94
|
+
const { hash, ...base } = entry;
|
|
95
|
+
if (base.prevHash !== prevHash || auditEntryHash(base) !== hash)
|
|
96
|
+
return { ok: false, brokenAt: i };
|
|
97
|
+
prevHash = hash;
|
|
98
|
+
}
|
|
99
|
+
return { ok: true };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Tie the evlog lane to one run: every `wide(...)` call writes an Analytics Engine row AND a hash-chained audit
|
|
103
|
+
* entry, both stamped with this run's identity (runId/cordId/tenantId). Pair with the AG-UI emitter (same runId)
|
|
104
|
+
* so the UI timeline, the analytics row, and the audit entry all correlate.
|
|
105
|
+
*/
|
|
106
|
+
export function cordObserver(opts) {
|
|
107
|
+
const write = analyticsEvlog(opts.analytics);
|
|
108
|
+
const audit = auditStore(opts.host);
|
|
109
|
+
return {
|
|
110
|
+
runId: opts.runId,
|
|
111
|
+
audit,
|
|
112
|
+
wide: (p) => {
|
|
113
|
+
const e = { ...p, runId: opts.runId, cordId: opts.cordId, tenantId: opts.tenantId, ts: new Date().toISOString() };
|
|
114
|
+
write(e);
|
|
115
|
+
audit.append({
|
|
116
|
+
actor: opts.cordId,
|
|
117
|
+
action: `${e.kind}:${e.name}`,
|
|
118
|
+
scopeId: opts.runId,
|
|
119
|
+
payload: { ok: e.ok, durationMs: e.durationMs, scope: e.scope, error: e.error, attrs: e.attrs },
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=evlog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evlog.js","sourceRoot":"","sources":["../src/evlog.ts"],"names":[],"mappings":"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"}
|
package/dist/guards.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export type GuardEvent = {
|
|
2
|
+
cord: string;
|
|
3
|
+
tool?: string;
|
|
4
|
+
scope?: string;
|
|
5
|
+
input: unknown;
|
|
6
|
+
};
|
|
7
|
+
export type WideEvent = {
|
|
8
|
+
ts: string;
|
|
9
|
+
runId: string;
|
|
10
|
+
tenantId: string;
|
|
11
|
+
cordId: string;
|
|
12
|
+
kind: "turn" | "step" | "model" | "tool" | "eval";
|
|
13
|
+
name: string;
|
|
14
|
+
durationMs: number;
|
|
15
|
+
ok: boolean;
|
|
16
|
+
scope?: string;
|
|
17
|
+
error?: {
|
|
18
|
+
code: string;
|
|
19
|
+
why: string;
|
|
20
|
+
};
|
|
21
|
+
attrs?: Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
export type AuditEntry = {
|
|
24
|
+
seq: number;
|
|
25
|
+
ts: string;
|
|
26
|
+
actor: string;
|
|
27
|
+
action: string;
|
|
28
|
+
scopeId: string;
|
|
29
|
+
payloadHash: string;
|
|
30
|
+
prevHash: string;
|
|
31
|
+
hash: string;
|
|
32
|
+
};
|
|
33
|
+
export type Guard = {
|
|
34
|
+
name: string;
|
|
35
|
+
/** Gate hook: deny by throwing (deepsec scope check), or instrument by side-effect. */
|
|
36
|
+
onCall?: (ev: GuardEvent) => void | Promise<void>;
|
|
37
|
+
/** Output transform applied before persist/export (deepsec redaction). */
|
|
38
|
+
redact?: <T>(value: T) => T;
|
|
39
|
+
/** Wide-event sink (deepeval instrumentation). */
|
|
40
|
+
onEvent?: (e: WideEvent) => void;
|
|
41
|
+
};
|
|
42
|
+
export type AuditChain = {
|
|
43
|
+
entries: AuditEntry[];
|
|
44
|
+
append(e: {
|
|
45
|
+
actor: string;
|
|
46
|
+
action: string;
|
|
47
|
+
scopeId: string;
|
|
48
|
+
payload: unknown;
|
|
49
|
+
}): AuditEntry;
|
|
50
|
+
};
|
|
51
|
+
export declare const makeAuditChain: () => AuditChain;
|
|
52
|
+
/** Re-derive every hash; any insert/edit/delete breaks the chain → returns false. (The S7 red test.) */
|
|
53
|
+
export declare const verifyChain: (entries: AuditEntry[]) => boolean;
|
|
54
|
+
/** deepsec — scope gate + redaction (ADR-10). The runtime also drives an audit chain tagged actor="deepsec". */
|
|
55
|
+
export declare const deepsec: (opts?: {
|
|
56
|
+
allow?: string[];
|
|
57
|
+
secrets?: RegExp[];
|
|
58
|
+
}) => Guard;
|
|
59
|
+
/** deepeval — instruments every run (ADR-24). Collects wide-events; prod forwards to evlog (OTLP + PostHog). */
|
|
60
|
+
export declare const deepeval: (sink?: WideEvent[]) => Guard;
|
|
61
|
+
//# sourceMappingURL=guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAGzF,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAC5D,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAChE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAChD,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxE,CAAC;AAGF,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IACxE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,0EAA0E;IAC1E,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;IAC5B,kDAAkD;IAClD,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;CAClC,CAAC;AAIF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,UAAU,CAAC;CAC7F,CAAC;AAKF,eAAO,MAAM,cAAc,QAAO,UAejC,CAAC;AAEF,wGAAwG;AACxG,eAAO,MAAM,WAAW,GAAI,SAAS,UAAU,EAAE,KAAG,OAUnD,CAAC;AA6BF,gHAAgH;AAChH,eAAO,MAAM,OAAO,GAAI,OAAM;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,KAAG,KAW7E,CAAC;AAEF,gHAAgH;AAChH,eAAO,MAAM,QAAQ,GAAI,OAAM,SAAS,EAAO,KAAG,KAGhD,CAAC"}
|
package/dist/guards.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// guards.ts — the system-cord guards, made REAL for H4 (no longer H0 no-op stubs).
|
|
2
|
+
//
|
|
3
|
+
// • deepsec (ADR-10, the security harness): (1) scope check at the gate — deny a run whose scope is off the
|
|
4
|
+
// allow-list; (2) redaction — scrub secrets/PII from the output BEFORE it is persisted to the vault or
|
|
5
|
+
// exported; (3) a tamper-evident, hash-chained audit (evlog AuditEntry shape, ADR-12).
|
|
6
|
+
// • deepeval (ADR-24, the quality harness): instruments every run — emits evlog wide-events (one fat event
|
|
7
|
+
// per unit of work). In prod the worker forwards these to OTLP + PostHog (companion 23 evlog §3).
|
|
8
|
+
//
|
|
9
|
+
// Both are plain functions returning a Guard the runtime (index.ts) drives. Pure TS; no deps beyond hash.ts.
|
|
10
|
+
import { hashHex } from "./hash.js";
|
|
11
|
+
const entryHash = (e) => hashHex([e.seq, e.ts, e.actor, e.action, e.scopeId, e.payloadHash, e.prevHash].join("|"));
|
|
12
|
+
export const makeAuditChain = () => {
|
|
13
|
+
const entries = [];
|
|
14
|
+
return {
|
|
15
|
+
entries,
|
|
16
|
+
append({ actor, action, scopeId, payload }) {
|
|
17
|
+
const seq = entries.length;
|
|
18
|
+
const ts = new Date().toISOString();
|
|
19
|
+
const prevHash = seq === 0 ? "GENESIS" : entries[seq - 1]?.hash ?? "GENESIS";
|
|
20
|
+
const payloadHash = hashHex(JSON.stringify(payload ?? null));
|
|
21
|
+
const base = { seq, ts, actor, action, scopeId, payloadHash, prevHash };
|
|
22
|
+
const entry = { ...base, hash: entryHash(base) };
|
|
23
|
+
entries.push(entry);
|
|
24
|
+
return entry;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/** Re-derive every hash; any insert/edit/delete breaks the chain → returns false. (The S7 red test.) */
|
|
29
|
+
export const verifyChain = (entries) => {
|
|
30
|
+
for (let i = 0; i < entries.length; i++) {
|
|
31
|
+
const e = entries[i];
|
|
32
|
+
if (!e)
|
|
33
|
+
return false;
|
|
34
|
+
const prevHash = i === 0 ? "GENESIS" : entries[i - 1]?.hash ?? "GENESIS";
|
|
35
|
+
if (e.prevHash !== prevHash)
|
|
36
|
+
return false;
|
|
37
|
+
const { hash, ...base } = e;
|
|
38
|
+
if (hash !== entryHash(base))
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
};
|
|
43
|
+
// ---- redaction ----
|
|
44
|
+
// Provider token shapes + key material. Loose-but-real; prod (deepsec lane) uses the full secret-scanner set.
|
|
45
|
+
const DEFAULT_SECRET_RES = [
|
|
46
|
+
/gh[poursa]_[A-Za-z0-9]{20,}/g, // GitHub PAT / oauth / app tokens
|
|
47
|
+
/github_pat_[A-Za-z0-9_]{20,}/g, // fine-grained PAT
|
|
48
|
+
/xox[baprs]-[A-Za-z0-9-]{10,}/g, // Slack
|
|
49
|
+
/AKIA[0-9A-Z]{16}/g, // AWS access key id
|
|
50
|
+
/sk-[A-Za-z0-9]{20,}/g, // OpenAI-style secret keys
|
|
51
|
+
/-----BEGIN (?:[A-Z ]+ )?PRIVATE KEY-----/g, // PEM private keys
|
|
52
|
+
];
|
|
53
|
+
const redactValue = (v, res) => {
|
|
54
|
+
if (typeof v === "string") {
|
|
55
|
+
let s = v;
|
|
56
|
+
for (const re of res)
|
|
57
|
+
s = s.replace(re, "[redacted]");
|
|
58
|
+
return s;
|
|
59
|
+
}
|
|
60
|
+
if (Array.isArray(v))
|
|
61
|
+
return v.map((x) => redactValue(x, res));
|
|
62
|
+
if (v && typeof v === "object") {
|
|
63
|
+
const o = {};
|
|
64
|
+
for (const k of Object.keys(v))
|
|
65
|
+
o[k] = redactValue(v[k], res);
|
|
66
|
+
return o;
|
|
67
|
+
}
|
|
68
|
+
return v;
|
|
69
|
+
};
|
|
70
|
+
/** deepsec — scope gate + redaction (ADR-10). The runtime also drives an audit chain tagged actor="deepsec". */
|
|
71
|
+
export const deepsec = (opts = {}) => {
|
|
72
|
+
const res = opts.secrets ?? DEFAULT_SECRET_RES;
|
|
73
|
+
return {
|
|
74
|
+
name: "deepsec",
|
|
75
|
+
onCall: ({ scope }) => {
|
|
76
|
+
if (opts.allow && scope !== undefined && !opts.allow.includes(scope)) {
|
|
77
|
+
throw new Error(`deepsec: scope "${scope}" not in allow-list [${opts.allow.join(", ")}]`);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
redact: (value) => redactValue(value, res),
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
/** deepeval — instruments every run (ADR-24). Collects wide-events; prod forwards to evlog (OTLP + PostHog). */
|
|
84
|
+
export const deepeval = (sink = []) => ({
|
|
85
|
+
name: "deepeval",
|
|
86
|
+
onEvent: (e) => { sink.push(e); },
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"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"}
|
package/dist/hash.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const hashHex: (s: string) => string;
|
|
2
|
+
/** A url-safe slug for vault keys (target → reports/<slug>/<runId>.json). */
|
|
3
|
+
export declare const slug: (s: string) => string;
|
|
4
|
+
/** A short, sortable-ish run id (timestamp + entropy). No node: deps. */
|
|
5
|
+
export declare const newId: () => string;
|
|
6
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,KAAG,MAOnC,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,IAAI,GAAI,GAAG,MAAM,KAAG,MACgG,CAAC;AAElI,yEAAyE;AACzE,eAAO,MAAM,KAAK,QAAO,MAC+C,CAAC"}
|
package/dist/hash.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// hash.ts — a tiny, deterministic, dependency-free hash for the H-shim (content-addressing + the audit
|
|
2
|
+
// chain). It is NOT cryptographic: production swaps in SHA-256 via Web Crypto (`crypto.subtle.digest`,
|
|
3
|
+
// available in both Workers and Node ≥18) — that's async, so the chain/manifest become async there. For the
|
|
4
|
+
// pure-Node verify path we want a sync, zero-dep hash so the whole runtime stays portable (Node AND a
|
|
5
|
+
// Worker, no imports). FNV-1a (32-bit) is enough to make tamper-evidence + content-addressing demonstrable.
|
|
6
|
+
export const hashHex = (s) => {
|
|
7
|
+
let h = 0x811c9dc5;
|
|
8
|
+
for (let i = 0; i < s.length; i++) {
|
|
9
|
+
h ^= s.charCodeAt(i);
|
|
10
|
+
h = Math.imul(h, 0x01000193);
|
|
11
|
+
}
|
|
12
|
+
return (h >>> 0).toString(16).padStart(8, "0");
|
|
13
|
+
};
|
|
14
|
+
/** A url-safe slug for vault keys (target → reports/<slug>/<runId>.json). */
|
|
15
|
+
export const slug = (s) => s.trim().toLowerCase().replace(/^https?:\/\//, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "target";
|
|
16
|
+
/** A short, sortable-ish run id (timestamp + entropy). No node: deps. */
|
|
17
|
+
export const newId = () => Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 8);
|
|
18
|
+
//# sourceMappingURL=hash.js.map
|
package/dist/hash.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA,uGAAuG;AACvG,uGAAuG;AACvG,4GAA4G;AAC5G,sGAAsG;AACtG,4GAA4G;AAC5G,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAS,EAAU,EAAE;IAC3C,IAAI,CAAC,GAAG,UAAU,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CACxC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC;AAElI,yEAAyE;AACzE,MAAM,CAAC,MAAM,KAAK,GAAG,GAAW,EAAE,CAChC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
export * from "./hash.ts";
|
|
2
|
+
export * from "./vault.ts";
|
|
3
|
+
export * from "./guards.ts";
|
|
4
|
+
export * from "./platform.ts";
|
|
5
|
+
export * from "./agent.ts";
|
|
6
|
+
export * from "./source.ts";
|
|
7
|
+
export * from "./agui.ts";
|
|
8
|
+
export * from "./tool.ts";
|
|
9
|
+
export * from "./config.ts";
|
|
10
|
+
export * from "./define.ts";
|
|
11
|
+
export * from "./evlog.ts";
|
|
12
|
+
export * from "./events.ts";
|
|
13
|
+
export * from "./usectx.ts";
|
|
14
|
+
export * from "./distill.ts";
|
|
15
|
+
export * from "./data.ts";
|
|
16
|
+
import type { Vault } from "./vault.ts";
|
|
17
|
+
import type { Resources, ResourceNeed } from "./platform.ts";
|
|
18
|
+
import { type Guard, type WideEvent, type AuditEntry } from "./guards.ts";
|
|
19
|
+
/** A sub-cord: an encapsulated unit composed into a parent. `any` generics (not `unknown`) so a typed
|
|
20
|
+
* `subcords` record — { scan: Subcord<string,Facts>, score: Subcord<Facts,EvalResult>, ... } — is assignable
|
|
21
|
+
* to Record<string, Subcord> (Subcord<X,Y> is NOT assignable to Subcord<unknown,unknown> — invariant `run`
|
|
22
|
+
* param — but IS assignable to Subcord<any,any>). Same heterogeneous-registry seam as data.ts's AnyFn. */
|
|
23
|
+
export type Subcord<I = any, O = any> = {
|
|
24
|
+
id: string;
|
|
25
|
+
mount: "local" | "registry";
|
|
26
|
+
run: (input: I) => Promise<O>;
|
|
27
|
+
};
|
|
28
|
+
/** Mount an OWNED sub-cord in-process (deterministic trunk). */
|
|
29
|
+
export declare function use<I, O>(sc: {
|
|
30
|
+
id: string;
|
|
31
|
+
run: (input: I) => Promise<O>;
|
|
32
|
+
}): Subcord<I, O>;
|
|
33
|
+
/** Mount a THIRD-PARTY/registry cord over MCP (the trust boundary; an executor toolkit). */
|
|
34
|
+
export declare function useRemote<I, O>(sc: {
|
|
35
|
+
id: string;
|
|
36
|
+
call: (input: I) => Promise<O>;
|
|
37
|
+
}): Subcord<I, O>;
|
|
38
|
+
export type Expose = {
|
|
39
|
+
codemode?: boolean;
|
|
40
|
+
mcp?: string;
|
|
41
|
+
cli?: boolean;
|
|
42
|
+
openapi?: boolean;
|
|
43
|
+
};
|
|
44
|
+
export type CordDef<Input, Output> = {
|
|
45
|
+
id: string;
|
|
46
|
+
kind?: "agent-ful" | "agent-less";
|
|
47
|
+
inference?: "managed" | "byo";
|
|
48
|
+
/** The scope this cord's run requests — checked by deepsec against its allow-list (H4). */
|
|
49
|
+
scope?: string;
|
|
50
|
+
expose?: Expose;
|
|
51
|
+
guards?: Guard[];
|
|
52
|
+
subcords?: Record<string, Subcord>;
|
|
53
|
+
/** Durable resources this cord requires; the host MUST bind them or the run fails fast (validated post-gate). */
|
|
54
|
+
needs?: ResourceNeed[];
|
|
55
|
+
/** The deterministic trunk: compose sub-cords (ctx) + use the host-bound resources (res). */
|
|
56
|
+
run: (input: Input, ctx: Record<string, (input: any) => Promise<any>>, res: Resources) => Promise<Output>;
|
|
57
|
+
};
|
|
58
|
+
export type RunBudget = {
|
|
59
|
+
cap: number;
|
|
60
|
+
used: number;
|
|
61
|
+
depth: number;
|
|
62
|
+
maxDepth: number;
|
|
63
|
+
};
|
|
64
|
+
export type RunOpts = {
|
|
65
|
+
tenantId?: string;
|
|
66
|
+
scope?: string;
|
|
67
|
+
vault?: Vault;
|
|
68
|
+
resources?: Resources;
|
|
69
|
+
budget?: Partial<Pick<RunBudget, "cap" | "maxDepth">>;
|
|
70
|
+
onEvent?: (e: WideEvent) => void;
|
|
71
|
+
};
|
|
72
|
+
export type RunResult<O> = {
|
|
73
|
+
output: O;
|
|
74
|
+
runId: string;
|
|
75
|
+
artifact?: {
|
|
76
|
+
key: string;
|
|
77
|
+
version: string;
|
|
78
|
+
hash: string;
|
|
79
|
+
};
|
|
80
|
+
audit: AuditEntry[];
|
|
81
|
+
events: WideEvent[];
|
|
82
|
+
budget: RunBudget;
|
|
83
|
+
};
|
|
84
|
+
export type CordManifest = {
|
|
85
|
+
id: string;
|
|
86
|
+
version: string;
|
|
87
|
+
kind: "agent-ful" | "agent-less";
|
|
88
|
+
inference: "managed" | "byo";
|
|
89
|
+
scope?: string;
|
|
90
|
+
expose: Expose;
|
|
91
|
+
subcords: string[];
|
|
92
|
+
guards: string[];
|
|
93
|
+
needs: ResourceNeed[];
|
|
94
|
+
};
|
|
95
|
+
export type Cord<Input, Output> = {
|
|
96
|
+
id: string;
|
|
97
|
+
expose: Expose;
|
|
98
|
+
manifest: CordManifest;
|
|
99
|
+
run: (input: Input, opts?: RunOpts) => Promise<Output>;
|
|
100
|
+
runFull: (input: Input, opts?: RunOpts) => Promise<RunResult<Output>>;
|
|
101
|
+
};
|
|
102
|
+
export declare function defineCord<Input, Output>(def: CordDef<Input, Output>): Cord<Input, Output>;
|
|
103
|
+
/** /.well-known/op0.json (ADR-18) generated from the cord's `expose`. Host is filled at deploy. */
|
|
104
|
+
export declare const wellKnown: (m: CordManifest, host?: string) => {
|
|
105
|
+
auth?: {
|
|
106
|
+
type: string;
|
|
107
|
+
scopes: string[];
|
|
108
|
+
};
|
|
109
|
+
skills: string;
|
|
110
|
+
cli?: string;
|
|
111
|
+
openapi?: string;
|
|
112
|
+
mcp: string[];
|
|
113
|
+
docs: string;
|
|
114
|
+
};
|
|
115
|
+
/** Content-address the manifest for skillkit publish/fork lineage (signed → forkOf{atCommit} later, ADR-22). */
|
|
116
|
+
export declare const signManifest: (m: CordManifest) => {
|
|
117
|
+
manifest: CordManifest;
|
|
118
|
+
hash: string;
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|