@floegence/flowersec-core 2.5.4 → 3.0.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.
Files changed (103) hide show
  1. package/README.md +46 -18
  2. package/dist/browser/connectSessionV3.d.ts +13 -0
  3. package/dist/browser/connectSessionV3.js +75 -0
  4. package/dist/browser/index.d.ts +3 -2
  5. package/dist/browser/index.js +2 -1
  6. package/dist/browser/v2.d.ts +3 -0
  7. package/dist/browser/v2.js +2 -0
  8. package/dist/facade.d.ts +15 -8
  9. package/dist/facade.js +5 -4
  10. package/dist/interop/proxyServerPeer.js +1 -1
  11. package/dist/interop/serverParityPeer.js +8 -1
  12. package/dist/node/acceptor.d.ts +10 -0
  13. package/dist/node/acceptor.js +45 -2
  14. package/dist/node/acceptorV3.d.ts +57 -0
  15. package/dist/node/acceptorV3.js +227 -0
  16. package/dist/node/connectSessionV3.d.ts +21 -0
  17. package/dist/node/connectSessionV3.js +73 -0
  18. package/dist/node/index.d.ts +15 -10
  19. package/dist/node/index.js +6 -5
  20. package/dist/node/nativeTransportAddon.d.ts +39 -1
  21. package/dist/node/nativeTransportAddon.js +29 -5
  22. package/dist/node/rawQuicAdapterV3.d.ts +10 -0
  23. package/dist/node/rawQuicAdapterV3.js +76 -0
  24. package/dist/node/rawQuicServerV3.d.ts +24 -0
  25. package/dist/node/rawQuicServerV3.js +34 -0
  26. package/dist/node/runtimeAuthorizationV3.d.ts +29 -0
  27. package/dist/node/runtimeAuthorizationV3.js +126 -0
  28. package/dist/node/tunnelRuntimeV3.d.ts +57 -0
  29. package/dist/node/tunnelRuntimeV3.js +857 -0
  30. package/dist/node/v2.d.ts +11 -0
  31. package/dist/node/v2.js +6 -0
  32. package/dist/node/webSocketServerV3.d.ts +27 -0
  33. package/dist/node/webSocketServerV3.js +219 -0
  34. package/dist/public/streamHandlers.d.ts +3 -0
  35. package/dist/public/streamHandlers.js +6 -1
  36. package/dist/v2/index.d.ts +14 -0
  37. package/dist/v2/index.js +7 -0
  38. package/dist/v2/protocol.js +23 -32
  39. package/dist/v2/session.d.ts +5 -0
  40. package/dist/v2/session.js +90 -35
  41. package/dist/v3/admissionError.d.ts +4 -0
  42. package/dist/v3/admissionError.js +8 -0
  43. package/dist/v3/artifact.d.ts +145 -0
  44. package/dist/v3/artifact.js +1162 -0
  45. package/dist/v3/artifactLease.d.ts +17 -0
  46. package/dist/v3/artifactLease.js +109 -0
  47. package/dist/v3/browserRuntime.d.ts +37 -0
  48. package/dist/v3/browserRuntime.js +197 -0
  49. package/dist/v3/browserSessionRuntime.d.ts +2 -0
  50. package/dist/v3/browserSessionRuntime.js +21 -0
  51. package/dist/v3/capability.d.ts +32 -0
  52. package/dist/v3/capability.js +345 -0
  53. package/dist/v3/carrier.d.ts +84 -0
  54. package/dist/v3/carrier.js +411 -0
  55. package/dist/v3/connectionController.d.ts +87 -0
  56. package/dist/v3/connectionController.js +805 -0
  57. package/dist/v3/contract.d.ts +65 -0
  58. package/dist/v3/contract.js +3 -0
  59. package/dist/v3/controller.d.ts +43 -0
  60. package/dist/v3/controller.js +303 -0
  61. package/dist/v3/handshake.d.ts +81 -0
  62. package/dist/v3/handshake.js +471 -0
  63. package/dist/v3/jcs.d.ts +6 -0
  64. package/dist/v3/jcs.js +69 -0
  65. package/dist/v3/jsonPreflight.d.ts +1 -0
  66. package/dist/v3/jsonPreflight.js +251 -0
  67. package/dist/v3/nodeRuntime.d.ts +40 -0
  68. package/dist/v3/nodeRuntime.js +315 -0
  69. package/dist/v3/nodeSessionRuntime.d.ts +2 -0
  70. package/dist/v3/nodeSessionRuntime.js +13 -0
  71. package/dist/v3/protocol.d.ts +99 -0
  72. package/dist/v3/protocol.js +773 -0
  73. package/dist/v3/publicApi.d.ts +12 -0
  74. package/dist/v3/publicApi.js +46 -0
  75. package/dist/v3/publicSession.d.ts +1 -0
  76. package/dist/v3/publicSession.js +281 -0
  77. package/dist/v3/retryDisposition.d.ts +16 -0
  78. package/dist/v3/retryDisposition.js +30 -0
  79. package/dist/v3/runtimeAdapters.d.ts +9 -0
  80. package/dist/v3/runtimeAdapters.js +109 -0
  81. package/dist/v3/security.d.ts +34 -0
  82. package/dist/v3/security.js +100 -0
  83. package/dist/v3/serverAdmission.d.ts +38 -0
  84. package/dist/v3/serverAdmission.js +223 -0
  85. package/dist/v3/session.d.ts +318 -0
  86. package/dist/v3/session.js +2289 -0
  87. package/dist/v3/sessionConnector.d.ts +37 -0
  88. package/dist/v3/sessionConnector.js +440 -0
  89. package/dist/v3/streamLifetimeLedger.d.ts +31 -0
  90. package/dist/v3/streamLifetimeLedger.js +131 -0
  91. package/dist/v3/streamMetadata.d.ts +1 -0
  92. package/dist/v3/streamMetadata.js +7 -0
  93. package/dist/v3/transportConstants.d.ts +56 -0
  94. package/dist/v3/transportConstants.js +59 -0
  95. package/dist/v3/unreliableMessage.d.ts +44 -0
  96. package/dist/v3/unreliableMessage.js +284 -0
  97. package/dist/v3/webSocketCarrier.d.ts +31 -0
  98. package/dist/v3/webSocketCarrier.js +370 -0
  99. package/dist/v3/webTransportCarrier.d.ts +27 -0
  100. package/dist/v3/webTransportCarrier.js +534 -0
  101. package/package.json +4 -4
  102. package/sbom/cyclonedx.json +6 -6
  103. package/sbom/spdx.json +11 -11
