@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.
- package/LICENSE +21 -0
- package/dist/config/index.d.ts +29 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +107 -0
- package/dist/config/index.js.map +1 -0
- package/dist/db/connection.d.ts +9 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +48 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/diffs.d.ts +22 -0
- package/dist/db/diffs.d.ts.map +1 -0
- package/dist/db/diffs.js +37 -0
- package/dist/db/diffs.js.map +1 -0
- package/dist/db/env-snapshots.d.ts +29 -0
- package/dist/db/env-snapshots.d.ts.map +1 -0
- package/dist/db/env-snapshots.js +57 -0
- package/dist/db/env-snapshots.js.map +1 -0
- package/dist/db/events.d.ts +91 -0
- package/dist/db/events.d.ts.map +1 -0
- package/dist/db/events.js +260 -0
- package/dist/db/events.js.map +1 -0
- package/dist/db/index.d.ts +10 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +10 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrations.d.ts +13 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +237 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/plans.d.ts +21 -0
- package/dist/db/plans.d.ts.map +1 -0
- package/dist/db/plans.js +52 -0
- package/dist/db/plans.js.map +1 -0
- package/dist/db/sessions.d.ts +23 -0
- package/dist/db/sessions.d.ts.map +1 -0
- package/dist/db/sessions.js +57 -0
- package/dist/db/sessions.js.map +1 -0
- package/dist/db/sync-state.d.ts +21 -0
- package/dist/db/sync-state.d.ts.map +1 -0
- package/dist/db/sync-state.js +36 -0
- package/dist/db/sync-state.js.map +1 -0
- package/dist/db/transcript-uploads.d.ts +57 -0
- package/dist/db/transcript-uploads.d.ts.map +1 -0
- package/dist/db/transcript-uploads.js +132 -0
- package/dist/db/transcript-uploads.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/perf/perf-log.d.ts +105 -0
- package/dist/perf/perf-log.d.ts.map +1 -0
- package/dist/perf/perf-log.js +280 -0
- package/dist/perf/perf-log.js.map +1 -0
- package/dist/security/content-redaction.d.ts +105 -0
- package/dist/security/content-redaction.d.ts.map +1 -0
- package/dist/security/content-redaction.js +365 -0
- package/dist/security/content-redaction.js.map +1 -0
- package/dist/sync/index.d.ts +3 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +3 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/ulid.d.ts +15 -0
- package/dist/sync/ulid.d.ts.map +1 -0
- package/dist/sync/ulid.js +34 -0
- package/dist/sync/ulid.js.map +1 -0
- package/dist/sync/vclock.d.ts +33 -0
- package/dist/sync/vclock.d.ts.map +1 -0
- package/dist/sync/vclock.js +69 -0
- package/dist/sync/vclock.js.map +1 -0
- package/dist/types/environment.d.ts +53 -0
- package/dist/types/environment.d.ts.map +1 -0
- package/dist/types/environment.js +8 -0
- package/dist/types/environment.js.map +1 -0
- package/dist/types/events.d.ts +88 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +40 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/plan.d.ts +30 -0
- package/dist/types/plan.d.ts.map +1 -0
- package/dist/types/plan.js +8 -0
- package/dist/types/plan.js.map +1 -0
- package/dist/types/session.d.ts +44 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +8 -0
- package/dist/types/session.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,365 @@
|
|
|
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
|
+
/**
|
|
14
|
+
* Built-in secret patterns based on common formats.
|
|
15
|
+
* Covers major cloud providers, VCS platforms, payment processors,
|
|
16
|
+
* communication tools, and generic credential formats.
|
|
17
|
+
*/
|
|
18
|
+
export const builtinPatterns = [
|
|
19
|
+
// AWS
|
|
20
|
+
{ name: "aws-access-key", pattern: /\bAKIA[0-9A-Z]{16}\b/ },
|
|
21
|
+
{ name: "aws-secret-key", pattern: /\b[A-Za-z0-9/+=]{40}\b(?=.*aws|.*secret)/i },
|
|
22
|
+
// GitHub
|
|
23
|
+
{ name: "github-pat-fine", pattern: /\bgithub_pat_[A-Za-z0-9_]{22,82}\b/ },
|
|
24
|
+
{ name: "github-pat", pattern: /\bghp_[A-Za-z0-9]{36,}\b/ },
|
|
25
|
+
{ name: "github-oauth", pattern: /\bgho_[A-Za-z0-9]{36,}\b/ },
|
|
26
|
+
{ name: "github-app-token", pattern: /\bghu_[A-Za-z0-9]{36,}\b/ },
|
|
27
|
+
{ name: "github-refresh-token", pattern: /\bghr_[A-Za-z0-9]{36,}\b/ },
|
|
28
|
+
// GitLab
|
|
29
|
+
{ name: "gitlab-pat", pattern: /\bglpat-[A-Za-z0-9\-_]{20,}\b/ },
|
|
30
|
+
{ name: "gitlab-pipeline-token", pattern: /\bglptt-[A-Za-z0-9\-_]{20,}\b/ },
|
|
31
|
+
{ name: "gitlab-runner-token", pattern: /\bGR1348941[A-Za-z0-9\-_]{20,}\b/ },
|
|
32
|
+
// GCP / Google
|
|
33
|
+
{ name: "gcp-api-key", pattern: /\bAIza[0-9A-Za-z\-_]{35}\b/ },
|
|
34
|
+
{ name: "gcp-service-account", pattern: /"type"\s*:\s*"service_account"/ },
|
|
35
|
+
// Azure
|
|
36
|
+
{ name: "azure-storage-key", pattern: /\b[A-Za-z0-9+/]{86}==\b/ },
|
|
37
|
+
// Stripe
|
|
38
|
+
{ name: "stripe-secret-key", pattern: /\bsk_live_[A-Za-z0-9]{24,}\b/ },
|
|
39
|
+
{ name: "stripe-publishable", pattern: /\bpk_live_[A-Za-z0-9]{24,}\b/ },
|
|
40
|
+
{ name: "stripe-restricted", pattern: /\brk_live_[A-Za-z0-9]{24,}\b/ },
|
|
41
|
+
// Slack
|
|
42
|
+
{ name: "slack-token", pattern: /\bxox[baprs]-[A-Za-z0-9\-]{10,}\b/ },
|
|
43
|
+
{ name: "slack-webhook", pattern: /https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]+/ },
|
|
44
|
+
// Discord
|
|
45
|
+
{ name: "discord-token", pattern: /\b[MN][A-Za-z0-9]{23,}\.[A-Za-z0-9\-_]{6}\.[A-Za-z0-9\-_]{27,}\b/ },
|
|
46
|
+
{ name: "discord-webhook", pattern: /https:\/\/discord(?:app)?\.com\/api\/webhooks\/\d+\/[A-Za-z0-9\-_]+/ },
|
|
47
|
+
// Twilio
|
|
48
|
+
{ name: "twilio-api-key", pattern: /\bSK[0-9a-fA-F]{32}\b/ },
|
|
49
|
+
// SendGrid
|
|
50
|
+
{ name: "sendgrid-api-key", pattern: /\bSG\.[A-Za-z0-9\-_]{22,}\.[A-Za-z0-9\-_]{22,}\b/ },
|
|
51
|
+
// npm
|
|
52
|
+
{ name: "npm-token", pattern: /\bnpm_[A-Za-z0-9]{36,}\b/ },
|
|
53
|
+
// PyPI
|
|
54
|
+
{ name: "pypi-token", pattern: /\bpypi-[A-Za-z0-9\-_]{16,}\b/ },
|
|
55
|
+
// Heroku
|
|
56
|
+
{ name: "heroku-api-key", pattern: /\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b/ },
|
|
57
|
+
// Private keys
|
|
58
|
+
{ name: "private-key-rsa", pattern: /-----BEGIN RSA PRIVATE KEY-----/ },
|
|
59
|
+
{ name: "private-key-dsa", pattern: /-----BEGIN DSA PRIVATE KEY-----/ },
|
|
60
|
+
{ name: "private-key-ec", pattern: /-----BEGIN EC PRIVATE KEY-----/ },
|
|
61
|
+
{ name: "private-key-openssh", pattern: /-----BEGIN OPENSSH PRIVATE KEY-----/ },
|
|
62
|
+
{ name: "private-key-pgp", pattern: /-----BEGIN PGP PRIVATE KEY BLOCK-----/ },
|
|
63
|
+
{ name: "private-key-generic", pattern: /-----BEGIN PRIVATE KEY-----/ },
|
|
64
|
+
// Generic credential patterns
|
|
65
|
+
{ name: "bearer-token", pattern: /\bBearer\s+[A-Za-z0-9\-_\.]{20,}\b/ },
|
|
66
|
+
{ name: "basic-auth", pattern: /\bBasic\s+[A-Za-z0-9+/=]{20,}\b/ },
|
|
67
|
+
{ name: "jwt", pattern: /\beyJ[A-Za-z0-9\-_]+\.eyJ[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\b/ },
|
|
68
|
+
// Database connection strings
|
|
69
|
+
{ name: "postgres-uri", pattern: /postgres(?:ql)?:\/\/[^\s'"]+:[^\s'"]+@[^\s'"]+/ },
|
|
70
|
+
{ name: "mysql-uri", pattern: /mysql:\/\/[^\s'"]+:[^\s'"]+@[^\s'"]+/ },
|
|
71
|
+
{ name: "mongodb-uri", pattern: /mongodb(?:\+srv)?:\/\/[^\s'"]+:[^\s'"]+@[^\s'"]+/ },
|
|
72
|
+
{ name: "redis-uri", pattern: /redis(?:s)?:\/\/[^\s'"]+:[^\s'"]+@[^\s'"]+/ },
|
|
73
|
+
// Generic password/secret in assignments
|
|
74
|
+
{ name: "password-assignment", pattern: /(?:password|passwd|pwd)\s*[:=]\s*["'][^"']{8,}["']/i },
|
|
75
|
+
{ name: "secret-assignment", pattern: /(?:secret|api_?key|access_?key|auth_?token)\s*[:=]\s*["'][^"']{8,}["']/i },
|
|
76
|
+
];
|
|
77
|
+
/**
|
|
78
|
+
* Default field names to skip when scanning structured data.
|
|
79
|
+
* These commonly contain high-entropy but non-secret data.
|
|
80
|
+
*/
|
|
81
|
+
export const defaultSkipFields = [
|
|
82
|
+
"id",
|
|
83
|
+
"ids",
|
|
84
|
+
"signature",
|
|
85
|
+
"hash",
|
|
86
|
+
"sha",
|
|
87
|
+
"checksum",
|
|
88
|
+
"digest",
|
|
89
|
+
"uuid",
|
|
90
|
+
"ulid",
|
|
91
|
+
];
|
|
92
|
+
/**
|
|
93
|
+
* Compute Shannon entropy for a string.
|
|
94
|
+
*
|
|
95
|
+
* Shannon entropy measures the randomness/information density of a string.
|
|
96
|
+
* Random strings (like API keys) typically have entropy > 4.5 bits per character,
|
|
97
|
+
* while natural language text is usually below 4.0.
|
|
98
|
+
*
|
|
99
|
+
* @param s - The string to analyze
|
|
100
|
+
* @returns Entropy in bits per character (0 to log2(charset_size))
|
|
101
|
+
*/
|
|
102
|
+
export function shannonEntropy(s) {
|
|
103
|
+
if (s.length === 0)
|
|
104
|
+
return 0;
|
|
105
|
+
const freq = new Map();
|
|
106
|
+
for (const ch of s) {
|
|
107
|
+
freq.set(ch, (freq.get(ch) ?? 0) + 1);
|
|
108
|
+
}
|
|
109
|
+
let entropy = 0;
|
|
110
|
+
const len = s.length;
|
|
111
|
+
for (const count of freq.values()) {
|
|
112
|
+
const p = count / len;
|
|
113
|
+
if (p > 0) {
|
|
114
|
+
entropy -= p * Math.log2(p);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return entropy;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Extract candidate tokens from text that might be secrets.
|
|
121
|
+
*
|
|
122
|
+
* Tokens are contiguous sequences of non-whitespace characters that
|
|
123
|
+
* meet minimum length requirements. We split on whitespace and common
|
|
124
|
+
* delimiters to isolate individual tokens.
|
|
125
|
+
*/
|
|
126
|
+
function extractTokens(text, minLength, maxLength) {
|
|
127
|
+
const results = [];
|
|
128
|
+
// Match contiguous non-whitespace tokens
|
|
129
|
+
const tokenRegex = /\S+/g;
|
|
130
|
+
let match;
|
|
131
|
+
while ((match = tokenRegex.exec(text)) !== null) {
|
|
132
|
+
const raw = match[0];
|
|
133
|
+
const offset = match.index;
|
|
134
|
+
// Strip common surrounding quotes/brackets
|
|
135
|
+
let token = raw;
|
|
136
|
+
let tokenOffset = offset;
|
|
137
|
+
if (/^["'`({[]/.test(token)) {
|
|
138
|
+
token = token.slice(1);
|
|
139
|
+
tokenOffset += 1;
|
|
140
|
+
}
|
|
141
|
+
if (/["'`)};\],.]$/.test(token)) {
|
|
142
|
+
token = token.slice(0, -1);
|
|
143
|
+
}
|
|
144
|
+
if (token.length >= minLength && token.length <= maxLength) {
|
|
145
|
+
results.push({ token, offset: tokenOffset });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return results;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Scan text for secrets using entropy-based detection.
|
|
152
|
+
*
|
|
153
|
+
* Extracts tokens and checks each for high Shannon entropy,
|
|
154
|
+
* which indicates randomly generated strings like API keys.
|
|
155
|
+
*/
|
|
156
|
+
function scanEntropy(text, threshold, minTokenLength, maxTokenLength) {
|
|
157
|
+
const detections = [];
|
|
158
|
+
const tokens = extractTokens(text, minTokenLength, maxTokenLength);
|
|
159
|
+
for (const { token, offset } of tokens) {
|
|
160
|
+
// Skip tokens that look like file paths, URLs, or common code patterns
|
|
161
|
+
if (looksLikeNonSecret(token))
|
|
162
|
+
continue;
|
|
163
|
+
const entropy = shannonEntropy(token);
|
|
164
|
+
if (entropy >= threshold) {
|
|
165
|
+
detections.push({
|
|
166
|
+
method: "entropy",
|
|
167
|
+
offset,
|
|
168
|
+
length: token.length,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return detections;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Check if a token looks like a non-secret high-entropy string.
|
|
176
|
+
* Helps reduce false positives from file paths, import statements, etc.
|
|
177
|
+
*/
|
|
178
|
+
function looksLikeNonSecret(token) {
|
|
179
|
+
// File paths
|
|
180
|
+
if (token.startsWith("/") || token.startsWith("./") || token.startsWith("../"))
|
|
181
|
+
return true;
|
|
182
|
+
if (token.includes("/src/") || token.includes("/node_modules/"))
|
|
183
|
+
return true;
|
|
184
|
+
// URLs without credentials
|
|
185
|
+
if (/^https?:\/\/[^:@]*$/.test(token))
|
|
186
|
+
return true;
|
|
187
|
+
// Package names and imports
|
|
188
|
+
if (token.startsWith("@") && token.includes("/"))
|
|
189
|
+
return true;
|
|
190
|
+
// Common code patterns (hex colors, version numbers, etc.)
|
|
191
|
+
if (/^#[0-9a-fA-F]{3,8}$/.test(token))
|
|
192
|
+
return true;
|
|
193
|
+
if (/^\d+\.\d+\.\d+/.test(token))
|
|
194
|
+
return true;
|
|
195
|
+
// Base64-encoded image data markers
|
|
196
|
+
if (token.startsWith("data:image/"))
|
|
197
|
+
return true;
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Scan text for secrets using pattern matching.
|
|
202
|
+
*/
|
|
203
|
+
function scanPatterns(text, patterns) {
|
|
204
|
+
const detections = [];
|
|
205
|
+
for (const { name, pattern } of patterns) {
|
|
206
|
+
// Create a global version of the pattern for scanning
|
|
207
|
+
const globalPattern = new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : pattern.flags + "g");
|
|
208
|
+
let match;
|
|
209
|
+
while ((match = globalPattern.exec(text)) !== null) {
|
|
210
|
+
detections.push({
|
|
211
|
+
method: "pattern",
|
|
212
|
+
patternName: name,
|
|
213
|
+
offset: match.index,
|
|
214
|
+
length: match[0].length,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return detections;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Merge overlapping detection ranges and sort by offset.
|
|
222
|
+
* When both entropy and pattern detection flag the same region,
|
|
223
|
+
* we keep the pattern-based detection (more specific).
|
|
224
|
+
*/
|
|
225
|
+
function mergeDetections(detections) {
|
|
226
|
+
if (detections.length <= 1)
|
|
227
|
+
return detections;
|
|
228
|
+
// Sort by offset
|
|
229
|
+
const sorted = [...detections].sort((a, b) => a.offset - b.offset);
|
|
230
|
+
const merged = [sorted[0]];
|
|
231
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
232
|
+
const prev = merged[merged.length - 1];
|
|
233
|
+
const curr = sorted[i];
|
|
234
|
+
// Check overlap
|
|
235
|
+
if (curr.offset <= prev.offset + prev.length) {
|
|
236
|
+
// Overlapping — keep the one that covers more or prefer pattern-based
|
|
237
|
+
if (curr.method === "pattern" && prev.method === "entropy") {
|
|
238
|
+
// Replace entropy detection with pattern detection
|
|
239
|
+
merged[merged.length - 1] = {
|
|
240
|
+
method: curr.method,
|
|
241
|
+
patternName: curr.patternName,
|
|
242
|
+
offset: Math.min(prev.offset, curr.offset),
|
|
243
|
+
length: Math.max(prev.offset + prev.length, curr.offset + curr.length) - Math.min(prev.offset, curr.offset),
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
// Extend the previous detection
|
|
248
|
+
const newEnd = Math.max(prev.offset + prev.length, curr.offset + curr.length);
|
|
249
|
+
merged[merged.length - 1] = {
|
|
250
|
+
...prev,
|
|
251
|
+
length: newEnd - prev.offset,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
merged.push(curr);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return merged;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Redact secrets from a text string.
|
|
263
|
+
*
|
|
264
|
+
* Combines entropy-based and pattern-based scanning to detect
|
|
265
|
+
* and replace secrets with a configurable placeholder.
|
|
266
|
+
*
|
|
267
|
+
* @param text - The text to scan and redact
|
|
268
|
+
* @param config - Optional configuration overrides
|
|
269
|
+
* @returns The redacted text and detection details
|
|
270
|
+
*/
|
|
271
|
+
export function redactContent(text, config = {}) {
|
|
272
|
+
const { entropyThreshold = 4.5, minTokenLength = 8, maxTokenLength = 256, replacement = "[REDACTED]", customPatterns = [], } = config;
|
|
273
|
+
if (!text || text.length === 0) {
|
|
274
|
+
return { redacted: text, secretsFound: 0, detections: [] };
|
|
275
|
+
}
|
|
276
|
+
// Run both detection methods
|
|
277
|
+
const entropyDetections = scanEntropy(text, entropyThreshold, minTokenLength, maxTokenLength);
|
|
278
|
+
const allPatterns = [...builtinPatterns, ...customPatterns];
|
|
279
|
+
const patternDetections = scanPatterns(text, allPatterns);
|
|
280
|
+
// Merge and deduplicate
|
|
281
|
+
const allDetections = mergeDetections([...entropyDetections, ...patternDetections]);
|
|
282
|
+
if (allDetections.length === 0) {
|
|
283
|
+
return { redacted: text, secretsFound: 0, detections: [] };
|
|
284
|
+
}
|
|
285
|
+
// Apply replacements from end to start to preserve offsets
|
|
286
|
+
let redacted = text;
|
|
287
|
+
for (let i = allDetections.length - 1; i >= 0; i--) {
|
|
288
|
+
const det = allDetections[i];
|
|
289
|
+
redacted =
|
|
290
|
+
redacted.substring(0, det.offset) +
|
|
291
|
+
replacement +
|
|
292
|
+
redacted.substring(det.offset + det.length);
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
redacted,
|
|
296
|
+
secretsFound: allDetections.length,
|
|
297
|
+
detections: allDetections,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Check if a field name should be skipped during structured data scanning.
|
|
302
|
+
*
|
|
303
|
+
* Fields like "id", "signature", "hash" etc. often contain high-entropy
|
|
304
|
+
* strings that are not secrets.
|
|
305
|
+
*/
|
|
306
|
+
export function shouldSkipField(fieldName, skipFields) {
|
|
307
|
+
const fields = skipFields ?? defaultSkipFields;
|
|
308
|
+
const lower = fieldName.toLowerCase();
|
|
309
|
+
for (const skip of fields) {
|
|
310
|
+
const skipLower = skip.toLowerCase();
|
|
311
|
+
if (lower === skipLower)
|
|
312
|
+
return true;
|
|
313
|
+
if (lower.endsWith(skipLower))
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
// Skip fields whose values are image/base64 data
|
|
317
|
+
if (lower === "type" || lower === "content_type")
|
|
318
|
+
return true;
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Recursively redact secrets from a structured object.
|
|
323
|
+
*
|
|
324
|
+
* Walks through all string values in the object tree and applies
|
|
325
|
+
* content-aware redaction. Skips fields that commonly contain
|
|
326
|
+
* non-secret high-entropy data (IDs, signatures, hashes).
|
|
327
|
+
*
|
|
328
|
+
* @param obj - The object to scan
|
|
329
|
+
* @param config - Optional redaction configuration
|
|
330
|
+
* @returns A new object with secrets redacted
|
|
331
|
+
*/
|
|
332
|
+
export function redactObject(obj, config = {}) {
|
|
333
|
+
if (obj === null || obj === undefined)
|
|
334
|
+
return obj;
|
|
335
|
+
if (typeof obj === "string") {
|
|
336
|
+
return redactContent(obj, config).redacted;
|
|
337
|
+
}
|
|
338
|
+
if (Array.isArray(obj)) {
|
|
339
|
+
return obj.map((item) => redactObject(item, config));
|
|
340
|
+
}
|
|
341
|
+
if (typeof obj === "object") {
|
|
342
|
+
const result = {};
|
|
343
|
+
const skipFields = config.skipFields ?? defaultSkipFields;
|
|
344
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
345
|
+
if (shouldSkipField(key, skipFields)) {
|
|
346
|
+
result[key] = value;
|
|
347
|
+
}
|
|
348
|
+
else if (typeof value === "string") {
|
|
349
|
+
// Check if this is an image/base64 value
|
|
350
|
+
if (typeof value === "string" && (value.startsWith("data:image/") || value.startsWith("base64,"))) {
|
|
351
|
+
result[key] = value;
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
result[key] = redactContent(value, config).redacted;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
result[key] = redactObject(value, config);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
return obj;
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=content-redaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-redaction.js","sourceRoot":"","sources":["../../src/security/content-redaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EACL,KAAK,WAAW,EAChB,WAAW,EACX,IAAI,EACJ,KAAK,EACL,OAAO,EACP,SAAS,EACT,WAAW,GACZ,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAEL,WAAW,EACX,IAAI,EACJ,KAAK,EACL,OAAO,EACP,SAAS,EACT,WAAW,GACZ,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ULID generation for globally unique, time-sortable identifiers.
|
|
3
|
+
*
|
|
4
|
+
* ULIDs are used as primary keys across all tables because:
|
|
5
|
+
* 1. They are time-sortable (first 48 bits = timestamp)
|
|
6
|
+
* 2. They are globally unique without coordination
|
|
7
|
+
* 3. They sort lexicographically = natural merge ordering for cloud sync
|
|
8
|
+
*/
|
|
9
|
+
/** Generate a new ULID (monotonic within same millisecond) */
|
|
10
|
+
export declare function generateId(): string;
|
|
11
|
+
/** Generate a ULID with a specific timestamp (for testing or import) */
|
|
12
|
+
export declare function generateIdAt(timestamp: number): string;
|
|
13
|
+
/** Extract the timestamp from a ULID */
|
|
14
|
+
export declare function extractTimestamp(id: string): number;
|
|
15
|
+
//# sourceMappingURL=ulid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ulid.d.ts","sourceRoot":"","sources":["../../src/sync/ulid.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,8DAA8D;AAC9D,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wCAAwC;AACxC,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAWnD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ULID generation for globally unique, time-sortable identifiers.
|
|
3
|
+
*
|
|
4
|
+
* ULIDs are used as primary keys across all tables because:
|
|
5
|
+
* 1. They are time-sortable (first 48 bits = timestamp)
|
|
6
|
+
* 2. They are globally unique without coordination
|
|
7
|
+
* 3. They sort lexicographically = natural merge ordering for cloud sync
|
|
8
|
+
*/
|
|
9
|
+
import { ulid, monotonicFactory } from "ulid";
|
|
10
|
+
/** Monotonic factory ensures ULIDs created in the same ms are still ordered */
|
|
11
|
+
const monotonic = monotonicFactory();
|
|
12
|
+
/** Generate a new ULID (monotonic within same millisecond) */
|
|
13
|
+
export function generateId() {
|
|
14
|
+
return monotonic();
|
|
15
|
+
}
|
|
16
|
+
/** Generate a ULID with a specific timestamp (for testing or import) */
|
|
17
|
+
export function generateIdAt(timestamp) {
|
|
18
|
+
return ulid(timestamp);
|
|
19
|
+
}
|
|
20
|
+
/** Extract the timestamp from a ULID */
|
|
21
|
+
export function extractTimestamp(id) {
|
|
22
|
+
// ULID encodes time in first 10 chars (Crockford Base32)
|
|
23
|
+
const ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
24
|
+
let time = 0;
|
|
25
|
+
const chars = id.substring(0, 10).toUpperCase();
|
|
26
|
+
for (const char of chars) {
|
|
27
|
+
const idx = ENCODING.indexOf(char);
|
|
28
|
+
if (idx === -1)
|
|
29
|
+
throw new Error(`Invalid ULID character: ${char}`);
|
|
30
|
+
time = time * 32 + idx;
|
|
31
|
+
}
|
|
32
|
+
return time;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=ulid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ulid.js","sourceRoot":"","sources":["../../src/sync/ulid.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAE9C,+EAA+E;AAC/E,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;AAErC,8DAA8D;AAC9D,MAAM,UAAU,UAAU;IACxB,OAAO,SAAS,EAAE,CAAC;AACrB,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;AACzB,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,gBAAgB,CAAC,EAAU;IACzC,yDAAyD;IACzD,MAAM,QAAQ,GAAG,kCAAkC,CAAC;IACpD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAChD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;QACnE,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC;IACzB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vector clock implementation for conflict detection.
|
|
3
|
+
*
|
|
4
|
+
* Each client maintains its own counter. When syncing to cloud:
|
|
5
|
+
* - If clock A dominates clock B → A is newer, no conflict
|
|
6
|
+
* - If neither dominates → concurrent edits, needs merge
|
|
7
|
+
*
|
|
8
|
+
* For ADIT's append-only events, conflicts are rare (two clients
|
|
9
|
+
* can't create the same ULID). Vector clocks primarily help with
|
|
10
|
+
* mutable records like sessions and plans.
|
|
11
|
+
*/
|
|
12
|
+
export interface VectorClock {
|
|
13
|
+
[clientId: string]: number;
|
|
14
|
+
}
|
|
15
|
+
/** Create a new vector clock with initial tick for this client */
|
|
16
|
+
export declare function createClock(clientId: string): VectorClock;
|
|
17
|
+
/** Increment this client's counter */
|
|
18
|
+
export declare function tick(clock: VectorClock, clientId: string): VectorClock;
|
|
19
|
+
/** Merge two clocks (take max of each client's counter) */
|
|
20
|
+
export declare function merge(a: VectorClock, b: VectorClock): VectorClock;
|
|
21
|
+
/**
|
|
22
|
+
* Compare two vector clocks.
|
|
23
|
+
* Returns:
|
|
24
|
+
* -1 if a < b (a happened before b)
|
|
25
|
+
* 0 if concurrent (neither dominates)
|
|
26
|
+
* 1 if a > b (a happened after b)
|
|
27
|
+
*/
|
|
28
|
+
export declare function compare(a: VectorClock, b: VectorClock): -1 | 0 | 1;
|
|
29
|
+
/** Serialize a vector clock to JSON string */
|
|
30
|
+
export declare function serialize(clock: VectorClock): string;
|
|
31
|
+
/** Deserialize a JSON string to vector clock */
|
|
32
|
+
export declare function deserialize(json: string): VectorClock;
|
|
33
|
+
//# sourceMappingURL=vclock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vclock.d.ts","sourceRoot":"","sources":["../../src/sync/vclock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,WAAW;IAC1B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAEzD;AAED,sCAAsC;AACtC,wBAAgB,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAKtE;AAED,2DAA2D;AAC3D,wBAAgB,KAAK,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,GAAG,WAAW,CAMjE;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAiBlE;AAED,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAEpD;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAMrD"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vector clock implementation for conflict detection.
|
|
3
|
+
*
|
|
4
|
+
* Each client maintains its own counter. When syncing to cloud:
|
|
5
|
+
* - If clock A dominates clock B → A is newer, no conflict
|
|
6
|
+
* - If neither dominates → concurrent edits, needs merge
|
|
7
|
+
*
|
|
8
|
+
* For ADIT's append-only events, conflicts are rare (two clients
|
|
9
|
+
* can't create the same ULID). Vector clocks primarily help with
|
|
10
|
+
* mutable records like sessions and plans.
|
|
11
|
+
*/
|
|
12
|
+
/** Create a new vector clock with initial tick for this client */
|
|
13
|
+
export function createClock(clientId) {
|
|
14
|
+
return { [clientId]: 1 };
|
|
15
|
+
}
|
|
16
|
+
/** Increment this client's counter */
|
|
17
|
+
export function tick(clock, clientId) {
|
|
18
|
+
return {
|
|
19
|
+
...clock,
|
|
20
|
+
[clientId]: (clock[clientId] ?? 0) + 1,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** Merge two clocks (take max of each client's counter) */
|
|
24
|
+
export function merge(a, b) {
|
|
25
|
+
const result = { ...a };
|
|
26
|
+
for (const [client, count] of Object.entries(b)) {
|
|
27
|
+
result[client] = Math.max(result[client] ?? 0, count);
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Compare two vector clocks.
|
|
33
|
+
* Returns:
|
|
34
|
+
* -1 if a < b (a happened before b)
|
|
35
|
+
* 0 if concurrent (neither dominates)
|
|
36
|
+
* 1 if a > b (a happened after b)
|
|
37
|
+
*/
|
|
38
|
+
export function compare(a, b) {
|
|
39
|
+
const allClients = new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
40
|
+
let aGreater = false;
|
|
41
|
+
let bGreater = false;
|
|
42
|
+
for (const client of allClients) {
|
|
43
|
+
const aVal = a[client] ?? 0;
|
|
44
|
+
const bVal = b[client] ?? 0;
|
|
45
|
+
if (aVal > bVal)
|
|
46
|
+
aGreater = true;
|
|
47
|
+
if (bVal > aVal)
|
|
48
|
+
bGreater = true;
|
|
49
|
+
}
|
|
50
|
+
if (aGreater && !bGreater)
|
|
51
|
+
return 1;
|
|
52
|
+
if (bGreater && !aGreater)
|
|
53
|
+
return -1;
|
|
54
|
+
return 0; // concurrent or equal
|
|
55
|
+
}
|
|
56
|
+
/** Serialize a vector clock to JSON string */
|
|
57
|
+
export function serialize(clock) {
|
|
58
|
+
return JSON.stringify(clock);
|
|
59
|
+
}
|
|
60
|
+
/** Deserialize a JSON string to vector clock */
|
|
61
|
+
export function deserialize(json) {
|
|
62
|
+
try {
|
|
63
|
+
return JSON.parse(json);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return {};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=vclock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vclock.js","sourceRoot":"","sources":["../../src/sync/vclock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,kEAAkE;AAClE,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;AAC3B,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,IAAI,CAAC,KAAkB,EAAE,QAAgB;IACvD,OAAO;QACL,GAAG,KAAK;QACR,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,KAAK,CAAC,CAAc,EAAE,CAAc;IAClD,MAAM,MAAM,GAAgB,EAAE,GAAG,CAAC,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CAAC,CAAc,EAAE,CAAc;IACpD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnE,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE5B,IAAI,IAAI,GAAG,IAAI;YAAE,QAAQ,GAAG,IAAI,CAAC;QACjC,IAAI,IAAI,GAAG,IAAI;YAAE,QAAQ,GAAG,IAAI,CAAC;IACnC,CAAC;IAED,IAAI,QAAQ,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,CAAC;IACpC,IAAI,QAAQ,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,CAAC,CAAC,sBAAsB;AAClC,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,SAAS,CAAC,KAAkB;IAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment snapshot types.
|
|
3
|
+
*
|
|
4
|
+
* Captures the execution context at a point in time —
|
|
5
|
+
* not just code, but the world around it.
|
|
6
|
+
*/
|
|
7
|
+
export interface EnvSnapshot {
|
|
8
|
+
/** ULID */
|
|
9
|
+
id: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
gitBranch: string;
|
|
12
|
+
gitHeadSha: string;
|
|
13
|
+
/** JSON array of modified file paths */
|
|
14
|
+
modifiedFiles: string | null;
|
|
15
|
+
/** Hash of the dependency lockfile */
|
|
16
|
+
depLockHash: string | null;
|
|
17
|
+
/** Which lockfile (package-lock.json, pnpm-lock.yaml, etc.) */
|
|
18
|
+
depLockPath: string | null;
|
|
19
|
+
/** Selected safe environment variables */
|
|
20
|
+
envVarsJson: string | null;
|
|
21
|
+
nodeVersion: string | null;
|
|
22
|
+
pythonVersion: string | null;
|
|
23
|
+
osInfo: string | null;
|
|
24
|
+
/** JSON: {inDocker: bool, image?: string} */
|
|
25
|
+
containerInfo: string | null;
|
|
26
|
+
/** JSON: {rust?, go?, java?, ruby?, ...} */
|
|
27
|
+
runtimeVersionsJson: string | null;
|
|
28
|
+
/** JSON: {shell, version} */
|
|
29
|
+
shellInfo: string | null;
|
|
30
|
+
/** JSON: {arch, cpuModel, totalMem, freeMem, diskFree?} */
|
|
31
|
+
systemResourcesJson: string | null;
|
|
32
|
+
/** JSON: {name, version, globalVersion?} */
|
|
33
|
+
packageManagerJson: string | null;
|
|
34
|
+
capturedAt: string;
|
|
35
|
+
/** Vector clock */
|
|
36
|
+
vclockJson: string;
|
|
37
|
+
/** Soft delete */
|
|
38
|
+
deletedAt: string | null;
|
|
39
|
+
}
|
|
40
|
+
/** Structured diff between two environment snapshots */
|
|
41
|
+
export interface EnvDiff {
|
|
42
|
+
changes: EnvChange[];
|
|
43
|
+
severity: "none" | "info" | "warning" | "breaking";
|
|
44
|
+
}
|
|
45
|
+
/** A single field-level change in the environment */
|
|
46
|
+
export interface EnvChange {
|
|
47
|
+
field: string;
|
|
48
|
+
category: "git" | "dependency" | "runtime" | "system";
|
|
49
|
+
oldValue: string | null;
|
|
50
|
+
newValue: string | null;
|
|
51
|
+
severity: "info" | "warning" | "breaking";
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=environment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/types/environment.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,WAAW;IAC1B,WAAW;IACX,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,sCAAsC;IACtC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,+DAA+D;IAC/D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,0CAA0C;IAC1C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,6CAA6C;IAC7C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,4CAA4C;IAC5C,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,6BAA6B;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,2DAA2D;IAC3D,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,4CAA4C;IAC5C,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,wDAAwD;AACxD,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;CACpD;AAED,qDAAqD;AACrD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;CAC3C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/types/environment.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|