@skillsmith/core 0.8.1 → 0.9.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/CHANGELOG.md +10 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/config/device-identity.d.ts +113 -0
- package/dist/src/config/device-identity.d.ts.map +1 -0
- package/dist/src/config/device-identity.js +171 -0
- package/dist/src/config/device-identity.js.map +1 -0
- package/dist/src/config/device-identity.test.d.ts +10 -0
- package/dist/src/config/device-identity.test.d.ts.map +1 -0
- package/dist/src/config/device-identity.test.js +213 -0
- package/dist/src/config/device-identity.test.js.map +1 -0
- package/dist/src/config/index.d.ts +9 -0
- package/dist/src/config/index.d.ts.map +1 -1
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/exports/services.d.ts +1 -1
- package/dist/src/exports/services.d.ts.map +1 -1
- package/dist/src/exports/services.js +5 -1
- package/dist/src/exports/services.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/install/index.d.ts +1 -1
- package/dist/src/install/index.d.ts.map +1 -1
- package/dist/src/install/index.js +1 -1
- package/dist/src/install/index.js.map +1 -1
- package/dist/src/install/paths.d.ts +16 -0
- package/dist/src/install/paths.d.ts.map +1 -1
- package/dist/src/install/paths.js +22 -0
- package/dist/src/install/paths.js.map +1 -1
- package/dist/src/install/paths.test.d.ts +2 -0
- package/dist/src/install/paths.test.d.ts.map +1 -0
- package/dist/src/install/paths.test.js +61 -0
- package/dist/src/install/paths.test.js.map +1 -0
- package/dist/src/provenance/SourceRecoveryService.d.ts +17 -4
- package/dist/src/provenance/SourceRecoveryService.d.ts.map +1 -1
- package/dist/src/provenance/SourceRecoveryService.js +37 -10
- package/dist/src/provenance/SourceRecoveryService.js.map +1 -1
- package/dist/src/provenance/index.d.ts +1 -0
- package/dist/src/provenance/index.d.ts.map +1 -1
- package/dist/src/provenance/index.js +1 -0
- package/dist/src/provenance/index.js.map +1 -1
- package/dist/src/provenance/name-variants.d.ts +32 -0
- package/dist/src/provenance/name-variants.d.ts.map +1 -0
- package/dist/src/provenance/name-variants.js +59 -0
- package/dist/src/provenance/name-variants.js.map +1 -0
- package/dist/src/provenance/types.d.ts +12 -0
- package/dist/src/provenance/types.d.ts.map +1 -1
- package/dist/src/provenance/types.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.scanners.d.ts +10 -0
- package/dist/src/security/scanner/SecurityScanner.scanners.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.scanners.js +68 -1
- package/dist/src/security/scanner/SecurityScanner.scanners.js.map +1 -1
- package/dist/src/sync/index.d.ts +6 -0
- package/dist/src/sync/index.d.ts.map +1 -1
- package/dist/src/sync/index.js +8 -0
- package/dist/src/sync/index.js.map +1 -1
- package/dist/src/sync/inventory-builder.d.ts +21 -0
- package/dist/src/sync/inventory-builder.d.ts.map +1 -0
- package/dist/src/sync/inventory-builder.js +26 -0
- package/dist/src/sync/inventory-builder.js.map +1 -0
- package/dist/src/sync/inventory-client.d.ts +64 -0
- package/dist/src/sync/inventory-client.d.ts.map +1 -0
- package/dist/src/sync/inventory-client.js +150 -0
- package/dist/src/sync/inventory-client.js.map +1 -0
- package/dist/src/sync/inventory-client.test.d.ts +14 -0
- package/dist/src/sync/inventory-client.test.d.ts.map +1 -0
- package/dist/src/sync/inventory-client.test.js +146 -0
- package/dist/src/sync/inventory-client.test.js.map +1 -0
- package/dist/src/sync/inventory-collector.d.ts +35 -0
- package/dist/src/sync/inventory-collector.d.ts.map +1 -0
- package/dist/src/sync/inventory-collector.js +149 -0
- package/dist/src/sync/inventory-collector.js.map +1 -0
- package/dist/src/sync/inventory-collector.test.d.ts +14 -0
- package/dist/src/sync/inventory-collector.test.d.ts.map +1 -0
- package/dist/src/sync/inventory-collector.test.js +107 -0
- package/dist/src/sync/inventory-collector.test.js.map +1 -0
- package/dist/src/sync/inventory-device.d.ts +36 -0
- package/dist/src/sync/inventory-device.d.ts.map +1 -0
- package/dist/src/sync/inventory-device.js +58 -0
- package/dist/src/sync/inventory-device.js.map +1 -0
- package/dist/src/sync/inventory-push.d.ts +45 -0
- package/dist/src/sync/inventory-push.d.ts.map +1 -0
- package/dist/src/sync/inventory-push.js +62 -0
- package/dist/src/sync/inventory-push.js.map +1 -0
- package/dist/src/sync/inventory-push.test.d.ts +16 -0
- package/dist/src/sync/inventory-push.test.d.ts.map +1 -0
- package/dist/src/sync/inventory-push.test.js +104 -0
- package/dist/src/sync/inventory-push.test.js.map +1 -0
- package/dist/src/sync/inventory-types.d.ts +101 -0
- package/dist/src/sync/inventory-types.d.ts.map +1 -0
- package/dist/src/sync/inventory-types.js +42 -0
- package/dist/src/sync/inventory-types.js.map +1 -0
- package/dist/tests/provenance/SourceRecoveryService.test.js +73 -0
- package/dist/tests/provenance/SourceRecoveryService.test.js.map +1 -1
- package/dist/tests/provenance/backfill.test.js +18 -0
- package/dist/tests/provenance/backfill.test.js.map +1 -1
- package/dist/tests/provenance/name-variants.test.d.ts +2 -0
- package/dist/tests/provenance/name-variants.test.d.ts.map +1 -0
- package/dist/tests/provenance/name-variants.test.js +51 -0
- package/dist/tests/provenance/name-variants.test.js.map +1 -0
- package/dist/tests/security/pii-detection.test.js +107 -0
- package/dist/tests/security/pii-detection.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,6 +17,16 @@ export declare function scanSocialEngineering(content: string, lineContexts?: Li
|
|
|
17
17
|
export declare function scanPromptLeaking(content: string, lineContexts?: LineContext[]): SecurityFinding[];
|
|
18
18
|
export declare function scanDataExfiltration(content: string, lineContexts?: LineContext[]): SecurityFinding[];
|
|
19
19
|
export declare function scanPrivilegeEscalation(content: string, lineContexts?: LineContext[]): SecurityFinding[];
|
|
20
|
+
/** SMI-5420: Shannon entropy (bits per character) of a string. */
|
|
21
|
+
export declare function shannonEntropy(s: string): number;
|
|
22
|
+
/**
|
|
23
|
+
* SMI-5420: a credential match is a documentation placeholder (not a real leaked
|
|
24
|
+
* secret) when it carries a named placeholder marker, is a single repeated
|
|
25
|
+
* character, or its value has sub-secret Shannon entropy. Such matches must NOT
|
|
26
|
+
* emit critical/high severity — the batch trust-scorer (trust-scorer.ts) and the
|
|
27
|
+
* install gate quarantine on severity, so an example secret would falsely flag.
|
|
28
|
+
*/
|
|
29
|
+
export declare function looksLikePlaceholderSecret(match: string): boolean;
|
|
20
30
|
/** SMI-3864: Detect PII patterns. Email in YAML frontmatter gets low severity. */
|
|
21
31
|
export declare function scanPiiPatterns(content: string, lineContexts?: LineContext[]): SecurityFinding[];
|
|
22
32
|
//# sourceMappingURL=SecurityScanner.scanners.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecurityScanner.scanners.d.ts","sourceRoot":"","sources":["../../../../src/security/scanner/SecurityScanner.scanners.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,YAAY,CAAA;AAUpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAO/D,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CA+BnB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CAgCnB;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CAgCnB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CAgCnB;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CAgCnB;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,WAAW,EAAE,GAAG,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"SecurityScanner.scanners.d.ts","sourceRoot":"","sources":["../../../../src/security/scanner/SecurityScanner.scanners.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,YAAY,CAAA;AAUpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAO/D,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CA+BnB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CAgCnB;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CAgCnB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CAgCnB;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CAgCnB;AAwBD,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAUhD;AAaD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAMjE;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,WAAW,EAAE,GAAG,eAAe,EAAE,CAuDhG"}
|
|
@@ -157,6 +157,65 @@ export function scanPrivilegeEscalation(content, lineContexts) {
|
|
|
157
157
|
});
|
|
158
158
|
return findings;
|
|
159
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* SMI-5420: credential PII pattern indices (api/secret/access key, provider
|
|
162
|
+
* tokens, password) whose matched VALUE can be a documentation placeholder.
|
|
163
|
+
* Excludes email (7), SSN (8), and the private-key marker (9) — those have no
|
|
164
|
+
* placeholder-secret failure mode.
|
|
165
|
+
*/
|
|
166
|
+
const CREDENTIAL_PII_INDICES = new Set([0, 1, 2, 3, 4, 5, 6, 10]);
|
|
167
|
+
/**
|
|
168
|
+
* SMI-5420: named-placeholder markers that indicate an example, not a real
|
|
169
|
+
* secret. Intentionally NO `X{4,}` rule — it would test the raw match string and
|
|
170
|
+
* short-circuit before the entropy check, downgrading a REAL high-entropy secret
|
|
171
|
+
* that coincidentally contains `xxxx` (governance FN). An all-repeated-char value
|
|
172
|
+
* (e.g. `xxxx…`) is caught by the `/^(.)\1+$/` check in looksLikePlaceholderSecret
|
|
173
|
+
* instead, and partial-repeat low-variety values by the entropy floor.
|
|
174
|
+
*/
|
|
175
|
+
const PLACEHOLDER_SECRET_RE = /EXAMPLE|YOUR[_-]?|PLACEHOLDER|CHANGE[_-]?ME|DUMMY|FAKE|SAMPLE|REDACTED|INSERT[_-]|\.\.\.|<[^>]+>/i;
|
|
176
|
+
/** SMI-5420: minimum Shannon entropy (bits/char) for a value to read as a real secret. */
|
|
177
|
+
const SECRET_ENTROPY_FLOOR = 3.0;
|
|
178
|
+
/** SMI-5420: Shannon entropy (bits per character) of a string. */
|
|
179
|
+
export function shannonEntropy(s) {
|
|
180
|
+
if (!s)
|
|
181
|
+
return 0;
|
|
182
|
+
const freq = new Map();
|
|
183
|
+
for (const ch of s)
|
|
184
|
+
freq.set(ch, (freq.get(ch) ?? 0) + 1);
|
|
185
|
+
let h = 0;
|
|
186
|
+
for (const c of freq.values()) {
|
|
187
|
+
const p = c / s.length;
|
|
188
|
+
h -= p * Math.log2(p);
|
|
189
|
+
}
|
|
190
|
+
return h;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* SMI-5420: extract the secret token from a credential match by stripping a
|
|
194
|
+
* leading `<key>:`/`<key>=` assignment prefix and surrounding quotes.
|
|
195
|
+
*/
|
|
196
|
+
function extractSecretValue(match) {
|
|
197
|
+
return match
|
|
198
|
+
.replace(/^[^:=]*[:=]\s*/, '')
|
|
199
|
+
.replace(/^['"]|['"]$/g, '')
|
|
200
|
+
.trim();
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* SMI-5420: a credential match is a documentation placeholder (not a real leaked
|
|
204
|
+
* secret) when it carries a named placeholder marker, is a single repeated
|
|
205
|
+
* character, or its value has sub-secret Shannon entropy. Such matches must NOT
|
|
206
|
+
* emit critical/high severity — the batch trust-scorer (trust-scorer.ts) and the
|
|
207
|
+
* install gate quarantine on severity, so an example secret would falsely flag.
|
|
208
|
+
*/
|
|
209
|
+
export function looksLikePlaceholderSecret(match) {
|
|
210
|
+
if (PLACEHOLDER_SECRET_RE.test(match))
|
|
211
|
+
return true;
|
|
212
|
+
const value = extractSecretValue(match);
|
|
213
|
+
if (value.length === 0)
|
|
214
|
+
return false;
|
|
215
|
+
if (/^(.)\1+$/.test(value))
|
|
216
|
+
return true;
|
|
217
|
+
return shannonEntropy(value) < SECRET_ENTROPY_FLOOR;
|
|
218
|
+
}
|
|
160
219
|
/** SMI-3864: Detect PII patterns. Email in YAML frontmatter gets low severity. */
|
|
161
220
|
export function scanPiiPatterns(content, lineContexts) {
|
|
162
221
|
const findings = [];
|
|
@@ -193,7 +252,15 @@ export function scanPiiPatterns(content, lineContexts) {
|
|
|
193
252
|
severity = 'critical';
|
|
194
253
|
else
|
|
195
254
|
severity = 'high';
|
|
196
|
-
|
|
255
|
+
let confidence = inDocContext || inEmailSafeContext ? 'low' : 'high';
|
|
256
|
+
// SMI-5420: a credential match that reads as a documentation placeholder
|
|
257
|
+
// (named placeholder, repeated char, or low entropy) must not emit
|
|
258
|
+
// critical/high — the batch trust-scorer quarantines on severity, so an
|
|
259
|
+
// example secret like `api_key: "YOUR_API_KEY_HERE"` would falsely flag.
|
|
260
|
+
if (CREDENTIAL_PII_INDICES.has(pi) && looksLikePlaceholderSecret(match[0])) {
|
|
261
|
+
severity = 'low';
|
|
262
|
+
confidence = 'low';
|
|
263
|
+
}
|
|
197
264
|
findings.push({
|
|
198
265
|
type: 'pii',
|
|
199
266
|
severity,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecurityScanner.scanners.js","sourceRoot":"","sources":["../../../../src/security/scanner/SecurityScanner.scanners.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EACL,uBAAuB,EACvB,2BAA2B,EAC3B,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,YAAY,GACb,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEhE,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,8BAA8B,CAAA;AAErC,MAAM,UAAU,kBAAkB,CAChC,OAAe,EACf,YAA4B;IAE5B,MAAM,QAAQ,GAAsB,EAAE,CAAA;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,QAAQ,GAAG,YAAY,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAEhE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;QAE3B,KAAK,MAAM,OAAO,IAAI,uBAAuB,EAAE,CAAC;YAC9C,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;gBAClC,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;gBAC1C,MAAM,YAAY,GAAG,GAAG,EAAE,YAAY,IAAI,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC,CAAC,CAAA;gBACrF,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,CAAA;gBAC9E,MAAM,UAAU,GAAsB,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;gBACnE,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAA;gBAEjD,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,gBAAgB;oBACtB,QAAQ;oBACR,OAAO,EAAE,4CAA4C,OAAO,CAAC,MAAM,EAAE;oBACrE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;oBACnC,UAAU,EAAE,KAAK,GAAG,CAAC;oBACrB,sBAAsB,EAAE,YAAY;oBACpC,UAAU;iBACX,CAAC,CAAA;gBACF,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,YAA4B;IAE5B,MAAM,QAAQ,GAAsB,EAAE,CAAA;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,QAAQ,GAAG,YAAY,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAEhE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;QAE3B,KAAK,MAAM,OAAO,IAAI,2BAA2B,EAAE,CAAC;YAClD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC1C,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,YAAY,GAAG,GAAG,EAAE,YAAY,IAAI,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAA;gBACpF,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,CAAA;gBAC9E,MAAM,UAAU,GAAsB,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;gBACnE,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAA;gBAEjD,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,oBAAoB;oBAC1B,QAAQ;oBACR,OAAO,EAAE,yCAAyC,KAAK,CAAC,CAAC,CAAC,GAAG;oBAC7D,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;oBACnC,UAAU,EAAE,KAAK,GAAG,CAAC;oBACrB,QAAQ,EAAE,oBAAoB;oBAC9B,sBAAsB,EAAE,YAAY;oBACpC,UAAU;iBACX,CAAC,CAAA;gBACF,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,YAA4B;IAE5B,MAAM,QAAQ,GAAsB,EAAE,CAAA;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,QAAQ,GAAG,YAAY,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAEhE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;QAE3B,KAAK,MAAM,OAAO,IAAI,uBAAuB,EAAE,CAAC;YAC9C,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC1C,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,YAAY,GAAG,GAAG,EAAE,YAAY,IAAI,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAA;gBACpF,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,CAAA;gBAC9E,MAAM,UAAU,GAAsB,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;gBACnE,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAA;gBAEnD,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,gBAAgB;oBACtB,QAAQ;oBACR,OAAO,EAAE,qCAAqC,KAAK,CAAC,CAAC,CAAC,GAAG;oBACzD,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;oBACnC,UAAU,EAAE,KAAK,GAAG,CAAC;oBACrB,QAAQ,EAAE,gBAAgB;oBAC1B,sBAAsB,EAAE,YAAY;oBACpC,UAAU;iBACX,CAAC,CAAA;gBACF,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,YAA4B;IAE5B,MAAM,QAAQ,GAAsB,EAAE,CAAA;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,QAAQ,GAAG,YAAY,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAEhE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;QAE3B,KAAK,MAAM,OAAO,IAAI,0BAA0B,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC1C,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,YAAY,GAAG,GAAG,EAAE,YAAY,IAAI,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAA;gBACpF,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,CAAA;gBAC9E,MAAM,UAAU,GAAsB,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;gBACnE,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAA;gBAEjD,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,mBAAmB;oBACzB,QAAQ;oBACR,OAAO,EAAE,yCAAyC,KAAK,CAAC,CAAC,CAAC,GAAG;oBAC7D,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;oBACnC,UAAU,EAAE,KAAK,GAAG,CAAC;oBACrB,QAAQ,EAAE,mBAAmB;oBAC7B,sBAAsB,EAAE,YAAY;oBACpC,UAAU;iBACX,CAAC,CAAA;gBACF,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,OAAe,EACf,YAA4B;IAE5B,MAAM,QAAQ,GAAsB,EAAE,CAAA;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,QAAQ,GAAG,YAAY,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAEhE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;QAE3B,KAAK,MAAM,OAAO,IAAI,6BAA6B,EAAE,CAAC;YACpD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC1C,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,YAAY,GAAG,GAAG,EAAE,YAAY,IAAI,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAA;gBACpF,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,CAAA;gBAC9E,MAAM,UAAU,GAAsB,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;gBACnE,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAA;gBAEnD,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,sBAAsB;oBAC5B,QAAQ;oBACR,OAAO,EAAE,2CAA2C,KAAK,CAAC,CAAC,CAAC,GAAG;oBAC/D,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;oBACnC,UAAU,EAAE,KAAK,GAAG,CAAC;oBACrB,QAAQ,EAAE,sBAAsB;oBAChC,sBAAsB,EAAE,YAAY;oBACpC,UAAU;iBACX,CAAC,CAAA;gBACF,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,YAA4B;IAC3E,MAAM,QAAQ,GAAsB,EAAE,CAAA;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,QAAQ,GAAG,YAAY,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAChE,IAAI,cAAc,GAAG,CAAC,CAAC,CAAA;IACvB,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;gBAC9B,cAAc,GAAG,CAAC,CAAA;gBAClB,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,iBAAiB,GAAG,CAAC,CAAA;IAC3B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC3B,MAAM,aAAa,GAAG,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,cAAc,CAAA;QACzD,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;YAChD,MAAM,OAAO,GAAG,YAAY,CAAC,EAAE,CAAC,CAAA;YAChC,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAC1C,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,YAAY,GAAG,GAAG,EAAE,YAAY,IAAI,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAA;gBACpF,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,CAAA;gBAC9E,MAAM,cAAc,GAAG,EAAE,KAAK,iBAAiB,CAAA;gBAC/C,MAAM,YAAY,GAAG,2CAA2C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAC3E,MAAM,kBAAkB,GAAG,cAAc,IAAI,CAAC,aAAa,IAAI,YAAY,CAAC,CAAA;gBAC5E,IAAI,QAAgD,CAAA;gBACpD,IAAI,kBAAkB;oBAAE,QAAQ,GAAG,KAAK,CAAA;qBACnC,IAAI,YAAY;oBAAE,QAAQ,GAAG,QAAQ,CAAA;qBACrC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;oBAAE,QAAQ,GAAG,UAAU,CAAA;;oBAC9C,QAAQ,GAAG,MAAM,CAAA;gBACtB,
|
|
1
|
+
{"version":3,"file":"SecurityScanner.scanners.js","sourceRoot":"","sources":["../../../../src/security/scanner/SecurityScanner.scanners.ts"],"names":[],"mappings":"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"}
|
package/dist/src/sync/index.d.ts
CHANGED
|
@@ -8,4 +8,10 @@ export { SyncConfigRepository, type SyncConfig, type SyncConfigUpdate, type Sync
|
|
|
8
8
|
export { SyncHistoryRepository, type SyncHistoryEntry, type SyncStatus, type SyncRunResult, } from '../repositories/SyncHistoryRepository.js';
|
|
9
9
|
export { SyncEngine, type SyncOptions, type SyncProgress, type SyncResult } from './SyncEngine.js';
|
|
10
10
|
export { BackgroundSyncService, createBackgroundSyncService, type BackgroundSyncOptions, type BackgroundSyncState, } from './BackgroundSyncService.js';
|
|
11
|
+
export { INVENTORY_LIMITS, INVENTORY_UPDATE_POLICIES, type InventoryDevice, type InventorySkillEntry, type InventoryUpdatePolicy, type InventoryUploadPayload, type InventoryUploadResult, } from './inventory-types.js';
|
|
12
|
+
export { collectDeviceSkills } from './inventory-collector.js';
|
|
13
|
+
export { buildInventoryDevice, type BuildInventoryDeviceOptions } from './inventory-device.js';
|
|
14
|
+
export { buildInventoryPayload } from './inventory-builder.js';
|
|
15
|
+
export { uploadInventory, InventoryAuthError, InventoryConflictError, InventoryValidationError, InventoryUploadError, } from './inventory-client.js';
|
|
16
|
+
export { pushInventory, maybeAutoPush, type PushInventoryOptions, type MaybeAutoPushOptions, } from './inventory-push.js';
|
|
11
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,oBAAoB,EACpB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,mBAAmB,GACpB,MAAM,yCAAyC,CAAA;AAEhD,OAAO,EACL,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,0CAA0C,CAAA;AAGjD,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAGlG,OAAO,EACL,qBAAqB,EACrB,2BAA2B,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,oBAAoB,EACpB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,mBAAmB,GACpB,MAAM,yCAAyC,CAAA;AAEhD,OAAO,EACL,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,0CAA0C,CAAA;AAGjD,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAGlG,OAAO,EACL,qBAAqB,EACrB,2BAA2B,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EACzB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAC9F,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAC9D,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,aAAa,EACb,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAA"}
|
package/dist/src/sync/index.js
CHANGED
|
@@ -11,4 +11,12 @@ export { SyncHistoryRepository, } from '../repositories/SyncHistoryRepository.js
|
|
|
11
11
|
export { SyncEngine } from './SyncEngine.js';
|
|
12
12
|
// Background service
|
|
13
13
|
export { BackgroundSyncService, createBackgroundSyncService, } from './BackgroundSyncService.js';
|
|
14
|
+
// Cross-harness inventory payload contract (SMI-5389)
|
|
15
|
+
export { INVENTORY_LIMITS, INVENTORY_UPDATE_POLICIES, } from './inventory-types.js';
|
|
16
|
+
// Cross-harness inventory service — shared local agent (SMI-5392)
|
|
17
|
+
export { collectDeviceSkills } from './inventory-collector.js';
|
|
18
|
+
export { buildInventoryDevice } from './inventory-device.js';
|
|
19
|
+
export { buildInventoryPayload } from './inventory-builder.js';
|
|
20
|
+
export { uploadInventory, InventoryAuthError, InventoryConflictError, InventoryValidationError, InventoryUploadError, } from './inventory-client.js';
|
|
21
|
+
export { pushInventory, maybeAutoPush, } from './inventory-push.js';
|
|
14
22
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAe;AACf,OAAO,EACL,oBAAoB,EAIpB,mBAAmB,GACpB,MAAM,yCAAyC,CAAA;AAEhD,OAAO,EACL,qBAAqB,GAItB,MAAM,0CAA0C,CAAA;AAEjD,mBAAmB;AACnB,OAAO,EAAE,UAAU,EAAwD,MAAM,iBAAiB,CAAA;AAElG,qBAAqB;AACrB,OAAO,EACL,qBAAqB,EACrB,2BAA2B,GAG5B,MAAM,4BAA4B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAe;AACf,OAAO,EACL,oBAAoB,EAIpB,mBAAmB,GACpB,MAAM,yCAAyC,CAAA;AAEhD,OAAO,EACL,qBAAqB,GAItB,MAAM,0CAA0C,CAAA;AAEjD,mBAAmB;AACnB,OAAO,EAAE,UAAU,EAAwD,MAAM,iBAAiB,CAAA;AAElG,qBAAqB;AACrB,OAAO,EACL,qBAAqB,EACrB,2BAA2B,GAG5B,MAAM,4BAA4B,CAAA;AAEnC,sDAAsD;AACtD,OAAO,EACL,gBAAgB,EAChB,yBAAyB,GAM1B,MAAM,sBAAsB,CAAA;AAE7B,kEAAkE;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAoC,MAAM,uBAAuB,CAAA;AAC9F,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAC9D,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,aAAa,EACb,aAAa,GAGd,MAAM,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inventory payload assembler (SMI-5392, umbrella SMI-5382).
|
|
3
|
+
*
|
|
4
|
+
* Combines the device descriptor ({@link buildInventoryDevice}) with the scanned
|
|
5
|
+
* skill set ({@link collectDeviceSkills}) into the full
|
|
6
|
+
* {@link InventoryUploadPayload} that {@link uploadInventory} POSTs to the
|
|
7
|
+
* `inventory-upload` edge function.
|
|
8
|
+
*
|
|
9
|
+
* @module @skillsmith/core/sync/inventory-builder
|
|
10
|
+
*/
|
|
11
|
+
import { type BuildInventoryDeviceOptions } from './inventory-device.js';
|
|
12
|
+
import type { InventoryUploadPayload } from './inventory-types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Build the complete inventory snapshot for this device.
|
|
15
|
+
*
|
|
16
|
+
* @param opts - Optional CLI version to stamp on the device descriptor.
|
|
17
|
+
* @returns `{ device, skills }` ready to upload.
|
|
18
|
+
* @see SMI-5392
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildInventoryPayload(opts?: BuildInventoryDeviceOptions): Promise<InventoryUploadPayload>;
|
|
21
|
+
//# sourceMappingURL=inventory-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory-builder.d.ts","sourceRoot":"","sources":["../../../src/sync/inventory-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAwB,KAAK,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAC9F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAElE;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,CAAC,EAAE,2BAA2B,GACjC,OAAO,CAAC,sBAAsB,CAAC,CAKjC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inventory payload assembler (SMI-5392, umbrella SMI-5382).
|
|
3
|
+
*
|
|
4
|
+
* Combines the device descriptor ({@link buildInventoryDevice}) with the scanned
|
|
5
|
+
* skill set ({@link collectDeviceSkills}) into the full
|
|
6
|
+
* {@link InventoryUploadPayload} that {@link uploadInventory} POSTs to the
|
|
7
|
+
* `inventory-upload` edge function.
|
|
8
|
+
*
|
|
9
|
+
* @module @skillsmith/core/sync/inventory-builder
|
|
10
|
+
*/
|
|
11
|
+
import { collectDeviceSkills } from './inventory-collector.js';
|
|
12
|
+
import { buildInventoryDevice } from './inventory-device.js';
|
|
13
|
+
/**
|
|
14
|
+
* Build the complete inventory snapshot for this device.
|
|
15
|
+
*
|
|
16
|
+
* @param opts - Optional CLI version to stamp on the device descriptor.
|
|
17
|
+
* @returns `{ device, skills }` ready to upload.
|
|
18
|
+
* @see SMI-5392
|
|
19
|
+
*/
|
|
20
|
+
export async function buildInventoryPayload(opts) {
|
|
21
|
+
return {
|
|
22
|
+
device: buildInventoryDevice(opts),
|
|
23
|
+
skills: await collectDeviceSkills(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=inventory-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory-builder.js","sourceRoot":"","sources":["../../../src/sync/inventory-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAoC,MAAM,uBAAuB,CAAA;AAG9F;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAkC;IAElC,OAAO;QACL,MAAM,EAAE,oBAAoB,CAAC,IAAI,CAAC;QAClC,MAAM,EAAE,MAAM,mBAAmB,EAAE;KACpC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inventory upload HTTP client (SMI-5392, umbrella SMI-5382).
|
|
3
|
+
*
|
|
4
|
+
* Authenticates with the stored device-login session (JWT + refresh) and POSTs a
|
|
5
|
+
* full inventory snapshot to the gateway-verified `inventory-upload` edge
|
|
6
|
+
* function. Maps the edge function's status codes onto typed errors so callers
|
|
7
|
+
* (CLI command, MCP tool) can render precise, actionable messages.
|
|
8
|
+
*
|
|
9
|
+
* @module @skillsmith/core/sync/inventory-client
|
|
10
|
+
*/
|
|
11
|
+
import type { InventoryUploadPayload, InventoryUploadResult } from './inventory-types.js';
|
|
12
|
+
/**
|
|
13
|
+
* No usable session (no stored credentials, or a refresh that failed). The
|
|
14
|
+
* message hints at the recovery action so the CLI/MCP surface can relay it.
|
|
15
|
+
*
|
|
16
|
+
* @see SMI-5392
|
|
17
|
+
*/
|
|
18
|
+
export declare class InventoryAuthError extends Error {
|
|
19
|
+
constructor(message?: string);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The `device_id` is already owned by another user (HTTP 409). The user must
|
|
23
|
+
* forget the local device and re-register before retrying.
|
|
24
|
+
*
|
|
25
|
+
* @see SMI-5392
|
|
26
|
+
*/
|
|
27
|
+
export declare class InventoryConflictError extends Error {
|
|
28
|
+
constructor(message?: string);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The server rejected the payload as malformed (HTTP 400) — e.g.
|
|
32
|
+
* `device_id_required`, `too_many_skills`, or an invalid field.
|
|
33
|
+
*
|
|
34
|
+
* @see SMI-5392
|
|
35
|
+
*/
|
|
36
|
+
export declare class InventoryValidationError extends Error {
|
|
37
|
+
constructor(message?: string);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Catch-all for transport failures and unexpected server responses (HTTP 5xx,
|
|
41
|
+
* network errors, unparseable bodies).
|
|
42
|
+
*
|
|
43
|
+
* @see SMI-5392
|
|
44
|
+
*/
|
|
45
|
+
export declare class InventoryUploadError extends Error {
|
|
46
|
+
constructor(message: string);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Upload a full inventory snapshot for this device.
|
|
50
|
+
*
|
|
51
|
+
* A `200` response is returned verbatim — this INCLUDES the consent-off no-op
|
|
52
|
+
* `{ ok: true, applied: false, reason: 'consent_disabled' }`, which is a success,
|
|
53
|
+
* not an error.
|
|
54
|
+
*
|
|
55
|
+
* @param payload - The device + skills snapshot to upload.
|
|
56
|
+
* @returns The edge function's {@link InventoryUploadResult}.
|
|
57
|
+
* @throws {InventoryAuthError} HTTP 401, or no/expired session.
|
|
58
|
+
* @throws {InventoryConflictError} HTTP 409 (device owned by another user).
|
|
59
|
+
* @throws {InventoryValidationError} HTTP 400 (malformed / oversized payload).
|
|
60
|
+
* @throws {InventoryUploadError} HTTP 5xx, network failure, or unparseable 200 body.
|
|
61
|
+
* @see SMI-5392
|
|
62
|
+
*/
|
|
63
|
+
export declare function uploadInventory(payload: InventoryUploadPayload): Promise<InventoryUploadResult>;
|
|
64
|
+
//# sourceMappingURL=inventory-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory-client.d.ts","sourceRoot":"","sources":["../../../src/sync/inventory-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAEzF;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,SAA6D;CAIjF;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,SAAoB;CAIxC;AAED;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,SAAoB;CAIxC;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAuCD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAyChC"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inventory upload HTTP client (SMI-5392, umbrella SMI-5382).
|
|
3
|
+
*
|
|
4
|
+
* Authenticates with the stored device-login session (JWT + refresh) and POSTs a
|
|
5
|
+
* full inventory snapshot to the gateway-verified `inventory-upload` edge
|
|
6
|
+
* function. Maps the edge function's status codes onto typed errors so callers
|
|
7
|
+
* (CLI command, MCP tool) can render precise, actionable messages.
|
|
8
|
+
*
|
|
9
|
+
* @module @skillsmith/core/sync/inventory-client
|
|
10
|
+
*/
|
|
11
|
+
import { loadCredentials, refreshAccessToken, storeCredentials, } from '../config/token-credentials.js';
|
|
12
|
+
import { DEFAULT_BASE_URL, PRODUCTION_ANON_KEY } from '../api/utils.js';
|
|
13
|
+
/**
|
|
14
|
+
* No usable session (no stored credentials, or a refresh that failed). The
|
|
15
|
+
* message hints at the recovery action so the CLI/MCP surface can relay it.
|
|
16
|
+
*
|
|
17
|
+
* @see SMI-5392
|
|
18
|
+
*/
|
|
19
|
+
export class InventoryAuthError extends Error {
|
|
20
|
+
constructor(message = 'Not authenticated. Run `skillsmith login` and try again.') {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'InventoryAuthError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The `device_id` is already owned by another user (HTTP 409). The user must
|
|
27
|
+
* forget the local device and re-register before retrying.
|
|
28
|
+
*
|
|
29
|
+
* @see SMI-5392
|
|
30
|
+
*/
|
|
31
|
+
export class InventoryConflictError extends Error {
|
|
32
|
+
constructor(message = 'device_conflict') {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = 'InventoryConflictError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The server rejected the payload as malformed (HTTP 400) — e.g.
|
|
39
|
+
* `device_id_required`, `too_many_skills`, or an invalid field.
|
|
40
|
+
*
|
|
41
|
+
* @see SMI-5392
|
|
42
|
+
*/
|
|
43
|
+
export class InventoryValidationError extends Error {
|
|
44
|
+
constructor(message = 'invalid payload') {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = 'InventoryValidationError';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Catch-all for transport failures and unexpected server responses (HTTP 5xx,
|
|
51
|
+
* network errors, unparseable bodies).
|
|
52
|
+
*
|
|
53
|
+
* @see SMI-5392
|
|
54
|
+
*/
|
|
55
|
+
export class InventoryUploadError extends Error {
|
|
56
|
+
constructor(message) {
|
|
57
|
+
super(message);
|
|
58
|
+
this.name = 'InventoryUploadError';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Refresh the access token this many ms before it actually expires. */
|
|
62
|
+
const TOKEN_REFRESH_SKEW_MS = 60_000;
|
|
63
|
+
/**
|
|
64
|
+
* Resolve a fresh access token, refreshing (and persisting) if the stored one is
|
|
65
|
+
* within {@link TOKEN_REFRESH_SKEW_MS} of expiry.
|
|
66
|
+
*
|
|
67
|
+
* @throws {InventoryAuthError} When no credentials exist or the refresh fails.
|
|
68
|
+
*/
|
|
69
|
+
async function resolveAccessToken() {
|
|
70
|
+
const creds = await loadCredentials();
|
|
71
|
+
if (!creds)
|
|
72
|
+
throw new InventoryAuthError();
|
|
73
|
+
if (creds.expiresAt <= Date.now() + TOKEN_REFRESH_SKEW_MS) {
|
|
74
|
+
const refreshed = await refreshAccessToken(creds.refreshToken);
|
|
75
|
+
if (!refreshed)
|
|
76
|
+
throw new InventoryAuthError();
|
|
77
|
+
await storeCredentials(refreshed);
|
|
78
|
+
return refreshed.accessToken;
|
|
79
|
+
}
|
|
80
|
+
return creds.accessToken;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Best-effort extraction of the server's `{ error: string }` body so a typed
|
|
84
|
+
* error can carry the precise server message. Returns `null` when the body is
|
|
85
|
+
* absent or not JSON.
|
|
86
|
+
*/
|
|
87
|
+
async function readServerError(res) {
|
|
88
|
+
try {
|
|
89
|
+
const body = (await res.json());
|
|
90
|
+
return typeof body.error === 'string' ? body.error : null;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Upload a full inventory snapshot for this device.
|
|
98
|
+
*
|
|
99
|
+
* A `200` response is returned verbatim — this INCLUDES the consent-off no-op
|
|
100
|
+
* `{ ok: true, applied: false, reason: 'consent_disabled' }`, which is a success,
|
|
101
|
+
* not an error.
|
|
102
|
+
*
|
|
103
|
+
* @param payload - The device + skills snapshot to upload.
|
|
104
|
+
* @returns The edge function's {@link InventoryUploadResult}.
|
|
105
|
+
* @throws {InventoryAuthError} HTTP 401, or no/expired session.
|
|
106
|
+
* @throws {InventoryConflictError} HTTP 409 (device owned by another user).
|
|
107
|
+
* @throws {InventoryValidationError} HTTP 400 (malformed / oversized payload).
|
|
108
|
+
* @throws {InventoryUploadError} HTTP 5xx, network failure, or unparseable 200 body.
|
|
109
|
+
* @see SMI-5392
|
|
110
|
+
*/
|
|
111
|
+
export async function uploadInventory(payload) {
|
|
112
|
+
const accessToken = await resolveAccessToken();
|
|
113
|
+
let res;
|
|
114
|
+
try {
|
|
115
|
+
res = await fetch(`${DEFAULT_BASE_URL}/inventory-upload`, {
|
|
116
|
+
method: 'POST',
|
|
117
|
+
headers: {
|
|
118
|
+
'Content-Type': 'application/json',
|
|
119
|
+
apikey: PRODUCTION_ANON_KEY,
|
|
120
|
+
Authorization: `Bearer ${accessToken}`,
|
|
121
|
+
},
|
|
122
|
+
body: JSON.stringify(payload),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
127
|
+
throw new InventoryUploadError(`Inventory upload request failed: ${detail}`);
|
|
128
|
+
}
|
|
129
|
+
if (res.ok) {
|
|
130
|
+
try {
|
|
131
|
+
return (await res.json());
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
135
|
+
throw new InventoryUploadError(`Inventory upload returned an unreadable body: ${detail}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const serverError = await readServerError(res);
|
|
139
|
+
switch (res.status) {
|
|
140
|
+
case 401:
|
|
141
|
+
throw new InventoryAuthError();
|
|
142
|
+
case 409:
|
|
143
|
+
throw new InventoryConflictError(serverError ?? 'device_conflict');
|
|
144
|
+
case 400:
|
|
145
|
+
throw new InventoryValidationError(serverError ?? 'invalid payload');
|
|
146
|
+
default:
|
|
147
|
+
throw new InventoryUploadError(`Inventory upload failed (HTTP ${res.status})${serverError ? `: ${serverError}` : ''}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=inventory-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory-client.js","sourceRoot":"","sources":["../../../src/sync/inventory-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inventory-client tests (SMI-5392).
|
|
3
|
+
*
|
|
4
|
+
* Mocks the token-credentials module and global fetch.
|
|
5
|
+
*
|
|
6
|
+
* UC-1: no credentials -> InventoryAuthError, no fetch.
|
|
7
|
+
* UC-2: expired credentials -> refresh path runs, new creds stored, new token used.
|
|
8
|
+
* UC-3: expired credentials + failed refresh -> InventoryAuthError.
|
|
9
|
+
* UC-4: 200 body returned verbatim (incl. the consent-off no-op).
|
|
10
|
+
* UC-5: 401 / 409 / 400 / 500 -> the matching typed error.
|
|
11
|
+
* UC-6: network throw -> InventoryUploadError.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=inventory-client.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory-client.test.d.ts","sourceRoot":"","sources":["../../../src/sync/inventory-client.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inventory-client tests (SMI-5392).
|
|
3
|
+
*
|
|
4
|
+
* Mocks the token-credentials module and global fetch.
|
|
5
|
+
*
|
|
6
|
+
* UC-1: no credentials -> InventoryAuthError, no fetch.
|
|
7
|
+
* UC-2: expired credentials -> refresh path runs, new creds stored, new token used.
|
|
8
|
+
* UC-3: expired credentials + failed refresh -> InventoryAuthError.
|
|
9
|
+
* UC-4: 200 body returned verbatim (incl. the consent-off no-op).
|
|
10
|
+
* UC-5: 401 / 409 / 400 / 500 -> the matching typed error.
|
|
11
|
+
* UC-6: network throw -> InventoryUploadError.
|
|
12
|
+
*/
|
|
13
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
14
|
+
vi.mock('../config/token-credentials.js', () => ({
|
|
15
|
+
loadCredentials: vi.fn(),
|
|
16
|
+
refreshAccessToken: vi.fn(),
|
|
17
|
+
storeCredentials: vi.fn(),
|
|
18
|
+
}));
|
|
19
|
+
import { loadCredentials, refreshAccessToken, storeCredentials, } from '../config/token-credentials.js';
|
|
20
|
+
import { uploadInventory, InventoryAuthError, InventoryConflictError, InventoryValidationError, InventoryUploadError, } from './inventory-client.js';
|
|
21
|
+
const fetchMock = vi.fn();
|
|
22
|
+
const payload = {
|
|
23
|
+
device: { device_id: '11111111-1111-4111-8111-111111111111' },
|
|
24
|
+
skills: [],
|
|
25
|
+
};
|
|
26
|
+
function jsonResponse(body, status) {
|
|
27
|
+
return new Response(JSON.stringify(body), {
|
|
28
|
+
status,
|
|
29
|
+
headers: { 'Content-Type': 'application/json' },
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const futureCreds = {
|
|
33
|
+
accessToken: 'at_valid',
|
|
34
|
+
refreshToken: 'rt_valid',
|
|
35
|
+
expiresAt: Date.now() + 3_600_000,
|
|
36
|
+
version: 2,
|
|
37
|
+
};
|
|
38
|
+
describe('inventory-client', () => {
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
vi.clearAllMocks();
|
|
41
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
42
|
+
});
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
vi.unstubAllGlobals();
|
|
45
|
+
});
|
|
46
|
+
it('UC-1: throws InventoryAuthError when no credentials are stored', async () => {
|
|
47
|
+
vi.mocked(loadCredentials).mockResolvedValue(null);
|
|
48
|
+
await expect(uploadInventory(payload)).rejects.toBeInstanceOf(InventoryAuthError);
|
|
49
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
50
|
+
});
|
|
51
|
+
it('UC-2: refreshes + stores when the access token is near expiry, then uses the new token', async () => {
|
|
52
|
+
vi.mocked(loadCredentials).mockResolvedValue({
|
|
53
|
+
accessToken: 'at_expired',
|
|
54
|
+
refreshToken: 'rt_old',
|
|
55
|
+
expiresAt: Date.now() - 1_000,
|
|
56
|
+
version: 2,
|
|
57
|
+
});
|
|
58
|
+
vi.mocked(refreshAccessToken).mockResolvedValue({
|
|
59
|
+
accessToken: 'at_new',
|
|
60
|
+
refreshToken: 'rt_new',
|
|
61
|
+
expiresAt: Date.now() + 3_600_000,
|
|
62
|
+
version: 2,
|
|
63
|
+
});
|
|
64
|
+
fetchMock.mockResolvedValue(jsonResponse({ ok: true, applied: true, device_id: 'd' }, 200));
|
|
65
|
+
const result = await uploadInventory(payload);
|
|
66
|
+
expect(refreshAccessToken).toHaveBeenCalledWith('rt_old');
|
|
67
|
+
expect(storeCredentials).toHaveBeenCalledWith(expect.objectContaining({ accessToken: 'at_new', version: 2 }));
|
|
68
|
+
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('/inventory-upload'), expect.objectContaining({
|
|
69
|
+
method: 'POST',
|
|
70
|
+
headers: expect.objectContaining({ Authorization: 'Bearer at_new' }),
|
|
71
|
+
}));
|
|
72
|
+
expect(result.applied).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
it('UC-3: throws InventoryAuthError when the refresh fails', async () => {
|
|
75
|
+
vi.mocked(loadCredentials).mockResolvedValue({
|
|
76
|
+
accessToken: 'at_expired',
|
|
77
|
+
refreshToken: 'rt_old',
|
|
78
|
+
expiresAt: Date.now() - 1_000,
|
|
79
|
+
version: 2,
|
|
80
|
+
});
|
|
81
|
+
vi.mocked(refreshAccessToken).mockResolvedValue(null);
|
|
82
|
+
await expect(uploadInventory(payload)).rejects.toBeInstanceOf(InventoryAuthError);
|
|
83
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
84
|
+
});
|
|
85
|
+
it('UC-4: returns the 200 body verbatim, including the consent-off no-op', async () => {
|
|
86
|
+
vi.mocked(loadCredentials).mockResolvedValue(futureCreds);
|
|
87
|
+
const consentOff = { ok: true, applied: false, reason: 'consent_disabled' };
|
|
88
|
+
fetchMock.mockResolvedValue(jsonResponse(consentOff, 200));
|
|
89
|
+
const result = await uploadInventory(payload);
|
|
90
|
+
expect(result).toEqual(consentOff);
|
|
91
|
+
expect(refreshAccessToken).not.toHaveBeenCalled();
|
|
92
|
+
});
|
|
93
|
+
it('UC-5a: maps 401 to InventoryAuthError', async () => {
|
|
94
|
+
vi.mocked(loadCredentials).mockResolvedValue(futureCreds);
|
|
95
|
+
fetchMock.mockResolvedValue(jsonResponse({ error: 'authentication_required' }, 401));
|
|
96
|
+
await expect(uploadInventory(payload)).rejects.toBeInstanceOf(InventoryAuthError);
|
|
97
|
+
});
|
|
98
|
+
it('UC-5b: maps 409 to InventoryConflictError', async () => {
|
|
99
|
+
vi.mocked(loadCredentials).mockResolvedValue(futureCreds);
|
|
100
|
+
fetchMock.mockResolvedValue(jsonResponse({ error: 'device_conflict' }, 409));
|
|
101
|
+
await expect(uploadInventory(payload)).rejects.toBeInstanceOf(InventoryConflictError);
|
|
102
|
+
});
|
|
103
|
+
it('UC-5c: maps 400 to InventoryValidationError carrying the server message', async () => {
|
|
104
|
+
vi.mocked(loadCredentials).mockResolvedValue(futureCreds);
|
|
105
|
+
fetchMock.mockResolvedValue(jsonResponse({ error: 'too_many_skills' }, 400));
|
|
106
|
+
// Single call: the mocked Response body can only be read once.
|
|
107
|
+
const error = await uploadInventory(payload).catch((e) => e);
|
|
108
|
+
expect(error).toBeInstanceOf(InventoryValidationError);
|
|
109
|
+
expect(error.message).toBe('too_many_skills');
|
|
110
|
+
});
|
|
111
|
+
it('UC-5d: maps 500 to InventoryUploadError', async () => {
|
|
112
|
+
vi.mocked(loadCredentials).mockResolvedValue(futureCreds);
|
|
113
|
+
fetchMock.mockResolvedValue(jsonResponse({ error: 'server_error' }, 500));
|
|
114
|
+
await expect(uploadInventory(payload)).rejects.toBeInstanceOf(InventoryUploadError);
|
|
115
|
+
});
|
|
116
|
+
it('UC-6: wraps a network throw in InventoryUploadError', async () => {
|
|
117
|
+
vi.mocked(loadCredentials).mockResolvedValue(futureCreds);
|
|
118
|
+
fetchMock.mockRejectedValue(new Error('ECONNREFUSED'));
|
|
119
|
+
await expect(uploadInventory(payload)).rejects.toBeInstanceOf(InventoryUploadError);
|
|
120
|
+
});
|
|
121
|
+
// Security invariant: tokens must never appear in error message strings.
|
|
122
|
+
// Covers both the non-200 response path and the network-throw path.
|
|
123
|
+
it('UC-7: error messages do not leak access tokens or refresh tokens (security invariant)', async () => {
|
|
124
|
+
const sentinelCreds = {
|
|
125
|
+
accessToken: 'at_SECRET_5392',
|
|
126
|
+
refreshToken: 'rt_SECRET_5392',
|
|
127
|
+
expiresAt: Date.now() + 3_600_000,
|
|
128
|
+
version: 2,
|
|
129
|
+
};
|
|
130
|
+
// Non-200 path: 500 → InventoryUploadError whose message must not contain tokens.
|
|
131
|
+
vi.mocked(loadCredentials).mockResolvedValue(sentinelCreds);
|
|
132
|
+
fetchMock.mockResolvedValue(jsonResponse({ error: 'server_error' }, 500));
|
|
133
|
+
const err500 = await uploadInventory(payload).catch((e) => e);
|
|
134
|
+
expect(err500).toBeInstanceOf(InventoryUploadError);
|
|
135
|
+
expect(err500.message).not.toContain('at_SECRET_5392');
|
|
136
|
+
expect(err500.message).not.toContain('rt_SECRET_5392');
|
|
137
|
+
// Network-throw path: fetch rejects → InventoryUploadError whose message must not contain tokens.
|
|
138
|
+
vi.mocked(loadCredentials).mockResolvedValue(sentinelCreds);
|
|
139
|
+
fetchMock.mockRejectedValue(new Error('ECONNREFUSED'));
|
|
140
|
+
const errNet = await uploadInventory(payload).catch((e) => e);
|
|
141
|
+
expect(errNet).toBeInstanceOf(InventoryUploadError);
|
|
142
|
+
expect(errNet.message).not.toContain('at_SECRET_5392');
|
|
143
|
+
expect(errNet.message).not.toContain('rt_SECRET_5392');
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=inventory-client.test.js.map
|