@viewportai/daemon 0.1.0 → 0.2.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/dist/cli/commands.d.ts +1 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +1 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/daemon-lifecycle.d.ts +3 -0
- package/dist/cli/daemon-lifecycle.d.ts.map +1 -1
- package/dist/cli/daemon-lifecycle.js +11 -1
- package/dist/cli/daemon-lifecycle.js.map +1 -1
- package/dist/cli/daemon-settings.d.ts.map +1 -1
- package/dist/cli/daemon-settings.js +115 -3
- package/dist/cli/daemon-settings.js.map +1 -1
- package/dist/cli/lifecycle-commands.d.ts.map +1 -1
- package/dist/cli/lifecycle-commands.js +2 -0
- package/dist/cli/lifecycle-commands.js.map +1 -1
- package/dist/cli/remote-commands.d.ts +3 -0
- package/dist/cli/remote-commands.d.ts.map +1 -0
- package/dist/cli/remote-commands.js +236 -0
- package/dist/cli/remote-commands.js.map +1 -0
- package/dist/cli/setup-command.d.ts.map +1 -1
- package/dist/cli/setup-command.js +4 -1
- package/dist/cli/setup-command.js.map +1 -1
- package/dist/cli/supervisor-protocol.d.ts +12 -0
- package/dist/cli/supervisor-protocol.d.ts.map +1 -1
- package/dist/cli/supervisor.d.ts.map +1 -1
- package/dist/cli/supervisor.js +30 -0
- package/dist/cli/supervisor.js.map +1 -1
- package/dist/core/config-schema.d.ts +16 -0
- package/dist/core/config-schema.d.ts.map +1 -1
- package/dist/core/config-schema.js +12 -0
- package/dist/core/config-schema.js.map +1 -1
- package/dist/core/config.d.ts +23 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +46 -3
- package/dist/core/config.js.map +1 -1
- package/dist/core/session-state-file.d.ts.map +1 -1
- package/dist/core/session-state-file.js +3 -1
- package/dist/core/session-state-file.js.map +1 -1
- package/dist/core/types.d.ts +7 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/hooks/installers/claude.js +4 -1
- package/dist/hooks/installers/claude.js.map +1 -1
- package/dist/hooks/router.d.ts.map +1 -1
- package/dist/hooks/router.js +11 -0
- package/dist/hooks/router.js.map +1 -1
- package/dist/hooks/supervision.d.ts +2 -0
- package/dist/hooks/supervision.d.ts.map +1 -1
- package/dist/hooks/supervision.js +12 -0
- package/dist/hooks/supervision.js.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +14 -0
- package/dist/plugins/loader.js.map +1 -1
- package/dist/relay/bridge-backoff.d.ts +3 -0
- package/dist/relay/bridge-backoff.d.ts.map +1 -0
- package/dist/relay/bridge-backoff.js +10 -0
- package/dist/relay/bridge-backoff.js.map +1 -0
- package/dist/relay/bridge-constants.d.ts +12 -0
- package/dist/relay/bridge-constants.d.ts.map +1 -0
- package/dist/relay/bridge-constants.js +12 -0
- package/dist/relay/bridge-constants.js.map +1 -0
- package/dist/relay/bridge-crypto.d.ts +18 -0
- package/dist/relay/bridge-crypto.d.ts.map +1 -0
- package/dist/relay/bridge-crypto.js +63 -0
- package/dist/relay/bridge-crypto.js.map +1 -0
- package/dist/relay/bridge-errors.d.ts +6 -0
- package/dist/relay/bridge-errors.d.ts.map +1 -0
- package/dist/relay/bridge-errors.js +9 -0
- package/dist/relay/bridge-errors.js.map +1 -0
- package/dist/relay/bridge-jwt.d.ts +18 -0
- package/dist/relay/bridge-jwt.d.ts.map +1 -0
- package/dist/relay/bridge-jwt.js +130 -0
- package/dist/relay/bridge-jwt.js.map +1 -0
- package/dist/relay/bridge-key-exchange.d.ts +49 -0
- package/dist/relay/bridge-key-exchange.d.ts.map +1 -0
- package/dist/relay/bridge-key-exchange.js +234 -0
- package/dist/relay/bridge-key-exchange.js.map +1 -0
- package/dist/relay/bridge-network.d.ts +12 -0
- package/dist/relay/bridge-network.d.ts.map +1 -0
- package/dist/relay/bridge-network.js +90 -0
- package/dist/relay/bridge-network.js.map +1 -0
- package/dist/relay/bridge-noise-v3.d.ts +74 -0
- package/dist/relay/bridge-noise-v3.d.ts.map +1 -0
- package/dist/relay/bridge-noise-v3.js +403 -0
- package/dist/relay/bridge-noise-v3.js.map +1 -0
- package/dist/relay/daemon-relay-bridge.d.ts +93 -0
- package/dist/relay/daemon-relay-bridge.d.ts.map +1 -0
- package/dist/relay/daemon-relay-bridge.js +1005 -0
- package/dist/relay/daemon-relay-bridge.js.map +1 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +9 -7
- package/dist/server/auth.js.map +1 -1
- package/dist/server/http-server.d.ts +6 -0
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/http-server.js +102 -15
- package/dist/server/http-server.js.map +1 -1
- package/dist/server/pairing-offers.d.ts +2 -1
- package/dist/server/pairing-offers.d.ts.map +1 -1
- package/dist/server/pairing-offers.js +438 -204
- package/dist/server/pairing-offers.js.map +1 -1
- package/dist/server/ring-buffer.d.ts +48 -7
- package/dist/server/ring-buffer.d.ts.map +1 -1
- package/dist/server/ring-buffer.js +387 -14
- package/dist/server/ring-buffer.js.map +1 -1
- package/dist/server/security.d.ts.map +1 -1
- package/dist/server/security.js +5 -1
- package/dist/server/security.js.map +1 -1
- package/dist/server/ws-command-handlers.d.ts.map +1 -1
- package/dist/server/ws-command-handlers.js +18 -6
- package/dist/server/ws-command-handlers.js.map +1 -1
- package/dist/server/ws-daemon-event-bridge.d.ts.map +1 -1
- package/dist/server/ws-daemon-event-bridge.js +14 -2
- package/dist/server/ws-daemon-event-bridge.js.map +1 -1
- package/dist/server/ws-server.d.ts.map +1 -1
- package/dist/server/ws-server.js +26 -3
- package/dist/server/ws-server.js.map +1 -1
- package/dist/startup-relay-security.d.ts +3 -0
- package/dist/startup-relay-security.d.ts.map +1 -0
- package/dist/startup-relay-security.js +61 -0
- package/dist/startup-relay-security.js.map +1 -0
- package/dist/startup-session-persistence.d.ts +7 -0
- package/dist/startup-session-persistence.d.ts.map +1 -0
- package/dist/startup-session-persistence.js +72 -0
- package/dist/startup-session-persistence.js.map +1 -0
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +115 -65
- package/dist/startup.js.map +1 -1
- package/dist/tracking/git-tracker.d.ts +4 -0
- package/dist/tracking/git-tracker.d.ts.map +1 -1
- package/dist/tracking/git-tracker.js +80 -15
- package/dist/tracking/git-tracker.js.map +1 -1
- package/docs/configuration.md +63 -5
- package/docs/relay-noise-conformance-vectors.json +41 -0
- package/docs/relay-noise-v3-conformance-vectors.json +50 -0
- package/docs/security.md +3 -2
- package/package.json +1 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
function isRelayHandshakeProfile(value) {
|
|
3
|
+
return value === 'noise-ik' || value === 'noise-ikpsk2';
|
|
4
|
+
}
|
|
5
|
+
function toEnvelopeAad(envelope) {
|
|
6
|
+
return Buffer.from(`viewport-relay-envelope-v2|${envelope.profile}|${envelope.sessionId}|${envelope.epoch}|${envelope.seq}`, 'utf8');
|
|
7
|
+
}
|
|
8
|
+
export function toBase64Url(buffer) {
|
|
9
|
+
return buffer.toString('base64url');
|
|
10
|
+
}
|
|
11
|
+
export function fromBase64Url(value) {
|
|
12
|
+
return Buffer.from(value, 'base64url');
|
|
13
|
+
}
|
|
14
|
+
export function parseRelayEnvelope(raw) {
|
|
15
|
+
const parsed = JSON.parse(raw);
|
|
16
|
+
if (parsed.type !== 'e2ee' ||
|
|
17
|
+
parsed.version !== 2 ||
|
|
18
|
+
!isRelayHandshakeProfile(parsed.profile) ||
|
|
19
|
+
typeof parsed.sessionId !== 'string' ||
|
|
20
|
+
parsed.sessionId.trim().length === 0 ||
|
|
21
|
+
typeof parsed.epoch !== 'number' ||
|
|
22
|
+
!Number.isInteger(parsed.epoch) ||
|
|
23
|
+
parsed.epoch < 1 ||
|
|
24
|
+
typeof parsed.seq !== 'number' ||
|
|
25
|
+
!Number.isInteger(parsed.seq) ||
|
|
26
|
+
parsed.seq < 1 ||
|
|
27
|
+
typeof parsed.iv !== 'string' ||
|
|
28
|
+
typeof parsed.tag !== 'string' ||
|
|
29
|
+
typeof parsed.ciphertext !== 'string') {
|
|
30
|
+
throw new Error('Invalid relay envelope');
|
|
31
|
+
}
|
|
32
|
+
return parsed;
|
|
33
|
+
}
|
|
34
|
+
export function encryptEnvelope(key, plaintext, metadata) {
|
|
35
|
+
const iv = crypto.randomBytes(12);
|
|
36
|
+
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
|
|
37
|
+
cipher.setAAD(toEnvelopeAad(metadata));
|
|
38
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
|
|
39
|
+
const tag = cipher.getAuthTag();
|
|
40
|
+
const envelope = {
|
|
41
|
+
type: 'e2ee',
|
|
42
|
+
version: 2,
|
|
43
|
+
profile: metadata.profile,
|
|
44
|
+
sessionId: metadata.sessionId,
|
|
45
|
+
epoch: metadata.epoch,
|
|
46
|
+
seq: metadata.seq,
|
|
47
|
+
iv: toBase64Url(iv),
|
|
48
|
+
tag: toBase64Url(tag),
|
|
49
|
+
ciphertext: toBase64Url(ciphertext),
|
|
50
|
+
};
|
|
51
|
+
return JSON.stringify(envelope);
|
|
52
|
+
}
|
|
53
|
+
export function decryptEnvelope(key, envelope) {
|
|
54
|
+
const iv = fromBase64Url(envelope.iv);
|
|
55
|
+
const tag = fromBase64Url(envelope.tag);
|
|
56
|
+
const ciphertext = fromBase64Url(envelope.ciphertext);
|
|
57
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
|
|
58
|
+
decipher.setAAD(toEnvelopeAad(envelope));
|
|
59
|
+
decipher.setAuthTag(tag);
|
|
60
|
+
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
61
|
+
return plaintext.toString('utf8');
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=bridge-crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-crypto.js","sourceRoot":"","sources":["../../src/relay/bridge-crypto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type BridgeErrorCode = 'TOKEN_ISSUE_FAILED' | 'TOKEN_RESPONSE_INVALID' | 'DAEMON_KEY_REGISTER_FAILED' | 'KEY_EXCHANGE_FAILED' | 'WEBSOCKET_CONNECT_TIMEOUT' | 'ENVELOPE_DECRYPT_FAILED' | 'CIRCUIT_OPEN' | 'WEBSOCKET_ERROR' | 'UNKNOWN';
|
|
2
|
+
export declare class BridgeError extends Error {
|
|
3
|
+
readonly code: BridgeErrorCode;
|
|
4
|
+
constructor(code: BridgeErrorCode, message: string);
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=bridge-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-errors.d.ts","sourceRoot":"","sources":["../../src/relay/bridge-errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,oBAAoB,GACpB,wBAAwB,GACxB,4BAA4B,GAC5B,qBAAqB,GACrB,2BAA2B,GAC3B,yBAAyB,GACzB,cAAc,GACd,iBAAiB,GACjB,SAAS,CAAC;AAEd,qBAAa,WAAY,SAAQ,KAAK;IAElC,QAAQ,CAAC,IAAI,EAAE,eAAe;gBAArB,IAAI,EAAE,eAAe,EAC9B,OAAO,EAAE,MAAM;CAKlB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-errors.js","sourceRoot":"","sources":["../../src/relay/bridge-errors.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,WAAY,SAAQ,KAAK;IAEzB;IADX,YACW,IAAqB,EAC9B,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHN,SAAI,GAAJ,IAAI,CAAiB;QAI9B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface RelayTokenClaims {
|
|
2
|
+
e2eeProfile?: string;
|
|
3
|
+
pairingSecret?: string;
|
|
4
|
+
iss?: string;
|
|
5
|
+
aud?: string | string[];
|
|
6
|
+
exp?: number;
|
|
7
|
+
iat?: number;
|
|
8
|
+
nbf?: number;
|
|
9
|
+
jti?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RelayTokenVerificationOptions {
|
|
12
|
+
issuer?: string;
|
|
13
|
+
audience?: string;
|
|
14
|
+
signingKeys: Record<string, string>;
|
|
15
|
+
clockSkewSec?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function verifyRelayTokenClaims(relayToken: string, options: RelayTokenVerificationOptions): RelayTokenClaims;
|
|
18
|
+
//# sourceMappingURL=bridge-jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-jwt.d.ts","sourceRoot":"","sources":["../../src/relay/bridge-jwt.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA+ED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,6BAA6B,GACrC,gBAAgB,CAiGlB"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import { BridgeError } from './bridge-errors.js';
|
|
3
|
+
function parseBase64UrlJson(segment, label) {
|
|
4
|
+
let decoded = '';
|
|
5
|
+
try {
|
|
6
|
+
decoded = Buffer.from(segment, 'base64url').toString('utf8');
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', `relay token ${label} decode failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(decoded);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', `relay token ${label} JSON invalid: ${error instanceof Error ? error.message : String(error)}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function secureCompare(aRaw, bRaw) {
|
|
19
|
+
const a = Buffer.from(aRaw, 'utf8');
|
|
20
|
+
const b = Buffer.from(bRaw, 'utf8');
|
|
21
|
+
const compareLength = Math.max(a.length, b.length, 1);
|
|
22
|
+
const paddedA = Buffer.alloc(compareLength);
|
|
23
|
+
const paddedB = Buffer.alloc(compareLength);
|
|
24
|
+
a.copy(paddedA);
|
|
25
|
+
b.copy(paddedB);
|
|
26
|
+
const equal = crypto.timingSafeEqual(paddedA, paddedB);
|
|
27
|
+
return equal && a.length === b.length;
|
|
28
|
+
}
|
|
29
|
+
function ensureNumericClaim(payload, name) {
|
|
30
|
+
const raw = payload[name];
|
|
31
|
+
if (raw === undefined)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (typeof raw !== 'number' || !Number.isFinite(raw)) {
|
|
34
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', `relay token ${name} claim must be numeric`);
|
|
35
|
+
}
|
|
36
|
+
return raw;
|
|
37
|
+
}
|
|
38
|
+
function ensureAudience(payload, expectedAudience) {
|
|
39
|
+
if (!expectedAudience)
|
|
40
|
+
return;
|
|
41
|
+
const aud = payload['aud'];
|
|
42
|
+
if (typeof aud === 'string') {
|
|
43
|
+
if (aud !== expectedAudience) {
|
|
44
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', `relay token audience mismatch (expected ${expectedAudience})`);
|
|
45
|
+
}
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (Array.isArray(aud) && aud.every((entry) => typeof entry === 'string')) {
|
|
49
|
+
if (!aud.includes(expectedAudience)) {
|
|
50
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', `relay token audience mismatch (expected ${expectedAudience})`);
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token aud claim is missing/invalid');
|
|
55
|
+
}
|
|
56
|
+
export function verifyRelayTokenClaims(relayToken, options) {
|
|
57
|
+
const parts = relayToken.split('.');
|
|
58
|
+
if (parts.length !== 3) {
|
|
59
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token is malformed');
|
|
60
|
+
}
|
|
61
|
+
const [headerPart, payloadPart, signaturePart] = parts;
|
|
62
|
+
if (!headerPart || !payloadPart || !signaturePart) {
|
|
63
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token is malformed');
|
|
64
|
+
}
|
|
65
|
+
const header = parseBase64UrlJson(headerPart, 'header');
|
|
66
|
+
if (!header || typeof header !== 'object' || Array.isArray(header)) {
|
|
67
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token header is invalid');
|
|
68
|
+
}
|
|
69
|
+
if (header.alg !== 'HS256' && header.alg !== 'RS256') {
|
|
70
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', `unsupported relay token alg: ${String(header.alg)}`);
|
|
71
|
+
}
|
|
72
|
+
const kid = typeof header.kid === 'string' && header.kid.trim().length > 0 ? header.kid : 'v1';
|
|
73
|
+
const signingKey = options.signingKeys[kid];
|
|
74
|
+
if (!signingKey || signingKey.trim().length === 0) {
|
|
75
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', `relay token key id ${kid} is not trusted`);
|
|
76
|
+
}
|
|
77
|
+
if (header.alg === 'HS256') {
|
|
78
|
+
const expectedSignature = Buffer.from(crypto.createHmac('sha256', signingKey).update(`${headerPart}.${payloadPart}`).digest()).toString('base64url');
|
|
79
|
+
if (!secureCompare(expectedSignature, signaturePart)) {
|
|
80
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token signature invalid');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
let signatureRaw;
|
|
85
|
+
try {
|
|
86
|
+
signatureRaw = Buffer.from(signaturePart, 'base64url');
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', `relay token signature decode failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
90
|
+
}
|
|
91
|
+
const valid = crypto.verify('RSA-SHA256', Buffer.from(`${headerPart}.${payloadPart}`, 'utf8'), signingKey, signatureRaw);
|
|
92
|
+
if (!valid) {
|
|
93
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token signature invalid');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const payload = parseBase64UrlJson(payloadPart, 'payload');
|
|
97
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
98
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token payload is not an object');
|
|
99
|
+
}
|
|
100
|
+
if (options.issuer) {
|
|
101
|
+
const iss = payload['iss'];
|
|
102
|
+
if (typeof iss !== 'string' || iss !== options.issuer) {
|
|
103
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', `relay token issuer mismatch (expected ${options.issuer})`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
ensureAudience(payload, options.audience);
|
|
107
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
108
|
+
const skew = Math.max(0, Math.floor(options.clockSkewSec ?? 30));
|
|
109
|
+
const exp = ensureNumericClaim(payload, 'exp');
|
|
110
|
+
const iat = ensureNumericClaim(payload, 'iat');
|
|
111
|
+
const nbf = ensureNumericClaim(payload, 'nbf');
|
|
112
|
+
if (exp === undefined) {
|
|
113
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token exp claim is required');
|
|
114
|
+
}
|
|
115
|
+
if (exp <= nowSec - skew) {
|
|
116
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token is expired');
|
|
117
|
+
}
|
|
118
|
+
if (iat !== undefined && iat > nowSec + skew) {
|
|
119
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token iat is in the future');
|
|
120
|
+
}
|
|
121
|
+
if (nbf !== undefined && nbf > nowSec + skew) {
|
|
122
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token is not active yet');
|
|
123
|
+
}
|
|
124
|
+
const jti = payload['jti'];
|
|
125
|
+
if (typeof jti !== 'string' || jti.trim().length === 0) {
|
|
126
|
+
throw new BridgeError('TOKEN_RESPONSE_INVALID', 'relay token jti claim is required');
|
|
127
|
+
}
|
|
128
|
+
return payload;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=bridge-jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-jwt.js","sourceRoot":"","sources":["../../src/relay/bridge-jwt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export interface DaemonRelayIdentity {
|
|
2
|
+
publicKey: string;
|
|
3
|
+
privateKey: string;
|
|
4
|
+
algorithm: 'p256';
|
|
5
|
+
}
|
|
6
|
+
export type RelayHandshakeProfile = 'noise-ik' | 'noise-ikpsk2';
|
|
7
|
+
export interface RelayKeyExchangeInitFrame {
|
|
8
|
+
type: 'relay_key_exchange_init';
|
|
9
|
+
version: 2;
|
|
10
|
+
profile: RelayHandshakeProfile;
|
|
11
|
+
requestId: string;
|
|
12
|
+
clientPublicKey: string;
|
|
13
|
+
clientNonce: string;
|
|
14
|
+
clientProof: string;
|
|
15
|
+
pairingPeerId?: string;
|
|
16
|
+
previousSessionId?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface RelayKeyExchangeResponseFrame {
|
|
19
|
+
type: 'relay_key_exchange_response';
|
|
20
|
+
version: 2;
|
|
21
|
+
profile: RelayHandshakeProfile;
|
|
22
|
+
requestId: string;
|
|
23
|
+
daemonPublicKey: string;
|
|
24
|
+
daemonNonce: string;
|
|
25
|
+
sessionId: string;
|
|
26
|
+
epoch: number;
|
|
27
|
+
proof: string;
|
|
28
|
+
}
|
|
29
|
+
export interface DerivedRelaySession {
|
|
30
|
+
key: Buffer;
|
|
31
|
+
profile: RelayHandshakeProfile;
|
|
32
|
+
sessionId: string;
|
|
33
|
+
epoch: number;
|
|
34
|
+
}
|
|
35
|
+
export declare function loadOrCreateIdentity(workspaceId: string): Promise<DaemonRelayIdentity>;
|
|
36
|
+
export declare function parseRelayHandshakeProfile(value: unknown): RelayHandshakeProfile | null;
|
|
37
|
+
export declare function parseRelayKeyExchangeInitFrame(value: unknown): RelayKeyExchangeInitFrame | null;
|
|
38
|
+
export declare function deriveSessionFromKeyExchange(params: {
|
|
39
|
+
init: RelayKeyExchangeInitFrame;
|
|
40
|
+
daemonIdentity: DaemonRelayIdentity;
|
|
41
|
+
nextEpoch: number;
|
|
42
|
+
pairingSecret?: Buffer;
|
|
43
|
+
daemonNonceOverride?: Buffer;
|
|
44
|
+
sessionIdOverride?: string;
|
|
45
|
+
}): {
|
|
46
|
+
session: DerivedRelaySession;
|
|
47
|
+
response: RelayKeyExchangeResponseFrame;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=bridge-key-exchange.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-key-exchange.d.ts","sourceRoot":"","sources":["../../src/relay/bridge-key-exchange.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,cAAc,CAAC;AAEhE,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,yBAAyB,CAAC;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAsBD,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAkC5F;AAwHD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,GAAG,IAAI,CAGvF;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,yBAAyB,GAAG,IAAI,CAiC/F;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE;IACnD,IAAI,EAAE,yBAAyB,CAAC;IAChC,cAAc,EAAE,mBAAmB,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG;IAAE,OAAO,EAAE,mBAAmB,CAAC;IAAC,QAAQ,EAAE,6BAA6B,CAAA;CAAE,CA2F5E"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { configDir } from '../core/config.js';
|
|
5
|
+
import { fromBase64Url, toBase64Url } from './bridge-crypto.js';
|
|
6
|
+
const SESSION_INFO_PREFIX = 'viewport-relay-session-v2';
|
|
7
|
+
const TRANSCRIPT_PREFIX = 'viewport-relay-transcript-v2';
|
|
8
|
+
const INIT_INFO_PREFIX = 'viewport-relay-kex-init-v1';
|
|
9
|
+
function safeWorkspaceId(workspaceId) {
|
|
10
|
+
return workspaceId.replace(/[^a-zA-Z0-9_.-]/g, '_');
|
|
11
|
+
}
|
|
12
|
+
function identityFilePath(workspaceId) {
|
|
13
|
+
return path.join(configDir(), `relay-daemon-identity-${safeWorkspaceId(workspaceId)}.json`);
|
|
14
|
+
}
|
|
15
|
+
async function writeJsonAtomic(filePath, value) {
|
|
16
|
+
const dir = path.dirname(filePath);
|
|
17
|
+
await fs.mkdir(dir, { recursive: true });
|
|
18
|
+
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
19
|
+
await fs.writeFile(tmp, JSON.stringify(value, null, 2) + '\n', { mode: 0o600 });
|
|
20
|
+
await fs.rename(tmp, filePath);
|
|
21
|
+
}
|
|
22
|
+
export async function loadOrCreateIdentity(workspaceId) {
|
|
23
|
+
const filePath = identityFilePath(workspaceId);
|
|
24
|
+
try {
|
|
25
|
+
const raw = await fs.readFile(filePath, 'utf8');
|
|
26
|
+
const parsed = JSON.parse(raw);
|
|
27
|
+
if (parsed.algorithm === 'p256' &&
|
|
28
|
+
typeof parsed.publicKey === 'string' &&
|
|
29
|
+
typeof parsed.privateKey === 'string') {
|
|
30
|
+
const priv = fromBase64Url(parsed.privateKey);
|
|
31
|
+
const pub = fromBase64Url(parsed.publicKey);
|
|
32
|
+
if (priv.length === 32 && pub.length === 65 && pub[0] === 0x04) {
|
|
33
|
+
return {
|
|
34
|
+
algorithm: 'p256',
|
|
35
|
+
publicKey: parsed.publicKey,
|
|
36
|
+
privateKey: parsed.privateKey,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// create below
|
|
43
|
+
}
|
|
44
|
+
const ecdh = crypto.createECDH('prime256v1');
|
|
45
|
+
const publicKey = ecdh.generateKeys();
|
|
46
|
+
const privateKey = ecdh.getPrivateKey();
|
|
47
|
+
const identity = {
|
|
48
|
+
algorithm: 'p256',
|
|
49
|
+
publicKey: toBase64Url(publicKey),
|
|
50
|
+
privateKey: toBase64Url(privateKey),
|
|
51
|
+
};
|
|
52
|
+
await writeJsonAtomic(filePath, identity);
|
|
53
|
+
return identity;
|
|
54
|
+
}
|
|
55
|
+
function toSessionInfo(profile, sessionId, epoch) {
|
|
56
|
+
return Buffer.from(`${SESSION_INFO_PREFIX}|${profile}|${sessionId}|${epoch}`, 'utf8');
|
|
57
|
+
}
|
|
58
|
+
function toTranscript(params) {
|
|
59
|
+
return Buffer.from([
|
|
60
|
+
TRANSCRIPT_PREFIX,
|
|
61
|
+
params.requestId,
|
|
62
|
+
params.profile,
|
|
63
|
+
params.clientPublicKey,
|
|
64
|
+
params.daemonPublicKey,
|
|
65
|
+
params.clientNonce,
|
|
66
|
+
params.daemonNonce,
|
|
67
|
+
params.sessionId,
|
|
68
|
+
String(params.epoch),
|
|
69
|
+
].join('|'), 'utf8');
|
|
70
|
+
}
|
|
71
|
+
function deriveSessionKey(params) {
|
|
72
|
+
const ikm = params.profile === 'noise-ikpsk2' && params.pairingSecret
|
|
73
|
+
? Buffer.concat([params.sharedSecret, params.pairingSecret])
|
|
74
|
+
: params.sharedSecret;
|
|
75
|
+
const salt = Buffer.concat([params.clientNonce, params.daemonNonce]);
|
|
76
|
+
const derived = crypto.hkdfSync('sha256', ikm, salt, toSessionInfo(params.profile, params.sessionId, params.epoch), 32);
|
|
77
|
+
return Buffer.isBuffer(derived) ? derived : Buffer.from(derived);
|
|
78
|
+
}
|
|
79
|
+
function computeProof(sessionKey, transcript) {
|
|
80
|
+
return crypto.createHmac('sha256', sessionKey).update(transcript).digest().subarray(0, 16);
|
|
81
|
+
}
|
|
82
|
+
function toInitInfo(params) {
|
|
83
|
+
return Buffer.from([
|
|
84
|
+
INIT_INFO_PREFIX,
|
|
85
|
+
params.requestId,
|
|
86
|
+
params.profile,
|
|
87
|
+
params.clientPublicKey,
|
|
88
|
+
params.daemonPublicKey,
|
|
89
|
+
params.clientNonce,
|
|
90
|
+
params.previousSessionId ?? '',
|
|
91
|
+
].join('|'), 'utf8');
|
|
92
|
+
}
|
|
93
|
+
function computeClientInitProof(params) {
|
|
94
|
+
const ikm = params.profile === 'noise-ikpsk2' && params.pairingSecret
|
|
95
|
+
? Buffer.concat([params.sharedSecret, params.pairingSecret])
|
|
96
|
+
: params.sharedSecret;
|
|
97
|
+
const initKey = crypto.hkdfSync('sha256', ikm, params.clientNonce, toInitInfo({
|
|
98
|
+
requestId: params.requestId,
|
|
99
|
+
profile: params.profile,
|
|
100
|
+
clientPublicKey: params.clientPublicKey,
|
|
101
|
+
daemonPublicKey: params.daemonPublicKey,
|
|
102
|
+
clientNonce: params.clientNonceEncoded,
|
|
103
|
+
previousSessionId: params.previousSessionId,
|
|
104
|
+
}), 32);
|
|
105
|
+
const normalized = Buffer.isBuffer(initKey) ? initKey : Buffer.from(initKey);
|
|
106
|
+
return crypto
|
|
107
|
+
.createHmac('sha256', normalized)
|
|
108
|
+
.update('client-proof', 'utf8')
|
|
109
|
+
.digest()
|
|
110
|
+
.subarray(0, 16);
|
|
111
|
+
}
|
|
112
|
+
export function parseRelayHandshakeProfile(value) {
|
|
113
|
+
if (value === 'noise-ik' || value === 'noise-ikpsk2')
|
|
114
|
+
return value;
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
export function parseRelayKeyExchangeInitFrame(value) {
|
|
118
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
119
|
+
return null;
|
|
120
|
+
const frame = value;
|
|
121
|
+
const profile = parseRelayHandshakeProfile(frame['profile']);
|
|
122
|
+
if (!profile)
|
|
123
|
+
return null;
|
|
124
|
+
if (frame['type'] !== 'relay_key_exchange_init' ||
|
|
125
|
+
frame['version'] !== 2 ||
|
|
126
|
+
typeof frame['requestId'] !== 'string' ||
|
|
127
|
+
typeof frame['clientPublicKey'] !== 'string' ||
|
|
128
|
+
typeof frame['clientNonce'] !== 'string' ||
|
|
129
|
+
typeof frame['clientProof'] !== 'string') {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const previousSessionId = typeof frame['previousSessionId'] === 'string' ? frame['previousSessionId'] : undefined;
|
|
133
|
+
const pairingPeerId = typeof frame['pairingPeerId'] === 'string' ? frame['pairingPeerId'] : undefined;
|
|
134
|
+
if (profile === 'noise-ikpsk2' && (!pairingPeerId || pairingPeerId.trim().length === 0)) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
type: 'relay_key_exchange_init',
|
|
139
|
+
version: 2,
|
|
140
|
+
profile,
|
|
141
|
+
requestId: frame['requestId'],
|
|
142
|
+
clientPublicKey: frame['clientPublicKey'],
|
|
143
|
+
clientNonce: frame['clientNonce'],
|
|
144
|
+
clientProof: frame['clientProof'],
|
|
145
|
+
pairingPeerId,
|
|
146
|
+
previousSessionId,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
export function deriveSessionFromKeyExchange(params) {
|
|
150
|
+
const clientPublic = fromBase64Url(params.init.clientPublicKey);
|
|
151
|
+
if (clientPublic.length !== 65 || clientPublic[0] !== 0x04) {
|
|
152
|
+
throw new Error('invalid client public key');
|
|
153
|
+
}
|
|
154
|
+
const clientNonce = fromBase64Url(params.init.clientNonce);
|
|
155
|
+
if (clientNonce.length < 12 || clientNonce.length > 32) {
|
|
156
|
+
throw new Error('invalid client nonce');
|
|
157
|
+
}
|
|
158
|
+
const daemonPrivate = fromBase64Url(params.daemonIdentity.privateKey);
|
|
159
|
+
if (daemonPrivate.length !== 32) {
|
|
160
|
+
throw new Error('invalid daemon private key');
|
|
161
|
+
}
|
|
162
|
+
if (params.init.profile === 'noise-ikpsk2' && !params.pairingSecret) {
|
|
163
|
+
throw new Error('pairing secret required for noise-ikpsk2');
|
|
164
|
+
}
|
|
165
|
+
const daemonNonce = params.daemonNonceOverride ?? crypto.randomBytes(16);
|
|
166
|
+
if (daemonNonce.length !== 16) {
|
|
167
|
+
throw new Error('invalid daemon nonce override');
|
|
168
|
+
}
|
|
169
|
+
const sessionId = params.sessionIdOverride ?? `rs_${crypto.randomBytes(12).toString('hex')}`;
|
|
170
|
+
if (sessionId.trim().length === 0) {
|
|
171
|
+
throw new Error('invalid session id override');
|
|
172
|
+
}
|
|
173
|
+
const epoch = Math.max(1, params.nextEpoch);
|
|
174
|
+
const ecdh = crypto.createECDH('prime256v1');
|
|
175
|
+
ecdh.setPrivateKey(daemonPrivate);
|
|
176
|
+
const sharedSecret = ecdh.computeSecret(clientPublic);
|
|
177
|
+
const expectedClientProof = computeClientInitProof({
|
|
178
|
+
sharedSecret,
|
|
179
|
+
clientNonce,
|
|
180
|
+
profile: params.init.profile,
|
|
181
|
+
requestId: params.init.requestId,
|
|
182
|
+
clientPublicKey: params.init.clientPublicKey,
|
|
183
|
+
daemonPublicKey: params.daemonIdentity.publicKey,
|
|
184
|
+
clientNonceEncoded: params.init.clientNonce,
|
|
185
|
+
previousSessionId: params.init.previousSessionId,
|
|
186
|
+
pairingSecret: params.pairingSecret,
|
|
187
|
+
});
|
|
188
|
+
const providedClientProof = fromBase64Url(params.init.clientProof);
|
|
189
|
+
if (providedClientProof.length !== expectedClientProof.length ||
|
|
190
|
+
!crypto.timingSafeEqual(providedClientProof, expectedClientProof)) {
|
|
191
|
+
throw new Error('invalid client key exchange proof');
|
|
192
|
+
}
|
|
193
|
+
const sessionKey = deriveSessionKey({
|
|
194
|
+
sharedSecret,
|
|
195
|
+
clientNonce,
|
|
196
|
+
daemonNonce,
|
|
197
|
+
profile: params.init.profile,
|
|
198
|
+
sessionId,
|
|
199
|
+
epoch,
|
|
200
|
+
pairingSecret: params.pairingSecret,
|
|
201
|
+
});
|
|
202
|
+
const daemonNonceEncoded = toBase64Url(daemonNonce);
|
|
203
|
+
const transcript = toTranscript({
|
|
204
|
+
requestId: params.init.requestId,
|
|
205
|
+
profile: params.init.profile,
|
|
206
|
+
clientPublicKey: params.init.clientPublicKey,
|
|
207
|
+
daemonPublicKey: params.daemonIdentity.publicKey,
|
|
208
|
+
clientNonce: params.init.clientNonce,
|
|
209
|
+
daemonNonce: daemonNonceEncoded,
|
|
210
|
+
sessionId,
|
|
211
|
+
epoch,
|
|
212
|
+
});
|
|
213
|
+
const proof = computeProof(sessionKey, transcript);
|
|
214
|
+
return {
|
|
215
|
+
session: {
|
|
216
|
+
key: sessionKey,
|
|
217
|
+
profile: params.init.profile,
|
|
218
|
+
sessionId,
|
|
219
|
+
epoch,
|
|
220
|
+
},
|
|
221
|
+
response: {
|
|
222
|
+
type: 'relay_key_exchange_response',
|
|
223
|
+
version: 2,
|
|
224
|
+
profile: params.init.profile,
|
|
225
|
+
requestId: params.init.requestId,
|
|
226
|
+
daemonPublicKey: params.daemonIdentity.publicKey,
|
|
227
|
+
daemonNonce: daemonNonceEncoded,
|
|
228
|
+
sessionId,
|
|
229
|
+
epoch,
|
|
230
|
+
proof: toBase64Url(proof),
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=bridge-key-exchange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-key-exchange.js","sourceRoot":"","sources":["../../src/relay/bridge-key-exchange.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WebSocket as WsType } from 'ws';
|
|
2
|
+
type RelayWs = WsType;
|
|
3
|
+
type WsCheckServerIdentity = (servername: string, cert: unknown) => boolean;
|
|
4
|
+
export declare function wsOpen(ws: RelayWs): Promise<void>;
|
|
5
|
+
export declare function resolveRelayTlsOptions(relayUrl: string, mode: 'auto' | '0' | '1', caCertPath?: string, relayTlsPins?: string[]): {
|
|
6
|
+
rejectUnauthorized?: boolean;
|
|
7
|
+
ca?: Buffer;
|
|
8
|
+
checkServerIdentity?: WsCheckServerIdentity;
|
|
9
|
+
};
|
|
10
|
+
export declare function closeQuietly(ws: RelayWs | null | undefined): void;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=bridge-network.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-network.d.ts","sourceRoot":"","sources":["../../src/relay/bridge-network.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,IAAI,MAAM,EAAE,MAAM,IAAI,CAAC;AAI9C,KAAK,OAAO,GAAG,MAAM,CAAC;AACtB,KAAK,qBAAqB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;AAE5E,wBAAgB,MAAM,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BjD;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,GAAG,GAAG,GAAG,EACxB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,qBAAqB,CAAA;CAAE,CA+C5F;AAaD,wBAAgB,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAOjE"}
|