@xagents_in/unmask 0.1.2 → 0.1.3

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.
@@ -0,0 +1,328 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ const states = new Map([
4
+ ["changed", "changed"],
5
+ ["artifact-only", "added"],
6
+ ["byte-identical", "identical"],
7
+ ["not-compared", "not-compared"],
8
+ ]);
9
+ const digest = (value) => (/^[a-f0-9]{64}$/.test(value ?? "") ? value : null);
10
+ const order = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
11
+ export const EXPLORATION_BYTE_LIMIT = 131072;
12
+ export const explorationLimitations = [
13
+ "States compare artifact and selected source, not releases or version history.",
14
+ "Source-only paths are recorded observations; their hashes, file types and excerpts may be unavailable.",
15
+ "Incomplete inventories and unassessed files do not establish safety or absence.",
16
+ ];
17
+
18
+ export function safeExplorationPath(value, { prefix = false } = {}) {
19
+ if (
20
+ typeof value !== "string" ||
21
+ value.length > 4096 ||
22
+ /[\x00-\x1f\x7f\\%:]/.test(value)
23
+ )
24
+ return false;
25
+ if (prefix && value === "") return true;
26
+ const parts = (
27
+ prefix && value.endsWith("/") ? value.slice(0, -1) : value
28
+ ).split("/");
29
+ return parts.every((part) => part && part !== "." && part !== "..");
30
+ }
31
+
32
+ export function explorationJson(value) {
33
+ return JSON.stringify(value).replace(
34
+ /[<>&\u2028\u2029]/g,
35
+ (character) =>
36
+ `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`,
37
+ );
38
+ }
39
+
40
+ export function reportFileRows(report, { reportId } = {}) {
41
+ if (reportId !== undefined && !/^[a-f0-9]{32}$/.test(reportId))
42
+ throw new TypeError("Invalid report identity");
43
+ const rows = [];
44
+ const paths = new Set();
45
+ let omitted = 0;
46
+ for (const file of report.files ?? []) {
47
+ if (
48
+ !states.has(file.state) ||
49
+ !safeExplorationPath(file.originalPath) ||
50
+ (file.path !== null && !safeExplorationPath(file.path))
51
+ ) {
52
+ omitted++;
53
+ continue;
54
+ }
55
+ if (file.path !== null) paths.add(file.path);
56
+ rows.push({
57
+ path: file.path,
58
+ originalPath: file.originalPath,
59
+ state: states.get(file.state),
60
+ comparisonState: file.state,
61
+ size:
62
+ Number.isSafeInteger(file.size) && file.size >= 0 ? file.size : null,
63
+ artifactSha256: digest(file.artifactSha256),
64
+ sourceSha256: digest(file.sourceSha256),
65
+ reason:
66
+ typeof file.reason === "string" ? file.reason.slice(0, 128) : null,
67
+ });
68
+ }
69
+ for (const path of new Set(report.coverage?.sourceOnly ?? [])) {
70
+ if (!safeExplorationPath(path)) {
71
+ omitted++;
72
+ continue;
73
+ }
74
+ if (paths.has(path)) continue;
75
+ rows.push({
76
+ path,
77
+ originalPath: null,
78
+ state: "removed",
79
+ comparisonState: "source-only",
80
+ size: null,
81
+ artifactSha256: null,
82
+ sourceSha256: null,
83
+ reason: "recorded-source-only",
84
+ });
85
+ }
86
+ rows.sort(
87
+ (a, b) =>
88
+ order(a.path ?? a.originalPath, b.path ?? b.originalPath) ||
89
+ order(a.originalPath ?? "", b.originalPath ?? ""),
90
+ );
91
+ if (reportId !== undefined)
92
+ for (const file of rows) {
93
+ file.fileId = `f-${createHash("sha256")
94
+ .update(
95
+ JSON.stringify([
96
+ "unmask-file-id-v1",
97
+ reportId,
98
+ file.path,
99
+ file.originalPath,
100
+ ]),
101
+ )
102
+ .digest("base64url")}`;
103
+ }
104
+ return { rows, omitted };
105
+ }
106
+
107
+ export function buildReportFileInventory(
108
+ report,
109
+ { state = "all", prefix = "", offset = 0, limit = 50 } = {},
110
+ context = {},
111
+ ) {
112
+ if (
113
+ !["all", "removed", ...states.values()].includes(state) ||
114
+ !safeExplorationPath(prefix, { prefix: true }) ||
115
+ !Number.isSafeInteger(offset) ||
116
+ offset < 0 ||
117
+ !Number.isSafeInteger(limit) ||
118
+ limit < 1 ||
119
+ limit > 100
120
+ )
121
+ throw new TypeError("Invalid inventory query");
122
+ const { rows, omitted } = reportFileRows(report, context);
123
+ const filtered = rows.filter(
124
+ (file) =>
125
+ (state === "all" || file.state === state) &&
126
+ (file.path ?? file.originalPath).startsWith(prefix),
127
+ );
128
+ const files = [];
129
+ let bytes = 0;
130
+ for (const file of filtered.slice(offset, offset + limit)) {
131
+ const size = Buffer.byteLength(explorationJson(file)) + 1;
132
+ if (
133
+ bytes + size >
134
+ EXPLORATION_BYTE_LIMIT -
135
+ Buffer.byteLength(explorationJson({ prefix })) -
136
+ 8192
137
+ )
138
+ break;
139
+ bytes += size;
140
+ files.push(file);
141
+ }
142
+ return {
143
+ schemaVersion: "1",
144
+ scope: "artifact-source",
145
+ state,
146
+ prefix,
147
+ offset,
148
+ limit,
149
+ total: filtered.length,
150
+ files,
151
+ nextOffset:
152
+ offset + files.length < filtered.length ? offset + files.length : null,
153
+ omittedUnsafePaths: omitted,
154
+ inventoryComplete: report.coverage?.inventory?.complete === true,
155
+ sourceComplete: report.coverage?.sourceComplete === true,
156
+ limitations: explorationLimitations,
157
+ };
158
+ }
159
+
160
+ function validRange(value, size) {
161
+ return (
162
+ Array.isArray(value) &&
163
+ value.length === 2 &&
164
+ value.every((number) => Number.isSafeInteger(number) && number >= 0) &&
165
+ value[0] <= value[1] &&
166
+ value[1] <= size
167
+ );
168
+ }
169
+
170
+ function recordedExcerpt(item) {
171
+ const unavailable = {
172
+ excerpt: null,
173
+ excerptRange: null,
174
+ recordedExcerptRange: null,
175
+ excerptTruncated: false,
176
+ excerptStatus: "not-recorded",
177
+ };
178
+ if (item.excerpt === undefined) return unavailable;
179
+ if (
180
+ typeof item.excerpt !== "string" ||
181
+ !validRange(item.excerptRange, item.size) ||
182
+ item.excerptRange[0] !== item.range[0] ||
183
+ item.excerptRange[1] > item.range[1] ||
184
+ Buffer.byteLength(item.excerpt) !==
185
+ item.excerptRange[1] - item.excerptRange[0]
186
+ )
187
+ return { ...unavailable, excerptStatus: "invalid-recorded-range" };
188
+ let excerpt = "",
189
+ bytes = 0;
190
+ for (const character of item.excerpt) {
191
+ const size = Buffer.byteLength(character);
192
+ if (bytes + size > 2048) break;
193
+ bytes += size;
194
+ excerpt += character;
195
+ }
196
+ return {
197
+ excerpt,
198
+ excerptRange: [item.excerptRange[0], item.excerptRange[0] + bytes],
199
+ recordedExcerptRange: item.excerptRange,
200
+ excerptTruncated: bytes < Buffer.byteLength(item.excerpt),
201
+ excerptStatus: "recorded",
202
+ };
203
+ }
204
+
205
+ export function buildReportFileEvidence(report, selection, context = {}) {
206
+ const keys = Object.keys(selection ?? {});
207
+ if (
208
+ keys.length !== 1 ||
209
+ !["path", "originalPath", "fileId"].includes(keys[0]) ||
210
+ (keys[0] === "fileId"
211
+ ? !/^[a-f0-9]{32}$/.test(context.reportId ?? "") ||
212
+ !/^f-[A-Za-z0-9_-]{43}$/.test(selection.fileId)
213
+ : !safeExplorationPath(selection[keys[0]]))
214
+ )
215
+ throw new TypeError("Invalid file selection");
216
+ const { rows } = reportFileRows(report, context);
217
+ const matches = rows.filter((file) =>
218
+ keys[0] === "fileId"
219
+ ? file.fileId === selection.fileId
220
+ : keys[0] === "path"
221
+ ? file.path === selection.path
222
+ : file.path === null && file.originalPath === selection.originalPath,
223
+ );
224
+ if (matches.length !== 1) return null;
225
+ const file = matches[0];
226
+ const rawFile = (report.files ?? []).find(
227
+ (item) =>
228
+ item.path === file.path && item.originalPath === file.originalPath,
229
+ );
230
+ const samePathEvidence = (report.evidence ?? []).filter((item) =>
231
+ file.path === null
232
+ ? item.side === "artifact" &&
233
+ item.path === null &&
234
+ item.originalPath === file.originalPath
235
+ : item.path === file.path &&
236
+ (file.state !== "removed" || item.side === "source"),
237
+ );
238
+ if (file.state === "removed") {
239
+ const hashes = new Set(
240
+ samePathEvidence
241
+ .filter(
242
+ (item) =>
243
+ digest(item.fileSha256) &&
244
+ digest(item.blobDigest) &&
245
+ item.blobDigest === report.inputs?.sourceArchive?.sha256,
246
+ )
247
+ .map((item) => item.fileSha256),
248
+ );
249
+ if (hashes.size === 1) file.sourceSha256 = [...hashes][0];
250
+ }
251
+ const candidateIds = new Set([
252
+ ...(rawFile?.evidenceIds ?? []),
253
+ ...samePathEvidence.map((item) => item.id),
254
+ ]);
255
+ const result = {
256
+ schemaVersion: "1",
257
+ scope: "artifact-source",
258
+ file,
259
+ recordedOnly: true,
260
+ evidence: [],
261
+ evidenceStatus: "unavailable",
262
+ evidenceOmitted: 0,
263
+ invalidEvidenceOmitted: 0,
264
+ limitations: [
265
+ ...explorationLimitations,
266
+ "Only previously recorded excerpts are returned; omitted text is not fetched or reconstructed. Hashes are recorded claims, not new artifact verification. Render excerpts as text, never HTML.",
267
+ ],
268
+ };
269
+ const evidenceById = new Map();
270
+ for (const item of report.evidence ?? [])
271
+ evidenceById.set(item.id, evidenceById.has(item.id) ? null : item);
272
+ let bytes = Buffer.byteLength(explorationJson(result));
273
+ for (const id of candidateIds) {
274
+ const item = evidenceById.get(id);
275
+ const expectedHash =
276
+ item?.side === "artifact" ? file.artifactSha256 : file.sourceSha256;
277
+ const input =
278
+ item?.side === "artifact"
279
+ ? report.inputs?.artifact
280
+ : report.inputs?.sourceArchive;
281
+ if (
282
+ !item ||
283
+ !/^ev-[a-f0-9]{64}$/.test(id) ||
284
+ !["artifact", "source"].includes(item.side) ||
285
+ item.path !== file.path ||
286
+ !safeExplorationPath(item.originalPath) ||
287
+ (item.side === "artifact" &&
288
+ (item.originalPath !== file.originalPath || item.size !== file.size)) ||
289
+ !expectedHash ||
290
+ item.fileSha256 !== expectedHash ||
291
+ !digest(item.blobDigest) ||
292
+ item.blobDigest !== input?.sha256 ||
293
+ !Number.isSafeInteger(item.size) ||
294
+ item.size < 0 ||
295
+ !validRange(item.range, item.size)
296
+ ) {
297
+ result.invalidEvidenceOmitted++;
298
+ continue;
299
+ }
300
+ const evidence = {
301
+ id,
302
+ side: item.side,
303
+ path: item.path,
304
+ originalPath: item.originalPath,
305
+ fileSha256: item.fileSha256,
306
+ blobDigest: item.blobDigest,
307
+ size: item.size,
308
+ range: item.range,
309
+ ...recordedExcerpt(item),
310
+ };
311
+ const size = Buffer.byteLength(explorationJson(evidence)) + 1;
312
+ if (
313
+ result.evidence.length >= 32 ||
314
+ bytes + size > EXPLORATION_BYTE_LIMIT - 2048
315
+ ) {
316
+ result.evidenceOmitted++;
317
+ continue;
318
+ }
319
+ bytes += size;
320
+ result.evidence.push(evidence);
321
+ }
322
+ if (result.evidence.length)
323
+ result.evidenceStatus =
324
+ result.evidenceOmitted || result.invalidEvidenceOmitted
325
+ ? "partial"
326
+ : "recorded";
327
+ return result;
328
+ }
@@ -1,8 +1,10 @@
1
1
  import { createServer } from "node:http";
