arc-1 1.0.2 → 1.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/bin/arc1-cli.js +3 -7
- package/bin/arc1.js +4 -9
- package/dist/adt/abapgit.d.ts +10 -5
- package/dist/adt/abapgit.d.ts.map +1 -1
- package/dist/adt/abapgit.js +357 -76
- package/dist/adt/abapgit.js.map +1 -1
- package/dist/adt/atc.d.ts +49 -0
- package/dist/adt/atc.d.ts.map +1 -0
- package/dist/adt/atc.js +294 -0
- package/dist/adt/atc.js.map +1 -0
- package/dist/adt/aunit-package.d.ts +22 -0
- package/dist/adt/aunit-package.d.ts.map +1 -0
- package/dist/adt/aunit-package.js +78 -0
- package/dist/adt/aunit-package.js.map +1 -0
- package/dist/adt/aunit.d.ts +143 -0
- package/dist/adt/aunit.d.ts.map +1 -0
- package/dist/adt/aunit.js +987 -0
- package/dist/adt/aunit.js.map +1 -0
- package/dist/adt/client.d.ts +9 -7
- package/dist/adt/client.d.ts.map +1 -1
- package/dist/adt/client.js +55 -64
- package/dist/adt/client.js.map +1 -1
- package/dist/adt/config.d.ts +2 -0
- package/dist/adt/config.d.ts.map +1 -1
- package/dist/adt/config.js +1 -0
- package/dist/adt/config.js.map +1 -1
- package/dist/adt/devtools.d.ts +8 -30
- package/dist/adt/devtools.d.ts.map +1 -1
- package/dist/adt/devtools.js +41 -218
- package/dist/adt/devtools.js.map +1 -1
- package/dist/adt/diagnostics.d.ts +1 -1
- package/dist/adt/diagnostics.d.ts.map +1 -1
- package/dist/adt/diagnostics.js +12 -12
- package/dist/adt/diagnostics.js.map +1 -1
- package/dist/adt/errors.d.ts +7 -0
- package/dist/adt/errors.d.ts.map +1 -1
- package/dist/adt/errors.js +7 -0
- package/dist/adt/errors.js.map +1 -1
- package/dist/adt/features.d.ts +9 -3
- package/dist/adt/features.d.ts.map +1 -1
- package/dist/adt/features.js +40 -8
- package/dist/adt/features.js.map +1 -1
- package/dist/adt/gcts.d.ts +12 -45
- package/dist/adt/gcts.d.ts.map +1 -1
- package/dist/adt/gcts.js +299 -171
- package/dist/adt/gcts.js.map +1 -1
- package/dist/adt/http-deadline.d.ts +23 -0
- package/dist/adt/http-deadline.d.ts.map +1 -0
- package/dist/adt/http-deadline.js +106 -0
- package/dist/adt/http-deadline.js.map +1 -0
- package/dist/adt/http-wire-body.d.ts +2 -0
- package/dist/adt/http-wire-body.d.ts.map +1 -0
- package/dist/adt/http-wire-body.js +14 -0
- package/dist/adt/http-wire-body.js.map +1 -0
- package/dist/adt/http.d.ts +10 -24
- package/dist/adt/http.d.ts.map +1 -1
- package/dist/adt/http.js +89 -53
- package/dist/adt/http.js.map +1 -1
- package/dist/adt/path-safety.d.ts +16 -0
- package/dist/adt/path-safety.d.ts.map +1 -0
- package/dist/adt/path-safety.js +101 -0
- package/dist/adt/path-safety.js.map +1 -0
- package/dist/adt/semaphore.d.ts +2 -2
- package/dist/adt/semaphore.d.ts.map +1 -1
- package/dist/adt/semaphore.js +26 -9
- package/dist/adt/semaphore.js.map +1 -1
- package/dist/adt/source-diff.d.ts +10 -1
- package/dist/adt/source-diff.d.ts.map +1 -1
- package/dist/adt/source-diff.js +33 -7
- package/dist/adt/source-diff.js.map +1 -1
- package/dist/adt/text-search.d.ts +25 -0
- package/dist/adt/text-search.d.ts.map +1 -0
- package/dist/adt/text-search.js +152 -0
- package/dist/adt/text-search.js.map +1 -0
- package/dist/adt/transport-diff.d.ts +128 -0
- package/dist/adt/transport-diff.d.ts.map +1 -0
- package/dist/adt/transport-diff.js +524 -0
- package/dist/adt/transport-diff.js.map +1 -0
- package/dist/adt/transport.d.ts +78 -13
- package/dist/adt/transport.d.ts.map +1 -1
- package/dist/adt/transport.js +443 -41
- package/dist/adt/transport.js.map +1 -1
- package/dist/adt/types.d.ts +23 -12
- package/dist/adt/types.d.ts.map +1 -1
- package/dist/adt/xml-parser.d.ts +1 -8
- package/dist/adt/xml-parser.d.ts.map +1 -1
- package/dist/adt/xml-parser.js +54 -60
- package/dist/adt/xml-parser.js.map +1 -1
- package/dist/authz/policy.d.ts.map +1 -1
- package/dist/authz/policy.js +5 -2
- package/dist/authz/policy.js.map +1 -1
- package/dist/cli-args.d.ts +2 -2
- package/dist/cli-args.js +2 -2
- package/dist/cli-checks.d.ts +56 -0
- package/dist/cli-checks.d.ts.map +1 -0
- package/dist/cli-checks.js +368 -0
- package/dist/cli-checks.js.map +1 -0
- package/dist/cli.d.ts +68 -15
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +677 -297
- package/dist/cli.js.map +1 -1
- package/dist/handlers/cds-hints.d.ts.map +1 -1
- package/dist/handlers/cds-hints.js +1 -10
- package/dist/handlers/cds-hints.js.map +1 -1
- package/dist/handlers/diagnose.d.ts +4 -0
- package/dist/handlers/diagnose.d.ts.map +1 -1
- package/dist/handlers/diagnose.js +616 -9
- package/dist/handlers/diagnose.js.map +1 -1
- package/dist/handlers/dispatch.d.ts.map +1 -1
- package/dist/handlers/dispatch.js +40 -1
- package/dist/handlers/dispatch.js.map +1 -1
- package/dist/handlers/git.d.ts.map +1 -1
- package/dist/handlers/git.js +165 -84
- package/dist/handlers/git.js.map +1 -1
- package/dist/handlers/read.d.ts.map +1 -1
- package/dist/handlers/read.js +15 -0
- package/dist/handlers/read.js.map +1 -1
- package/dist/handlers/schemas.d.ts +15 -2
- package/dist/handlers/schemas.d.ts.map +1 -1
- package/dist/handlers/schemas.js +75 -6
- package/dist/handlers/schemas.js.map +1 -1
- package/dist/handlers/search.js +1 -1
- package/dist/handlers/search.js.map +1 -1
- package/dist/handlers/tools.d.ts.map +1 -1
- package/dist/handlers/tools.js +51 -42
- package/dist/handlers/tools.js.map +1 -1
- package/dist/handlers/transport.d.ts +2 -1
- package/dist/handlers/transport.d.ts.map +1 -1
- package/dist/handlers/transport.js +128 -27
- package/dist/handlers/transport.js.map +1 -1
- package/dist/handlers/write/create.d.ts.map +1 -1
- package/dist/handlers/write/create.js +11 -0
- package/dist/handlers/write/create.js.map +1 -1
- package/dist/handlers/write/update-delete.d.ts.map +1 -1
- package/dist/handlers/write/update-delete.js +33 -10
- package/dist/handlers/write/update-delete.js.map +1 -1
- package/dist/handlers/write-helpers.d.ts.map +1 -1
- package/dist/handlers/write-helpers.js +3 -2
- package/dist/handlers/write-helpers.js.map +1 -1
- package/dist/server/audit.d.ts +1 -1
- package/dist/server/audit.d.ts.map +1 -1
- package/dist/server/audit.js +228 -21
- package/dist/server/audit.js.map +1 -1
- package/dist/server/config.d.ts +16 -0
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js +145 -17
- package/dist/server/config.js.map +1 -1
- package/dist/server/effective-policy-log.d.ts +2 -1
- package/dist/server/effective-policy-log.d.ts.map +1 -1
- package/dist/server/effective-policy-log.js +8 -2
- package/dist/server/effective-policy-log.js.map +1 -1
- package/dist/server/multi-target-runtime.d.ts.map +1 -1
- package/dist/server/multi-target-runtime.js +3 -0
- package/dist/server/multi-target-runtime.js.map +1 -1
- package/dist/server/multi-target-tools.d.ts.map +1 -1
- package/dist/server/multi-target-tools.js +5 -0
- package/dist/server/multi-target-tools.js.map +1 -1
- package/dist/server/server.d.ts +15 -13
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +36 -26
- package/dist/server/server.js.map +1 -1
- package/dist/server/types.d.ts +2 -0
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +1 -0
- package/dist/server/types.js.map +1 -1
- package/package.json +13 -13
package/dist/server/audit.js
CHANGED
|
@@ -9,59 +9,266 @@
|
|
|
9
9
|
*/
|
|
10
10
|
const SENSITIVE_KEY_FRAGMENTS = [
|
|
11
11
|
'password',
|
|
12
|
+
'passwd',
|
|
13
|
+
'passphrase',
|
|
14
|
+
'pwd',
|
|
12
15
|
'token',
|
|
13
16
|
'secret',
|
|
14
17
|
'cookie',
|
|
18
|
+
'session',
|
|
19
|
+
'sessionid',
|
|
20
|
+
'jsessionid',
|
|
21
|
+
'sapsessionid',
|
|
15
22
|
'authorization',
|
|
16
23
|
'csrf',
|
|
17
24
|
'apikey',
|
|
18
25
|
'authpwd',
|
|
26
|
+
'authuser',
|
|
19
27
|
'authtoken',
|
|
20
28
|
'remotepassword',
|
|
29
|
+
'credential',
|
|
30
|
+
'accesskey',
|
|
31
|
+
'privatekey',
|
|
32
|
+
'sshkey',
|
|
33
|
+
'signature',
|
|
21
34
|
];
|
|
35
|
+
const KNOWN_SENSITIVE_FIELD_KEYS = new Set([
|
|
36
|
+
'password',
|
|
37
|
+
'passwd',
|
|
38
|
+
'passphrase',
|
|
39
|
+
'pwd',
|
|
40
|
+
'token',
|
|
41
|
+
'secret',
|
|
42
|
+
'cookie',
|
|
43
|
+
'session',
|
|
44
|
+
'sessionid',
|
|
45
|
+
'jsessionid',
|
|
46
|
+
'sap-sessionid',
|
|
47
|
+
'sap_sessionid',
|
|
48
|
+
'authorization',
|
|
49
|
+
'csrf',
|
|
50
|
+
'apikey',
|
|
51
|
+
'api-key',
|
|
52
|
+
'api_key',
|
|
53
|
+
'authpwd',
|
|
54
|
+
'auth-pwd',
|
|
55
|
+
'auth_pwd',
|
|
56
|
+
'authuser',
|
|
57
|
+
'auth-user',
|
|
58
|
+
'auth_user',
|
|
59
|
+
'authtoken',
|
|
60
|
+
'auth-token',
|
|
61
|
+
'auth_token',
|
|
62
|
+
'remotepassword',
|
|
63
|
+
'remote-password',
|
|
64
|
+
'remote_password',
|
|
65
|
+
'credential',
|
|
66
|
+
'accesskey',
|
|
67
|
+
'access-key',
|
|
68
|
+
'access_key',
|
|
69
|
+
'privatekey',
|
|
70
|
+
'private-key',
|
|
71
|
+
'private_key',
|
|
72
|
+
'sshkey',
|
|
73
|
+
'ssh-key',
|
|
74
|
+
'ssh_key',
|
|
75
|
+
'signature',
|
|
76
|
+
'x-csrf-token',
|
|
77
|
+
'x_csrf_token',
|
|
78
|
+
'set-cookie',
|
|
79
|
+
'x-api-key',
|
|
80
|
+
'proxy-authorization',
|
|
81
|
+
]);
|
|
82
|
+
const KNOWN_SAFE_FIELD_KEYS = new Set(['includesignature']);
|
|
22
83
|
const PAYLOAD_BODY_KEYS = new Set(['errorbody', 'errormessage', 'requestbody', 'responsebody', 'resultpreview']);
|
|
84
|
+
const REDACTION_LIMIT_MARKER = '[TRUNCATED: redaction budget exceeded]';
|
|
85
|
+
const MAX_REDACTION_DEPTH = 16;
|
|
86
|
+
const MAX_REDACTION_ENTRIES = 512;
|
|
87
|
+
const MAX_AUDIT_STRING_LENGTH = 500;
|
|
88
|
+
const AUDIT_STRING_PREFIX_LENGTH = 200;
|
|
89
|
+
function normalizeSafeUnicodeEscapes(value) {
|
|
90
|
+
return value.replace(/\\{1,8}u([0-9a-f]{4})/gi, (encoded, hex) => {
|
|
91
|
+
const decoded = String.fromCharCode(Number.parseInt(hex, 16));
|
|
92
|
+
return /^[a-z0-9_.-]$/i.test(decoded) ? decoded : encoded;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function canonicalKey(key) {
|
|
96
|
+
return normalizeSafeUnicodeEscapes(key)
|
|
97
|
+
.toLowerCase()
|
|
98
|
+
.replace(/[^a-z0-9]/g, '');
|
|
99
|
+
}
|
|
23
100
|
function isSensitiveKey(key) {
|
|
101
|
+
const normalized = canonicalKey(key);
|
|
102
|
+
return (!KNOWN_SAFE_FIELD_KEYS.has(normalized) && SENSITIVE_KEY_FRAGMENTS.some((fragment) => normalized.includes(fragment)));
|
|
103
|
+
}
|
|
104
|
+
function isUrlKey(key) {
|
|
105
|
+
const normalized = canonicalKey(key);
|
|
106
|
+
return ['url', 'urls', 'uri', 'uris', 'href', 'hrefs'].some((suffix) => normalized === suffix || normalized.endsWith(suffix));
|
|
107
|
+
}
|
|
108
|
+
function isSensitiveUrlQueryKey(key) {
|
|
24
109
|
const lower = key.toLowerCase();
|
|
25
|
-
return
|
|
110
|
+
return (isSensitiveKey(key) ||
|
|
111
|
+
['auth', 'credential', 'access_key', 'accesskey', 'signature'].some((fragment) => lower.includes(fragment)));
|
|
112
|
+
}
|
|
113
|
+
function redactCredentialAssignments(value) {
|
|
114
|
+
return value
|
|
115
|
+
.replace(/\bauthorization\s*([:=])\s*(?:bearer|basic)\s+(?:\\{1,64}"[^"]*\\{1,64}"|\\{1,64}'[^']*\\{1,64}'|"[^"]*"|'[^']*'|[^\s,;&<>"']+)/gi, 'authorization$1[REDACTED]')
|
|
116
|
+
.replace(/\b(bearer|basic)\s+(?:\\{1,64}"[^"]*\\{1,64}"|\\{1,64}'[^']*\\{1,64}'|"[^"]*"|'[^']*'|[^\s,;&<>"']+)/gi, '$1 [REDACTED]')
|
|
117
|
+
.replace(/\b(password|passwd|passphrase|pwd|token|secret|api[_-]?key|authorization|credential|access[_-]?key|private[_-]?key|ssh[_-]?key|signature|cookie|jsessionid|sap[_-]?sessionid|sessionid|session|(?:client[_-]?vcs[_-]?)?auth[_-]?(?:pwd|user|token)|remote[_-]?(?:password|user|token))(?:(?:\\{1,64})?["'])?\s*([:=])\s*(?:(?:bearer|basic)\s+)?(?:\\{1,64}"[^"]*\\{1,64}"|\\{1,64}'[^']*\\{1,64}'|"[^"]*"|'[^']*'|[^\s,;&<>"']+)/gi, '$1$2[REDACTED]');
|
|
118
|
+
}
|
|
119
|
+
function normalizeEscapedUrlSlashes(value) {
|
|
120
|
+
return normalizeSafeUnicodeEscapes(value.replace(/\\{1,8}\//g, '/'));
|
|
121
|
+
}
|
|
122
|
+
/** Redact query-style assignments in a query string or URL fragment, including encoded keys. */
|
|
123
|
+
function sanitizeUrlAssignments(value) {
|
|
124
|
+
return redactCredentialAssignments(value).replace(/(^|[&;])([^=&;]+)(?:=([^&;]*))?/g, (part, separator, rawKey) => {
|
|
125
|
+
let decodedKey = rawKey;
|
|
126
|
+
try {
|
|
127
|
+
decodedKey = decodeURIComponent(rawKey.replace(/\+/g, ' '));
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// Keep the raw key for the sensitivity check.
|
|
131
|
+
}
|
|
132
|
+
return isSensitiveUrlQueryKey(decodedKey) ? `${separator}[REDACTED]=[REDACTED]` : part;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function sanitizeUrl(value) {
|
|
136
|
+
const normalizedValue = normalizeEscapedUrlSlashes(value);
|
|
137
|
+
try {
|
|
138
|
+
const parsed = new URL(normalizedValue);
|
|
139
|
+
let changed = parsed.username.length > 0 || parsed.password.length > 0;
|
|
140
|
+
if (changed) {
|
|
141
|
+
parsed.username = '';
|
|
142
|
+
parsed.password = '';
|
|
143
|
+
}
|
|
144
|
+
const sanitizedPath = redactCredentialAssignments(parsed.pathname);
|
|
145
|
+
if (sanitizedPath !== parsed.pathname) {
|
|
146
|
+
parsed.pathname = sanitizedPath;
|
|
147
|
+
changed = true;
|
|
148
|
+
}
|
|
149
|
+
if (parsed.search) {
|
|
150
|
+
const sanitizedSearch = sanitizeUrlAssignments(parsed.search.slice(1));
|
|
151
|
+
if (sanitizedSearch !== parsed.search.slice(1)) {
|
|
152
|
+
parsed.search = `?${sanitizedSearch}`;
|
|
153
|
+
changed = true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (parsed.hash) {
|
|
157
|
+
const sanitizedHash = sanitizeUrlAssignments(parsed.hash.slice(1));
|
|
158
|
+
if (sanitizedHash !== parsed.hash.slice(1)) {
|
|
159
|
+
parsed.hash = `#${sanitizedHash}`;
|
|
160
|
+
changed = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return changed ? parsed.toString() : normalizedValue;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Invalid URLs are rejected later by the handler, but audit runs before validation. Apply a
|
|
167
|
+
// best-effort textual scrub so malformed userinfo/query secrets cannot escape first.
|
|
168
|
+
const withoutUserinfo = normalizedValue.replace(/^([a-z][a-z\d+.-]*:\/\/)[^/@\s]+@/i, '$1[REDACTED]@');
|
|
169
|
+
const fragmentStart = withoutUserinfo.indexOf('#');
|
|
170
|
+
const beforeFragment = fragmentStart >= 0 ? withoutUserinfo.slice(0, fragmentStart) : withoutUserinfo;
|
|
171
|
+
const fragment = fragmentStart >= 0 ? withoutUserinfo.slice(fragmentStart + 1) : undefined;
|
|
172
|
+
const queryStart = beforeFragment.indexOf('?');
|
|
173
|
+
const path = queryStart >= 0 ? beforeFragment.slice(0, queryStart) : beforeFragment;
|
|
174
|
+
const query = queryStart >= 0 ? beforeFragment.slice(queryStart + 1) : undefined;
|
|
175
|
+
return `${redactCredentialAssignments(path)}${query === undefined ? '' : `?${sanitizeUrlAssignments(query)}`}${fragment === undefined ? '' : `#${sanitizeUrlAssignments(fragment)}`}`;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function sanitizeText(value) {
|
|
179
|
+
const normalized = normalizeEscapedUrlSlashes(value);
|
|
180
|
+
return redactCredentialAssignments(normalized).replace(/https?:\/\/[^\s<>"']+/gi, (candidate) => {
|
|
181
|
+
const trailing = candidate.match(/[),.;]+$/)?.[0] ?? '';
|
|
182
|
+
const core = trailing ? candidate.slice(0, -trailing.length) : candidate;
|
|
183
|
+
return `${sanitizeUrl(core)}${trailing}`;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function boundAuditString(value, originalLength = value.length) {
|
|
187
|
+
if (value.length <= MAX_AUDIT_STRING_LENGTH && originalLength <= MAX_AUDIT_STRING_LENGTH)
|
|
188
|
+
return value;
|
|
189
|
+
return `${value.slice(0, AUDIT_STRING_PREFIX_LENGTH)}... [truncated ${originalLength} chars]`;
|
|
190
|
+
}
|
|
191
|
+
function auditStringInput(value) {
|
|
192
|
+
return value.length <= MAX_AUDIT_STRING_LENGTH ? value : value.slice(0, MAX_AUDIT_STRING_LENGTH);
|
|
193
|
+
}
|
|
194
|
+
function redactedAuditKey(entryKey, target) {
|
|
195
|
+
const normalizedEntryKey = normalizeSafeUnicodeEscapes(auditStringInput(entryKey));
|
|
196
|
+
const sensitiveKeyContainsData = isSensitiveKey(normalizedEntryKey) && !KNOWN_SENSITIVE_FIELD_KEYS.has(normalizedEntryKey.toLowerCase());
|
|
197
|
+
const sanitized = sensitiveKeyContainsData
|
|
198
|
+
? '[REDACTED sensitive key]'
|
|
199
|
+
: boundAuditString(sanitizeText(normalizedEntryKey), entryKey.length);
|
|
200
|
+
if (!Object.hasOwn(target, sanitized))
|
|
201
|
+
return sanitized;
|
|
202
|
+
let collision = 2;
|
|
203
|
+
while (Object.hasOwn(target, `[REDACTED duplicate key ${collision}]`))
|
|
204
|
+
collision += 1;
|
|
205
|
+
return `[REDACTED duplicate key ${collision}]`;
|
|
206
|
+
}
|
|
207
|
+
function setAuditEntry(target, entryKey, value) {
|
|
208
|
+
Object.defineProperty(target, redactedAuditKey(entryKey, target), {
|
|
209
|
+
value,
|
|
210
|
+
enumerable: true,
|
|
211
|
+
configurable: true,
|
|
212
|
+
writable: true,
|
|
213
|
+
});
|
|
26
214
|
}
|
|
27
215
|
function redactPayloadValue(value) {
|
|
28
216
|
if (typeof value === 'string')
|
|
29
217
|
return `[REDACTED ${value.length} chars]`;
|
|
30
218
|
return '[REDACTED]';
|
|
31
219
|
}
|
|
32
|
-
function redactValue(key, value) {
|
|
220
|
+
function redactValue(key, value, state, depth, mode) {
|
|
221
|
+
if (depth > MAX_REDACTION_DEPTH || state.remainingEntries <= 0)
|
|
222
|
+
return REDACTION_LIMIT_MARKER;
|
|
223
|
+
state.remainingEntries -= 1;
|
|
33
224
|
if (isSensitiveKey(key))
|
|
34
225
|
return '[REDACTED]';
|
|
35
|
-
if (PAYLOAD_BODY_KEYS.has(key
|
|
226
|
+
if (mode === 'audit-event' && PAYLOAD_BODY_KEYS.has(canonicalKey(key))) {
|
|
36
227
|
if (value == null)
|
|
37
228
|
return value;
|
|
38
229
|
return redactPayloadValue(value);
|
|
39
230
|
}
|
|
40
|
-
if (
|
|
41
|
-
|
|
231
|
+
if (typeof value === 'string') {
|
|
232
|
+
const boundedInput = auditStringInput(value);
|
|
233
|
+
const sanitized = isUrlKey(key) ? sanitizeUrl(boundedInput) : sanitizeText(boundedInput);
|
|
234
|
+
return boundAuditString(sanitized, value.length);
|
|
235
|
+
}
|
|
236
|
+
if (Array.isArray(value)) {
|
|
237
|
+
if (state.seen.has(value))
|
|
238
|
+
return REDACTION_LIMIT_MARKER;
|
|
239
|
+
state.seen.add(value);
|
|
240
|
+
const result = [];
|
|
241
|
+
for (const entry of value) {
|
|
242
|
+
if (state.remainingEntries <= 0) {
|
|
243
|
+
result.push(REDACTION_LIMIT_MARKER);
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
result.push(redactValue(key, entry, state, depth + 1, mode));
|
|
247
|
+
}
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
42
250
|
if (value && typeof value === 'object') {
|
|
43
|
-
|
|
251
|
+
if (state.seen.has(value))
|
|
252
|
+
return REDACTION_LIMIT_MARKER;
|
|
253
|
+
state.seen.add(value);
|
|
254
|
+
const result = {};
|
|
255
|
+
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
256
|
+
if (state.remainingEntries <= 0) {
|
|
257
|
+
setAuditEntry(result, '__truncated__', REDACTION_LIMIT_MARKER);
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
setAuditEntry(result, entryKey, redactValue(entryKey, entryValue, state, depth + 1, mode));
|
|
261
|
+
}
|
|
262
|
+
return result;
|
|
44
263
|
}
|
|
45
264
|
return value;
|
|
46
265
|
}
|
|
47
266
|
/** Redact sensitive or high-volume SAP payload fields before any audit sink sees them. */
|
|
48
267
|
export function redactAuditEvent(event) {
|
|
49
|
-
return redactValue('', event);
|
|
268
|
+
return redactValue('', event, { remainingEntries: MAX_REDACTION_ENTRIES, seen: new WeakSet() }, 0, 'audit-event');
|
|
50
269
|
}
|
|
51
|
-
/** Sanitize tool call arguments
|
|
270
|
+
/** Sanitize tool call arguments before the pre-dispatch audit event is emitted. */
|
|
52
271
|
export function sanitizeArgs(args) {
|
|
53
|
-
|
|
54
|
-
for (const [key, value] of Object.entries(args)) {
|
|
55
|
-
if (isSensitiveKey(key)) {
|
|
56
|
-
result[key] = '[REDACTED]';
|
|
57
|
-
}
|
|
58
|
-
else if (typeof value === 'string' && value.length > 500) {
|
|
59
|
-
result[key] = `${value.slice(0, 200)}... [truncated ${value.length} chars]`;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
result[key] = value;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return result;
|
|
272
|
+
return redactValue('', args, { remainingEntries: MAX_REDACTION_ENTRIES, seen: new WeakSet() }, 0, 'tool-args');
|
|
66
273
|
}
|
|
67
274
|
//# sourceMappingURL=audit.js.map
|
package/dist/server/audit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/server/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA+PH,MAAM,uBAAuB,GAAG;IAC9B,UAAU;IACV,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,eAAe;IACf,MAAM;IACN,QAAQ;IACR,SAAS;IACT,WAAW;IACX,gBAAgB;
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/server/audit.ts"],"names":[],"mappings":"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"}
|
package/dist/server/config.d.ts
CHANGED
|
@@ -17,6 +17,20 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import type { SafetyConfig } from '../adt/safety.js';
|
|
19
19
|
import type { ConfigSource, ServerConfig } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Parse metadata for configuration flags accepted by the CLI.
|
|
22
|
+
*
|
|
23
|
+
* `resolveConfig()` remains the source of truth for defaults, environment
|
|
24
|
+
* variables, precedence, and validation. This table only describes the argv
|
|
25
|
+
* grammar so Commander and the low-level resolver cannot drift apart.
|
|
26
|
+
*/
|
|
27
|
+
export interface CliConfigOptionSpec {
|
|
28
|
+
name: string;
|
|
29
|
+
valueName: string;
|
|
30
|
+
description: string;
|
|
31
|
+
valueOptional?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare const CLI_CONFIG_OPTION_SPECS: readonly CliConfigOptionSpec[];
|
|
20
34
|
/**
|
|
21
35
|
* Named API-key profiles — the safety config + scope set granted to a key
|
|
22
36
|
* with that profile name. Used by multi-key auth (`ARC1_API_KEYS=key:profile`).
|
|
@@ -38,6 +52,8 @@ export declare function parseApiKeys(raw: string): Array<{
|
|
|
38
52
|
key: string;
|
|
39
53
|
profile: string;
|
|
40
54
|
}>;
|
|
55
|
+
/** Fail with migration guidance before a strict CLI parser rejects removed flags as unknown. */
|
|
56
|
+
export declare function assertNoRemovedCliFlags(args: readonly string[]): void;
|
|
41
57
|
/**
|
|
42
58
|
* Parse CLI args + env into a `{ config, sources }` pair.
|
|
43
59
|
* `sources` records where each field's value came from (default / env / flag / file).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,KAAK,EACV,YAAY,EAGZ,YAAY,EAGb,MAAM,YAAY,CAAC;AAGpB;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,kFAAkF;IAClF,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/B;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CA2E1D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,KAAK,EACV,YAAY,EAGZ,YAAY,EAGb,MAAM,YAAY,CAAC;AAGpB;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,uBAAuB,EAAE,SAAS,mBAAmB,EAwGjE,CAAC;AAUF;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,kFAAkF;IAClF,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/B;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CA2E1D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA8BjF;AAkFD,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAMrE;AA8BD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CAAE,CA6f7G;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAEtD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CA4KzD"}
|
package/dist/server/config.js
CHANGED
|
@@ -18,6 +18,117 @@
|
|
|
18
18
|
import { parseDenyActions, validateDenyActions } from './deny-actions.js';
|
|
19
19
|
import { logger } from './logger.js';
|
|
20
20
|
import { DEFAULT_CONFIG } from './types.js';
|
|
21
|
+
export const CLI_CONFIG_OPTION_SPECS = [
|
|
22
|
+
{ name: 'url', valueName: 'url', description: 'SAP base URL' },
|
|
23
|
+
{ name: 'user', valueName: 'user', description: 'SAP username (prefer SAP_USER in CI)' },
|
|
24
|
+
{ name: 'password', valueName: 'password', description: 'SAP password (prefer SAP_PASSWORD in CI)' },
|
|
25
|
+
{ name: 'client', valueName: 'client', description: 'SAP client' },
|
|
26
|
+
{ name: 'language', valueName: 'language', description: 'SAP logon and object master language' },
|
|
27
|
+
{ name: 'insecure', valueName: 'boolean', description: 'Disable SAP TLS verification (true/false)' },
|
|
28
|
+
{
|
|
29
|
+
name: 'gzip-datapreview-body',
|
|
30
|
+
valueName: 'boolean',
|
|
31
|
+
description: 'Gzip data-preview POST bodies for WAF compatibility (true/false)',
|
|
32
|
+
},
|
|
33
|
+
{ name: 'cookie-file', valueName: 'path', description: 'Netscape-format SAP cookie file' },
|
|
34
|
+
{ name: 'cookie-string', valueName: 'cookies', description: 'SAP Cookie header value' },
|
|
35
|
+
{ name: 'transport', valueName: 'transport', description: 'MCP transport: stdio or http-streamable' },
|
|
36
|
+
{ name: 'http-addr', valueName: 'host:port', description: 'HTTP transport bind address' },
|
|
37
|
+
{ name: 'port', valueName: 'port', description: 'HTTP transport port override' },
|
|
38
|
+
{ name: 'server-name', valueName: 'name', description: 'MCP server name' },
|
|
39
|
+
{
|
|
40
|
+
name: 'ui',
|
|
41
|
+
valueName: 'mode',
|
|
42
|
+
description: 'Enable the read-only admin UI (optional: local/web/off)',
|
|
43
|
+
valueOptional: true,
|
|
44
|
+
},
|
|
45
|
+
{ name: 'ui-addr', valueName: 'host:port', description: 'Admin UI bind address' },
|
|
46
|
+
{ name: 'ui-port', valueName: 'port', description: 'Admin UI port override' },
|
|
47
|
+
{ name: 'ui-open', valueName: 'boolean', description: 'Open the local admin UI in a browser (true/false)' },
|
|
48
|
+
{ name: 'allow-writes', valueName: 'boolean', description: 'Enable SAP mutations (true/false)' },
|
|
49
|
+
{ name: 'allow-data-preview', valueName: 'boolean', description: 'Enable table data preview (true/false)' },
|
|
50
|
+
{ name: 'allow-free-sql', valueName: 'boolean', description: 'Enable freestyle SQL (true/false)' },
|
|
51
|
+
{
|
|
52
|
+
name: 'allow-transport-writes',
|
|
53
|
+
valueName: 'boolean',
|
|
54
|
+
description: 'Enable transport mutations (true/false)',
|
|
55
|
+
},
|
|
56
|
+
{ name: 'allow-git-writes', valueName: 'boolean', description: 'Enable Git mutations (true/false)' },
|
|
57
|
+
{ name: 'allowed-packages', valueName: 'patterns', description: 'Comma-separated write package allowlist' },
|
|
58
|
+
{ name: 'allowed-transports', valueName: 'ids', description: 'Comma-separated transport allowlist' },
|
|
59
|
+
{ name: 'deny-actions', valueName: 'patterns', description: 'Action deny patterns or file path' },
|
|
60
|
+
{ name: 'feature-abapgit', valueName: 'mode', description: 'abapGit feature toggle: auto/on/off' },
|
|
61
|
+
{ name: 'feature-gcts', valueName: 'mode', description: 'gCTS feature toggle: auto/on/off' },
|
|
62
|
+
{ name: 'feature-rap', valueName: 'mode', description: 'RAP feature toggle: auto/on/off' },
|
|
63
|
+
{ name: 'feature-amdp', valueName: 'mode', description: 'AMDP feature toggle: auto/on/off' },
|
|
64
|
+
{ name: 'feature-ui5', valueName: 'mode', description: 'UI5 feature toggle: auto/on/off' },
|
|
65
|
+
{ name: 'feature-transport', valueName: 'mode', description: 'Transport feature toggle: auto/on/off' },
|
|
66
|
+
{ name: 'feature-hana', valueName: 'mode', description: 'HANA feature toggle: auto/on/off' },
|
|
67
|
+
{ name: 'feature-ui5repo', valueName: 'mode', description: 'UI5 repository feature toggle: auto/on/off' },
|
|
68
|
+
{ name: 'feature-flp', valueName: 'mode', description: 'FLP feature toggle: auto/on/off' },
|
|
69
|
+
{ name: 'system-type', valueName: 'type', description: 'SAP system type: auto/btp/onprem' },
|
|
70
|
+
{ name: 'abap-release', valueName: 'release', description: 'ABAP release override for abaplint' },
|
|
71
|
+
{ name: 'api-keys', valueName: 'keys', description: 'MCP API keys (prefer ARC1_API_KEYS in CI)' },
|
|
72
|
+
{ name: 'oidc-issuer', valueName: 'url', description: 'OIDC issuer URL' },
|
|
73
|
+
{ name: 'oidc-audience', valueName: 'audience', description: 'OIDC audience' },
|
|
74
|
+
{ name: 'oidc-clock-tolerance', valueName: 'seconds', description: 'OIDC clock tolerance' },
|
|
75
|
+
{ name: 'oidc-discovery', valueName: 'boolean', description: 'Enable OIDC discovery (true/false)' },
|
|
76
|
+
{ name: 'oidc-scopes', valueName: 'scopes', description: 'OIDC scopes' },
|
|
77
|
+
{ name: 'xsuaa-auth', valueName: 'boolean', description: 'Enable XSUAA MCP authentication (true/false)' },
|
|
78
|
+
{ name: 'allow-http-no-auth', valueName: 'boolean', description: 'Allow unauthenticated HTTP MCP (true/false)' },
|
|
79
|
+
{ name: 'oauth-dcr-ttl-seconds', valueName: 'seconds', description: 'OAuth DCR client lifetime' },
|
|
80
|
+
{ name: 'dcr-signing-secret', valueName: 'secret', description: 'OAuth DCR signing secret' },
|
|
81
|
+
{ name: 'btp-service-key', valueName: 'json', description: 'BTP ABAP service-key JSON' },
|
|
82
|
+
{ name: 'btp-service-key-file', valueName: 'path', description: 'BTP ABAP service-key file' },
|
|
83
|
+
{ name: 'btp-oauth-callback-port', valueName: 'port', description: 'BTP OAuth callback port' },
|
|
84
|
+
{ name: 'multi-target-endpoints', valueName: 'boolean', description: 'Enable multi-target endpoints (true/false)' },
|
|
85
|
+
{
|
|
86
|
+
name: 'multi-target-allow-basic-auth',
|
|
87
|
+
valueName: 'boolean',
|
|
88
|
+
description: 'Allow shared Basic multi-target identity (true/false)',
|
|
89
|
+
},
|
|
90
|
+
{ name: 'pp-enabled', valueName: 'boolean', description: 'Enable principal propagation (true/false)' },
|
|
91
|
+
{ name: 'pp-strict', valueName: 'boolean', description: 'Require principal propagation (true/false)' },
|
|
92
|
+
{
|
|
93
|
+
name: 'pp-allow-shared-cookies',
|
|
94
|
+
valueName: 'boolean',
|
|
95
|
+
description: 'Allow shared cookies beside principal propagation (true/false)',
|
|
96
|
+
},
|
|
97
|
+
{ name: 'disable-saml', valueName: 'boolean', description: 'Disable SAP SAML redirects (true/false)' },
|
|
98
|
+
{ name: 'tool-mode', valueName: 'mode', description: 'Tool mode: standard or hyperfocused' },
|
|
99
|
+
{
|
|
100
|
+
name: 'schema-nullable-optionals',
|
|
101
|
+
valueName: 'mode',
|
|
102
|
+
description: 'Optional-schema null mode: auto/on/off',
|
|
103
|
+
},
|
|
104
|
+
{ name: 'plugins', valueName: 'paths', description: 'Comma-separated extension paths' },
|
|
105
|
+
{ name: 'allow-plugin-execute', valueName: 'boolean', description: 'Enable plugin class execution (true/false)' },
|
|
106
|
+
{
|
|
107
|
+
name: 'allow-plugin-raw-writes',
|
|
108
|
+
valueName: 'boolean',
|
|
109
|
+
description: 'Enable plugin non-ADT writes (true/false)',
|
|
110
|
+
},
|
|
111
|
+
{ name: 'abaplint-config', valueName: 'path', description: 'Custom abaplint configuration file' },
|
|
112
|
+
{ name: 'lint-before-write', valueName: 'boolean', description: 'Lint before source writes (true/false)' },
|
|
113
|
+
{ name: 'check-before-write', valueName: 'boolean', description: 'Run SAP syntax check before writes (true/false)' },
|
|
114
|
+
{ name: 'cache', valueName: 'mode', description: 'Cache mode: auto/memory/sqlite/none' },
|
|
115
|
+
{ name: 'cache-file', valueName: 'path', description: 'SQLite cache file' },
|
|
116
|
+
{ name: 'max-concurrent', valueName: 'count', description: 'Maximum concurrent SAP requests' },
|
|
117
|
+
{ name: 'auth-rate-limit', valueName: 'per-minute', description: 'OAuth requests per IP per minute' },
|
|
118
|
+
{ name: 'rate-limit', valueName: 'per-minute', description: 'MCP calls per user per minute' },
|
|
119
|
+
{ name: 'allowed-origins', valueName: 'origins', description: 'Comma-separated browser CORS origins' },
|
|
120
|
+
{ name: 'log-file', valueName: 'path', description: 'Audit/log output file' },
|
|
121
|
+
{ name: 'log-level', valueName: 'level', description: 'Log level: debug/info/warn/error' },
|
|
122
|
+
{ name: 'log-format', valueName: 'format', description: 'Log format: text or json' },
|
|
123
|
+
{ name: 'minimal-errors', valueName: 'boolean', description: 'Hide SAP diagnostic details (true/false)' },
|
|
124
|
+
{ name: 'verbose', valueName: 'boolean', description: 'Enable verbose logging (true/false)' },
|
|
125
|
+
];
|
|
126
|
+
const CLI_CONFIG_OPTION_NAMES = new Set(CLI_CONFIG_OPTION_SPECS.map((spec) => spec.name));
|
|
127
|
+
function assertRegisteredCliConfigOption(name) {
|
|
128
|
+
if (!CLI_CONFIG_OPTION_NAMES.has(name)) {
|
|
129
|
+
throw new Error(`Internal configuration error: CLI flag --${name} is not registered`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
21
132
|
export const API_KEY_PROFILES = {
|
|
22
133
|
viewer: {
|
|
23
134
|
scopes: ['read'],
|
|
@@ -100,22 +211,24 @@ export const API_KEY_PROFILES = {
|
|
|
100
211
|
*/
|
|
101
212
|
export function parseApiKeys(raw) {
|
|
102
213
|
const entries = [];
|
|
103
|
-
|
|
214
|
+
const validProfiles = Object.keys(API_KEY_PROFILES).join(', ');
|
|
215
|
+
const invalidEntry = (position) => new Error(`Invalid API key entry at position ${position}: expected a non-empty key and valid profile in 'key:profile' format. ` +
|
|
216
|
+
`Valid profiles: ${validProfiles}`);
|
|
217
|
+
for (const [index, pair] of raw.split(',').entries()) {
|
|
104
218
|
const trimmed = pair.trim();
|
|
105
219
|
if (!trimmed)
|
|
106
220
|
continue;
|
|
107
221
|
const colonIdx = trimmed.lastIndexOf(':');
|
|
108
222
|
if (colonIdx === -1) {
|
|
109
|
-
throw
|
|
110
|
-
`Valid profiles: ${Object.keys(API_KEY_PROFILES).join(', ')}`);
|
|
223
|
+
throw invalidEntry(index + 1);
|
|
111
224
|
}
|
|
112
225
|
const key = trimmed.slice(0, colonIdx);
|
|
113
226
|
const profile = trimmed.slice(colonIdx + 1);
|
|
114
227
|
if (!key) {
|
|
115
|
-
throw
|
|
228
|
+
throw invalidEntry(index + 1);
|
|
116
229
|
}
|
|
117
230
|
if (!API_KEY_PROFILES[profile]) {
|
|
118
|
-
throw
|
|
231
|
+
throw invalidEntry(index + 1);
|
|
119
232
|
}
|
|
120
233
|
entries.push({ key, profile });
|
|
121
234
|
}
|
|
@@ -177,6 +290,26 @@ const RETIRED_CLI_FLAGS = {
|
|
|
177
290
|
'cache-warmup': RETIRED_ENV_VARS.ARC1_CACHE_WARMUP,
|
|
178
291
|
'cache-warmup-packages': RETIRED_ENV_VARS.ARC1_CACHE_WARMUP_PACKAGES,
|
|
179
292
|
};
|
|
293
|
+
function cliFlagViolations(args, flags) {
|
|
294
|
+
return Object.entries(flags)
|
|
295
|
+
.filter(([flag]) => args.some((arg) => arg === `--${flag}` || arg.startsWith(`--${flag}=`)))
|
|
296
|
+
.map(([flag, hint]) => ` --${flag}: ${hint}`);
|
|
297
|
+
}
|
|
298
|
+
function legacyConfigError(violations) {
|
|
299
|
+
return new Error(`Legacy authorization config detected (removed in v0.7):\n${violations.join('\n')}\n\nSee docs_page/updating.md#v07-authorization-refactor-breaking-change for the full migration guide.`);
|
|
300
|
+
}
|
|
301
|
+
function retiredConfigError(violations) {
|
|
302
|
+
return new Error(`Removed ARC-1 configuration detected:\n${violations.join('\n')}\n\nSee docs_page/updating.md for migration details.`);
|
|
303
|
+
}
|
|
304
|
+
/** Fail with migration guidance before a strict CLI parser rejects removed flags as unknown. */
|
|
305
|
+
export function assertNoRemovedCliFlags(args) {
|
|
306
|
+
const legacyViolations = cliFlagViolations(args, LEGACY_CLI_FLAGS);
|
|
307
|
+
if (legacyViolations.length > 0)
|
|
308
|
+
throw legacyConfigError(legacyViolations);
|
|
309
|
+
const retiredViolations = cliFlagViolations(args, RETIRED_CLI_FLAGS);
|
|
310
|
+
if (retiredViolations.length > 0)
|
|
311
|
+
throw retiredConfigError(retiredViolations);
|
|
312
|
+
}
|
|
180
313
|
/** Migration guard — throws a helpful error if any legacy identifier is set. */
|
|
181
314
|
function detectLegacyConfig(args) {
|
|
182
315
|
const violations = [];
|
|
@@ -185,13 +318,9 @@ function detectLegacyConfig(args) {
|
|
|
185
318
|
violations.push(` ${env}: ${LEGACY_ENV_VARS[env]}`);
|
|
186
319
|
}
|
|
187
320
|
}
|
|
188
|
-
|
|
189
|
-
if (args.some((a) => a === `--${flag}` || a.startsWith(`--${flag}=`))) {
|
|
190
|
-
violations.push(` --${flag}: ${LEGACY_CLI_FLAGS[flag]}`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
321
|
+
violations.push(...cliFlagViolations(args, LEGACY_CLI_FLAGS));
|
|
193
322
|
if (violations.length > 0) {
|
|
194
|
-
throw
|
|
323
|
+
throw legacyConfigError(violations);
|
|
195
324
|
}
|
|
196
325
|
}
|
|
197
326
|
function detectRetiredConfig(args) {
|
|
@@ -200,13 +329,9 @@ function detectRetiredConfig(args) {
|
|
|
200
329
|
if (process.env[env] !== undefined)
|
|
201
330
|
violations.push(` ${env}: ${RETIRED_ENV_VARS[env]}`);
|
|
202
331
|
}
|
|
203
|
-
|
|
204
|
-
if (args.some((arg) => arg === `--${flag}` || arg.startsWith(`--${flag}=`))) {
|
|
205
|
-
violations.push(` --${flag}: ${RETIRED_CLI_FLAGS[flag]}`);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
332
|
+
violations.push(...cliFlagViolations(args, RETIRED_CLI_FLAGS));
|
|
208
333
|
if (violations.length > 0) {
|
|
209
|
-
throw
|
|
334
|
+
throw retiredConfigError(violations);
|
|
210
335
|
}
|
|
211
336
|
}
|
|
212
337
|
/**
|
|
@@ -221,6 +346,7 @@ export function resolveConfig(args) {
|
|
|
221
346
|
const sources = {};
|
|
222
347
|
// ── Resolvers ──────────────────────────────────────────────────────
|
|
223
348
|
const getFlag = (name) => {
|
|
349
|
+
assertRegisteredCliConfigOption(name);
|
|
224
350
|
const prefix = `--${name}=`;
|
|
225
351
|
for (let i = 0; i < args.length; i++) {
|
|
226
352
|
if (args[i] === `--${name}` && i + 1 < args.length)
|
|
@@ -231,6 +357,7 @@ export function resolveConfig(args) {
|
|
|
231
357
|
return undefined;
|
|
232
358
|
};
|
|
233
359
|
const getOptionalFlagValue = (name) => {
|
|
360
|
+
assertRegisteredCliConfigOption(name);
|
|
234
361
|
const prefix = `--${name}=`;
|
|
235
362
|
for (let i = 0; i < args.length; i++) {
|
|
236
363
|
if (args[i] === `--${name}`) {
|
|
@@ -311,6 +438,7 @@ export function resolveConfig(args) {
|
|
|
311
438
|
config.client = resolveStr('client', 'SAP_CLIENT', '100', 'client');
|
|
312
439
|
config.language = resolveStr('language', 'SAP_LANGUAGE', 'EN', 'language');
|
|
313
440
|
config.insecure = resolveBool('insecure', 'SAP_INSECURE', false, 'insecure');
|
|
441
|
+
config.gzipDataPreviewBody = resolveBool('gzip-datapreview-body', 'SAP_GZIP_DATAPREVIEW_BODY', false, 'gzipDataPreviewBody');
|
|
314
442
|
// ── Cookie Auth ────────────────────────────────────────────────────
|
|
315
443
|
config.cookieFile = resolveOptionalStr('cookie-file', 'SAP_COOKIE_FILE', 'cookieFile');
|
|
316
444
|
config.cookieString = resolveOptionalStr('cookie-string', 'SAP_COOKIE_STRING', 'cookieString');
|