@varveai/adit-core 0.2.1

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.
Files changed (90) hide show
  1. package/LICENSE +21 -0
  2. package/dist/config/index.d.ts +29 -0
  3. package/dist/config/index.d.ts.map +1 -0
  4. package/dist/config/index.js +107 -0
  5. package/dist/config/index.js.map +1 -0
  6. package/dist/db/connection.d.ts +9 -0
  7. package/dist/db/connection.d.ts.map +1 -0
  8. package/dist/db/connection.js +48 -0
  9. package/dist/db/connection.js.map +1 -0
  10. package/dist/db/diffs.d.ts +22 -0
  11. package/dist/db/diffs.d.ts.map +1 -0
  12. package/dist/db/diffs.js +37 -0
  13. package/dist/db/diffs.js.map +1 -0
  14. package/dist/db/env-snapshots.d.ts +29 -0
  15. package/dist/db/env-snapshots.d.ts.map +1 -0
  16. package/dist/db/env-snapshots.js +57 -0
  17. package/dist/db/env-snapshots.js.map +1 -0
  18. package/dist/db/events.d.ts +91 -0
  19. package/dist/db/events.d.ts.map +1 -0
  20. package/dist/db/events.js +260 -0
  21. package/dist/db/events.js.map +1 -0
  22. package/dist/db/index.d.ts +10 -0
  23. package/dist/db/index.d.ts.map +1 -0
  24. package/dist/db/index.js +10 -0
  25. package/dist/db/index.js.map +1 -0
  26. package/dist/db/migrations.d.ts +13 -0
  27. package/dist/db/migrations.d.ts.map +1 -0
  28. package/dist/db/migrations.js +237 -0
  29. package/dist/db/migrations.js.map +1 -0
  30. package/dist/db/plans.d.ts +21 -0
  31. package/dist/db/plans.d.ts.map +1 -0
  32. package/dist/db/plans.js +52 -0
  33. package/dist/db/plans.js.map +1 -0
  34. package/dist/db/sessions.d.ts +23 -0
  35. package/dist/db/sessions.d.ts.map +1 -0
  36. package/dist/db/sessions.js +57 -0
  37. package/dist/db/sessions.js.map +1 -0
  38. package/dist/db/sync-state.d.ts +21 -0
  39. package/dist/db/sync-state.d.ts.map +1 -0
  40. package/dist/db/sync-state.js +36 -0
  41. package/dist/db/sync-state.js.map +1 -0
  42. package/dist/db/transcript-uploads.d.ts +57 -0
  43. package/dist/db/transcript-uploads.d.ts.map +1 -0
  44. package/dist/db/transcript-uploads.js +132 -0
  45. package/dist/db/transcript-uploads.js.map +1 -0
  46. package/dist/index.d.ts +17 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +17 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/perf/perf-log.d.ts +105 -0
  51. package/dist/perf/perf-log.d.ts.map +1 -0
  52. package/dist/perf/perf-log.js +280 -0
  53. package/dist/perf/perf-log.js.map +1 -0
  54. package/dist/security/content-redaction.d.ts +105 -0
  55. package/dist/security/content-redaction.d.ts.map +1 -0
  56. package/dist/security/content-redaction.js +365 -0
  57. package/dist/security/content-redaction.js.map +1 -0
  58. package/dist/sync/index.d.ts +3 -0
  59. package/dist/sync/index.d.ts.map +1 -0
  60. package/dist/sync/index.js +3 -0
  61. package/dist/sync/index.js.map +1 -0
  62. package/dist/sync/ulid.d.ts +15 -0
  63. package/dist/sync/ulid.d.ts.map +1 -0
  64. package/dist/sync/ulid.js +34 -0
  65. package/dist/sync/ulid.js.map +1 -0
  66. package/dist/sync/vclock.d.ts +33 -0
  67. package/dist/sync/vclock.d.ts.map +1 -0
  68. package/dist/sync/vclock.js +69 -0
  69. package/dist/sync/vclock.js.map +1 -0
  70. package/dist/types/environment.d.ts +53 -0
  71. package/dist/types/environment.d.ts.map +1 -0
  72. package/dist/types/environment.js +8 -0
  73. package/dist/types/environment.js.map +1 -0
  74. package/dist/types/events.d.ts +88 -0
  75. package/dist/types/events.d.ts.map +1 -0
  76. package/dist/types/events.js +40 -0
  77. package/dist/types/events.js.map +1 -0
  78. package/dist/types/index.d.ts +6 -0
  79. package/dist/types/index.d.ts.map +1 -0
  80. package/dist/types/index.js +2 -0
  81. package/dist/types/index.js.map +1 -0
  82. package/dist/types/plan.d.ts +30 -0
  83. package/dist/types/plan.d.ts.map +1 -0
  84. package/dist/types/plan.js +8 -0
  85. package/dist/types/plan.js.map +1 -0
  86. package/dist/types/session.d.ts +44 -0
  87. package/dist/types/session.d.ts.map +1 -0
  88. package/dist/types/session.js +8 -0
  89. package/dist/types/session.js.map +1 -0
  90. package/package.json +29 -0
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Performance logging for time-sensitive operations.
3
+ *
4
+ * Records call timing for hook handlers, git operations, network calls,
5
+ * and other time-sensitive operations. Logs are stored as daily JSONL files
6
+ * in .adit/perf-logs/ and auto-pruned after 7 days.
7
+ */
8
+ import { mkdirSync, appendFileSync, readdirSync, readFileSync, unlinkSync, existsSync, } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { performance } from "node:perf_hooks";
11
+ const RETENTION_DAYS = 7;
12
+ const PERF_LOG_DIR = "perf-logs";
13
+ /** Get the perf log directory path */
14
+ function getPerfLogDir(dataDir) {
15
+ return join(dataDir, PERF_LOG_DIR);
16
+ }
17
+ /** Get today's date string (YYYY-MM-DD) */
18
+ function todayDateStr() {
19
+ return new Date().toISOString().slice(0, 10);
20
+ }
21
+ /** Get the log file path for a given date */
22
+ function logFilePath(dataDir, dateStr) {
23
+ return join(getPerfLogDir(dataDir), `${dateStr}.jsonl`);
24
+ }
25
+ /**
26
+ * Prune log files older than the retention period.
27
+ * Called on each write to keep the directory clean.
28
+ */
29
+ export function pruneOldLogs(dataDir) {
30
+ const dir = getPerfLogDir(dataDir);
31
+ if (!existsSync(dir))
32
+ return;
33
+ const cutoff = new Date();
34
+ cutoff.setDate(cutoff.getDate() - RETENTION_DAYS);
35
+ const cutoffStr = cutoff.toISOString().slice(0, 10);
36
+ try {
37
+ const files = readdirSync(dir);
38
+ for (const file of files) {
39
+ if (!file.endsWith(".jsonl"))
40
+ continue;
41
+ const dateStr = file.replace(".jsonl", "");
42
+ if (dateStr < cutoffStr) {
43
+ try {
44
+ unlinkSync(join(dir, file));
45
+ }
46
+ catch {
47
+ // Best effort
48
+ }
49
+ }
50
+ }
51
+ }
52
+ catch {
53
+ // Best effort
54
+ }
55
+ }
56
+ /**
57
+ * Record a performance log entry.
58
+ *
59
+ * @param dataDir - The ADIT data directory (.adit/)
60
+ * @param entry - The performance entry to record
61
+ */
62
+ export function recordPerf(dataDir, entry) {
63
+ try {
64
+ const dir = getPerfLogDir(dataDir);
65
+ mkdirSync(dir, { recursive: true });
66
+ const filePath = logFilePath(dataDir, todayDateStr());
67
+ const line = JSON.stringify(entry) + "\n";
68
+ appendFileSync(filePath, line, "utf-8");
69
+ // Prune old logs (best effort, non-blocking)
70
+ pruneOldLogs(dataDir);
71
+ }
72
+ catch {
73
+ // Fail-open: never let perf logging break the application
74
+ }
75
+ }
76
+ /**
77
+ * Wrap an async function with performance logging.
78
+ *
79
+ * @param dataDir - The ADIT data directory (.adit/)
80
+ * @param category - Category of the operation
81
+ * @param operation - Name of the operation
82
+ * @param fn - The async function to measure
83
+ * @returns The result of the function
84
+ */
85
+ export async function withPerf(dataDir, category, operation, fn) {
86
+ const start = performance.now();
87
+ const timestamp = new Date().toISOString();
88
+ try {
89
+ const result = await fn();
90
+ recordPerf(dataDir, {
91
+ timestamp,
92
+ category,
93
+ operation,
94
+ durationMs: Math.round((performance.now() - start) * 100) / 100,
95
+ success: true,
96
+ });
97
+ return result;
98
+ }
99
+ catch (err) {
100
+ recordPerf(dataDir, {
101
+ timestamp,
102
+ category,
103
+ operation,
104
+ durationMs: Math.round((performance.now() - start) * 100) / 100,
105
+ success: false,
106
+ error: err instanceof Error ? err.message : String(err),
107
+ });
108
+ throw err;
109
+ }
110
+ }
111
+ /**
112
+ * Wrap a sync function with performance logging.
113
+ */
114
+ export function withPerfSync(dataDir, category, operation, fn) {
115
+ const start = performance.now();
116
+ const timestamp = new Date().toISOString();
117
+ try {
118
+ const result = fn();
119
+ recordPerf(dataDir, {
120
+ timestamp,
121
+ category,
122
+ operation,
123
+ durationMs: Math.round((performance.now() - start) * 100) / 100,
124
+ success: true,
125
+ });
126
+ return result;
127
+ }
128
+ catch (err) {
129
+ recordPerf(dataDir, {
130
+ timestamp,
131
+ category,
132
+ operation,
133
+ durationMs: Math.round((performance.now() - start) * 100) / 100,
134
+ success: false,
135
+ error: err instanceof Error ? err.message : String(err),
136
+ });
137
+ throw err;
138
+ }
139
+ }
140
+ /**
141
+ * Read all perf log entries within the retention window.
142
+ *
143
+ * @param dataDir - The ADIT data directory (.adit/)
144
+ * @param fromDate - Optional start date (YYYY-MM-DD). Defaults to 7 days ago.
145
+ * @param toDate - Optional end date (YYYY-MM-DD). Defaults to today.
146
+ * @returns Array of perf entries
147
+ */
148
+ export function readPerfLogs(dataDir, fromDate, toDate) {
149
+ const dir = getPerfLogDir(dataDir);
150
+ if (!existsSync(dir))
151
+ return [];
152
+ const today = todayDateStr();
153
+ const defaultFrom = new Date();
154
+ defaultFrom.setDate(defaultFrom.getDate() - RETENTION_DAYS);
155
+ const from = fromDate ?? defaultFrom.toISOString().slice(0, 10);
156
+ const to = toDate ?? today;
157
+ const entries = [];
158
+ try {
159
+ const files = readdirSync(dir).filter((f) => f.endsWith(".jsonl")).sort();
160
+ for (const file of files) {
161
+ const dateStr = file.replace(".jsonl", "");
162
+ if (dateStr < from || dateStr > to)
163
+ continue;
164
+ const content = readFileSync(join(dir, file), "utf-8");
165
+ for (const line of content.split("\n")) {
166
+ if (!line.trim())
167
+ continue;
168
+ try {
169
+ entries.push(JSON.parse(line));
170
+ }
171
+ catch {
172
+ // Skip malformed lines
173
+ }
174
+ }
175
+ }
176
+ }
177
+ catch {
178
+ // Return whatever we collected
179
+ }
180
+ return entries;
181
+ }
182
+ /**
183
+ * Generate a stats report from perf log entries.
184
+ *
185
+ * @param entries - Array of perf entries to analyze
186
+ * @returns Stats report with per-operation aggregations
187
+ */
188
+ export function generatePerfStats(entries) {
189
+ const now = new Date().toISOString();
190
+ if (entries.length === 0) {
191
+ return {
192
+ generatedAt: now,
193
+ fromDate: "",
194
+ toDate: "",
195
+ totalEntries: 0,
196
+ operations: [],
197
+ };
198
+ }
199
+ // Find date range
200
+ const timestamps = entries.map((e) => e.timestamp).sort();
201
+ const fromDate = timestamps[0].slice(0, 10);
202
+ const toDate = timestamps[timestamps.length - 1].slice(0, 10);
203
+ // Group by category:operation
204
+ const groups = new Map();
205
+ for (const entry of entries) {
206
+ const key = `${entry.category}:${entry.operation}`;
207
+ const group = groups.get(key);
208
+ if (group) {
209
+ group.push(entry);
210
+ }
211
+ else {
212
+ groups.set(key, [entry]);
213
+ }
214
+ }
215
+ // Compute per-operation stats
216
+ const operations = [];
217
+ for (const [, group] of groups) {
218
+ const durations = group.map((e) => e.durationMs).sort((a, b) => a - b);
219
+ const totalMs = durations.reduce((sum, d) => sum + d, 0);
220
+ const avgMs = totalMs / group.length;
221
+ const p95Index = Math.min(Math.ceil(durations.length * 0.95) - 1, durations.length - 1);
222
+ // Standard deviation
223
+ const variance = group.length > 1
224
+ ? durations.reduce((sum, d) => sum + (d - avgMs) ** 2, 0) /
225
+ (group.length - 1)
226
+ : 0;
227
+ const stddevMs = Math.round(Math.sqrt(variance) * 100) / 100;
228
+ operations.push({
229
+ category: group[0].category,
230
+ operation: group[0].operation,
231
+ count: group.length,
232
+ avgMs: Math.round(avgMs * 100) / 100,
233
+ minMs: durations[0],
234
+ maxMs: durations[durations.length - 1],
235
+ p95Ms: durations[p95Index],
236
+ stddevMs,
237
+ failures: group.filter((e) => !e.success).length,
238
+ });
239
+ }
240
+ // Sort by call count descending
241
+ operations.sort((a, b) => b.count - a.count);
242
+ return {
243
+ generatedAt: now,
244
+ fromDate,
245
+ toDate,
246
+ totalEntries: entries.length,
247
+ operations,
248
+ };
249
+ }
250
+ /**
251
+ * Clear all performance logs.
252
+ *
253
+ * @param dataDir - The ADIT data directory (.adit/)
254
+ * @returns Number of files deleted
255
+ */
256
+ export function clearPerfLogs(dataDir) {
257
+ const dir = getPerfLogDir(dataDir);
258
+ if (!existsSync(dir))
259
+ return 0;
260
+ let count = 0;
261
+ try {
262
+ const files = readdirSync(dir);
263
+ for (const file of files) {
264
+ if (!file.endsWith(".jsonl"))
265
+ continue;
266
+ try {
267
+ unlinkSync(join(dir, file));
268
+ count++;
269
+ }
270
+ catch {
271
+ // Best effort
272
+ }
273
+ }
274
+ }
275
+ catch {
276
+ // Best effort
277
+ }
278
+ return count;
279
+ }
280
+ //# sourceMappingURL=perf-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perf-log.js","sourceRoot":"","sources":["../../src/perf/perf-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Content-aware secret redaction.
3
+ *
4
+ * Scans text content for secrets using two complementary techniques:
5
+ * 1. Shannon entropy scoring — flags high-entropy strings that look like
6
+ * randomly generated secrets (API keys, tokens, passwords).
7
+ * 2. Pattern matching — regex-based detection of known secret formats
8
+ * (AWS keys, GitHub tokens, JWTs, private keys, etc.).
9
+ *
10
+ * Inspired by gitleaks/trufflehog approaches. Designed to run on transcript
11
+ * data (prompts, responses, tool I/O) before writing to the database.
12
+ */
13
+ /** Result of scanning a single string for secrets */
14
+ export interface RedactionResult {
15
+ /** The redacted text with secrets replaced */
16
+ redacted: string;
17
+ /** Number of secrets found and replaced */
18
+ secretsFound: number;
19
+ /** Details of each detection for logging/debugging */
20
+ detections: SecretDetection[];
21
+ }
22
+ export interface SecretDetection {
23
+ /** What triggered the detection */
24
+ method: "entropy" | "pattern";
25
+ /** Name of the matched pattern (if pattern-based) */
26
+ patternName?: string;
27
+ /** Character offset in the original string */
28
+ offset: number;
29
+ /** Length of the matched secret */
30
+ length: number;
31
+ }
32
+ /** Configuration for the content redaction pipeline */
33
+ export interface RedactionConfig {
34
+ /** Shannon entropy threshold (default: 4.5) */
35
+ entropyThreshold?: number;
36
+ /** Minimum token length to check for entropy (default: 8) */
37
+ minTokenLength?: number;
38
+ /** Maximum token length to check for entropy (default: 256) */
39
+ maxTokenLength?: number;
40
+ /** Replacement string for detected secrets (default: "[REDACTED]") */
41
+ replacement?: string;
42
+ /** Additional custom patterns to match */
43
+ customPatterns?: SecretPattern[];
44
+ /** Field names to skip scanning (e.g., "id", "signature") */
45
+ skipFields?: string[];
46
+ }
47
+ export interface SecretPattern {
48
+ /** Human-readable name for this pattern */
49
+ name: string;
50
+ /** Regex to match the secret */
51
+ pattern: RegExp;
52
+ }
53
+ /**
54
+ * Built-in secret patterns based on common formats.
55
+ * Covers major cloud providers, VCS platforms, payment processors,
56
+ * communication tools, and generic credential formats.
57
+ */
58
+ export declare const builtinPatterns: SecretPattern[];
59
+ /**
60
+ * Default field names to skip when scanning structured data.
61
+ * These commonly contain high-entropy but non-secret data.
62
+ */
63
+ export declare const defaultSkipFields: string[];
64
+ /**
65
+ * Compute Shannon entropy for a string.
66
+ *
67
+ * Shannon entropy measures the randomness/information density of a string.
68
+ * Random strings (like API keys) typically have entropy > 4.5 bits per character,
69
+ * while natural language text is usually below 4.0.
70
+ *
71
+ * @param s - The string to analyze
72
+ * @returns Entropy in bits per character (0 to log2(charset_size))
73
+ */
74
+ export declare function shannonEntropy(s: string): number;
75
+ /**
76
+ * Redact secrets from a text string.
77
+ *
78
+ * Combines entropy-based and pattern-based scanning to detect
79
+ * and replace secrets with a configurable placeholder.
80
+ *
81
+ * @param text - The text to scan and redact
82
+ * @param config - Optional configuration overrides
83
+ * @returns The redacted text and detection details
84
+ */
85
+ export declare function redactContent(text: string, config?: RedactionConfig): RedactionResult;
86
+ /**
87
+ * Check if a field name should be skipped during structured data scanning.
88
+ *
89
+ * Fields like "id", "signature", "hash" etc. often contain high-entropy
90
+ * strings that are not secrets.
91
+ */
92
+ export declare function shouldSkipField(fieldName: string, skipFields?: string[]): boolean;
93
+ /**
94
+ * Recursively redact secrets from a structured object.
95
+ *
96
+ * Walks through all string values in the object tree and applies
97
+ * content-aware redaction. Skips fields that commonly contain
98
+ * non-secret high-entropy data (IDs, signatures, hashes).
99
+ *
100
+ * @param obj - The object to scan
101
+ * @param config - Optional redaction configuration
102
+ * @returns A new object with secrets redacted
103
+ */
104
+ export declare function redactObject(obj: unknown, config?: RedactionConfig): unknown;
105
+ //# sourceMappingURL=content-redaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-redaction.d.ts","sourceRoot":"","sources":["../../src/security/content-redaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,qDAAqD;AACrD,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EA0E1C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,UAU7B,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAiBhD;AAsKD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAAoB,GAC3B,eAAe,CAwCjB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,OAAO,CAcT;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,MAAM,GAAE,eAAoB,GAC3B,OAAO,CAiCT"}