@de-otio/repo-aegis-core 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/age.d.ts +32 -0
- package/dist/age.d.ts.map +1 -0
- package/dist/age.js +98 -0
- package/dist/age.js.map +1 -0
- package/dist/audit-log.d.ts +50 -0
- package/dist/audit-log.d.ts.map +1 -0
- package/dist/audit-log.js +183 -0
- package/dist/audit-log.js.map +1 -0
- package/dist/audit-log.test.d.ts +2 -0
- package/dist/audit-log.test.d.ts.map +1 -0
- package/dist/audit-log.test.js +181 -0
- package/dist/audit-log.test.js.map +1 -0
- package/dist/deny-set.d.ts +43 -0
- package/dist/deny-set.d.ts.map +1 -0
- package/dist/deny-set.js +165 -0
- package/dist/deny-set.js.map +1 -0
- package/dist/deny-set.test.d.ts +2 -0
- package/dist/deny-set.test.d.ts.map +1 -0
- package/dist/deny-set.test.js +155 -0
- package/dist/deny-set.test.js.map +1 -0
- package/dist/exceptions.d.ts +96 -0
- package/dist/exceptions.d.ts.map +1 -0
- package/dist/exceptions.js +143 -0
- package/dist/exceptions.js.map +1 -0
- package/dist/exit-codes.d.ts +4 -0
- package/dist/exit-codes.d.ts.map +1 -0
- package/dist/exit-codes.js +6 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/first-touch.d.ts +57 -0
- package/dist/first-touch.d.ts.map +1 -0
- package/dist/first-touch.js +112 -0
- package/dist/first-touch.js.map +1 -0
- package/dist/import-graph.test.d.ts +2 -0
- package/dist/import-graph.test.d.ts.map +1 -0
- package/dist/import-graph.test.js +210 -0
- package/dist/import-graph.test.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/lock.d.ts +22 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lock.js +86 -0
- package/dist/lock.js.map +1 -0
- package/dist/lock.test.d.ts +2 -0
- package/dist/lock.test.d.ts.map +1 -0
- package/dist/lock.test.js +125 -0
- package/dist/lock.test.js.map +1 -0
- package/dist/paths.d.ts +22 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +46 -0
- package/dist/paths.js.map +1 -0
- package/dist/paths.test.d.ts +2 -0
- package/dist/paths.test.d.ts.map +1 -0
- package/dist/paths.test.js +78 -0
- package/dist/paths.test.js.map +1 -0
- package/dist/redaction.d.ts +29 -0
- package/dist/redaction.d.ts.map +1 -0
- package/dist/redaction.js +48 -0
- package/dist/redaction.js.map +1 -0
- package/dist/redaction.test.d.ts +2 -0
- package/dist/redaction.test.d.ts.map +1 -0
- package/dist/redaction.test.js +67 -0
- package/dist/redaction.test.js.map +1 -0
- package/dist/regex-safety.d.ts +87 -0
- package/dist/regex-safety.d.ts.map +1 -0
- package/dist/regex-safety.js +322 -0
- package/dist/regex-safety.js.map +1 -0
- package/dist/regex-safety.test.d.ts +2 -0
- package/dist/regex-safety.test.d.ts.map +1 -0
- package/dist/regex-safety.test.js +149 -0
- package/dist/regex-safety.test.js.map +1 -0
- package/dist/registry-mutate.d.ts +35 -0
- package/dist/registry-mutate.d.ts.map +1 -0
- package/dist/registry-mutate.js +149 -0
- package/dist/registry-mutate.js.map +1 -0
- package/dist/registry-mutate.test.d.ts +2 -0
- package/dist/registry-mutate.test.d.ts.map +1 -0
- package/dist/registry-mutate.test.js +96 -0
- package/dist/registry-mutate.test.js.map +1 -0
- package/dist/registry.d.ts +64 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +120 -0
- package/dist/registry.js.map +1 -0
- package/dist/registry.test.d.ts +2 -0
- package/dist/registry.test.d.ts.map +1 -0
- package/dist/registry.test.js +316 -0
- package/dist/registry.test.js.map +1 -0
- package/dist/remote-url.d.ts +18 -0
- package/dist/remote-url.d.ts.map +1 -0
- package/dist/remote-url.js +66 -0
- package/dist/remote-url.js.map +1 -0
- package/dist/remote-url.test.d.ts +2 -0
- package/dist/remote-url.test.d.ts.map +1 -0
- package/dist/remote-url.test.js +116 -0
- package/dist/remote-url.test.js.map +1 -0
- package/dist/render.d.ts +54 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +182 -0
- package/dist/render.js.map +1 -0
- package/dist/render.test.d.ts +2 -0
- package/dist/render.test.d.ts.map +1 -0
- package/dist/render.test.js +152 -0
- package/dist/render.test.js.map +1 -0
- package/dist/repo.d.ts +40 -0
- package/dist/repo.d.ts.map +1 -0
- package/dist/repo.js +214 -0
- package/dist/repo.js.map +1 -0
- package/dist/repo.test.d.ts +2 -0
- package/dist/repo.test.d.ts.map +1 -0
- package/dist/repo.test.js +234 -0
- package/dist/repo.test.js.map +1 -0
- package/dist/scan.d.ts +103 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/scan.js +436 -0
- package/dist/scan.js.map +1 -0
- package/dist/scan.test.d.ts +2 -0
- package/dist/scan.test.d.ts.map +1 -0
- package/dist/scan.test.js +437 -0
- package/dist/scan.test.js.map +1 -0
- package/dist/schemas.d.ts +50 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +190 -0
- package/dist/schemas.js.map +1 -0
- package/dist/secret-markers.d.ts +34 -0
- package/dist/secret-markers.d.ts.map +1 -0
- package/dist/secret-markers.js +118 -0
- package/dist/secret-markers.js.map +1 -0
- package/dist/secret-markers.test.d.ts +2 -0
- package/dist/secret-markers.test.d.ts.map +1 -0
- package/dist/secret-markers.test.js +154 -0
- package/dist/secret-markers.test.js.map +1 -0
- package/dist/trust-boundary.d.ts +33 -0
- package/dist/trust-boundary.d.ts.map +1 -0
- package/dist/trust-boundary.js +77 -0
- package/dist/trust-boundary.js.map +1 -0
- package/dist/trust-boundary.test.d.ts +2 -0
- package/dist/trust-boundary.test.d.ts.map +1 -0
- package/dist/trust-boundary.test.js +170 -0
- package/dist/trust-boundary.test.js.map +1 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/working-tree.d.ts +38 -0
- package/dist/working-tree.d.ts.map +1 -0
- package/dist/working-tree.js +133 -0
- package/dist/working-tree.js.map +1 -0
- package/dist/working-tree.test.d.ts +2 -0
- package/dist/working-tree.test.d.ts.map +1 -0
- package/dist/working-tree.test.js +162 -0
- package/dist/working-tree.test.js.map +1 -0
- package/package.json +40 -0
- package/src/age.ts +113 -0
- package/src/audit-log.test.ts +222 -0
- package/src/audit-log.ts +215 -0
- package/src/deny-set.test.ts +208 -0
- package/src/deny-set.ts +231 -0
- package/src/exceptions.ts +134 -0
- package/src/exit-codes.ts +5 -0
- package/src/first-touch.ts +172 -0
- package/src/import-graph.test.ts +239 -0
- package/src/index.ts +191 -0
- package/src/lock.test.ts +151 -0
- package/src/lock.ts +88 -0
- package/src/paths.test.ts +94 -0
- package/src/paths.ts +55 -0
- package/src/redaction.test.ts +81 -0
- package/src/redaction.ts +49 -0
- package/src/regex-safety.test.ts +194 -0
- package/src/regex-safety.ts +349 -0
- package/src/registry-mutate.test.ts +134 -0
- package/src/registry-mutate.ts +185 -0
- package/src/registry.test.ts +460 -0
- package/src/registry.ts +178 -0
- package/src/remote-url.test.ts +121 -0
- package/src/remote-url.ts +78 -0
- package/src/render.test.ts +206 -0
- package/src/render.ts +215 -0
- package/src/repo.test.ts +275 -0
- package/src/repo.ts +245 -0
- package/src/scan.test.ts +580 -0
- package/src/scan.ts +531 -0
- package/src/schemas.ts +207 -0
- package/src/secret-markers.test.ts +183 -0
- package/src/secret-markers.ts +145 -0
- package/src/trust-boundary.test.ts +198 -0
- package/src/trust-boundary.ts +98 -0
- package/src/types.ts +55 -0
- package/src/working-tree.test.ts +193 -0
- package/src/working-tree.ts +130 -0
package/dist/deny-set.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Richard Myers and contributors.
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync, } from "node:fs";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { denySetCachePath as defaultDenySetCachePath, markersDir as defaultMarkersDir, } from "./paths.js";
|
|
7
|
+
export const ALWAYS_FILE_STEM = "_always";
|
|
8
|
+
// Bumped to 2 when patternSources was added; v1 caches are invalidated
|
|
9
|
+
// (the read path's schemaVersion check returns null, falling through to
|
|
10
|
+
// recompute).
|
|
11
|
+
const DENY_SET_CACHE_VERSION = 2;
|
|
12
|
+
/**
|
|
13
|
+
* Build a fingerprint of the inputs to computeDenySet. Two calls with the
|
|
14
|
+
* same fingerprint produce the same deny set. Includes:
|
|
15
|
+
* - repo class + sorted engagements (these change the per-engagement
|
|
16
|
+
* filtering applied to the marker file set)
|
|
17
|
+
* - the marker dir's file list, mtimes, and sizes (any edit to a marker
|
|
18
|
+
* file or addition/removal invalidates the cache)
|
|
19
|
+
*/
|
|
20
|
+
function computeFingerprint(repo, dir) {
|
|
21
|
+
const fileSummaries = [];
|
|
22
|
+
if (existsSync(dir)) {
|
|
23
|
+
const files = readdirSync(dir).filter(f => f.endsWith(".txt")).sort();
|
|
24
|
+
for (const f of files) {
|
|
25
|
+
const st = statSync(join(dir, f));
|
|
26
|
+
fileSummaries.push(`${f}:${st.mtimeMs}:${st.size}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const sortedEng = [...repo.engagements].sort().join(",");
|
|
30
|
+
const input = `v${DENY_SET_CACHE_VERSION}|${repo.class}|${sortedEng}|${fileSummaries.join(";")}`;
|
|
31
|
+
return createHash("sha256").update(input).digest("hex");
|
|
32
|
+
}
|
|
33
|
+
function readCache(cachePath) {
|
|
34
|
+
if (!existsSync(cachePath))
|
|
35
|
+
return null;
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(readFileSync(cachePath, "utf8"));
|
|
38
|
+
if (parsed.schemaVersion !== DENY_SET_CACHE_VERSION ||
|
|
39
|
+
typeof parsed.key !== "string" ||
|
|
40
|
+
!Array.isArray(parsed.files) ||
|
|
41
|
+
!Array.isArray(parsed.patterns) ||
|
|
42
|
+
!Array.isArray(parsed.patternSources) ||
|
|
43
|
+
parsed.patternSources.length !== parsed.patterns.length ||
|
|
44
|
+
typeof parsed.combinedRegex !== "string" ||
|
|
45
|
+
!Array.isArray(parsed.warnings)) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return parsed;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function writeCache(cachePath, entry) {
|
|
55
|
+
try {
|
|
56
|
+
mkdirSync(dirname(cachePath), { recursive: true });
|
|
57
|
+
writeFileSync(cachePath, JSON.stringify(entry, null, 2), { mode: 0o600 });
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
/* cache is best-effort; failure to write is not fatal */
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Compute the per-repo deny set. Class-aware:
|
|
65
|
+
*
|
|
66
|
+
* - `public-eligible` / `private-strict`: full union (every marker file).
|
|
67
|
+
* Engagement field on the repo is ignored; if set, a warning is emitted.
|
|
68
|
+
* - `customer-coupled`: union of `_always.txt` + every per-engagement file
|
|
69
|
+
* whose stem is NOT in this repo's `engagements` list.
|
|
70
|
+
* - `scratch`: same set as `customer-coupled`, but the caller (the CLI's
|
|
71
|
+
* `check`) treats hits as advisory and exits 0.
|
|
72
|
+
*/
|
|
73
|
+
export function computeDenySet(repo, opts = {}) {
|
|
74
|
+
const dir = opts.markersDir ?? defaultMarkersDir();
|
|
75
|
+
const warnings = [];
|
|
76
|
+
if ((repo.class === "public-eligible" || repo.class === "private-strict") &&
|
|
77
|
+
repo.engagements.length > 0) {
|
|
78
|
+
warnings.push(`repo class is ${repo.class} but ${repo.engagements.length} engagement(s) are set; ` +
|
|
79
|
+
`engagement field is ignored for non-customer-coupled classes`);
|
|
80
|
+
}
|
|
81
|
+
// Cache fast-path. Cache is keyed on (class, engagements, marker-file
|
|
82
|
+
// mtimes+sizes). An exact key match returns the cached deny set without
|
|
83
|
+
// re-reading any marker file. Caller can disable with cachePath: null
|
|
84
|
+
// (tests) or override the path. The base warnings (repo-class engagement
|
|
85
|
+
// mismatch, computed above) are always recomputed so they reflect the
|
|
86
|
+
// current call rather than what the cache wrote at fingerprint time.
|
|
87
|
+
const cachePath = opts.cachePath === null ? null : opts.cachePath ?? defaultDenySetCachePath();
|
|
88
|
+
const fingerprint = computeFingerprint(repo, dir);
|
|
89
|
+
if (cachePath !== null) {
|
|
90
|
+
const cached = readCache(cachePath);
|
|
91
|
+
if (cached !== null && cached.key === fingerprint) {
|
|
92
|
+
return {
|
|
93
|
+
files: cached.files,
|
|
94
|
+
patterns: cached.patterns,
|
|
95
|
+
patternSources: cached.patternSources,
|
|
96
|
+
combinedRegex: cached.combinedRegex,
|
|
97
|
+
warnings: [...warnings, ...cached.warnings.filter(w => !warnings.includes(w))],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (!existsSync(dir)) {
|
|
102
|
+
const empty = { files: [], patterns: [], patternSources: [], combinedRegex: "", warnings };
|
|
103
|
+
if (cachePath !== null) {
|
|
104
|
+
writeCache(cachePath, {
|
|
105
|
+
schemaVersion: DENY_SET_CACHE_VERSION,
|
|
106
|
+
key: fingerprint,
|
|
107
|
+
files: [],
|
|
108
|
+
patterns: [],
|
|
109
|
+
patternSources: [],
|
|
110
|
+
combinedRegex: "",
|
|
111
|
+
warnings: [],
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return empty;
|
|
115
|
+
}
|
|
116
|
+
const own = new Set(repo.engagements);
|
|
117
|
+
const useScoping = repo.class === "customer-coupled" || repo.class === "scratch";
|
|
118
|
+
const files = readdirSync(dir)
|
|
119
|
+
.filter(f => f.endsWith(".txt"))
|
|
120
|
+
.map(f => ({ stem: f.replace(/\.txt$/, ""), path: join(dir, f) }))
|
|
121
|
+
.filter(({ stem }) => {
|
|
122
|
+
if (stem === ALWAYS_FILE_STEM)
|
|
123
|
+
return true;
|
|
124
|
+
if (!useScoping)
|
|
125
|
+
return true;
|
|
126
|
+
return !own.has(stem);
|
|
127
|
+
});
|
|
128
|
+
const patterns = [];
|
|
129
|
+
const patternSources = [];
|
|
130
|
+
for (const f of files) {
|
|
131
|
+
const lines = readFileSync(f.path, "utf8").split("\n");
|
|
132
|
+
for (const raw of lines) {
|
|
133
|
+
const trimmed = raw.trim();
|
|
134
|
+
// A line is a comment only if its first non-whitespace character is `;`.
|
|
135
|
+
// Mid-line `;` is part of the pattern (e.g. `db;internal` is a literal
|
|
136
|
+
// marker, not "db" with a comment).
|
|
137
|
+
if (trimmed.length === 0 || trimmed.startsWith(";"))
|
|
138
|
+
continue;
|
|
139
|
+
patterns.push(trimmed);
|
|
140
|
+
patternSources.push(f.stem);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const result = {
|
|
144
|
+
files,
|
|
145
|
+
patterns,
|
|
146
|
+
patternSources,
|
|
147
|
+
combinedRegex: patterns.join("|"),
|
|
148
|
+
warnings,
|
|
149
|
+
};
|
|
150
|
+
if (cachePath !== null) {
|
|
151
|
+
writeCache(cachePath, {
|
|
152
|
+
schemaVersion: DENY_SET_CACHE_VERSION,
|
|
153
|
+
key: fingerprint,
|
|
154
|
+
files,
|
|
155
|
+
patterns,
|
|
156
|
+
patternSources,
|
|
157
|
+
combinedRegex: result.combinedRegex,
|
|
158
|
+
// Cache only the input-derived warnings; the call-time class mismatch
|
|
159
|
+
// warning is recomputed above per call.
|
|
160
|
+
warnings: [],
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=deny-set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deny-set.js","sourceRoot":"","sources":["../src/deny-set.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deny-set.test.d.ts","sourceRoot":"","sources":["../src/deny-set.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Richard Myers and contributors.
|
|
3
|
+
import { describe, it, before, after } from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import { existsSync, mkdtempSync, mkdirSync, readdirSync, readFileSync, writeFileSync, rmSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { computeDenySet, ALWAYS_FILE_STEM } from "./deny-set.js";
|
|
9
|
+
let tmp;
|
|
10
|
+
let markersDir;
|
|
11
|
+
function setupMarkers() {
|
|
12
|
+
rmSync(markersDir, { recursive: true, force: true });
|
|
13
|
+
mkdirSync(markersDir, { recursive: true });
|
|
14
|
+
writeFileSync(join(markersDir, `${ALWAYS_FILE_STEM}.txt`), "PROJECT-CODENAME-ALPHA\n");
|
|
15
|
+
writeFileSync(join(markersDir, "customer-a.txt"), "acme-corp\nacme\\.com\n");
|
|
16
|
+
writeFileSync(join(markersDir, "customer-b.txt"), "betaco\nbetaco\\.tech\n");
|
|
17
|
+
}
|
|
18
|
+
function makeRepo(cls, engagements = []) {
|
|
19
|
+
return {
|
|
20
|
+
cwd: "/tmp/fake",
|
|
21
|
+
isGitRepo: true,
|
|
22
|
+
class: cls,
|
|
23
|
+
classExplicit: true,
|
|
24
|
+
engagements,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
before(() => {
|
|
28
|
+
tmp = mkdtempSync(join(tmpdir(), "repo-aegis-denyset-"));
|
|
29
|
+
markersDir = join(tmp, "markers");
|
|
30
|
+
setupMarkers();
|
|
31
|
+
});
|
|
32
|
+
after(() => {
|
|
33
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
34
|
+
});
|
|
35
|
+
describe("computeDenySet", () => {
|
|
36
|
+
it("returns empty set when markers dir does not exist", () => {
|
|
37
|
+
const ds = computeDenySet(makeRepo("private-strict"), { markersDir: join(tmp, "no-such-dir") });
|
|
38
|
+
assert.equal(ds.patterns.length, 0);
|
|
39
|
+
assert.equal(ds.combinedRegex, "");
|
|
40
|
+
});
|
|
41
|
+
it("public-eligible: full union (all marker files, no scoping)", () => {
|
|
42
|
+
const ds = computeDenySet(makeRepo("public-eligible"), { markersDir });
|
|
43
|
+
assert.equal(ds.files.length, 3);
|
|
44
|
+
assert.ok(ds.patterns.includes("acme-corp"));
|
|
45
|
+
assert.ok(ds.patterns.includes("betaco"));
|
|
46
|
+
assert.ok(ds.patterns.includes("PROJECT-CODENAME-ALPHA"));
|
|
47
|
+
});
|
|
48
|
+
it("private-strict: same as public-eligible", () => {
|
|
49
|
+
const ds = computeDenySet(makeRepo("private-strict"), { markersDir });
|
|
50
|
+
assert.equal(ds.files.length, 3);
|
|
51
|
+
});
|
|
52
|
+
it("public-eligible warns if engagement is set", () => {
|
|
53
|
+
const ds = computeDenySet(makeRepo("public-eligible", ["customer-a"]), { markersDir });
|
|
54
|
+
assert.ok(ds.warnings.length > 0);
|
|
55
|
+
// engagement is ignored: full deny set
|
|
56
|
+
assert.equal(ds.files.length, 3);
|
|
57
|
+
assert.ok(ds.patterns.includes("acme-corp"));
|
|
58
|
+
});
|
|
59
|
+
it("customer-coupled: scopes deny set, excluding own engagement", () => {
|
|
60
|
+
const ds = computeDenySet(makeRepo("customer-coupled", ["customer-a"]), { markersDir });
|
|
61
|
+
const stems = ds.files.map(f => f.stem).sort();
|
|
62
|
+
assert.deepEqual(stems, [ALWAYS_FILE_STEM, "customer-b"]);
|
|
63
|
+
assert.ok(ds.patterns.includes("betaco"));
|
|
64
|
+
assert.ok(ds.patterns.includes("PROJECT-CODENAME-ALPHA"));
|
|
65
|
+
assert.ok(!ds.patterns.includes("acme-corp"));
|
|
66
|
+
});
|
|
67
|
+
it("customer-coupled: still blocks _always", () => {
|
|
68
|
+
const ds = computeDenySet(makeRepo("customer-coupled", ["customer-a"]), { markersDir });
|
|
69
|
+
assert.ok(ds.patterns.includes("PROJECT-CODENAME-ALPHA"));
|
|
70
|
+
});
|
|
71
|
+
it("customer-coupled: multi-engagement excludes both own files", () => {
|
|
72
|
+
const ds = computeDenySet(makeRepo("customer-coupled", ["customer-a", "customer-b"]), { markersDir });
|
|
73
|
+
const stems = ds.files.map(f => f.stem).sort();
|
|
74
|
+
assert.deepEqual(stems, [ALWAYS_FILE_STEM]);
|
|
75
|
+
assert.ok(!ds.patterns.includes("acme-corp"));
|
|
76
|
+
assert.ok(!ds.patterns.includes("betaco"));
|
|
77
|
+
});
|
|
78
|
+
it("customer-coupled: empty engagements still computes deny set (caller enforces error)", () => {
|
|
79
|
+
const ds = computeDenySet(makeRepo("customer-coupled", []), { markersDir });
|
|
80
|
+
// Library doesn't enforce the error; that's the CLI's job. Library returns full set.
|
|
81
|
+
assert.equal(ds.files.length, 3);
|
|
82
|
+
});
|
|
83
|
+
it("scratch: same scoping as customer-coupled", () => {
|
|
84
|
+
const ds = computeDenySet(makeRepo("scratch", ["customer-a"]), { markersDir });
|
|
85
|
+
assert.equal(ds.files.length, 2);
|
|
86
|
+
});
|
|
87
|
+
it("strips ; comments and blank lines from marker files", () => {
|
|
88
|
+
writeFileSync(join(markersDir, "customer-c.txt"), "; comment line\n\nfirst-pattern\n; another comment\nsecond-pattern\n");
|
|
89
|
+
const ds = computeDenySet(makeRepo("private-strict"), { markersDir });
|
|
90
|
+
assert.ok(ds.patterns.includes("first-pattern"));
|
|
91
|
+
assert.ok(ds.patterns.includes("second-pattern"));
|
|
92
|
+
assert.ok(!ds.patterns.some(p => p.includes("comment")));
|
|
93
|
+
// restore
|
|
94
|
+
rmSync(join(markersDir, "customer-c.txt"));
|
|
95
|
+
});
|
|
96
|
+
it("writes a cache file with the expected shape on miss", () => {
|
|
97
|
+
const cachePath = join(tmp, "cache-shape.json");
|
|
98
|
+
const repo = makeRepo("private-strict");
|
|
99
|
+
const ds = computeDenySet(repo, { markersDir, cachePath });
|
|
100
|
+
assert.ok(existsSync(cachePath), "cache file written");
|
|
101
|
+
const cached = JSON.parse(readFileSync(cachePath, "utf8"));
|
|
102
|
+
assert.equal(cached.schemaVersion, 2);
|
|
103
|
+
assert.equal(typeof cached.key, "string");
|
|
104
|
+
assert.equal(cached.key.length, 64, "fingerprint is sha256 hex");
|
|
105
|
+
assert.deepEqual(cached.patterns, ds.patterns);
|
|
106
|
+
assert.equal(cached.combinedRegex, ds.combinedRegex);
|
|
107
|
+
});
|
|
108
|
+
it("invalidates cache when a marker file changes (mtime updated)", () => {
|
|
109
|
+
const cachePath = join(tmp, "cache-invalidate.json");
|
|
110
|
+
const repo = makeRepo("private-strict");
|
|
111
|
+
const ds1 = computeDenySet(repo, { markersDir, cachePath });
|
|
112
|
+
// Change a marker file with a NEW mtime + different size.
|
|
113
|
+
const acmePath = join(markersDir, "customer-a.txt");
|
|
114
|
+
writeFileSync(acmePath, "completely-different-content\n");
|
|
115
|
+
const ds2 = computeDenySet(repo, { markersDir, cachePath });
|
|
116
|
+
assert.notDeepEqual(ds2.patterns, ds1.patterns, "cache must invalidate on marker change");
|
|
117
|
+
assert.ok(ds2.patterns.includes("completely-different-content"));
|
|
118
|
+
// Restore for downstream tests.
|
|
119
|
+
setupMarkers();
|
|
120
|
+
});
|
|
121
|
+
it("cachePath: null disables caching", () => {
|
|
122
|
+
const repo = makeRepo("private-strict");
|
|
123
|
+
const initialFiles = readdirSync(tmp).filter(f => f.endsWith(".json")).length;
|
|
124
|
+
computeDenySet(repo, { markersDir, cachePath: null });
|
|
125
|
+
const after = readdirSync(tmp).filter(f => f.endsWith(".json")).length;
|
|
126
|
+
assert.equal(after, initialFiles, "no cache file should be written");
|
|
127
|
+
});
|
|
128
|
+
it("populates patternSources parallel to patterns", () => {
|
|
129
|
+
const repo = makeRepo("private-strict");
|
|
130
|
+
const ds = computeDenySet(repo, { markersDir, cachePath: null });
|
|
131
|
+
assert.equal(ds.patternSources?.length, ds.patterns.length, "lengths must match");
|
|
132
|
+
// Spot-check: alphabetical file order is _always, customer-a, customer-b
|
|
133
|
+
const alwaysIdx = ds.patterns.findIndex(p => p === "PROJECT-CODENAME-ALPHA");
|
|
134
|
+
if (alwaysIdx >= 0) {
|
|
135
|
+
assert.equal(ds.patternSources[alwaysIdx], "_always");
|
|
136
|
+
}
|
|
137
|
+
const acmeIdx = ds.patterns.findIndex(p => p === "acme-corp");
|
|
138
|
+
if (acmeIdx >= 0) {
|
|
139
|
+
assert.equal(ds.patternSources[acmeIdx], "customer-a");
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
it("preserves mid-line ; characters in marker patterns", () => {
|
|
143
|
+
// Regression: legitimate patterns containing `;` (e.g. `db;internal`,
|
|
144
|
+
// `key;value` form codenames) used to be silently truncated at the
|
|
145
|
+
// first `;`. Only lines whose first non-whitespace character is `;`
|
|
146
|
+
// are comments.
|
|
147
|
+
writeFileSync(join(markersDir, "customer-d.txt"), "db;internal\nkey;val;more\n ; leading-space-comment\n");
|
|
148
|
+
const ds = computeDenySet(makeRepo("private-strict"), { markersDir });
|
|
149
|
+
assert.ok(ds.patterns.includes("db;internal"), "mid-line ; must not truncate");
|
|
150
|
+
assert.ok(ds.patterns.includes("key;val;more"), "multiple mid-line ; must survive");
|
|
151
|
+
assert.ok(!ds.patterns.some(p => p.includes("leading-space-comment")), "leading-whitespace ; lines are still comments");
|
|
152
|
+
rmSync(join(markersDir, "customer-d.txt"));
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=deny-set.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deny-set.test.js","sourceRoot":"","sources":["../src/deny-set.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export declare class RegistryNotFoundError extends Error {
|
|
2
|
+
path: string;
|
|
3
|
+
readonly code: "REGISTRY_NOT_FOUND";
|
|
4
|
+
constructor(path: string);
|
|
5
|
+
}
|
|
6
|
+
export declare class RegistryParseError extends Error {
|
|
7
|
+
path: string;
|
|
8
|
+
cause: unknown;
|
|
9
|
+
readonly code: "REGISTRY_PARSE";
|
|
10
|
+
constructor(path: string, cause: unknown);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Raised by `loadRegistry` when the plaintext registry path is absent
|
|
14
|
+
* but a sibling `<path>.age` ciphertext exists. The user (or the agent
|
|
15
|
+
* on their behalf) must run `repo-aegis registry decrypt --identity
|
|
16
|
+
* <path>` before any registry-reading command will work.
|
|
17
|
+
*
|
|
18
|
+
* Why this is its own error: encrypted-at-rest is the *intended* state
|
|
19
|
+
* during periods of non-use. Auto-decrypt would defeat the purpose
|
|
20
|
+
* (any process could read the registry). Surfacing a distinct code
|
|
21
|
+
* lets the agent guide the user to the right command without trying
|
|
22
|
+
* to recover blindly.
|
|
23
|
+
*/
|
|
24
|
+
export declare class RegistryEncryptedError extends Error {
|
|
25
|
+
path: string;
|
|
26
|
+
ciphertextPath: string;
|
|
27
|
+
readonly code: "REGISTRY_ENCRYPTED";
|
|
28
|
+
constructor(path: string, ciphertextPath: string);
|
|
29
|
+
}
|
|
30
|
+
export declare class NotAGitRepoError extends Error {
|
|
31
|
+
readonly code: "NOT_GIT_REPO";
|
|
32
|
+
constructor();
|
|
33
|
+
}
|
|
34
|
+
export declare class AmbiguousQueryError extends Error {
|
|
35
|
+
query: string;
|
|
36
|
+
candidateCount: number;
|
|
37
|
+
readonly code: "AMBIGUOUS_QUERY";
|
|
38
|
+
constructor(query: string, candidateCount: number);
|
|
39
|
+
}
|
|
40
|
+
export declare class EngagementNotFoundError extends Error {
|
|
41
|
+
query: string;
|
|
42
|
+
readonly code: "ENGAGEMENT_NOT_FOUND";
|
|
43
|
+
constructor(query: string);
|
|
44
|
+
}
|
|
45
|
+
export declare class PatternValidationError extends Error {
|
|
46
|
+
invalid: {
|
|
47
|
+
pattern: string;
|
|
48
|
+
reason: string;
|
|
49
|
+
engagementId?: string;
|
|
50
|
+
}[];
|
|
51
|
+
readonly code: "PATTERN_VALIDATION";
|
|
52
|
+
constructor(invalid: {
|
|
53
|
+
pattern: string;
|
|
54
|
+
reason: string;
|
|
55
|
+
engagementId?: string;
|
|
56
|
+
}[]);
|
|
57
|
+
/**
|
|
58
|
+
* Same shape as {@link invalid} but with each `pattern` field passed
|
|
59
|
+
* through {@link redactMatch} so the literal customer-derived substring
|
|
60
|
+
* never leaves the process.
|
|
61
|
+
*
|
|
62
|
+
* Marker patterns are user-authored regexes that typically embed
|
|
63
|
+
* customer-derived strings (e.g. `acmeengineering\.com`). They fall
|
|
64
|
+
* under the same redaction policy as match values whenever they are
|
|
65
|
+
* surfaced to JSON, log files, or anything an AI agent might
|
|
66
|
+
* subsequently read.
|
|
67
|
+
*
|
|
68
|
+
* Callers serialising this error to JSON, stderr, or any persisted
|
|
69
|
+
* artifact should prefer `redactedPatterns`. The raw `invalid` field
|
|
70
|
+
* remains for the in-process renderer (it needs the literal pattern to
|
|
71
|
+
* point the user at the offending entry in their own marker file) —
|
|
72
|
+
* that is an internal contract; do not leak it across a process
|
|
73
|
+
* boundary.
|
|
74
|
+
*/
|
|
75
|
+
get redactedPatterns(): {
|
|
76
|
+
pattern: string;
|
|
77
|
+
reason: string;
|
|
78
|
+
engagementId?: string;
|
|
79
|
+
}[];
|
|
80
|
+
}
|
|
81
|
+
export declare class OutsideWorkingTreeError extends Error {
|
|
82
|
+
path: string;
|
|
83
|
+
workingTree: string;
|
|
84
|
+
readonly code: "OUTSIDE_WORKING_TREE";
|
|
85
|
+
constructor(path: string, workingTree: string);
|
|
86
|
+
}
|
|
87
|
+
export declare class LockTimeoutError extends Error {
|
|
88
|
+
lockPath: string;
|
|
89
|
+
readonly code: "LOCK_TIMEOUT";
|
|
90
|
+
constructor(lockPath: string);
|
|
91
|
+
}
|
|
92
|
+
export declare class CustomerCoupledNoEngagementError extends Error {
|
|
93
|
+
readonly code: "CUSTOMER_COUPLED_NO_ENGAGEMENT";
|
|
94
|
+
constructor();
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=exceptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exceptions.d.ts","sourceRoot":"","sources":["../src/exceptions.ts"],"names":[],"mappings":"AAIA,qBAAa,qBAAsB,SAAQ,KAAK;IAE3B,IAAI,EAAE,MAAM;IAD/B,QAAQ,CAAC,IAAI,EAAG,oBAAoB,CAAU;gBAC3B,IAAI,EAAE,MAAM;CAIhC;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAExB,IAAI,EAAE,MAAM;IAAkB,KAAK,EAAE,OAAO;IAD/D,QAAQ,CAAC,IAAI,EAAG,gBAAgB,CAAU;gBACvB,IAAI,EAAE,MAAM,EAAkB,KAAK,EAAE,OAAO;CAIhE;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAE5B,IAAI,EAAE,MAAM;IAAS,cAAc,EAAE,MAAM;IAD9D,QAAQ,CAAC,IAAI,EAAG,oBAAoB,CAAU;gBAC3B,IAAI,EAAE,MAAM,EAAS,cAAc,EAAE,MAAM;CAQ/D;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;;CAKzC;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAEzB,KAAK,EAAE,MAAM;IAAS,cAAc,EAAE,MAAM;IAD/D,QAAQ,CAAC,IAAI,EAAG,iBAAiB,CAAU;gBACxB,KAAK,EAAE,MAAM,EAAS,cAAc,EAAE,MAAM;CAIhE;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAE7B,KAAK,EAAE,MAAM;IADhC,QAAQ,CAAC,IAAI,EAAG,sBAAsB,CAAU;gBAC7B,KAAK,EAAE,MAAM;CAIjC;AAED,qBAAa,sBAAuB,SAAQ,KAAK;IAGtC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE;IAF9E,QAAQ,CAAC,IAAI,EAAG,oBAAoB,CAAU;gBAErC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE;IAM9E;;;;;;;;;;;;;;;;;OAiBG;IACH,IAAI,gBAAgB,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CASnF;CACF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAE7B,IAAI,EAAE,MAAM;IAAS,WAAW,EAAE,MAAM;IAD3D,QAAQ,CAAC,IAAI,EAAG,sBAAsB,CAAU;gBAC7B,IAAI,EAAE,MAAM,EAAS,WAAW,EAAE,MAAM;CAI5D;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IAEtB,QAAQ,EAAE,MAAM;IADnC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;gBACrB,QAAQ,EAAE,MAAM;CAIpC;AAED,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,QAAQ,CAAC,IAAI,EAAG,gCAAgC,CAAU;;CAS3D"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Richard Myers and contributors.
|
|
3
|
+
import { redactMatch } from "./redaction.js";
|
|
4
|
+
export class RegistryNotFoundError extends Error {
|
|
5
|
+
path;
|
|
6
|
+
code = "REGISTRY_NOT_FOUND";
|
|
7
|
+
constructor(path) {
|
|
8
|
+
super(`engagement registry not found at ${path}`);
|
|
9
|
+
this.path = path;
|
|
10
|
+
this.name = "RegistryNotFoundError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class RegistryParseError extends Error {
|
|
14
|
+
path;
|
|
15
|
+
cause;
|
|
16
|
+
code = "REGISTRY_PARSE";
|
|
17
|
+
constructor(path, cause) {
|
|
18
|
+
super(`failed to parse registry at ${path}: ${cause.message ?? cause}`);
|
|
19
|
+
this.path = path;
|
|
20
|
+
this.cause = cause;
|
|
21
|
+
this.name = "RegistryParseError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Raised by `loadRegistry` when the plaintext registry path is absent
|
|
26
|
+
* but a sibling `<path>.age` ciphertext exists. The user (or the agent
|
|
27
|
+
* on their behalf) must run `repo-aegis registry decrypt --identity
|
|
28
|
+
* <path>` before any registry-reading command will work.
|
|
29
|
+
*
|
|
30
|
+
* Why this is its own error: encrypted-at-rest is the *intended* state
|
|
31
|
+
* during periods of non-use. Auto-decrypt would defeat the purpose
|
|
32
|
+
* (any process could read the registry). Surfacing a distinct code
|
|
33
|
+
* lets the agent guide the user to the right command without trying
|
|
34
|
+
* to recover blindly.
|
|
35
|
+
*/
|
|
36
|
+
export class RegistryEncryptedError extends Error {
|
|
37
|
+
path;
|
|
38
|
+
ciphertextPath;
|
|
39
|
+
code = "REGISTRY_ENCRYPTED";
|
|
40
|
+
constructor(path, ciphertextPath) {
|
|
41
|
+
super(`engagement registry at ${path} is encrypted at rest ` +
|
|
42
|
+
`(ciphertext present at ${ciphertextPath}); ` +
|
|
43
|
+
`run \`repo-aegis registry decrypt --identity <path>\` first`);
|
|
44
|
+
this.path = path;
|
|
45
|
+
this.ciphertextPath = ciphertextPath;
|
|
46
|
+
this.name = "RegistryEncryptedError";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export class NotAGitRepoError extends Error {
|
|
50
|
+
code = "NOT_GIT_REPO";
|
|
51
|
+
constructor() {
|
|
52
|
+
super("not inside a git repository");
|
|
53
|
+
this.name = "NotAGitRepoError";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export class AmbiguousQueryError extends Error {
|
|
57
|
+
query;
|
|
58
|
+
candidateCount;
|
|
59
|
+
code = "AMBIGUOUS_QUERY";
|
|
60
|
+
constructor(query, candidateCount) {
|
|
61
|
+
super(`ambiguous engagement query "${query}" (${candidateCount} candidates)`);
|
|
62
|
+
this.query = query;
|
|
63
|
+
this.candidateCount = candidateCount;
|
|
64
|
+
this.name = "AmbiguousQueryError";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export class EngagementNotFoundError extends Error {
|
|
68
|
+
query;
|
|
69
|
+
code = "ENGAGEMENT_NOT_FOUND";
|
|
70
|
+
constructor(query) {
|
|
71
|
+
super(`no engagement matches "${query}"`);
|
|
72
|
+
this.query = query;
|
|
73
|
+
this.name = "EngagementNotFoundError";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export class PatternValidationError extends Error {
|
|
77
|
+
invalid;
|
|
78
|
+
code = "PATTERN_VALIDATION";
|
|
79
|
+
constructor(invalid) {
|
|
80
|
+
super(`${invalid.length} marker pattern${invalid.length === 1 ? "" : "s"} failed validation`);
|
|
81
|
+
this.invalid = invalid;
|
|
82
|
+
this.name = "PatternValidationError";
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Same shape as {@link invalid} but with each `pattern` field passed
|
|
86
|
+
* through {@link redactMatch} so the literal customer-derived substring
|
|
87
|
+
* never leaves the process.
|
|
88
|
+
*
|
|
89
|
+
* Marker patterns are user-authored regexes that typically embed
|
|
90
|
+
* customer-derived strings (e.g. `acmeengineering\.com`). They fall
|
|
91
|
+
* under the same redaction policy as match values whenever they are
|
|
92
|
+
* surfaced to JSON, log files, or anything an AI agent might
|
|
93
|
+
* subsequently read.
|
|
94
|
+
*
|
|
95
|
+
* Callers serialising this error to JSON, stderr, or any persisted
|
|
96
|
+
* artifact should prefer `redactedPatterns`. The raw `invalid` field
|
|
97
|
+
* remains for the in-process renderer (it needs the literal pattern to
|
|
98
|
+
* point the user at the offending entry in their own marker file) —
|
|
99
|
+
* that is an internal contract; do not leak it across a process
|
|
100
|
+
* boundary.
|
|
101
|
+
*/
|
|
102
|
+
get redactedPatterns() {
|
|
103
|
+
return this.invalid.map(entry => {
|
|
104
|
+
const out = {
|
|
105
|
+
pattern: redactMatch(entry.pattern),
|
|
106
|
+
reason: entry.reason,
|
|
107
|
+
};
|
|
108
|
+
if (entry.engagementId !== undefined)
|
|
109
|
+
out.engagementId = entry.engagementId;
|
|
110
|
+
return out;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export class OutsideWorkingTreeError extends Error {
|
|
115
|
+
path;
|
|
116
|
+
workingTree;
|
|
117
|
+
code = "OUTSIDE_WORKING_TREE";
|
|
118
|
+
constructor(path, workingTree) {
|
|
119
|
+
super(`path ${path} is outside the working tree ${workingTree}`);
|
|
120
|
+
this.path = path;
|
|
121
|
+
this.workingTree = workingTree;
|
|
122
|
+
this.name = "OutsideWorkingTreeError";
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export class LockTimeoutError extends Error {
|
|
126
|
+
lockPath;
|
|
127
|
+
code = "LOCK_TIMEOUT";
|
|
128
|
+
constructor(lockPath) {
|
|
129
|
+
super(`could not acquire registry lock at ${lockPath} (another repo-aegis process is running?)`);
|
|
130
|
+
this.lockPath = lockPath;
|
|
131
|
+
this.name = "LockTimeoutError";
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
export class CustomerCoupledNoEngagementError extends Error {
|
|
135
|
+
code = "CUSTOMER_COUPLED_NO_ENGAGEMENT";
|
|
136
|
+
constructor() {
|
|
137
|
+
super("repo-aegis.class=customer-coupled but no repo-aegis.engagement is set; " +
|
|
138
|
+
"run `repo-aegis allow <engagement-id>` to declare which engagement(s) " +
|
|
139
|
+
"this repo legitimately references");
|
|
140
|
+
this.name = "CustomerCoupledNoEngagementError";
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=exceptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exceptions.js","sourceRoot":"","sources":["../src/exceptions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,UAAU,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,qDAAqD;AACrD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC1B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC"}
|