2
+ import { createRegistryFactsHandler } from "./registry-facts.mjs";
2
3
  import { buildPackageDetails } from "../core/package-details.mjs";
3
4
  import { attachVulnerabilityCheck } from "./enrichment.mjs";
4
5
  import { createQueue, resolveLimits, systemClock } from "./queue.mjs";
5
6
  import { createReportStore } from "./store.mjs";
7
+ import { handleReportExploration } from "./report-exploration.mjs";
6
8
  import { renderReport } from "../viewer/render.mjs";
7
9
  import {
8
10
  renderHome,
@@ -105,6 +107,7 @@ export function createApp({
105
107
  versionInfo,
106
108
  limits: overrides,
107
109
  clock = systemClock,
110
+ registryFacts = {},
108
111
  } = {}) {
109
112
  if (typeof runAnalysis !== "function")
110
113
  throw new TypeError("runAnalysis is required");
@@ -119,6 +122,7 @@ export function createApp({
119
122
  );
120
123
  if (enrichJob !== undefined && typeof enrichJob !== "function")
121
124
  throw new TypeError("enrichJob must be a function");
125
+ const registryFactsHandler = createRegistryFactsHandler(registryFacts);
122
126
  const limits = resolveLimits(overrides);
123
127
  const version = Object.fromEntries(
124
128
  ["version", "commit", "tarballSha256"].map((key) => [
@@ -174,6 +178,7 @@ export function createApp({
174
178
  }
175
179
  async function handle() {
176
180
  const path = req.url;
181
+ if (await registryFactsHandler(req, json)) return;
177
182
  if (path === "/check") {
178
183
  if (req.method !== "POST")
179
184
  return error(
@@ -257,6 +262,7 @@ export function createApp({
257
262
  "Use the release form to start a check.",
258
263
  { allow: "GET" },
259
264
  );
265
+ if (handleReportExploration({ path, getJob: queue.get, send })) return;
260
266
  if (path === "/") return send(200, renderHome());
261
267
  if (path === "/healthz") return json(200, { status: "ok" });
262
268
  if (path === "/version") return json(200, version);
@@ -0,0 +1,118 @@
1
+ import {
2
+ getRegistryFacts,
3
+ getRegistryHistory,
4
+ registryIdentity,
5
+ } from "../core/registry-facts.mjs";
6
+
7
+ export function createRegistryFactsHandler(options = {}) {
8
+ const maxConcurrent = options.maxConcurrent ?? 2;
9
+ const maxRequests = options.maxRequests ?? 30;
10
+ if (
11
+ !Number.isSafeInteger(maxConcurrent) ||
12
+ maxConcurrent < 1 ||
13
+ maxConcurrent > 2 ||
14
+ !Number.isSafeInteger(maxRequests) ||
15
+ maxRequests < 1 ||
16
+ maxRequests > 30
17
+ )
18
+ throw new TypeError("Invalid registry lookup admission limits");
19
+ let active = 0,
20
+ used = 0,
21
+ windowStart = Date.now();
22
+ return async function handleRegistryFacts(req, json) {
23
+ const url = new URL(req.url, "http://localhost");
24
+ const history = url.pathname === "/api/registry/history";
25
+ if (url.pathname !== "/api/registry/facts" && !history) return false;
26
+ if (req.method !== "GET") {
27
+ json(
28
+ 405,
29
+ { status: "rejected", reason: "method-not-allowed" },
30
+ { allow: "GET" },
31
+ );
32
+ return true;
33
+ }
34
+ const spec = url.searchParams.get("package");
35
+ let limit = 20;
36
+ try {
37
+ const allowed = history ? ["package", "limit"] : ["package"];
38
+ if (
39
+ !spec ||
40
+ [...url.searchParams.keys()].some((key) => !allowed.includes(key)) ||
41
+ allowed.some((key) => url.searchParams.getAll(key).length > 1)
42
+ )
43
+ throw new Error();
44
+ if (history) {
45
+ registryIdentity(`${spec}@0.0.0`);
46
+ if (url.searchParams.has("limit")) {
47
+ const raw = url.searchParams.get("limit");
48
+ if (!/^[1-9]\d{0,2}$/.test(raw)) throw new Error();
49
+ limit = Number(raw);
50
+ if (limit > 100) throw new Error();
51
+ }
52
+ } else registryIdentity(spec);
53
+ } catch {
54
+ json(400, {
55
+ status: "rejected",
56
+ reason: history
57
+ ? "package-name-and-bounded-limit-required"
58
+ : "exact-package-required",
59
+ });
60
+ return true;
61
+ }
62
+ const now = Date.now();
63
+ if (now - windowStart >= 60000) {
64
+ used = 0;
65
+ windowStart = now;
66
+ }
67
+ if (active >= maxConcurrent || used >= maxRequests) {
68
+ json(
69
+ 429,
70
+ { status: "unavailable", reason: "registry-lookup-limit" },
71
+ {
72
+ "retry-after": String(
73
+ Math.max(1, Math.ceil((60000 - (now - windowStart)) / 1000)),
74
+ ),
75
+ },
76
+ );
77
+ return true;
78
+ }
79
+ used++;
80
+ active++;
81
+ try {
82
+ json(
83
+ 200,
84
+ history
85
+ ? await getRegistryHistory(spec, { ...options, limit })
86
+ : await getRegistryFacts(spec, options),
87
+ );
88
+ } catch (error) {
89
+ const reason = [
90
+ "acquisition-timeout",
91
+ "response-cap",
92
+ "redirect-refused",
93
+ "invalid-registry-document",
94
+ "registry-identity-mismatch",
95
+ "http-status",
96
+ "network-failure",
97
+ "invalid-response",
98
+ "registry-history-cap",
99
+ ].includes(error.code)
100
+ ? error.code
101
+ : "registry-unavailable";
102
+ const status =
103
+ reason === "acquisition-timeout"
104
+ ? 504
105
+ : error.observation?.status === 404
106
+ ? 404
107
+ : 502;
108
+ json(status, {
109
+ status: "unavailable",
110
+ reason,
111
+ safetyVerdict: "not-provided",
112
+ });
113
+ } finally {
114
+ active--;
115
+ }
116
+ return true;
117
+ };
118
+ }
@@ -0,0 +1,87 @@
1
+ import {
2
+ buildReportFileInventory,
3
+ buildReportFileEvidence,
4
+ explorationJson,
5
+ } from "../core/report-exploration.mjs";
6
+
7
+ function queryParameters(raw, allowed) {
8
+ if (raw.length > 16384) throw new TypeError("Query too long");
9
+ decodeURIComponent(raw.replace(/\+/g, " "));
10
+ const params = new URLSearchParams(raw);
11
+ for (const key of params.keys())
12
+ if (!allowed.includes(key) || params.getAll(key).length !== 1)
13
+ throw new TypeError("Unknown or duplicate query key");
14
+ return params;
15
+ }
16
+ function integer(params, name, fallback) {
17
+ if (!params.has(name)) return fallback;
18
+ const value = params.get(name);
19
+ if (!/^(0|[1-9]\d*)$/.test(value)) throw new TypeError("Invalid integer");
20
+ return Number(value);
21
+ }
22
+
23
+ export function handleReportExploration({ path, getJob, send }) {
24
+ const match = /^\/r\/([a-f0-9]{32})\/(files|file)\.json(?:\?([^#]*))?$/.exec(
25
+ path,
26
+ );
27
+ if (!match) return false;
28
+ const json = (status, body, headers = {}) =>
29
+ send(status, explorationJson(body), "application/json; charset=utf-8", {
30
+ "content-disposition":
31
+ match[2] === "file"
32
+ ? 'attachment; filename="unmask-file-evidence.json"'
33
+ : 'attachment; filename="unmask-files.json"',
34
+ ...headers,
35
+ });
36
+ const drilldown = match[2] === "file";
37
+ const context = { reportId: match[1] };
38
+ let options;
39
+ try {
40
+ if (drilldown) {
41
+ const params = queryParameters(match[3] ?? "", [
42
+ "path",
43
+ "originalPath",
44
+ "fileId",
45
+ ]);
46
+ options = Object.fromEntries(params);
47
+ buildReportFileEvidence({ files: [] }, options, context);
48
+ } else {
49
+ const params = queryParameters(match[3] ?? "", [
50
+ "state",
51
+ "prefix",
52
+ "offset",
53
+ "limit",
54
+ ]);
55
+ options = {
56
+ state: params.get("state") ?? "all",
57
+ prefix: params.get("prefix") ?? "",
58
+ offset: integer(params, "offset", 0),
59
+ limit: integer(params, "limit", 50),
60
+ };
61
+ buildReportFileInventory({ files: [] }, options, context);
62
+ }
63
+ } catch {
64
+ json(400, { error: "invalid-query" });
65
+ return true;
66
+ }
67
+ const job = getJob(match[1]);
68
+ if (!job) json(404, { error: "report-unavailable" });
69
+ else if (!job.report) {
70
+ const pending = ["queued", "running"].includes(job.status);
71
+ json(
72
+ pending ? 202 : 409,
73
+ {
74
+ error: pending ? "report-pending" : "report-unavailable",
75
+ status: job.status,
76
+ },
77
+ pending ? { "retry-after": "3" } : {},
78
+ );
79
+ } else {
80
+ const body = drilldown
81
+ ? buildReportFileEvidence(job.report, options, context)
82
+ : buildReportFileInventory(job.report, options, context);
83
+ if (!body) json(404, { error: "file-unavailable" });
84
+ else json(200, { reportId: match[1], ...body });
85
+ }
86
+ return true;
87
+ }
package/dist/version.json CHANGED
@@ -1 +1 @@
1
- {"buildSchema":"1","version":"0.1.2","dirty":false,"commit":"85bd6d9c0ce7bc31c16d3b1aef695826c0b52354","sourceSha256":"41b4925fd7f4c0d5e8a0018bce3244e138397b48b9663b68a08a9e0e4b32f898","packageSha256":"97af1181106db21be2cde05366ede4e8c018c367cf9bd6b21168dcb78baaff56","lockfileSha256":"84beb1a861f96a8cb788de5bfeeaddcaff04af8c766ec6489601ba42b89fc583","files":{"cli/hosted.mjs":{"sha256":"dea7b512a2e811102521565e9f218c77aab916fe05e838f55a9aeb7b43cd0852","size":7436},"cli/main.mjs":{"sha256":"3bff23e18025d73dbfd8eb3a9571a7797702f03ed14e8d2d1edd6a12304c579e","size":6597},"core/acquire.mjs":{"sha256":"aee5ed002292edf1b03385ceec8ebfb03de452dba36bbdced96f888eaafa1d67","size":9549},"core/advisories.mjs":{"sha256":"388088e44422ffeb3b60d930c84cec29fbc89b98d8dfd2879bc6ede50f4e7ea9","size":13004},"core/archive.mjs":{"sha256":"80aa4373c0324458fe322a83af18a4cfd0ffec4b39ebdeffc9084639a8655410","size":16193},"core/compare.mjs":{"sha256":"540614266e06a2875010793d036d256ddfac72f978157cd3d147ffb99015d8e4","size":7579},"core/manifests.mjs":{"sha256":"29c40e01ff1e1dfaed444600d8c78380d23d4bc9be71960251e39ea3594de2f1","size":17891},"core/online.mjs":{"sha256":"368a3f2558e16db0701d2eaf068b48e2661e7e01ab7cf5605cdd22766aeb5cca","size":9741},"core/package-details.mjs":{"sha256":"770551a6ab84e523dbc56ede6131b08eb22b8c21fc9c8b179fe0d1769fb2ec00","size":21538},"core/pipeline.mjs":{"sha256":"9c4ddc5c258a99455a1230c978fd132c135057ad7bb6c7baa201ae530ee136fd","size":11060},"core/policy.mjs":{"sha256":"4281c626c00a6424992f5e1eba26876e2b70f4b968450a8ca52fa42f5a121ba5","size":2954},"core/report.mjs":{"sha256":"aa167c94c257a5ff6d830630a37a51a9a9e47f82aa4a0a7b96ead91a5967294b","size":15844},"core/resolve.mjs":{"sha256":"d5575da49ff78e8fea8df1f2fc10a39540adea285eddfa347746e848f9fdf957","size":5202},"core/source.mjs":{"sha256":"798fe74e3fba836b82576cd46e1b91e6f6e0a4e3cf273c533b5e074247c81373","size":3238},"core/syntax.mjs":{"sha256":"2d50f2e73e17aedbcbccd92af280e171de4ef78b55acccd23d6b6ef11e891776","size":10450},"model/client.mjs":{"sha256":"efb68132710cbdff6b86b58cbac006c48e10f9317e852f00b120ef7c3c7ed9c1","size":42865},"model/config.mjs":{"sha256":"127605979a299616be15f4a47e94dcd82928b00ad2af71744ffaa6e359516486","size":3245},"server/app.mjs":{"sha256":"54cb435f6ab70739c16a2db9eb63eb91704a5e1515cbb2c25793f47baa4e0299","size":10128},"server/enrichment.mjs":{"sha256":"3c5cc57f2c8f019f79418457f366a9422e0a03a8ba86a41b0767aba636bde179","size":3825},"server/main.mjs":{"sha256":"e5bdcd02209c2ccc1ed8c73b85b9988d61aa3e1bcf7c8d119eed782a4bfcd224","size":4587},"server/queue.mjs":{"sha256":"23e30f3ff570771b77a244be9200ad510d2f19811eee566d68b364b7f741a9d7","size":7371},"server/runner.mjs":{"sha256":"a6ca5bfbd7b239f7110639d854ca9a263f4cf3aaf06701ea54493b29f8244706","size":9071},"server/store.mjs":{"sha256":"efa2a35c7e9d0344c26e24ba360a457cdf80f4f48975f0186f81844b9fb7a097","size":2706},"server/worker.mjs":{"sha256":"1df839608cd1c691fc2801d89e698daeef3e48d7f4b8843ce1252a21fde9730a","size":1902},"viewer/render.mjs":{"sha256":"c77442c27041a5fe28269b8c80c9d24c72b73a226e8d4491e6d7285a9feb5309","size":19443},"viewer/shell.mjs":{"sha256":"5f800d0a97fe416d02cf9abef766d651b444b4745ad3a998926599469358ca79","size":9408}}}
1
+ {"buildSchema":"1","version":"0.1.3","dirty":false,"commit":"541bc4d2e4710b411202882ec2480801994b6cf9","sourceSha256":"429745022e980eb8d09b1c6a6614b8b25f49921bd1883b0b111dfd5c3137ada3","packageSha256":"28210403766aff6ca070f8ca93df42117e93eedb5005b2a1b1fec4ee2f68c0c0","lockfileSha256":"2f632db652163f9f8f55ed649962fc5e4f718daf2edf6b0f0eea5d9501013dac","files":{"cli/batch.mjs":{"sha256":"101f7ecb4c3d5890c42f402e5ca00ab97351c4a4d90e07a1fa4367e3c0807650","size":7296},"cli/hosted.mjs":{"sha256":"dea7b512a2e811102521565e9f218c77aab916fe05e838f55a9aeb7b43cd0852","size":7436},"cli/main.mjs":{"sha256":"c4429dd331b377a1b1ca9b25a04721d51f38c39ee395de2239d0ad2bf7ccb57c","size":6825},"cli/scan.mjs":{"sha256":"9bf33e926ededf1beb1e4af73c861ba5bf33bee74ca0544151112284e0afc1b5","size":3906},"core/acquire.mjs":{"sha256":"aee5ed002292edf1b03385ceec8ebfb03de452dba36bbdced96f888eaafa1d67","size":9549},"core/advisories.mjs":{"sha256":"388088e44422ffeb3b60d930c84cec29fbc89b98d8dfd2879bc6ede50f4e7ea9","size":13004},"core/archive.mjs":{"sha256":"80aa4373c0324458fe322a83af18a4cfd0ffec4b39ebdeffc9084639a8655410","size":16193},"core/compare.mjs":{"sha256":"540614266e06a2875010793d036d256ddfac72f978157cd3d147ffb99015d8e4","size":7579},"core/manifests.mjs":{"sha256":"29c40e01ff1e1dfaed444600d8c78380d23d4bc9be71960251e39ea3594de2f1","size":17891},"core/online.mjs":{"sha256":"368a3f2558e16db0701d2eaf068b48e2661e7e01ab7cf5605cdd22766aeb5cca","size":9741},"core/package-details.mjs":{"sha256":"770551a6ab84e523dbc56ede6131b08eb22b8c21fc9c8b179fe0d1769fb2ec00","size":21538},"core/pipeline.mjs":{"sha256":"9c4ddc5c258a99455a1230c978fd132c135057ad7bb6c7baa201ae530ee136fd","size":11060},"core/policy.mjs":{"sha256":"4281c626c00a6424992f5e1eba26876e2b70f4b968450a8ca52fa42f5a121ba5","size":2954},"core/registry-facts.mjs":{"sha256":"726344597044b0c23fb74aff4fbfe7c60cbbfc4c0bee838abf9257134f9c96db","size":11013},"core/report-exploration.mjs":{"sha256":"1dcc9897d3bbc98ee3107ef8f8279d9eed6ee6d104455eb214a5e5644bd197fb","size":10137},"core/report.mjs":{"sha256":"aa167c94c257a5ff6d830630a37a51a9a9e47f82aa4a0a7b96ead91a5967294b","size":15844},"core/resolve.mjs":{"sha256":"d5575da49ff78e8fea8df1f2fc10a39540adea285eddfa347746e848f9fdf957","size":5202},"core/source.mjs":{"sha256":"798fe74e3fba836b82576cd46e1b91e6f6e0a4e3cf273c533b5e074247c81373","size":3238},"core/syntax.mjs":{"sha256":"2d50f2e73e17aedbcbccd92af280e171de4ef78b55acccd23d6b6ef11e891776","size":10450},"model/client.mjs":{"sha256":"efb68132710cbdff6b86b58cbac006c48e10f9317e852f00b120ef7c3c7ed9c1","size":42865},"model/config.mjs":{"sha256":"127605979a299616be15f4a47e94dcd82928b00ad2af71744ffaa6e359516486","size":3245},"server/app.mjs":{"sha256":"2aa5678bcdd38702707fa05ec7aa749d46f1590993e491ec0adc408a35d2f890","size":10498},"server/enrichment.mjs":{"sha256":"3c5cc57f2c8f019f79418457f366a9422e0a03a8ba86a41b0767aba636bde179","size":3825},"server/main.mjs":{"sha256":"e5bdcd02209c2ccc1ed8c73b85b9988d61aa3e1bcf7c8d119eed782a4bfcd224","size":4587},"server/queue.mjs":{"sha256":"23e30f3ff570771b77a244be9200ad510d2f19811eee566d68b364b7f741a9d7","size":7371},"server/registry-facts.mjs":{"sha256":"58bce5b2a40f25e7561f122ea012594c9eb6789f993ca83dadc07f198afca9e3","size":3315},"server/report-exploration.mjs":{"sha256":"862b8d0ea07b627368aaca3a0f66359cfc638b14c54ab4158f8ef313602c3810","size":2774},"server/runner.mjs":{"sha256":"a6ca5bfbd7b239f7110639d854ca9a263f4cf3aaf06701ea54493b29f8244706","size":9071},"server/store.mjs":{"sha256":"efa2a35c7e9d0344c26e24ba360a457cdf80f4f48975f0186f81844b9fb7a097","size":2706},"server/worker.mjs":{"sha256":"1df839608cd1c691fc2801d89e698daeef3e48d7f4b8843ce1252a21fde9730a","size":1902},"viewer/render.mjs":{"sha256":"c77442c27041a5fe28269b8c80c9d24c72b73a226e8d4491e6d7285a9feb5309","size":19443},"viewer/shell.mjs":{"sha256":"5f800d0a97fe416d02cf9abef766d651b444b4745ad3a998926599469358ca79","size":9408}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xagents_in/unmask",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "description": "Evidence-based comparison of npm packages and their source archives",
6
6
  "license": "MIT",