@vordsec/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +33 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +86 -0
- package/dist/bin.js.map +1 -0
- package/dist/commands/explain.d.ts +20 -0
- package/dist/commands/explain.d.ts.map +1 -0
- package/dist/commands/explain.js +61 -0
- package/dist/commands/explain.js.map +1 -0
- package/dist/commands/guard.d.ts +41 -0
- package/dist/commands/guard.d.ts.map +1 -0
- package/dist/commands/guard.js +106 -0
- package/dist/commands/guard.js.map +1 -0
- package/dist/commands/hook.d.ts +66 -0
- package/dist/commands/hook.d.ts.map +1 -0
- package/dist/commands/hook.js +127 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/ignore.d.ts +40 -0
- package/dist/commands/ignore.d.ts.map +1 -0
- package/dist/commands/ignore.js +159 -0
- package/dist/commands/ignore.js.map +1 -0
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +75 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install-gate.d.ts +19 -0
- package/dist/commands/install-gate.d.ts.map +1 -0
- package/dist/commands/install-gate.js +118 -0
- package/dist/commands/install-gate.js.map +1 -0
- package/dist/commands/mcp.d.ts +53 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +155 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/scan.d.ts +21 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +77 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/exit-codes.d.ts +38 -0
- package/dist/exit-codes.d.ts.map +1 -0
- package/dist/exit-codes.js +40 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/report/gate.d.ts +41 -0
- package/dist/report/gate.d.ts.map +1 -0
- package/dist/report/gate.js +111 -0
- package/dist/report/gate.js.map +1 -0
- package/dist/report/scan.d.ts +34 -0
- package/dist/report/scan.d.ts.map +1 -0
- package/dist/report/scan.js +170 -0
- package/dist/report/scan.js.map +1 -0
- package/dist/shim/artifacts.d.ts +54 -0
- package/dist/shim/artifacts.d.ts.map +1 -0
- package/dist/shim/artifacts.js +114 -0
- package/dist/shim/artifacts.js.map +1 -0
- package/dist/shim/decide.d.ts +68 -0
- package/dist/shim/decide.d.ts.map +1 -0
- package/dist/shim/decide.js +62 -0
- package/dist/shim/decide.js.map +1 -0
- package/dist/shim/install.d.ts +76 -0
- package/dist/shim/install.d.ts.map +1 -0
- package/dist/shim/install.js +174 -0
- package/dist/shim/install.js.map +1 -0
- package/dist/shim/log.d.ts +52 -0
- package/dist/shim/log.d.ts.map +1 -0
- package/dist/shim/log.js +78 -0
- package/dist/shim/log.js.map +1 -0
- package/dist/shim/run.d.ts +37 -0
- package/dist/shim/run.d.ts.map +1 -0
- package/dist/shim/run.js +100 -0
- package/dist/shim/run.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Rule } from '@vordsec/core';
|
|
2
|
+
import { type ExitCode } from '../exit-codes.js';
|
|
3
|
+
import { type ScanFormat } from '../report/scan.js';
|
|
4
|
+
/** 구현된 Tier 1 룰. **없는 룰을 도움말에 적지 않는다** */
|
|
5
|
+
export declare const TIER1_RULES: readonly Rule[];
|
|
6
|
+
export interface ScanArgs {
|
|
7
|
+
readonly cwd: string;
|
|
8
|
+
readonly format: ScanFormat;
|
|
9
|
+
/** 확인 불가를 실패로 볼 것인가 */
|
|
10
|
+
readonly strict: boolean;
|
|
11
|
+
/** 무시 규칙을 무시한다 (무엇이 꺼져 있는지 볼 때) */
|
|
12
|
+
readonly noIgnore: boolean;
|
|
13
|
+
readonly usageError?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function parseScanArgs(argv: readonly string[], cwd: string): ScanArgs;
|
|
16
|
+
export interface ScanResult {
|
|
17
|
+
readonly lines: readonly string[];
|
|
18
|
+
readonly exitCode: ExitCode;
|
|
19
|
+
}
|
|
20
|
+
export declare function runScan(args: ScanArgs): ScanResult;
|
|
21
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGhE,0CAA0C;AAC1C,eAAO,MAAM,WAAW,EAAE,SAAS,IAAI,EAAqD,CAAC;AAE7F,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,uBAAuB;IACvB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAyB5E;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAyBlD"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vord scan` — Tier 1 스캔 진입점.
|
|
3
|
+
*
|
|
4
|
+
* `buildContext`(⑤) → `scan`(⑥·⑦) 을 부르는 얇은 층이다. 판정은 전부 엔진과 룰에 있다.
|
|
5
|
+
*
|
|
6
|
+
* ## 종료 코드에서 갈린 것 하나
|
|
7
|
+
*
|
|
8
|
+
* Tier 0 는 확인 불가를 **2** 로 낸다 — 설치를 멈추기 때문이다(ADR-017).
|
|
9
|
+
* 스캔은 다르다. 실측에서 **SEC-004 가 안전한 레포의 29% 에서 확인 불가를 냈다.**
|
|
10
|
+
* 그걸 기본값으로 CI 를 깨면 사용자는 스캔을 끄고, **꺼진 스캔은 없는 것과 같다**(ADR-004).
|
|
11
|
+
* 그래서 확인 불가는 기본 **0** 이고, 실패로 다루고 싶으면 `--strict` 를 쓴다.
|
|
12
|
+
* 취약은 언제나 **1** 이다.
|
|
13
|
+
*/
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import { buildContext, scan, sec001Rule, sec002Rule, sec003Rule, sec004Rule, VERSION } from '@vordsec/core';
|
|
16
|
+
import { EXIT } from '../exit-codes.js';
|
|
17
|
+
import { renderScan } from '../report/scan.js';
|
|
18
|
+
import { applyIgnores, readIgnoreFile } from './ignore.js';
|
|
19
|
+
/** 구현된 Tier 1 룰. **없는 룰을 도움말에 적지 않는다** */
|
|
20
|
+
export const TIER1_RULES = [sec001Rule, sec002Rule, sec003Rule, sec004Rule];
|
|
21
|
+
export function parseScanArgs(argv, cwd) {
|
|
22
|
+
let format = 'pretty';
|
|
23
|
+
let strict = false;
|
|
24
|
+
let noIgnore = false;
|
|
25
|
+
let target;
|
|
26
|
+
let usageError;
|
|
27
|
+
for (let i = 0; i < argv.length; i++) {
|
|
28
|
+
const a = argv[i];
|
|
29
|
+
if (a === '--json')
|
|
30
|
+
format = 'json';
|
|
31
|
+
else if (a === '--sarif')
|
|
32
|
+
format = 'sarif';
|
|
33
|
+
else if (a === '--strict')
|
|
34
|
+
strict = true;
|
|
35
|
+
else if (a === '--no-ignore')
|
|
36
|
+
noIgnore = true;
|
|
37
|
+
else if (a === '--cwd') {
|
|
38
|
+
target = argv[++i];
|
|
39
|
+
}
|
|
40
|
+
else if (a.startsWith('-'))
|
|
41
|
+
usageError = `모르는 옵션이다: ${a}`;
|
|
42
|
+
else
|
|
43
|
+
target = a;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
cwd: target === undefined ? cwd : path.resolve(cwd, target),
|
|
47
|
+
format,
|
|
48
|
+
strict,
|
|
49
|
+
noIgnore,
|
|
50
|
+
...(usageError === undefined ? {} : { usageError }),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function runScan(args) {
|
|
54
|
+
if (args.usageError !== undefined) {
|
|
55
|
+
return {
|
|
56
|
+
lines: [
|
|
57
|
+
args.usageError,
|
|
58
|
+
'',
|
|
59
|
+
'vord scan [경로] [--json | --sarif] [--strict] [--no-ignore]',
|
|
60
|
+
],
|
|
61
|
+
exitCode: EXIT.USAGE,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const ctx = buildContext(args.cwd);
|
|
65
|
+
const raw = scan(ctx, TIER1_RULES);
|
|
66
|
+
const entries = args.noIgnore ? [] : readIgnoreFile(args.cwd);
|
|
67
|
+
const { kept, suppressed } = applyIgnores(raw.findings, entries);
|
|
68
|
+
const report = { ...raw, findings: kept };
|
|
69
|
+
const lines = renderScan({ report, suppressed, root: args.cwd }, args.format, VERSION);
|
|
70
|
+
// **취약이 확인 불가를 이긴다** — 게이트와 같은 규칙이다
|
|
71
|
+
if (kept.length > 0)
|
|
72
|
+
return { lines, exitCode: EXIT.BLOCKED };
|
|
73
|
+
if (args.strict && report.unknowns.length > 0)
|
|
74
|
+
return { lines, exitCode: EXIT.UNVERIFIABLE };
|
|
75
|
+
return { lines, exitCode: EXIT.OK };
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 종료 코드 — **기계가 읽는 판정이다** (ADR-010 §2 · ADR-017).
|
|
3
|
+
*
|
|
4
|
+
* 이 제품은 "위험함" 과 "모름" 을 뭉치지 않는다는 원칙을 판정 등급·메시지·집계에서
|
|
5
|
+
* 전부 지켜 왔다. 종료 코드만 뭉치면 **그 원칙이 기계가 읽는 자리에서만 깨진다** —
|
|
6
|
+
* CI 는 메시지를 안 읽고 코드만 본다.
|
|
7
|
+
*
|
|
8
|
+
* 그래서 차단과 확인 불가를 가른다. 나가는 동작은 같아도(둘 다 설치를 멈춘다)
|
|
9
|
+
* 뜻이 다르고, 대응도 다르다 — 차단은 패키지를 바꿔야 하고 확인 불가는 다시 시도하면 된다.
|
|
10
|
+
*
|
|
11
|
+
* | 코드 | 뜻 | 무엇을 하면 되나 |
|
|
12
|
+
* |------|-----|-----------------|
|
|
13
|
+
* | 0 | 통과 (경고 포함) | 그대로 진행 |
|
|
14
|
+
* | 1 | **차단** — 위험하다고 판단했다 | 패키지를 바꾸거나 `--ignore-scripts` |
|
|
15
|
+
* | 2 | **확인 불가** — 판단하지 못했다 | 네트워크 확인 후 재시도 · `vord init` · `--allow-unverified` |
|
|
16
|
+
* | 3 | 사용법 오류 | 명령을 고친다 |
|
|
17
|
+
*
|
|
18
|
+
* **경고는 0 이다.** 경고로 CI 를 깨면 사용자는 경고를 끄고, 꺼진 경고는 없는 것과 같다
|
|
19
|
+
* (ADR-004). 경고를 실패로 다루고 싶으면 호출부가 출력을 보고 정한다.
|
|
20
|
+
*/
|
|
21
|
+
export declare const EXIT: {
|
|
22
|
+
readonly OK: 0;
|
|
23
|
+
readonly BLOCKED: 1;
|
|
24
|
+
readonly UNVERIFIABLE: 2;
|
|
25
|
+
readonly USAGE: 3;
|
|
26
|
+
};
|
|
27
|
+
export type ExitCode = typeof EXIT[keyof typeof EXIT];
|
|
28
|
+
/**
|
|
29
|
+
* 판정에서 종료 코드를 고른다.
|
|
30
|
+
*
|
|
31
|
+
* **차단이 확인 불가를 이긴다.** 둘이 섞였으면 위험한 쪽이 더 강한 신호다 —
|
|
32
|
+
* "다시 시도하면 된다" 고 말하면 안 되는 상황이기 때문이다.
|
|
33
|
+
*/
|
|
34
|
+
export declare function exitCodeFor(input: {
|
|
35
|
+
readonly blocked: boolean;
|
|
36
|
+
readonly unverifiable: boolean;
|
|
37
|
+
}): ExitCode;
|
|
38
|
+
//# sourceMappingURL=exit-codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,IAAI;;;;;CAKP,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,MAAM,OAAO,IAAI,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAChC,GAAG,QAAQ,CAIX"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 종료 코드 — **기계가 읽는 판정이다** (ADR-010 §2 · ADR-017).
|
|
3
|
+
*
|
|
4
|
+
* 이 제품은 "위험함" 과 "모름" 을 뭉치지 않는다는 원칙을 판정 등급·메시지·집계에서
|
|
5
|
+
* 전부 지켜 왔다. 종료 코드만 뭉치면 **그 원칙이 기계가 읽는 자리에서만 깨진다** —
|
|
6
|
+
* CI 는 메시지를 안 읽고 코드만 본다.
|
|
7
|
+
*
|
|
8
|
+
* 그래서 차단과 확인 불가를 가른다. 나가는 동작은 같아도(둘 다 설치를 멈춘다)
|
|
9
|
+
* 뜻이 다르고, 대응도 다르다 — 차단은 패키지를 바꿔야 하고 확인 불가는 다시 시도하면 된다.
|
|
10
|
+
*
|
|
11
|
+
* | 코드 | 뜻 | 무엇을 하면 되나 |
|
|
12
|
+
* |------|-----|-----------------|
|
|
13
|
+
* | 0 | 통과 (경고 포함) | 그대로 진행 |
|
|
14
|
+
* | 1 | **차단** — 위험하다고 판단했다 | 패키지를 바꾸거나 `--ignore-scripts` |
|
|
15
|
+
* | 2 | **확인 불가** — 판단하지 못했다 | 네트워크 확인 후 재시도 · `vord init` · `--allow-unverified` |
|
|
16
|
+
* | 3 | 사용법 오류 | 명령을 고친다 |
|
|
17
|
+
*
|
|
18
|
+
* **경고는 0 이다.** 경고로 CI 를 깨면 사용자는 경고를 끄고, 꺼진 경고는 없는 것과 같다
|
|
19
|
+
* (ADR-004). 경고를 실패로 다루고 싶으면 호출부가 출력을 보고 정한다.
|
|
20
|
+
*/
|
|
21
|
+
export const EXIT = {
|
|
22
|
+
OK: 0,
|
|
23
|
+
BLOCKED: 1,
|
|
24
|
+
UNVERIFIABLE: 2,
|
|
25
|
+
USAGE: 3,
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* 판정에서 종료 코드를 고른다.
|
|
29
|
+
*
|
|
30
|
+
* **차단이 확인 불가를 이긴다.** 둘이 섞였으면 위험한 쪽이 더 강한 신호다 —
|
|
31
|
+
* "다시 시도하면 된다" 고 말하면 안 되는 상황이기 때문이다.
|
|
32
|
+
*/
|
|
33
|
+
export function exitCodeFor(input) {
|
|
34
|
+
if (input.blocked)
|
|
35
|
+
return EXIT.BLOCKED;
|
|
36
|
+
if (input.unverifiable)
|
|
37
|
+
return EXIT.UNVERIFIABLE;
|
|
38
|
+
return EXIT.OK;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=exit-codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,EAAE,EAAE,CAAC;IACL,OAAO,EAAE,CAAC;IACV,YAAY,EAAE,CAAC;IACf,KAAK,EAAE,CAAC;CACA,CAAC;AAIX;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,KAG3B;IACC,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC;IACvC,IAAI,KAAK,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC,YAAY,CAAC;IACjD,OAAO,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const VERSION = "0.0.0";
|
|
2
|
+
export { SHIM_MANAGERS, SHIM_EXTENSIONS, RUNTIME_FILENAME, buildArtifact, buildArtifacts, expectedFilenames, isSafePath, UnsafePathError, } from './shim/artifacts.js';
|
|
3
|
+
export type { ShimManager, ShimExtension, ShimTarget, ShimArtifact } from './shim/artifacts.js';
|
|
4
|
+
export { install, remove, verify, planInstall, findRealBinary, isShimFirst, defaultShimDir, splitPath, pathInstructions, runtimeSource, } from './shim/install.js';
|
|
5
|
+
export type { Env, InstallPlan, InstallResult, RemoveResult, VerifyResult, } from './shim/install.js';
|
|
6
|
+
export { decide, CRASH_PASSES_THROUGH_PROVISIONAL } from './shim/decide.js';
|
|
7
|
+
export type { Decision, DecideInput, GateSummary } from './shim/decide.js';
|
|
8
|
+
export { fileLogger, summarize, NO_LOG, LOG_FILENAME, MAX_LOG_BYTES } from './shim/log.js';
|
|
9
|
+
export type { ShimLogger, ShimLogRecord, ShimOutcome, ShimStats } from './shim/log.js';
|
|
10
|
+
export { runShim, formatFindings, toSummary } from './shim/run.js';
|
|
11
|
+
export type { RunShimInput, RunShimDeps } from './shim/run.js';
|
|
12
|
+
export { runInstallGate, parseArgs } from './commands/install-gate.js';
|
|
13
|
+
export type { InstallGateOptions, InstallGateAction, CommandResult } from './commands/install-gate.js';
|
|
14
|
+
export { runInit, parseInitArgs, defaultCacheFile, CACHE_FILENAME } from './commands/init.js';
|
|
15
|
+
export { runGuard, parseGuardArgs, GUARD_USAGE } from './commands/guard.js';
|
|
16
|
+
export type { GuardCliOptions, GuardCliResult } from './commands/guard.js';
|
|
17
|
+
export { runExplain, renderRule } from './commands/explain.js';
|
|
18
|
+
export type { ExplainResult } from './commands/explain.js';
|
|
19
|
+
export { runHook, parseHookInput, readStdin } from './commands/hook.js';
|
|
20
|
+
export type { HookInput, HookDecision, HookResult } from './commands/hook.js';
|
|
21
|
+
export { runMcpServer, handleMcpLine, handleMcpRequest, MCP_PROTOCOL_VERSION, TOOL_NAME, } from './commands/mcp.js';
|
|
22
|
+
export { runScan, parseScanArgs, TIER1_RULES } from './commands/scan.js';
|
|
23
|
+
export type { ScanArgs, ScanResult } from './commands/scan.js';
|
|
24
|
+
export { runIgnore, applyIgnores, readIgnoreFile, parseIgnoreFile, parseIgnoreLine, matchesPattern, IGNORE_FILE, } from './commands/ignore.js';
|
|
25
|
+
export type { IgnoreEntry, IgnoreResult, SuppressResult } from './commands/ignore.js';
|
|
26
|
+
export { renderScan, renderSarif, renderPretty as renderScanPretty, renderJson as renderScanJson, } from './report/scan.js';
|
|
27
|
+
export type { ScanOutput, ScanFormat } from './report/scan.js';
|
|
28
|
+
export { renderGate, renderPretty, renderJson, renderReport } from './report/gate.js';
|
|
29
|
+
export type { GateRenderInput } from './report/gate.js';
|
|
30
|
+
export { EXIT, exitCodeFor } from './exit-codes.js';
|
|
31
|
+
export type { ExitCode } from './exit-codes.js';
|
|
32
|
+
export type { InitOptions, InitResult } from './commands/init.js';
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// @vordsec/cli — 터미널 인터페이스
|
|
2
|
+
export const VERSION = '0.0.0';
|
|
3
|
+
// 설치 경계 shim (ADR-026)
|
|
4
|
+
export { SHIM_MANAGERS, SHIM_EXTENSIONS, RUNTIME_FILENAME, buildArtifact, buildArtifacts, expectedFilenames, isSafePath, UnsafePathError, } from './shim/artifacts.js';
|
|
5
|
+
export { install, remove, verify, planInstall, findRealBinary, isShimFirst, defaultShimDir, splitPath, pathInstructions, runtimeSource, } from './shim/install.js';
|
|
6
|
+
export { decide, CRASH_PASSES_THROUGH_PROVISIONAL } from './shim/decide.js';
|
|
7
|
+
export { fileLogger, summarize, NO_LOG, LOG_FILENAME, MAX_LOG_BYTES } from './shim/log.js';
|
|
8
|
+
export { runShim, formatFindings, toSummary } from './shim/run.js';
|
|
9
|
+
export { runInstallGate, parseArgs } from './commands/install-gate.js';
|
|
10
|
+
export { runInit, parseInitArgs, defaultCacheFile, CACHE_FILENAME } from './commands/init.js';
|
|
11
|
+
export { runGuard, parseGuardArgs, GUARD_USAGE } from './commands/guard.js';
|
|
12
|
+
export { runExplain, renderRule } from './commands/explain.js';
|
|
13
|
+
export { runHook, parseHookInput, readStdin } from './commands/hook.js';
|
|
14
|
+
export { runMcpServer, handleMcpLine, handleMcpRequest, MCP_PROTOCOL_VERSION, TOOL_NAME, } from './commands/mcp.js';
|
|
15
|
+
export { runScan, parseScanArgs, TIER1_RULES } from './commands/scan.js';
|
|
16
|
+
export { runIgnore, applyIgnores, readIgnoreFile, parseIgnoreFile, parseIgnoreLine, matchesPattern, IGNORE_FILE, } from './commands/ignore.js';
|
|
17
|
+
export { renderScan, renderSarif, renderPretty as renderScanPretty, renderJson as renderScanJson, } from './report/scan.js';
|
|
18
|
+
export { renderGate, renderPretty, renderJson, renderReport } from './report/gate.js';
|
|
19
|
+
export { EXIT, exitCodeFor } from './exit-codes.js';
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,uBAAuB;AACvB,OAAO,EACL,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAChD,aAAa,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,eAAe,GAC9E,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EACjE,cAAc,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,GAC3D,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAAE,MAAM,EAAE,gCAAgC,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE3F,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE5E,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EACL,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,SAAS,GAC/E,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,EACL,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EACzE,cAAc,EAAE,WAAW,GAC5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,UAAU,EAAE,WAAW,EACvB,YAAY,IAAI,gBAAgB,EAAE,UAAU,IAAI,cAAc,GAC/D,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEtF,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 게이트 판정 리포터 — **shim 과 `guard` 가 같은 것을 쓴다.**
|
|
3
|
+
*
|
|
4
|
+
* 전에는 `shim/run.ts` 안에 있었다. 거기 두면 shim 을 깐 사람만 그 출력을 보고,
|
|
5
|
+
* `npx` · MCP 경로는 각자 다른 문장을 만들게 된다 (ADR-012 는 세 경로를 병행한다).
|
|
6
|
+
* **같은 판정이 경로마다 다르게 읽히면 그건 다른 제품이다.**
|
|
7
|
+
*
|
|
8
|
+
* 순수 함수다. 쓰지도 읽지도 않고 줄 배열만 낸다.
|
|
9
|
+
*
|
|
10
|
+
* ## 독자가 둘이다 (ADR-010 §2)
|
|
11
|
+
*
|
|
12
|
+
* 사람과 **에이전트**가 같은 출력을 읽는다. 그래서
|
|
13
|
+
* - `pretty` 는 사람이 읽되 **에이전트가 파싱할 수 있을 만큼 규칙적**이어야 하고
|
|
14
|
+
* - `json` 은 기계가 읽되 사람이 눈으로 훑을 수 있어야 한다
|
|
15
|
+
* 사유 코드(`GateCode`)를 양쪽 다 싣는 이유가 이것이다 — 산문만 주면
|
|
16
|
+
* 에이전트는 이유를 이해 못 하고 같은 명령을 재시도한다.
|
|
17
|
+
*/
|
|
18
|
+
import { type GateFinding, type GateReport } from '@vordsec/core';
|
|
19
|
+
export interface GateRenderInput {
|
|
20
|
+
readonly stop: boolean;
|
|
21
|
+
readonly notApplicable?: string;
|
|
22
|
+
readonly findings: readonly GateFinding[];
|
|
23
|
+
readonly contextDegraded?: boolean;
|
|
24
|
+
readonly notes?: readonly string[];
|
|
25
|
+
readonly bypassed?: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 판정 하나하나를 줄로. **통과는 싣지 않는다** — 통과가 대다수라 같이 내면 사유가 묻힌다.
|
|
29
|
+
*
|
|
30
|
+
* 이름을 `formatFindings` 로 유지한다. shim 이 쓰던 이름이고, 출력 모양도 그대로다 —
|
|
31
|
+
* 리포터를 옮기면서 사용자가 보던 문장이 바뀌면 그건 이동이 아니라 변경이다.
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatFindings(findings: readonly GateFinding[]): readonly string[];
|
|
34
|
+
/** 사람이 읽는 출력. 에이전트도 이걸 읽는다 */
|
|
35
|
+
export declare function renderPretty(r: GateRenderInput): readonly string[];
|
|
36
|
+
/** 기계가 읽는 출력. **사유 코드를 싣는다** — 산문만 주면 에이전트가 재시도한다 */
|
|
37
|
+
export declare function renderJson(r: GateRenderInput): string;
|
|
38
|
+
export declare function renderGate(report: GateRenderInput, json: boolean): readonly string[];
|
|
39
|
+
/** `GateReport` 를 그대로 받는 편의 — 필드 이름이 같아 옮겨 담을 것이 없다 */
|
|
40
|
+
export declare function renderReport(report: GateReport, json: boolean): readonly string[];
|
|
41
|
+
//# sourceMappingURL=gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/report/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAEY,KAAK,WAAW,EAAE,KAAK,UAAU,EACnD,MAAM,eAAe,CAAC;AAUvB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,MAAM,EAAE,CAWlF;AAED,8BAA8B;AAC9B,wBAAgB,YAAY,CAAC,CAAC,EAAE,eAAe,GAAG,SAAS,MAAM,EAAE,CAmClE;AAED,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,CAAC,EAAE,eAAe,GAAG,MAAM,CA0BrD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAEpF;AAED,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAEjF"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 게이트 판정 리포터 — **shim 과 `guard` 가 같은 것을 쓴다.**
|
|
3
|
+
*
|
|
4
|
+
* 전에는 `shim/run.ts` 안에 있었다. 거기 두면 shim 을 깐 사람만 그 출력을 보고,
|
|
5
|
+
* `npx` · MCP 경로는 각자 다른 문장을 만들게 된다 (ADR-012 는 세 경로를 병행한다).
|
|
6
|
+
* **같은 판정이 경로마다 다르게 읽히면 그건 다른 제품이다.**
|
|
7
|
+
*
|
|
8
|
+
* 순수 함수다. 쓰지도 읽지도 않고 줄 배열만 낸다.
|
|
9
|
+
*
|
|
10
|
+
* ## 독자가 둘이다 (ADR-010 §2)
|
|
11
|
+
*
|
|
12
|
+
* 사람과 **에이전트**가 같은 출력을 읽는다. 그래서
|
|
13
|
+
* - `pretty` 는 사람이 읽되 **에이전트가 파싱할 수 있을 만큼 규칙적**이어야 하고
|
|
14
|
+
* - `json` 은 기계가 읽되 사람이 눈으로 훑을 수 있어야 한다
|
|
15
|
+
* 사유 코드(`GateCode`)를 양쪽 다 싣는 이유가 이것이다 — 산문만 주면
|
|
16
|
+
* 에이전트는 이유를 이해 못 하고 같은 명령을 재시도한다.
|
|
17
|
+
*/
|
|
18
|
+
import { countActions, stopsInstall, } from '@vordsec/core';
|
|
19
|
+
/** 판정별 한국어 표시. **상수는 영문, 표시는 한국어** (프로젝트 언어 규칙) */
|
|
20
|
+
const MARK = {
|
|
21
|
+
block: '차단',
|
|
22
|
+
unverifiable: '확인 불가',
|
|
23
|
+
warn: '경고',
|
|
24
|
+
allow: '통과',
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* 판정 하나하나를 줄로. **통과는 싣지 않는다** — 통과가 대다수라 같이 내면 사유가 묻힌다.
|
|
28
|
+
*
|
|
29
|
+
* 이름을 `formatFindings` 로 유지한다. shim 이 쓰던 이름이고, 출력 모양도 그대로다 —
|
|
30
|
+
* 리포터를 옮기면서 사용자가 보던 문장이 바뀌면 그건 이동이 아니라 변경이다.
|
|
31
|
+
*/
|
|
32
|
+
export function formatFindings(findings) {
|
|
33
|
+
const out = [];
|
|
34
|
+
for (const f of findings) {
|
|
35
|
+
if (f.action === 'allow')
|
|
36
|
+
continue;
|
|
37
|
+
out.push(` [${MARK[f.action]}] ${f.rule} ${f.packageName} — ${f.message}`);
|
|
38
|
+
if (f.fix !== undefined)
|
|
39
|
+
out.push(` ${f.fix}`);
|
|
40
|
+
if (f.alternatives !== undefined && f.alternatives.length > 0) {
|
|
41
|
+
out.push(` 다른 후보: ${f.alternatives.join(' · ')}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
/** 사람이 읽는 출력. 에이전트도 이걸 읽는다 */
|
|
47
|
+
export function renderPretty(r) {
|
|
48
|
+
if (r.notApplicable !== undefined) {
|
|
49
|
+
return [`vord: 검사 대상이 아니다 — ${r.notApplicable}`];
|
|
50
|
+
}
|
|
51
|
+
const lines = formatFindings(r.findings);
|
|
52
|
+
const counts = countActions(r.findings);
|
|
53
|
+
const stopping = r.findings.filter((f) => stopsInstall(f.action));
|
|
54
|
+
const onlyUnverifiable = stopping.length > 0 && stopping.every((f) => f.action === 'unverifiable');
|
|
55
|
+
const head = !r.stop
|
|
56
|
+
? (counts.warned > 0 ? 'vord: 통과 — 다만 볼 것이 있다.' : 'vord: 통과.')
|
|
57
|
+
: onlyUnverifiable
|
|
58
|
+
// **"위험함" 과 "모름" 을 뭉치지 않는다** (ADR-017 장치 3)
|
|
59
|
+
? 'vord: 확인하지 못해 멈췄다. 위험해서 막은 것이 아니다.'
|
|
60
|
+
: 'vord: 설치를 막았다.';
|
|
61
|
+
const tail = [];
|
|
62
|
+
if (r.contextDegraded === true) {
|
|
63
|
+
tail.push('', '⚠️ 워크스페이스 구성을 다 읽지 못했다 — 통과시킨 것 중 일부는 못 본 탓일 수 있다.');
|
|
64
|
+
}
|
|
65
|
+
for (const n of r.notes ?? [])
|
|
66
|
+
tail.push(` ${n}`);
|
|
67
|
+
if (r.bypassed !== undefined && r.bypassed.length > 0) {
|
|
68
|
+
// 조용히 쓰는 수단이 되지 않게 **반드시 출력한다** (ADR-017 장치 4)
|
|
69
|
+
tail.push('', `⚠️ 검증 없이 통과시킨 것 ${r.bypassed.length}개: ${r.bypassed.join(' · ')}`);
|
|
70
|
+
}
|
|
71
|
+
if (onlyUnverifiable) {
|
|
72
|
+
tail.push('', '다시 시도하거나, 네트워크를 확인한 뒤 `vord init` 으로 캐시를 채운다.', '판단을 건너뛰고 진행하려면 `--allow-unverified` 를 쓴다 — 그러면 기록에 남는다.');
|
|
73
|
+
}
|
|
74
|
+
return [head, ...(lines.length > 0 ? ['', ...lines] : []), ...tail];
|
|
75
|
+
}
|
|
76
|
+
/** 기계가 읽는 출력. **사유 코드를 싣는다** — 산문만 주면 에이전트가 재시도한다 */
|
|
77
|
+
export function renderJson(r) {
|
|
78
|
+
const counts = countActions(r.findings);
|
|
79
|
+
const stopping = r.findings.filter((f) => stopsInstall(f.action));
|
|
80
|
+
return JSON.stringify({
|
|
81
|
+
stop: r.stop,
|
|
82
|
+
...(r.notApplicable === undefined ? {} : { notApplicable: r.notApplicable }),
|
|
83
|
+
reason: !r.stop ? 'ok'
|
|
84
|
+
: (stopping.length > 0 && stopping.every((f) => f.action === 'unverifiable')
|
|
85
|
+
? 'unverifiable' : 'blocked'),
|
|
86
|
+
counts,
|
|
87
|
+
contextDegraded: r.contextDegraded === true,
|
|
88
|
+
findings: r.findings.map((f) => ({
|
|
89
|
+
rule: f.rule,
|
|
90
|
+
action: f.action,
|
|
91
|
+
code: f.code,
|
|
92
|
+
ecosystem: f.ecosystem,
|
|
93
|
+
packageName: f.packageName,
|
|
94
|
+
raw: f.raw,
|
|
95
|
+
message: f.message,
|
|
96
|
+
...(f.fix === undefined ? {} : { fix: f.fix }),
|
|
97
|
+
...(f.alternatives === undefined ? {} : { alternatives: f.alternatives }),
|
|
98
|
+
...(f.flags === undefined ? {} : { flags: f.flags }),
|
|
99
|
+
})),
|
|
100
|
+
...(r.notes === undefined || r.notes.length === 0 ? {} : { notes: r.notes }),
|
|
101
|
+
...(r.bypassed === undefined || r.bypassed.length === 0 ? {} : { bypassed: r.bypassed }),
|
|
102
|
+
}, null, 2);
|
|
103
|
+
}
|
|
104
|
+
export function renderGate(report, json) {
|
|
105
|
+
return json ? [renderJson(report)] : renderPretty(report);
|
|
106
|
+
}
|
|
107
|
+
/** `GateReport` 를 그대로 받는 편의 — 필드 이름이 같아 옮겨 담을 것이 없다 */
|
|
108
|
+
export function renderReport(report, json) {
|
|
109
|
+
return renderGate(report, json);
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/report/gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 스캔 리포터 — pretty · json · sarif.
|
|
3
|
+
*
|
|
4
|
+
* **`report/gate.ts` 와 나란한 자리다.** 게이트는 설치 명령을, 여기는 파일을 판정한다.
|
|
5
|
+
* 계약이 달라(`GateFinding` ↔ `Finding`) 한 벌로 못 합친다 — 대신 규율은 같다.
|
|
6
|
+
*
|
|
7
|
+
* ## 규율 셋
|
|
8
|
+
*
|
|
9
|
+
* 1. **건너뛴 파일을 반드시 표시한다** (ADR-009 계약 4). 표시하지 않으면 "취약점 0건" 이
|
|
10
|
+
* "검사하지 못했음" 을 감춘다 — 이건 오탐보다 나쁘다
|
|
11
|
+
* 2. **무시된 항목을 조용히 지우지 않는다.** 몇 건을 껐는지 항상 센다
|
|
12
|
+
* 3. **확인 불가를 취약과 같은 톤으로 쓰지 않는다** (ADR-021). "위험함" 과 "모름" 은 다르다
|
|
13
|
+
*/
|
|
14
|
+
import type { Finding, ScanReport, SkippedFile, UnknownReport } from '@vordsec/core';
|
|
15
|
+
export interface ScanOutput {
|
|
16
|
+
readonly report: ScanReport;
|
|
17
|
+
/** 무시 규칙에 걸려 빠진 것들 — **숨기지 않고 센다** */
|
|
18
|
+
readonly suppressed: readonly Finding[];
|
|
19
|
+
/** 스캔 루트 (표시용) */
|
|
20
|
+
readonly root: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function renderPretty(out: ScanOutput): readonly string[];
|
|
23
|
+
export declare function renderJson(out: ScanOutput): readonly string[];
|
|
24
|
+
/**
|
|
25
|
+
* SARIF 2.1.0. GitHub code scanning 이 읽는 형식이다.
|
|
26
|
+
*
|
|
27
|
+
* **확인 불가도 싣는다** — `note` 등급에 `vord.verdict: unknown` 을 붙인다.
|
|
28
|
+
* 안 실으면 "검사했는데 아무것도 없었다" 와 구분이 안 된다.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderSarif(out: ScanOutput, version?: string): readonly string[];
|
|
31
|
+
export type ScanFormat = 'pretty' | 'json' | 'sarif';
|
|
32
|
+
export declare function renderScan(out: ScanOutput, format: ScanFormat, version?: string): readonly string[];
|
|
33
|
+
export type { Finding, ScanReport, SkippedFile, UnknownReport };
|
|
34
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/report/scan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,OAAO,EAAU,UAAU,EAAY,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGvG,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,sCAAsC;IACtC,QAAQ,CAAC,UAAU,EAAE,SAAS,OAAO,EAAE,CAAC;IACxC,kBAAkB;IAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAuBD,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,MAAM,EAAE,CA8C/D;AAID,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,MAAM,EAAE,CA6B7D;AA0BD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,SAAU,GAAG,SAAS,MAAM,EAAE,CAqDjF;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAInG;AAED,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC"}
|