@assertion-runtime/sdk-node 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/README.md ADDED
@@ -0,0 +1,6 @@
1
+ # Assertion Runtime Node SDK
2
+
3
+ ## Output lint
4
+
5
+ Use `emitFinding(output, { endpoint, apiKey })` to lint an output string. The SDK applies simple heuristics, captures
6
+ best-effort emission site metadata, and emits a finding only when the output looks risky.
@@ -0,0 +1,42 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "assr://schemas/assertion-finding/1.0.0",
4
+ "title": "AssertionFinding",
5
+ "type": "object",
6
+ "required": [
7
+ "finding_id",
8
+ "output_excerpt",
9
+ "reason",
10
+ "created_at",
11
+ "emission_site"
12
+ ],
13
+ "properties": {
14
+ "finding_id": {
15
+ "type": "string",
16
+ "format": "uuid"
17
+ },
18
+ "output_excerpt": {
19
+ "type": "string"
20
+ },
21
+ "reason": {
22
+ "type": "string"
23
+ },
24
+ "emission_site": {
25
+ "type": "object",
26
+ "required": ["file", "line", "runtime", "stack_hash"],
27
+ "properties": {
28
+ "file": { "type": "string" },
29
+ "line": { "type": "number" },
30
+ "function": { "type": "string" },
31
+ "runtime": { "type": "string" },
32
+ "stack_hash": { "type": "string" }
33
+ },
34
+ "additionalProperties": false
35
+ },
36
+ "created_at": {
37
+ "type": "string",
38
+ "format": "date-time"
39
+ }
40
+ },
41
+ "additionalProperties": false
42
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ type Finding = {
3
+ finding_id: string;
4
+ output_excerpt: string;
5
+ reason: string;
6
+ file_path?: string | null;
7
+ line_number?: number | null;
8
+ created_at?: string;
9
+ };
10
+ declare function formatEmissionSite(finding: Finding): string;
11
+ declare function formatCreatedAt(value?: string): string;
12
+ declare function parseArgs(argv: string[]): {
13
+ command: string | undefined;
14
+ json: boolean;
15
+ };
16
+ declare function fetchFindings(endpoint: string, apiKey?: string): Promise<Finding[]>;
17
+ declare function main(): Promise<void>;
18
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,KAAK,OAAO,GAAG;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,iBAAS,kBAAkB,CAAC,OAAO,EAAE,OAAO,UAM3C;AAED,iBAAS,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,UAUtC;AAED,iBAAS,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE;;;EAKhC;AAED,iBAAe,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,sBAa7D;AAED,iBAAe,IAAI,kBAoClB"}
package/dist/cli.js ADDED
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ function formatEmissionSite(finding) {
4
+ if (!finding.file_path)
5
+ return "-";
6
+ if (typeof finding.line_number === "number") {
7
+ return `${finding.file_path}:${finding.line_number}`;
8
+ }
9
+ return finding.file_path;
10
+ }
11
+ function formatCreatedAt(value) {
12
+ if (!value)
13
+ return "-";
14
+ const date = new Date(value);
15
+ if (Number.isNaN(date.getTime()))
16
+ return value;
17
+ return new Intl.DateTimeFormat("en-US", {
18
+ month: "short",
19
+ day: "2-digit",
20
+ hour: "2-digit",
21
+ minute: "2-digit",
22
+ }).format(date);
23
+ }
24
+ function parseArgs(argv) {
25
+ const args = [...argv];
26
+ const command = args[0] && !args[0].startsWith("-") ? args.shift() : "lint";
27
+ const json = args.includes("--json");
28
+ return { command, json };
29
+ }
30
+ async function fetchFindings(endpoint, apiKey) {
31
+ const url = `${endpoint.replace(/\/$/, "")}/findings?limit=200&offset=0`;
32
+ const response = await fetch(url, {
33
+ headers: {
34
+ ...(apiKey ? { authorization: `Bearer ${apiKey}` } : {}),
35
+ },
36
+ });
37
+ if (!response.ok) {
38
+ const body = await response.text();
39
+ throw new Error(`Finding fetch failed (${response.status}): ${body}`);
40
+ }
41
+ const payload = (await response.json());
42
+ return Array.isArray(payload.findings) ? payload.findings : [];
43
+ }
44
+ async function main() {
45
+ const { command, json } = parseArgs(process.argv.slice(2));
46
+ if (command !== "lint") {
47
+ console.error("Usage: assertion-runtime lint [--json]");
48
+ process.exit(2);
49
+ }
50
+ const endpoint = process.env.ASSR_RUNTIME_API_URL || process.env.RUNTIME_API_URL || "http://localhost:4000";
51
+ const apiKey = process.env.ASSR_ADMIN_API_KEY || process.env.ASSR_API_KEY;
52
+ try {
53
+ const findings = await fetchFindings(endpoint, apiKey);
54
+ if (json) {
55
+ process.stdout.write(`${JSON.stringify({ findings }, null, 2)}\n`);
56
+ process.exit(findings.length > 0 ? 1 : 0);
57
+ }
58
+ if (findings.length === 0) {
59
+ console.log("No risky outputs detected.");
60
+ process.exit(0);
61
+ }
62
+ console.log(`${findings.length} risky outputs detected:`);
63
+ for (const finding of findings) {
64
+ console.log(`- ${finding.finding_id.slice(0, 8)} ${finding.output_excerpt}`);
65
+ console.log(` ${finding.reason}`);
66
+ console.log(` Emitted from: ${formatEmissionSite(finding)}`);
67
+ console.log(` Created: ${formatCreatedAt(finding.created_at)}`);
68
+ console.log("");
69
+ }
70
+ process.exit(1);
71
+ }
72
+ catch (error) {
73
+ console.error(error instanceof Error ? error.message : "CLI failed");
74
+ process.exit(2);
75
+ }
76
+ }
77
+ void main();
78
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ export interface EmitOptions {
2
+ endpoint?: string;
3
+ apiKey?: string;
4
+ }
5
+ export interface EmissionSite {
6
+ file?: string;
7
+ line?: number;
8
+ function?: string;
9
+ runtime?: string;
10
+ stack_hash?: string;
11
+ }
12
+ export interface AssertionFinding {
13
+ finding_id: string;
14
+ output_excerpt: string;
15
+ reason: string;
16
+ emission_site?: EmissionSite;
17
+ created_at: string;
18
+ }
19
+ export declare function lintOutput(output: string): {
20
+ reason: string;
21
+ } | null;
22
+ export declare function buildFinding(output: string): AssertionFinding | null;
23
+ export declare function emitFinding(output: string, options?: EmitOptions): Promise<unknown>;
24
+ export interface SdkDiagnosticEvent {
25
+ diagnostic_id: string;
26
+ project_id: string;
27
+ sdk: {
28
+ language: "node" | "python";
29
+ version: string;
30
+ runtime?: string;
31
+ platform?: string;
32
+ };
33
+ window: {
34
+ start: string;
35
+ end: string;
36
+ duration_sec?: number;
37
+ };
38
+ counters: Record<string, number>;
39
+ buffer: {
40
+ backend?: "file" | "sqlite" | "memory";
41
+ current_depth: number;
42
+ max_depth?: number;
43
+ oldest_event_age_sec?: number;
44
+ };
45
+ latency_ms?: Record<string, number>;
46
+ flags?: Record<string, boolean>;
47
+ timestamp: string;
48
+ schema_version: string;
49
+ extensions?: Record<string, unknown>;
50
+ }
51
+ export interface DiagnosticsOptions {
52
+ endpoint: string;
53
+ apiKey?: string;
54
+ projectId: string;
55
+ sdkVersion: string;
56
+ runtime?: string;
57
+ platform?: string;
58
+ schemaVersion?: string;
59
+ }
60
+ export declare class DiagnosticsEmitter {
61
+ private options;
62
+ private windowStart;
63
+ private counters;
64
+ private bufferState;
65
+ private latency;
66
+ private flags;
67
+ private flushInFlight;
68
+ private flushOnExitBound;
69
+ constructor(options: DiagnosticsOptions);
70
+ increment(counter: string, value?: number): void;
71
+ setBufferState(state: SdkDiagnosticEvent["buffer"]): void;
72
+ setLatency(metrics: Record<string, number>): void;
73
+ setFlags(flags: Record<string, boolean>): void;
74
+ emit(): Promise<unknown>;
75
+ registerShutdownHooks(): void;
76
+ unregisterShutdownHooks(): void;
77
+ }
78
+ //# 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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"}
package/dist/index.js ADDED
@@ -0,0 +1,273 @@
1
+ import crypto from "node:crypto";
2
+ import Ajv from "ajv";
3
+ import addFormats from "ajv-formats";
4
+ import { readFileSync } from "node:fs";
5
+ import { fileURLToPath } from "node:url";
6
+ import { dirname, join } from "node:path";
7
+ const currentDir = dirname(fileURLToPath(import.meta.url));
8
+ const diagnosticSchemaPath = join(currentDir, "sdk-diagnostic.schema.json");
9
+ const findingSchemaPath = join(currentDir, "assertion-finding.schema.json");
10
+ const diagnosticSchema = JSON.parse(readFileSync(diagnosticSchemaPath, "utf-8"));
11
+ const findingSchema = JSON.parse(readFileSync(findingSchemaPath, "utf-8"));
12
+ const ajv = new Ajv({ allErrors: true, strict: false });
13
+ addFormats(ajv);
14
+ const validateDiagnostic = ajv.compile(diagnosticSchema);
15
+ const validateFinding = ajv.compile(findingSchema);
16
+ function validateDiagnosticEvent(event) {
17
+ const ok = validateDiagnostic(event);
18
+ if (!ok) {
19
+ const error = new Error("invalid_diagnostic");
20
+ error.details = validateDiagnostic.errors ?? [];
21
+ throw error;
22
+ }
23
+ }
24
+ const seenFindings = new Set();
25
+ function validateFindingEvent(event) {
26
+ const ok = validateFinding(event);
27
+ if (!ok) {
28
+ const error = new Error("invalid_finding");
29
+ error.details = validateFinding.errors ?? [];
30
+ throw error;
31
+ }
32
+ }
33
+ function summarizeOutput(output, maxLength = 140) {
34
+ const trimmed = output.trim();
35
+ if (trimmed.length <= maxLength)
36
+ return trimmed;
37
+ return `${trimmed.slice(0, maxLength - 1)}…`;
38
+ }
39
+ function hashStackLocation(params) {
40
+ const payload = `${params.file}:${params.line}:${params.functionName ?? ""}`;
41
+ return crypto.createHash("sha256").update(payload).digest("hex");
42
+ }
43
+ function parseStackLine(line) {
44
+ const stripFileUrl = (value) => {
45
+ if (!value.startsWith("file://"))
46
+ return value;
47
+ try {
48
+ return fileURLToPath(value);
49
+ }
50
+ catch {
51
+ return value;
52
+ }
53
+ };
54
+ const withFunc = line.match(/^at\s+(?:async\s+)?(.+?)\s+\((.+):(\d+):(\d+)\)$/);
55
+ if (withFunc) {
56
+ return {
57
+ function: withFunc[1],
58
+ file: stripFileUrl(withFunc[2]),
59
+ line: Number(withFunc[3]),
60
+ };
61
+ }
62
+ const withoutFunc = line.match(/^at\s+(?:async\s+)?(.+):(\d+):(\d+)$/);
63
+ if (withoutFunc) {
64
+ return {
65
+ file: stripFileUrl(withoutFunc[1]),
66
+ line: Number(withoutFunc[2]),
67
+ };
68
+ }
69
+ return null;
70
+ }
71
+ function captureEmissionSite() {
72
+ const stack = new Error().stack;
73
+ if (!stack)
74
+ return undefined;
75
+ const lines = stack.split("\n").map((line) => line.trim());
76
+ const skipPatterns = ["node:internal", "/node_modules/", "assr_sdk", "sdk-node", "internal/process"];
77
+ const candidate = lines
78
+ .slice(1)
79
+ .map((line) => ({ line, parsed: parseStackLine(line) }))
80
+ .find((entry) => entry.parsed && !skipPatterns.some((pattern) => entry.line.includes(pattern)));
81
+ if (!candidate?.parsed) {
82
+ return undefined;
83
+ }
84
+ return {
85
+ file: candidate.parsed.file,
86
+ line: candidate.parsed.line,
87
+ function: candidate.parsed.function,
88
+ runtime: `node${process.version}`,
89
+ stack_hash: hashStackLocation({
90
+ file: candidate.parsed.file,
91
+ line: candidate.parsed.line,
92
+ functionName: candidate.parsed.function,
93
+ }),
94
+ };
95
+ }
96
+ function hasQualifier(output) {
97
+ return /\b(estimate|approximately|approx|may|might|likely|suggests|early data|could)\b/i.test(output);
98
+ }
99
+ function isDebugLog(output) {
100
+ return /^(?:\s*\[?(?:debug|trace|info|warn|error)\]?:\s*|\s*(?:fetched|loaded|processing|queued|executed|query|cache|http)\b)/i.test(output);
101
+ }
102
+ function isForwardLooking(output) {
103
+ return /\b(q1|next quarter|will|predicts|expected)\b/i.test(output);
104
+ }
105
+ function isClaimCandidate(output) {
106
+ if (hasQualifier(output))
107
+ return false;
108
+ if (isDebugLog(output))
109
+ return false;
110
+ if (output.length <= 10)
111
+ return false;
112
+ return true;
113
+ }
114
+ function isDeclarative(output) {
115
+ return !hasQualifier(output);
116
+ }
117
+ export function lintOutput(output) {
118
+ const trimmed = output.trim();
119
+ if (!trimmed)
120
+ return null;
121
+ if (!isClaimCandidate(trimmed))
122
+ return null;
123
+ if (!isForwardLooking(trimmed))
124
+ return null;
125
+ if (!isDeclarative(trimmed))
126
+ return null;
127
+ return { reason: "Forward-looking claim without sufficient supporting context" };
128
+ }
129
+ export function buildFinding(output) {
130
+ const lint = lintOutput(output);
131
+ if (!lint)
132
+ return null;
133
+ const findingId = crypto.randomUUID();
134
+ const emissionSite = captureEmissionSite();
135
+ if (!emissionSite?.stack_hash || !emissionSite.file || typeof emissionSite.line !== "number")
136
+ return null;
137
+ return {
138
+ finding_id: findingId,
139
+ output_excerpt: summarizeOutput(output),
140
+ reason: lint.reason,
141
+ emission_site: emissionSite,
142
+ created_at: new Date().toISOString(),
143
+ };
144
+ }
145
+ export async function emitFinding(output, options = {}) {
146
+ const finding = buildFinding(output);
147
+ if (!finding) {
148
+ return { status: "skipped", reason: "not_risky" };
149
+ }
150
+ const stackHash = finding.emission_site?.stack_hash;
151
+ const key = stackHash ? `${stackHash}::${finding.output_excerpt}` : null;
152
+ if (key && seenFindings.has(key)) {
153
+ return { status: "skipped", reason: "deduped" };
154
+ }
155
+ if (key) {
156
+ seenFindings.add(key);
157
+ }
158
+ validateFindingEvent(finding);
159
+ if (!options.endpoint) {
160
+ throw new Error("Missing endpoint; provide endpoint.");
161
+ }
162
+ try {
163
+ const response = await fetch(`${options.endpoint}/findings`, {
164
+ method: "POST",
165
+ headers: {
166
+ "content-type": "application/json",
167
+ ...(options.apiKey ? { authorization: `Bearer ${options.apiKey}` } : {}),
168
+ },
169
+ body: JSON.stringify(finding),
170
+ });
171
+ if (!response.ok) {
172
+ const body = await response.text();
173
+ return { status: "skipped", reason: "fail_open", error: `Finding emit failed (${response.status}): ${body}` };
174
+ }
175
+ return response.json();
176
+ }
177
+ catch (error) {
178
+ return {
179
+ status: "skipped",
180
+ reason: "fail_open",
181
+ error: error instanceof Error ? error.message : "finding_emit_failed",
182
+ };
183
+ }
184
+ }
185
+ export class DiagnosticsEmitter {
186
+ constructor(options) {
187
+ this.options = options;
188
+ this.windowStart = new Date();
189
+ this.counters = {};
190
+ this.bufferState = { current_depth: 0 };
191
+ this.flushInFlight = false;
192
+ this.flushOnExitBound = null;
193
+ }
194
+ increment(counter, value = 1) {
195
+ this.counters[counter] = (this.counters[counter] ?? 0) + value;
196
+ }
197
+ setBufferState(state) {
198
+ this.bufferState = state;
199
+ }
200
+ setLatency(metrics) {
201
+ this.latency = metrics;
202
+ }
203
+ setFlags(flags) {
204
+ this.flags = flags;
205
+ }
206
+ async emit() {
207
+ if (this.flushInFlight) {
208
+ return { status: "skipped", reason: "in_flight" };
209
+ }
210
+ this.flushInFlight = true;
211
+ const windowEnd = new Date();
212
+ const payload = {
213
+ diagnostic_id: crypto.randomUUID(),
214
+ project_id: this.options.projectId,
215
+ sdk: {
216
+ language: "node",
217
+ version: this.options.sdkVersion,
218
+ runtime: this.options.runtime,
219
+ platform: this.options.platform,
220
+ },
221
+ window: {
222
+ start: this.windowStart.toISOString(),
223
+ end: windowEnd.toISOString(),
224
+ duration_sec: Math.max(1, Math.floor((windowEnd.getTime() - this.windowStart.getTime()) / 1000)),
225
+ },
226
+ counters: this.counters,
227
+ buffer: this.bufferState,
228
+ latency_ms: this.latency,
229
+ flags: this.flags,
230
+ timestamp: windowEnd.toISOString(),
231
+ schema_version: this.options.schemaVersion ?? "1.0.0",
232
+ };
233
+ validateDiagnosticEvent(payload);
234
+ const response = await fetch(`${this.options.endpoint}/sdk-diagnostics`, {
235
+ method: "POST",
236
+ headers: {
237
+ "content-type": "application/json",
238
+ ...(this.options.apiKey ? { authorization: `Bearer ${this.options.apiKey}` } : {}),
239
+ },
240
+ body: JSON.stringify(payload),
241
+ });
242
+ if (!response.ok) {
243
+ const body = await response.text();
244
+ this.flushInFlight = false;
245
+ throw new Error(`Diagnostics emit failed (${response.status}): ${body}`);
246
+ }
247
+ this.windowStart = windowEnd;
248
+ this.counters = {};
249
+ this.flushInFlight = false;
250
+ return response.json();
251
+ }
252
+ registerShutdownHooks() {
253
+ if (this.flushOnExitBound)
254
+ return;
255
+ this.flushOnExitBound = () => {
256
+ void this.emit().catch(() => {
257
+ // Best-effort on shutdown; never throw.
258
+ });
259
+ };
260
+ process.on("beforeExit", this.flushOnExitBound);
261
+ process.on("SIGTERM", this.flushOnExitBound);
262
+ process.on("SIGINT", this.flushOnExitBound);
263
+ }
264
+ unregisterShutdownHooks() {
265
+ if (!this.flushOnExitBound)
266
+ return;
267
+ process.off("beforeExit", this.flushOnExitBound);
268
+ process.off("SIGTERM", this.flushOnExitBound);
269
+ process.off("SIGINT", this.flushOnExitBound);
270
+ this.flushOnExitBound = null;
271
+ }
272
+ }
273
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "SDK Diagnostic Event",
4
+ "type": "object",
5
+ "required": [
6
+ "diagnostic_id",
7
+ "project_id",
8
+ "sdk",
9
+ "window",
10
+ "counters",
11
+ "buffer",
12
+ "timestamp",
13
+ "schema_version"
14
+ ],
15
+ "properties": {
16
+ "diagnostic_id": { "type": "string", "format": "uuid" },
17
+ "project_id": { "type": "string", "format": "uuid" },
18
+ "sdk": {
19
+ "type": "object",
20
+ "required": ["language", "version"],
21
+ "properties": {
22
+ "language": { "enum": ["node", "python"] },
23
+ "version": { "type": "string" },
24
+ "runtime": { "type": "string" },
25
+ "platform": { "type": "string" }
26
+ },
27
+ "additionalProperties": false
28
+ },
29
+ "window": {
30
+ "type": "object",
31
+ "required": ["start", "end"],
32
+ "properties": {
33
+ "start": { "type": "string", "format": "date-time" },
34
+ "end": { "type": "string", "format": "date-time" },
35
+ "duration_sec": { "type": "number" }
36
+ },
37
+ "additionalProperties": false
38
+ },
39
+ "counters": {
40
+ "type": "object",
41
+ "additionalProperties": { "type": "number" }
42
+ },
43
+ "buffer": {
44
+ "type": "object",
45
+ "required": ["current_depth"],
46
+ "properties": {
47
+ "backend": { "enum": ["file", "sqlite", "memory"] },
48
+ "current_depth": { "type": "number" },
49
+ "max_depth": { "type": "number" },
50
+ "oldest_event_age_sec": { "type": "number" }
51
+ },
52
+ "additionalProperties": false
53
+ },
54
+ "latency_ms": {
55
+ "type": "object",
56
+ "additionalProperties": { "type": "number" }
57
+ },
58
+ "flags": {
59
+ "type": "object",
60
+ "additionalProperties": { "type": "boolean" }
61
+ },
62
+ "timestamp": { "type": "string", "format": "date-time" },
63
+ "schema_version": { "type": "string" },
64
+ "extensions": { "type": "object" }
65
+ },
66
+ "additionalProperties": false
67
+ }
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@assertion-runtime/sdk-node",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "assertion-runtime": "dist/cli.js"
10
+ },
11
+ "scripts": {
12
+ "build": "rm -rf dist && tsc -p tsconfig.json && cp src/*.json dist/"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "dependencies": {
18
+ "ajv": "^8.17.1",
19
+ "ajv-formats": "^2.1.1"
20
+ }
21
+ }