@floegence/flowersec-core 2.4.1 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/framing/jsonframe.js +9 -2
- package/dist/node/acceptor.js +78 -60
- package/dist/node/controlplane.js +6 -2
- package/dist/public/artifactLease.js +2 -9
- package/dist/rpc/server.js +11 -2
- package/dist/rpc/validate.d.ts +2 -1
- package/dist/rpc/validate.js +25 -7
- package/package.json +3 -3
- package/sbom/cyclonedx.json +6 -6
- package/sbom/spdx.json +11 -11
|
@@ -2,7 +2,7 @@ import { readU32be, u32be } from "../utils/bin.js";
|
|
|
2
2
|
import { SDK_DEFAULTS } from "../defaults.js";
|
|
3
3
|
export const DEFAULT_MAX_JSON_FRAME_BYTES = SDK_DEFAULTS.rpc.maxJsonFrameBytes;
|
|
4
4
|
const te = new TextEncoder();
|
|
5
|
-
const td = new TextDecoder();
|
|
5
|
+
const td = new TextDecoder("utf-8", { fatal: true });
|
|
6
6
|
// JsonFramingError marks malformed or oversized frames.
|
|
7
7
|
export class JsonFramingError extends Error {
|
|
8
8
|
}
|
|
@@ -29,5 +29,12 @@ export async function readJsonFrame(readExactly, maxBytes) {
|
|
|
29
29
|
if (maxBytes > 0 && n > maxBytes)
|
|
30
30
|
throw new JsonFramingError("frame too large");
|
|
31
31
|
const payload = await read(n);
|
|
32
|
-
|
|
32
|
+
let text;
|
|
33
|
+
try {
|
|
34
|
+
text = td.decode(payload);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
throw new JsonFramingError("invalid UTF-8");
|
|
38
|
+
}
|
|
39
|
+
return JSON.parse(text);
|
|
33
40
|
}
|
package/dist/node/acceptor.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RpcRouter } from "../rpc/server.js";
|
|
2
|
+
import { assertRpcError } from "../rpc/validate.js";
|
|
2
3
|
import { acceptReceivedSessionV2, receiveSessionAdmissionV2, rejectSessionAdmissionV2, } from "../connector/sessionAcceptor.js";
|
|
3
4
|
import { nodeSessionRuntimeV2 } from "./sessionRuntime.js";
|
|
4
5
|
import { startNodeWebSocketServer, } from "./webSocketServer.js";
|
|
@@ -264,11 +265,27 @@ export class Acceptor {
|
|
|
264
265
|
}
|
|
265
266
|
async close() {
|
|
266
267
|
const state = acceptorState(this);
|
|
267
|
-
state.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
await
|
|
271
|
-
|
|
268
|
+
if (state.lifecycle.completion === undefined) {
|
|
269
|
+
state.lifecycle.completion = closeAcceptor(state);
|
|
270
|
+
}
|
|
271
|
+
await withCleanupTimeout(state.lifecycle.completion, state.cleanupTimeoutMs);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
const MAX_CONCURRENT_ADMISSIONS = 64;
|
|
275
|
+
const MAX_PENDING_ACCEPTED_SESSIONS = 64;
|
|
276
|
+
async function closeAcceptor(state) {
|
|
277
|
+
state.abort.abort();
|
|
278
|
+
const queued = state.accepted.close();
|
|
279
|
+
const cleanup = await Promise.allSettled([
|
|
280
|
+
...state.listeners.map(async (listener) => await listener.close()),
|
|
281
|
+
...queued.map(async (accepted) => await accepted.close()),
|
|
282
|
+
]);
|
|
283
|
+
while (state.tasks.size > 0) {
|
|
284
|
+
await Promise.allSettled([...state.tasks]);
|
|
285
|
+
}
|
|
286
|
+
if (cleanup.some((result) => result.status === "rejected") ||
|
|
287
|
+
state.lifecycle.cleanupFailed) {
|
|
288
|
+
throw new SessionError("operation_failed");
|
|
272
289
|
}
|
|
273
290
|
}
|
|
274
291
|
async function releaseLease(state, leaseId) {
|
|
@@ -280,7 +297,7 @@ async function authorizeCarrier(state, carrier) {
|
|
|
280
297
|
const received = await receiveSessionAdmissionV2(carrier, state.abort.signal);
|
|
281
298
|
const decoded = received.decoded;
|
|
282
299
|
const request = runtimeAuthorizationRequestFromDecoded(decoded);
|
|
283
|
-
const decision = await
|
|
300
|
+
const decision = await state.options.authorize(request, { signal: state.abort.signal });
|
|
284
301
|
if (decision.decision !== "allow") {
|
|
285
302
|
return await rejectSessionAdmissionV2(received, {
|
|
286
303
|
accepted: false,
|
|
@@ -294,9 +311,7 @@ async function authorizeCarrier(state, carrier) {
|
|
|
294
311
|
try {
|
|
295
312
|
const registry = state.options.resolveHandlers === undefined
|
|
296
313
|
? new SessionHandlers()
|
|
297
|
-
: await
|
|
298
|
-
signal: state.abort.signal,
|
|
299
|
-
})), state.abort.signal);
|
|
314
|
+
: await state.options.resolveHandlers(request, { signal: state.abort.signal });
|
|
300
315
|
const handlers = freezeSessionHandlers(registry);
|
|
301
316
|
const leg = {
|
|
302
317
|
received,
|
|
@@ -326,28 +341,50 @@ async function processCarrier(state, carrier) {
|
|
|
326
341
|
const leg = await authorizeCarrier(state, carrier);
|
|
327
342
|
if (leg === undefined)
|
|
328
343
|
return;
|
|
344
|
+
let releaseOwnedByAcceptedSession = false;
|
|
329
345
|
try {
|
|
330
346
|
if (leg.received.decoded.request.pathKind !== "direct" ||
|
|
331
347
|
leg.artifact.path.kind !== "direct") {
|
|
332
348
|
await leg.received.carrier.close().catch(() => undefined);
|
|
333
349
|
throw new SessionError("operation_failed");
|
|
334
350
|
}
|
|
335
|
-
|
|
351
|
+
const accepted = await establishDirect(leg, state.abort.signal, leg.leaseId === undefined ? undefined : () => releaseLease(state, leg.leaseId));
|
|
352
|
+
releaseOwnedByAcceptedSession = true;
|
|
353
|
+
if (state.accepted.push(accepted) === "rejected") {
|
|
354
|
+
try {
|
|
355
|
+
await accepted.close();
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
state.lifecycle.cleanupFailed = true;
|
|
359
|
+
throw new SessionError("operation_failed");
|
|
360
|
+
}
|
|
361
|
+
}
|
|
336
362
|
}
|
|
337
363
|
catch (error) {
|
|
338
|
-
|
|
364
|
+
if (!releaseOwnedByAcceptedSession) {
|
|
365
|
+
await releaseLease(state, leg.leaseId).catch(() => undefined);
|
|
366
|
+
}
|
|
339
367
|
throw error;
|
|
340
368
|
}
|
|
341
369
|
}
|
|
342
370
|
async function runAcceptLoop(state) {
|
|
343
371
|
while (!state.abort.signal.aborted) {
|
|
344
372
|
try {
|
|
373
|
+
while (state.admissions.size >= MAX_CONCURRENT_ADMISSIONS) {
|
|
374
|
+
await Promise.race(state.admissions);
|
|
375
|
+
if (state.abort.signal.aborted)
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
345
378
|
const carrier = await state.accept({ signal: state.abort.signal });
|
|
346
379
|
const task = processCarrier(state, carrier)
|
|
347
380
|
.catch(async () => {
|
|
348
381
|
await carrier.close().catch(() => undefined);
|
|
349
382
|
})
|
|
350
|
-
.finally(() =>
|
|
383
|
+
.finally(() => {
|
|
384
|
+
state.admissions.delete(task);
|
|
385
|
+
state.tasks.delete(task);
|
|
386
|
+
});
|
|
387
|
+
state.admissions.add(task);
|
|
351
388
|
state.tasks.add(task);
|
|
352
389
|
}
|
|
353
390
|
catch (error) {
|
|
@@ -362,16 +399,19 @@ class AcceptedQueue {
|
|
|
362
399
|
waiters = new Set();
|
|
363
400
|
failure;
|
|
364
401
|
push(value) {
|
|
365
|
-
if (this.failure !== undefined)
|
|
366
|
-
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
402
|
+
if (this.failure !== undefined)
|
|
403
|
+
return "rejected";
|
|
369
404
|
const waiter = this.waiters.values().next().value;
|
|
370
|
-
if (waiter === undefined)
|
|
405
|
+
if (waiter === undefined) {
|
|
406
|
+
if (this.values.length >= MAX_PENDING_ACCEPTED_SESSIONS)
|
|
407
|
+
return "rejected";
|
|
371
408
|
this.values.push(value);
|
|
409
|
+
return "queued";
|
|
410
|
+
}
|
|
372
411
|
else {
|
|
373
412
|
this.waiters.delete(waiter);
|
|
374
413
|
waiter.resolve(value);
|
|
414
|
+
return "delivered";
|
|
375
415
|
}
|
|
376
416
|
}
|
|
377
417
|
async shift(signal) {
|
|
@@ -412,6 +452,7 @@ class AcceptedQueue {
|
|
|
412
452
|
}
|
|
413
453
|
close() {
|
|
414
454
|
this.fail(new SessionError("closed"));
|
|
455
|
+
return this.values.splice(0);
|
|
415
456
|
}
|
|
416
457
|
}
|
|
417
458
|
const acceptorStates = new WeakMap();
|
|
@@ -482,6 +523,7 @@ export async function createAcceptor(options) {
|
|
|
482
523
|
const accepted = new AcceptedQueue();
|
|
483
524
|
const abort = new AbortController();
|
|
484
525
|
const tasks = new Set();
|
|
526
|
+
const admissions = new Set();
|
|
485
527
|
let started = false;
|
|
486
528
|
const state = {
|
|
487
529
|
listeners,
|
|
@@ -490,7 +532,9 @@ export async function createAcceptor(options) {
|
|
|
490
532
|
accepted,
|
|
491
533
|
abort,
|
|
492
534
|
tasks,
|
|
535
|
+
admissions,
|
|
493
536
|
cleanupTimeoutMs,
|
|
537
|
+
lifecycle: { cleanupFailed: false },
|
|
494
538
|
start() {
|
|
495
539
|
if (started)
|
|
496
540
|
return;
|
|
@@ -502,52 +546,26 @@ export async function createAcceptor(options) {
|
|
|
502
546
|
acceptorStates.set(acceptor, state);
|
|
503
547
|
return Object.freeze(acceptor);
|
|
504
548
|
}
|
|
505
|
-
async function
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
return;
|
|
520
|
-
settled = true;
|
|
521
|
-
cleanup();
|
|
522
|
-
reject(signal.reason instanceof Error ? signal.reason : new SessionError("closed"));
|
|
523
|
-
};
|
|
524
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
525
|
-
void promise.then((value) => {
|
|
526
|
-
if (settled)
|
|
527
|
-
return;
|
|
528
|
-
settled = true;
|
|
529
|
-
cleanup();
|
|
530
|
-
resolve(value);
|
|
531
|
-
}, (error) => {
|
|
532
|
-
if (settled)
|
|
533
|
-
return;
|
|
534
|
-
settled = true;
|
|
535
|
-
cleanup();
|
|
536
|
-
reject(error);
|
|
537
|
-
});
|
|
538
|
-
});
|
|
549
|
+
async function withCleanupTimeout(completion, timeoutMs) {
|
|
550
|
+
let timer;
|
|
551
|
+
try {
|
|
552
|
+
await Promise.race([
|
|
553
|
+
completion,
|
|
554
|
+
new Promise((_, reject) => {
|
|
555
|
+
timer = setTimeout(() => reject(new SessionError("timeout")), timeoutMs);
|
|
556
|
+
}),
|
|
557
|
+
]);
|
|
558
|
+
}
|
|
559
|
+
finally {
|
|
560
|
+
if (timer !== undefined)
|
|
561
|
+
clearTimeout(timer);
|
|
562
|
+
}
|
|
539
563
|
}
|
|
540
564
|
function validRPCError(error) {
|
|
541
|
-
|
|
542
|
-
error
|
|
543
|
-
error.code > 0xffff_ffff) {
|
|
544
|
-
return { code: 500, message: "handler failed" };
|
|
565
|
+
try {
|
|
566
|
+
return assertRpcError(error);
|
|
545
567
|
}
|
|
546
|
-
|
|
547
|
-
encoder.encode(error.message).length > 1024) {
|
|
568
|
+
catch {
|
|
548
569
|
return { code: 500, message: "handler failed" };
|
|
549
570
|
}
|
|
550
|
-
return error.message === undefined
|
|
551
|
-
? { code: error.code }
|
|
552
|
-
: { code: error.code, message: error.message };
|
|
553
571
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { randomBytes as nodeRandomBytes } from "node:crypto";
|
|
1
|
+
import { randomBytes as nodeRandomBytes, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { buildFSB2RequestV2, canonicalizeCandidatesV2, computeSessionContractHashV2, decodeArtifactV2JSON, decodeFSB2RequestV2, encodeArtifactV2JSON, encodeFSB2RequestV2, } from "../v2/artifact.js";
|
|
3
3
|
import { wrapArtifact } from "../public/artifact.js";
|
|
4
4
|
import { base64urlDecode, base64urlEncode } from "../utils/base64url.js";
|
|
@@ -413,7 +413,11 @@ function validTCPAddress(value) {
|
|
|
413
413
|
return port >= 1 && port <= 65_535;
|
|
414
414
|
}
|
|
415
415
|
function validObservedText(value) { return value.length > 0 && value.length <= 512 && !/[\u0000-\u001f\u007f]/u.test(value); }
|
|
416
|
-
function bytesEqual(a, b) {
|
|
416
|
+
function bytesEqual(a, b) {
|
|
417
|
+
if (a.length !== b.length)
|
|
418
|
+
return false;
|
|
419
|
+
return timingSafeEqual(a, b);
|
|
420
|
+
}
|
|
417
421
|
function strictObject(bytes) {
|
|
418
422
|
let value;
|
|
419
423
|
try {
|
|
@@ -36,13 +36,6 @@ export async function commitArtifactLeaseSpend(lease, signal) {
|
|
|
36
36
|
const leaseState = artifactLeaseStates.get(lease);
|
|
37
37
|
if (leaseState === undefined || leaseState.state !== "idle")
|
|
38
38
|
throw new ArtifactLeaseError();
|
|
39
|
-
leaseState.state = "
|
|
40
|
-
|
|
41
|
-
await leaseState.commitSpend(signal);
|
|
42
|
-
leaseState.state = "consumed";
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
leaseState.state = "idle";
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
39
|
+
leaseState.state = "consumed";
|
|
40
|
+
await leaseState.commitSpend(signal);
|
|
48
41
|
}
|
package/dist/rpc/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_MAX_JSON_FRAME_BYTES, readJsonFrame, writeJsonFrame } from "../framing/jsonframe.js";
|
|
2
|
-
import { assertRpcEnvelope } from "./validate.js";
|
|
2
|
+
import { assertRpcEnvelope, assertRpcError } from "./validate.js";
|
|
3
3
|
import { SDK_DEFAULTS } from "../defaults.js";
|
|
4
4
|
const DEFAULT_RPC_SERVER_OPTIONS = Object.freeze({
|
|
5
5
|
maxConcurrentRequests: SDK_DEFAULTS.rpc.maxConcurrentRequests,
|
|
@@ -217,12 +217,21 @@ export class RpcServer {
|
|
|
217
217
|
waiters.shift()?.();
|
|
218
218
|
}
|
|
219
219
|
async writeResponse(request, out) {
|
|
220
|
+
let error;
|
|
221
|
+
if (out.error != null) {
|
|
222
|
+
try {
|
|
223
|
+
error = assertRpcError(out.error);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
error = { code: 500, message: "internal error" };
|
|
227
|
+
}
|
|
228
|
+
}
|
|
220
229
|
const resp = {
|
|
221
230
|
type_id: request.type_id,
|
|
222
231
|
request_id: 0,
|
|
223
232
|
response_to: request.request_id,
|
|
224
233
|
payload: out.payload,
|
|
225
|
-
...(
|
|
234
|
+
...(error != null ? { error } : {}),
|
|
226
235
|
};
|
|
227
236
|
await this.writeEnvelope(resp);
|
|
228
237
|
}
|
package/dist/rpc/validate.d.ts
CHANGED
package/dist/rpc/validate.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { isSafeU32Number, isSafeU64Number } from "../utils/number.js";
|
|
2
|
+
const encoder = new TextEncoder();
|
|
3
|
+
const strictDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
2
4
|
// assertRpcEnvelope validates numeric fields that are u32/u64 in the IDL.
|
|
3
5
|
//
|
|
4
6
|
// The wire format is JSON, so JS numbers are used. For u64 we enforce the safe integer range
|
|
@@ -15,13 +17,29 @@ export function assertRpcEnvelope(v) {
|
|
|
15
17
|
throw new Error("bad rpc envelope: response_to");
|
|
16
18
|
// payload: unknown (JSON)
|
|
17
19
|
if (o.error != null) {
|
|
18
|
-
|
|
19
|
-
throw new Error("bad rpc envelope: error");
|
|
20
|
-
if (!isSafeU32Number(o.error.code))
|
|
21
|
-
throw new Error("bad rpc envelope: error.code");
|
|
22
|
-
const msg = o.error.message;
|
|
23
|
-
if (msg !== undefined && typeof msg !== "string")
|
|
24
|
-
throw new Error("bad rpc envelope: error.message");
|
|
20
|
+
assertRpcError(o.error);
|
|
25
21
|
}
|
|
26
22
|
return o;
|
|
27
23
|
}
|
|
24
|
+
export function assertRpcError(value) {
|
|
25
|
+
if (typeof value !== "object" || value == null)
|
|
26
|
+
throw new Error("bad rpc envelope: error");
|
|
27
|
+
const error = value;
|
|
28
|
+
if (Object.keys(error).some((key) => key !== "code" && key !== "message")) {
|
|
29
|
+
throw new Error("bad rpc envelope: error shape");
|
|
30
|
+
}
|
|
31
|
+
if (!isSafeU32Number(error.code) || error.code === 0) {
|
|
32
|
+
throw new Error("bad rpc envelope: error.code");
|
|
33
|
+
}
|
|
34
|
+
const message = error.message;
|
|
35
|
+
if (message !== undefined && typeof message !== "string") {
|
|
36
|
+
throw new Error("bad rpc envelope: error.message");
|
|
37
|
+
}
|
|
38
|
+
if (typeof message === "string") {
|
|
39
|
+
const encoded = encoder.encode(message);
|
|
40
|
+
if (encoded.byteLength > 1_024 || strictDecoder.decode(encoded) !== message) {
|
|
41
|
+
throw new Error("bad rpc envelope: error.message");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return message === undefined ? { code: error.code } : { code: error.code, message };
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@floegence/flowersec-core",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"description": "Flowersec core TypeScript library for carrier-neutral encrypted sessions and multiplexed streams.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"ws": "^8.21.2"
|
|
78
78
|
},
|
|
79
79
|
"optionalDependencies": {
|
|
80
|
-
"@floegence/flowersec-node-native": "2.4.
|
|
80
|
+
"@floegence/flowersec-node-native": "2.4.2"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@playwright/test": "1.62.1",
|
|
@@ -95,5 +95,5 @@
|
|
|
95
95
|
"vite": "^8.2.1",
|
|
96
96
|
"vitest": "4.1.10"
|
|
97
97
|
},
|
|
98
|
-
"flowersecSourceCommit": "
|
|
98
|
+
"flowersecSourceCommit": "1393acdb891a6c935a435bee9068f65b68268795"
|
|
99
99
|
}
|
package/sbom/cyclonedx.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.5",
|
|
4
|
-
"serialNumber": "urn:uuid:
|
|
4
|
+
"serialNumber": "urn:uuid:a7cb7385-1123-5452-8424-bbcb7904bbbb",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
7
|
"component": {
|
|
8
8
|
"type": "library",
|
|
9
9
|
"name": "@floegence/flowersec-core",
|
|
10
|
-
"version": "2.4.
|
|
11
|
-
"purl": "pkg:npm/%40floegence/flowersec-core@2.4.
|
|
12
|
-
"bom-ref": "pkg:npm/%40floegence/flowersec-core@2.4.
|
|
10
|
+
"version": "2.4.2",
|
|
11
|
+
"purl": "pkg:npm/%40floegence/flowersec-core@2.4.2",
|
|
12
|
+
"bom-ref": "pkg:npm/%40floegence/flowersec-core@2.4.2"
|
|
13
13
|
},
|
|
14
14
|
"properties": [
|
|
15
15
|
{
|
|
16
16
|
"name": "flowersec:source-inventory-sha256",
|
|
17
|
-
"value": "
|
|
17
|
+
"value": "59d233df0e12f2c371ab542c83edf97a2968a75c7d17c057e453b97f530a90e4"
|
|
18
18
|
}
|
|
19
19
|
]
|
|
20
20
|
},
|
|
@@ -190,7 +190,7 @@
|
|
|
190
190
|
],
|
|
191
191
|
"dependencies": [
|
|
192
192
|
{
|
|
193
|
-
"ref": "pkg:npm/%40floegence/flowersec-core@2.4.
|
|
193
|
+
"ref": "pkg:npm/%40floegence/flowersec-core@2.4.2",
|
|
194
194
|
"dependsOn": [
|
|
195
195
|
"pkg:npm/%40noble/ciphers@2.3.0",
|
|
196
196
|
"pkg:npm/%40noble/curves@2.3.0",
|
package/sbom/spdx.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"dataLicense": "CC0-1.0",
|
|
4
4
|
"SPDXID": "SPDXRef-DOCUMENT",
|
|
5
5
|
"name": "flowersec-ts",
|
|
6
|
-
"documentNamespace": "https://github.com/floegence/flowersec/sbom/flowersec-ts/
|
|
6
|
+
"documentNamespace": "https://github.com/floegence/flowersec/sbom/flowersec-ts/59d233df0e12f2c371ab542c83edf97a2968a75c7d17c057e453b97f530a90e4",
|
|
7
7
|
"creationInfo": {
|
|
8
8
|
"created": "1970-01-01T00:00:00Z",
|
|
9
9
|
"creators": [
|
|
@@ -13,19 +13,19 @@
|
|
|
13
13
|
"packages": [
|
|
14
14
|
{
|
|
15
15
|
"name": "@floegence/flowersec-core",
|
|
16
|
-
"SPDXID": "SPDXRef-Package-
|
|
17
|
-
"versionInfo": "2.4.
|
|
16
|
+
"SPDXID": "SPDXRef-Package-9eec732cc29715c69e1e",
|
|
17
|
+
"versionInfo": "2.4.2",
|
|
18
18
|
"downloadLocation": "NOASSERTION",
|
|
19
19
|
"filesAnalyzed": false,
|
|
20
20
|
"licenseConcluded": "NOASSERTION",
|
|
21
21
|
"licenseDeclared": "NOASSERTION",
|
|
22
22
|
"copyrightText": "NOASSERTION",
|
|
23
|
-
"comment": "Flowersec source inventory SHA-256:
|
|
23
|
+
"comment": "Flowersec source inventory SHA-256: 59d233df0e12f2c371ab542c83edf97a2968a75c7d17c057e453b97f530a90e4",
|
|
24
24
|
"externalRefs": [
|
|
25
25
|
{
|
|
26
26
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
27
27
|
"referenceType": "purl",
|
|
28
|
-
"referenceLocator": "pkg:npm/%40floegence/flowersec-core@2.4.
|
|
28
|
+
"referenceLocator": "pkg:npm/%40floegence/flowersec-core@2.4.2"
|
|
29
29
|
}
|
|
30
30
|
]
|
|
31
31
|
},
|
|
@@ -136,30 +136,30 @@
|
|
|
136
136
|
{
|
|
137
137
|
"spdxElementId": "SPDXRef-DOCUMENT",
|
|
138
138
|
"relationshipType": "DESCRIBES",
|
|
139
|
-
"relatedSpdxElement": "SPDXRef-Package-
|
|
139
|
+
"relatedSpdxElement": "SPDXRef-Package-9eec732cc29715c69e1e"
|
|
140
140
|
},
|
|
141
141
|
{
|
|
142
|
-
"spdxElementId": "SPDXRef-Package-
|
|
142
|
+
"spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
|
|
143
143
|
"relationshipType": "DEPENDS_ON",
|
|
144
144
|
"relatedSpdxElement": "SPDXRef-Package-5ce913a03239b02770fb"
|
|
145
145
|
},
|
|
146
146
|
{
|
|
147
|
-
"spdxElementId": "SPDXRef-Package-
|
|
147
|
+
"spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
|
|
148
148
|
"relationshipType": "DEPENDS_ON",
|
|
149
149
|
"relatedSpdxElement": "SPDXRef-Package-01009adf60db02c13634"
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
|
-
"spdxElementId": "SPDXRef-Package-
|
|
152
|
+
"spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
|
|
153
153
|
"relationshipType": "DEPENDS_ON",
|
|
154
154
|
"relatedSpdxElement": "SPDXRef-Package-8815b117c8a1d5f7eeb0"
|
|
155
155
|
},
|
|
156
156
|
{
|
|
157
|
-
"spdxElementId": "SPDXRef-Package-
|
|
157
|
+
"spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
|
|
158
158
|
"relationshipType": "DEPENDS_ON",
|
|
159
159
|
"relatedSpdxElement": "SPDXRef-Package-f8b45a289df643042b94"
|
|
160
160
|
},
|
|
161
161
|
{
|
|
162
|
-
"spdxElementId": "SPDXRef-Package-
|
|
162
|
+
"spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
|
|
163
163
|
"relationshipType": "DEPENDS_ON",
|
|
164
164
|
"relatedSpdxElement": "SPDXRef-Package-b779412f685822663496"
|
|
165
165
|
},
|