@@ -0,0 +1,29 @@
1
+ import { type ArtifactHandleV3 } from "../v3/publicApi.js";
2
+ /** Opaque, secret-free authorization lookup for one observed FSB3 request. */
3
+ export declare class RuntimeAuthorizationRequestV3 {
4
+ #private;
5
+ private constructor();
6
+ /** Returns the non-secret credential digest used to locate authorization state. */
7
+ lookupKey(): string;
8
+ toString(): string;
9
+ toJSON(): Readonly<Record<string, never>>;
10
+ }
11
+ /**
12
+ * Opaque, secret-free proof that a tunnel authorization record exactly matched
13
+ * one observed FSB3 request.
14
+ */
15
+ export declare class TunnelAuthorizationGrantV3 {
16
+ private readonly tunnelAuthorizationGrantBrand;
17
+ private constructor();
18
+ toString(): string;
19
+ toJSON(): Readonly<Record<string, never>>;
20
+ }
21
+ export type TunnelAuthorizationGrantOptionsV3 = Readonly<{
22
+ leaseId: string;
23
+ allowReplacement?: boolean;
24
+ }>;
25
+ /**
26
+ * Verifies a trusted authorization artifact against the complete observed FSB3
27
+ * and mints a request-bound grant that contains no artifact secrets.
28
+ */
29
+ export declare function verifyTunnelAuthorizationGrantV3(request: RuntimeAuthorizationRequestV3, artifactHandle: ArtifactHandleV3, options: TunnelAuthorizationGrantOptionsV3): TunnelAuthorizationGrantV3;
@@ -0,0 +1,126 @@
1
+ import { createHash, timingSafeEqual } from "node:crypto";
2
+ import { buildFSB3RequestV3, encodeFSB3RequestV3, } from "../v3/artifact.js";
3
+ import { unwrapArtifactHandleV3, } from "../v3/publicApi.js";
4
+ const ID = /^[A-Za-z0-9._~-]{1,128}$/u;
5
+ const requests = new WeakMap();
6
+ /** Opaque, secret-free authorization lookup for one observed FSB3 request. */
7
+ export class RuntimeAuthorizationRequestV3 {
8
+ #lookupKey;
9
+ constructor(lookupKey) {
10
+ this.#lookupKey = lookupKey;
11
+ }
12
+ /** Returns the non-secret credential digest used to locate authorization state. */
13
+ lookupKey() { return this.#lookupKey; }
14
+ toString() { return "Flowersec.RuntimeAuthorizationRequestV3"; }
15
+ toJSON() { return Object.freeze({}); }
16
+ /** @internal */
17
+ static fromDecoded(decoded) {
18
+ const credential = decoded.request.pathKind === "direct"
19
+ ? decoded.request.routing_token
20
+ : decoded.request.attach_token;
21
+ const lookupKey = createHash("sha256").update(credential, "utf8").digest("base64url");
22
+ const request = new RuntimeAuthorizationRequestV3(lookupKey);
23
+ requests.set(request, Object.freeze({
24
+ lookupKey,
25
+ decoded,
26
+ requestDigest: createHash("sha256").update(decoded.raw).digest(),
27
+ }));
28
+ Object.freeze(request);
29
+ return request;
30
+ }
31
+ }
32
+ /**
33
+ * Opaque, secret-free proof that a tunnel authorization record exactly matched
34
+ * one observed FSB3 request.
35
+ */
36
+ export class TunnelAuthorizationGrantV3 {
37
+ constructor() { }
38
+ toString() { return "Flowersec.TunnelAuthorizationGrantV3"; }
39
+ toJSON() { return Object.freeze({}); }
40
+ }
41
+ const grants = new WeakMap();
42
+ /**
43
+ * Verifies a trusted authorization artifact against the complete observed FSB3
44
+ * and mints a request-bound grant that contains no artifact secrets.
45
+ */
46
+ export function verifyTunnelAuthorizationGrantV3(request, artifactHandle, options) {
47
+ const observed = requests.get(request);
48
+ if (observed === undefined || typeof options !== "object" || options === null ||
49
+ !ID.test(options.leaseId) ||
50
+ (options.allowReplacement !== undefined && typeof options.allowReplacement !== "boolean")) {
51
+ throw invalidAuthorization();
52
+ }
53
+ try {
54
+ const artifact = unwrapArtifactHandleV3(artifactHandle);
55
+ const received = observed.decoded.request;
56
+ if (artifact.path.kind !== "tunnel" || received.pathKind !== "tunnel" ||
57
+ artifact.session.init_expire_at_unix_s <= Math.floor(Date.now() / 1_000) ||
58
+ artifact.path.expected_peer_endpoint_instance_id === received.endpoint_instance_id) {
59
+ throw invalidAuthorization();
60
+ }
61
+ const expected = encodeFSB3RequestV3(buildFSB3RequestV3(artifact, received.chosen_candidate_id));
62
+ if (!constantTimeEqual(expected, observed.decoded.raw))
63
+ throw invalidAuthorization();
64
+ const grant = new TunnelAuthorizationGrantV3();
65
+ grants.set(grant, {
66
+ claims: Object.freeze({
67
+ requestDigest: observed.requestDigest.slice(),
68
+ credentialId: observed.lookupKey,
69
+ leaseId: options.leaseId,
70
+ expiresAtUnixSeconds: artifact.session.init_expire_at_unix_s,
71
+ expectedPeerEndpointInstanceId: artifact.path.expected_peer_endpoint_instance_id,
72
+ allowReplacement: options.allowReplacement === true,
73
+ }),
74
+ consumed: false,
75
+ });
76
+ return Object.freeze(grant);
77
+ }
78
+ catch (error) {
79
+ if (error instanceof TypeError && error.message === "invalid Flowersec tunnel authorization") {
80
+ throw error;
81
+ }
82
+ throw invalidAuthorization();
83
+ }
84
+ }
85
+ /** @internal */
86
+ export function inspectTunnelAuthorizationGrantV3(grant) {
87
+ return grants.get(grant)?.claims;
88
+ }
89
+ /** @internal */
90
+ export function validateTunnelAuthorizationGrantV3(grant, request) {
91
+ const record = grants.get(grant);
92
+ const claims = record?.claims;
93
+ const observed = requests.get(request);
94
+ if (record?.consumed !== false || claims === undefined || observed === undefined ||
95
+ claims.credentialId !== observed.lookupKey ||
96
+ !constantTimeEqual(claims.requestDigest, observed.requestDigest))
97
+ return undefined;
98
+ return claims;
99
+ }
100
+ /** @internal */
101
+ export function consumeTunnelAuthorizationGrantV3(grant, request) {
102
+ const claims = validateTunnelAuthorizationGrantV3(grant, request);
103
+ const record = grants.get(grant);
104
+ if (claims === undefined || record === undefined)
105
+ return undefined;
106
+ record.consumed = true;
107
+ return claims;
108
+ }
109
+ /** @internal */
110
+ export function retireTunnelAuthorizationGrantV3(grant) {
111
+ const record = grants.get(grant);
112
+ if (record === undefined || record.consumed)
113
+ return undefined;
114
+ record.consumed = true;
115
+ return record.claims;
116
+ }
117
+ /** @internal */
118
+ export function runtimeAuthorizationRequestV3FromDecoded(decoded) {
119
+ return RuntimeAuthorizationRequestV3.fromDecoded(decoded);
120
+ }
121
+ function constantTimeEqual(left, right) {
122
+ return left.length === right.length && timingSafeEqual(left, right);
123
+ }
124
+ function invalidAuthorization() {
125
+ return new TypeError("invalid Flowersec tunnel authorization");
126
+ }
@@ -0,0 +1,57 @@
1
+ import { type ReceivedSessionAdmissionV3 } from "../v3/serverAdmission.js";
2
+ import type { CarrierStreamV3 } from "../v3/carrier.js";
3
+ import type { OperationOptions } from "../public/contract.js";
4
+ import { type RuntimeAuthorizationRequestV3, type TunnelAuthorizationGrantV3 } from "./runtimeAuthorizationV3.js";
5
+ export type TunnelAuthorizationDecisionV3 = Readonly<{
6
+ decision: "allow";
7
+ grant: TunnelAuthorizationGrantV3;
8
+ }> | Readonly<{
9
+ decision: "reject" | "retry";
10
+ reason: string;
11
+ }>;
12
+ export type TunnelRuntimeListenerV3 = Readonly<{
13
+ carrier: "websocket";
14
+ host: string;
15
+ port: number;
16
+ tls: Readonly<{
17
+ certificate: string;
18
+ privateKey: string;
19
+ }>;
20
+ allowedOrigins: readonly string[];
21
+ }> | Readonly<{
22
+ carrier: "raw_quic";
23
+ host: string;
24
+ port: number;
25
+ tls: Readonly<{
26
+ certificate: string | Uint8Array;
27
+ privateKey: string | Uint8Array;
28
+ }>;
29
+ }>;
30
+ export type TunnelRuntimeOptionsV3 = Readonly<{
31
+ listeners: readonly TunnelRuntimeListenerV3[];
32
+ maxInboundStreams: number;
33
+ maxPendingLegs?: number;
34
+ maxActivePairs?: number;
35
+ maxConcurrentStreams?: number;
36
+ maxConcurrentAdmissions?: number;
37
+ pairTimeoutMs?: number;
38
+ admissionTimeoutMs?: number;
39
+ cleanupTimeoutMs?: number;
40
+ admissionReasons?: readonly string[];
41
+ authorize(request: RuntimeAuthorizationRequestV3, options: OperationOptions): Promise<TunnelAuthorizationDecisionV3>;
42
+ release?(leaseId: string, options: Readonly<{
43
+ signal: AbortSignal;
44
+ }>): Promise<void> | void;
45
+ }>;
46
+ export declare class TunnelRuntimeV3 {
47
+ private constructor();
48
+ start(): Promise<void>;
49
+ addresses(): readonly Readonly<{
50
+ host: string;
51
+ port: number;
52
+ }>[];
53
+ close(): Promise<void>;
54
+ }
55
+ export declare function createTunnelRuntimeV3(options: TunnelRuntimeOptionsV3): TunnelRuntimeV3;
56
+ export declare function spliceTunnelStreamsV3(left: CarrierStreamV3, right: CarrierStreamV3, signal: AbortSignal, halfCloseGraceMs?: number): Promise<void>;
57
+ export declare function respondTunnelPairAdmissionsV3(first: ReceivedSessionAdmissionV3, second: ReceivedSessionAdmissionV3, signal: AbortSignal, timeoutMs: number): Promise<void>;