@decibelsystems/tools 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/dist/agentCommands.d.ts +0 -1
- package/dist/agentCommands.d.ts.map +1 -1
- package/dist/agentCommands.js +19 -8
- package/dist/agentCommands.js.map +1 -1
- package/dist/agentPresence.d.ts +5 -3
- package/dist/agentPresence.d.ts.map +1 -1
- package/dist/agentPresence.js +20 -29
- package/dist/agentPresence.js.map +1 -1
- package/dist/architectAdrs.d.ts +13 -1
- package/dist/architectAdrs.d.ts.map +1 -1
- package/dist/architectAdrs.js +83 -1
- package/dist/architectAdrs.js.map +1 -1
- package/dist/artifacts.d.ts +60 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +208 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/asks.d.ts +93 -0
- package/dist/asks.d.ts.map +1 -0
- package/dist/asks.js +383 -0
- package/dist/asks.js.map +1 -0
- package/dist/chat.d.ts +47 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +288 -0
- package/dist/chat.js.map +1 -0
- package/dist/daemon.d.ts +14 -3
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +44 -14
- package/dist/daemon.js.map +1 -1
- package/dist/daemonConfig.d.ts +22 -0
- package/dist/daemonConfig.d.ts.map +1 -1
- package/dist/daemonConfig.js +11 -0
- package/dist/daemonConfig.js.map +1 -1
- package/dist/domain/issue.d.ts +19 -15
- package/dist/domain/issue.d.ts.map +1 -1
- package/dist/domain/issue.js +4 -32
- package/dist/domain/issue.js.map +1 -1
- package/dist/domain/issueCodec.d.ts.map +1 -1
- package/dist/domain/issueCodec.js +10 -0
- package/dist/domain/issueCodec.js.map +1 -1
- package/dist/domain/issueRepository.d.ts +35 -2
- package/dist/domain/issueRepository.d.ts.map +1 -1
- package/dist/domain/issueRepository.js +40 -1
- package/dist/domain/issueRepository.js.map +1 -1
- package/dist/domain/uid.d.ts +16 -0
- package/dist/domain/uid.d.ts.map +1 -0
- package/dist/domain/uid.js +43 -0
- package/dist/domain/uid.js.map +1 -0
- package/dist/facades/definitions.d.ts.map +1 -1
- package/dist/facades/definitions.js +46 -3
- package/dist/facades/definitions.js.map +1 -1
- package/dist/hq/defineAgent.d.ts.map +1 -1
- package/dist/hq/defineAgent.js +7 -11
- package/dist/hq/defineAgent.js.map +1 -1
- package/dist/httpServer.d.ts.map +1 -1
- package/dist/httpServer.js +201 -48
- package/dist/httpServer.js.map +1 -1
- package/dist/identity.d.ts +123 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +312 -0
- package/dist/identity.js.map +1 -0
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +24 -1
- package/dist/kernel.js.map +1 -1
- package/dist/killSwitch.d.ts +117 -0
- package/dist/killSwitch.d.ts.map +1 -0
- package/dist/killSwitch.js +161 -0
- package/dist/killSwitch.js.map +1 -0
- package/dist/lib/atomicWrite.d.ts +23 -0
- package/dist/lib/atomicWrite.d.ts.map +1 -1
- package/dist/lib/atomicWrite.js +84 -0
- package/dist/lib/atomicWrite.js.map +1 -1
- package/dist/lib/recordIdAllocator.d.ts +21 -5
- package/dist/lib/recordIdAllocator.d.ts.map +1 -1
- package/dist/lib/recordIdAllocator.js +25 -7
- package/dist/lib/recordIdAllocator.js.map +1 -1
- package/dist/orgId.d.ts +23 -0
- package/dist/orgId.d.ts.map +1 -0
- package/dist/orgId.js +73 -0
- package/dist/orgId.js.map +1 -0
- package/dist/pairCli.d.ts +2 -0
- package/dist/pairCli.d.ts.map +1 -0
- package/dist/pairCli.js +97 -0
- package/dist/pairCli.js.map +1 -0
- package/dist/peerBroker.d.ts +40 -0
- package/dist/peerBroker.d.ts.map +1 -0
- package/dist/peerBroker.js +70 -0
- package/dist/peerBroker.js.map +1 -0
- package/dist/peerBrokerSupervisor.d.ts +21 -0
- package/dist/peerBrokerSupervisor.d.ts.map +1 -0
- package/dist/peerBrokerSupervisor.js +131 -0
- package/dist/peerBrokerSupervisor.js.map +1 -0
- package/dist/projectPaths.d.ts.map +1 -1
- package/dist/projectPaths.js +1 -19
- package/dist/projectPaths.js.map +1 -1
- package/dist/projectRegistry.d.ts +22 -0
- package/dist/projectRegistry.d.ts.map +1 -1
- package/dist/projectRegistry.js +58 -2
- package/dist/projectRegistry.js.map +1 -1
- package/dist/pty/boundary.d.ts +39 -0
- package/dist/pty/boundary.d.ts.map +1 -0
- package/dist/pty/boundary.js +100 -0
- package/dist/pty/boundary.js.map +1 -0
- package/dist/pty/errors.d.ts +6 -0
- package/dist/pty/errors.d.ts.map +1 -0
- package/dist/pty/errors.js +12 -0
- package/dist/pty/errors.js.map +1 -0
- package/dist/pty/fleet.d.ts +159 -0
- package/dist/pty/fleet.d.ts.map +1 -0
- package/dist/pty/fleet.js +543 -0
- package/dist/pty/fleet.js.map +1 -0
- package/dist/pty/launchProfile.d.ts +45 -0
- package/dist/pty/launchProfile.d.ts.map +1 -0
- package/dist/pty/launchProfile.js +149 -0
- package/dist/pty/launchProfile.js.map +1 -0
- package/dist/pty/openTerminal.d.ts +48 -0
- package/dist/pty/openTerminal.d.ts.map +1 -0
- package/dist/pty/openTerminal.js +185 -0
- package/dist/pty/openTerminal.js.map +1 -0
- package/dist/pty/pairDialog.d.ts +16 -0
- package/dist/pty/pairDialog.d.ts.map +1 -0
- package/dist/pty/pairDialog.js +121 -0
- package/dist/pty/pairDialog.js.map +1 -0
- package/dist/pty/pairing.d.ts +86 -0
- package/dist/pty/pairing.d.ts.map +1 -0
- package/dist/pty/pairing.js +351 -0
- package/dist/pty/pairing.js.map +1 -0
- package/dist/pty/routes.d.ts +49 -0
- package/dist/pty/routes.d.ts.map +1 -0
- package/dist/pty/routes.js +624 -0
- package/dist/pty/routes.js.map +1 -0
- package/dist/pty/sessions.d.ts +167 -0
- package/dist/pty/sessions.d.ts.map +1 -0
- package/dist/pty/sessions.js +513 -0
- package/dist/pty/sessions.js.map +1 -0
- package/dist/pty/tmux.d.ts +109 -0
- package/dist/pty/tmux.d.ts.map +1 -0
- package/dist/pty/tmux.js +271 -0
- package/dist/pty/tmux.js.map +1 -0
- package/dist/roster.d.ts +37 -0
- package/dist/roster.d.ts.map +1 -0
- package/dist/roster.js +126 -0
- package/dist/roster.js.map +1 -0
- package/dist/runtime/daemonMeta.d.ts +53 -0
- package/dist/runtime/daemonMeta.d.ts.map +1 -0
- package/dist/runtime/daemonMeta.js +121 -0
- package/dist/runtime/daemonMeta.js.map +1 -0
- package/dist/runtime/ensureRuntime.d.ts.map +1 -1
- package/dist/runtime/ensureRuntime.js +5 -10
- package/dist/runtime/ensureRuntime.js.map +1 -1
- package/dist/sentinelIssues.d.ts +16 -0
- package/dist/sentinelIssues.d.ts.map +1 -1
- package/dist/sentinelIssues.js +42 -1
- package/dist/sentinelIssues.js.map +1 -1
- package/dist/server.js +66 -5
- package/dist/server.js.map +1 -1
- package/dist/toolConfig.d.ts.map +1 -1
- package/dist/toolConfig.js +12 -0
- package/dist/toolConfig.js.map +1 -1
- package/dist/tools/agentic/agentQueue.d.ts.map +1 -1
- package/dist/tools/agentic/agentQueue.js +4 -0
- package/dist/tools/agentic/agentQueue.js.map +1 -1
- package/dist/tools/architect/index.d.ts +1 -0
- package/dist/tools/architect/index.d.ts.map +1 -1
- package/dist/tools/architect/index.js +45 -1
- package/dist/tools/architect/index.js.map +1 -1
- package/dist/tools/architect.d.ts.map +1 -1
- package/dist/tools/architect.js +59 -8
- package/dist/tools/architect.js.map +1 -1
- package/dist/tools/artifacts.d.ts +5 -0
- package/dist/tools/artifacts.d.ts.map +1 -0
- package/dist/tools/artifacts.js +89 -0
- package/dist/tools/artifacts.js.map +1 -0
- package/dist/tools/asks.d.ts +6 -0
- package/dist/tools/asks.d.ts.map +1 -0
- package/dist/tools/asks.js +104 -0
- package/dist/tools/asks.js.map +1 -0
- package/dist/tools/coordinator/index.d.ts +1 -0
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +42 -2
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/tools/data-inspector.d.ts +1 -1
- package/dist/tools/data-inspector.d.ts.map +1 -1
- package/dist/tools/data-inspector.js +1 -1
- package/dist/tools/data-inspector.js.map +1 -1
- package/dist/tools/dojo/index.d.ts.map +1 -1
- package/dist/tools/dojo/index.js +52 -3
- package/dist/tools/dojo/index.js.map +1 -1
- package/dist/tools/dojo.d.ts +62 -1
- package/dist/tools/dojo.d.ts.map +1 -1
- package/dist/tools/dojo.js +84 -1
- package/dist/tools/dojo.js.map +1 -1
- package/dist/tools/guardian.d.ts +7 -0
- package/dist/tools/guardian.d.ts.map +1 -1
- package/dist/tools/guardian.js +146 -9
- package/dist/tools/guardian.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/killswitch/index.d.ts +13 -0
- package/dist/tools/killswitch/index.d.ts.map +1 -0
- package/dist/tools/killswitch/index.js +138 -0
- package/dist/tools/killswitch/index.js.map +1 -0
- package/dist/tools/oracle/index.d.ts.map +1 -1
- package/dist/tools/oracle/index.js +8 -0
- package/dist/tools/oracle/index.js.map +1 -1
- package/dist/tools/oracle.d.ts +7 -0
- package/dist/tools/oracle.d.ts.map +1 -1
- package/dist/tools/oracle.js +22 -6
- package/dist/tools/oracle.js.map +1 -1
- package/dist/tools/provenance.d.ts +11 -2
- package/dist/tools/provenance.d.ts.map +1 -1
- package/dist/tools/provenance.js +26 -24
- package/dist/tools/provenance.js.map +1 -1
- package/dist/tools/registry/index.d.ts.map +1 -1
- package/dist/tools/registry/index.js +24 -0
- package/dist/tools/registry/index.js.map +1 -1
- package/dist/tools/sentinel/index.d.ts.map +1 -1
- package/dist/tools/sentinel/index.js +54 -2
- package/dist/tools/sentinel/index.js.map +1 -1
- package/dist/tools/sentinel.d.ts +50 -0
- package/dist/tools/sentinel.d.ts.map +1 -1
- package/dist/tools/sentinel.js +72 -7
- package/dist/tools/sentinel.js.map +1 -1
- package/dist/tools/shared/runTracker.d.ts +2 -0
- package/dist/tools/shared/runTracker.d.ts.map +1 -1
- package/dist/tools/shared/runTracker.js +38 -0
- package/dist/tools/shared/runTracker.js.map +1 -1
- package/dist/tools/swarm.d.ts +3 -1
- package/dist/tools/swarm.d.ts.map +1 -1
- package/dist/tools/swarm.js +6 -12
- package/dist/tools/swarm.js.map +1 -1
- package/dist/tools/voice/index.d.ts +1 -0
- package/dist/tools/voice/index.d.ts.map +1 -1
- package/dist/tools/voice/index.js +33 -2
- package/dist/tools/voice/index.js.map +1 -1
- package/dist/tools/voice.d.ts +48 -1
- package/dist/tools/voice.d.ts.map +1 -1
- package/dist/tools/voice.js +63 -3
- package/dist/tools/voice.js.map +1 -1
- package/dist/transports/bridge.d.ts.map +1 -1
- package/dist/transports/bridge.js +2 -1
- package/dist/transports/bridge.js.map +1 -1
- package/dist/transports/mcp.d.ts.map +1 -1
- package/dist/transports/mcp.js +2 -1
- package/dist/transports/mcp.js.map +1 -1
- package/dist/version.d.ts +5 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +23 -0
- package/dist/version.js.map +1 -0
- package/package.json +13 -2
- package/templates/AGENT.md +3 -0
- package/templates/CLAUDE-decibel.md +11 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'http';
|
|
2
|
+
export declare const PENDING_TTL_MS: number;
|
|
3
|
+
/** Approved pairings idle this long expire (Ben, 2026-09-25). */
|
|
4
|
+
export declare const IDLE_EXPIRY_MS: number;
|
|
5
|
+
export declare const NONCE_TTL_MS = 60000;
|
|
6
|
+
/** Signed requests must be this fresh, in either direction. */
|
|
7
|
+
export declare const IAT_SKEW_MS = 60000;
|
|
8
|
+
export interface PublicJwk {
|
|
9
|
+
kty: 'EC';
|
|
10
|
+
crv: 'P-256';
|
|
11
|
+
x: string;
|
|
12
|
+
y: string;
|
|
13
|
+
}
|
|
14
|
+
export interface Pairing {
|
|
15
|
+
id: string;
|
|
16
|
+
origin: string;
|
|
17
|
+
label: string;
|
|
18
|
+
public_key_jwk: PublicJwk;
|
|
19
|
+
status: 'pending' | 'approved';
|
|
20
|
+
/** pending only: what HQ shows and the human types. */
|
|
21
|
+
code?: string;
|
|
22
|
+
requested_at: string;
|
|
23
|
+
approved_at?: string;
|
|
24
|
+
last_used?: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function pairingsPath(): string;
|
|
27
|
+
export declare function listPairings(): Pairing[];
|
|
28
|
+
export declare function isPairingActive(id: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* A P-256 PUBLIC key and nothing else. A JWK carrying `d` is a private key: the
|
|
31
|
+
* page is supposed to hold a non-extractable key, so receiving one means
|
|
32
|
+
* something is badly wrong, and it is refused rather than stored.
|
|
33
|
+
*/
|
|
34
|
+
export declare function validatePublicJwk(v: unknown): PublicJwk;
|
|
35
|
+
/** RFC 7638 thumbprint. */
|
|
36
|
+
export declare function thumbprint(jwk: PublicJwk): string;
|
|
37
|
+
/**
|
|
38
|
+
* The code both sides show. Derived from the key AND a daemon nonce: from the
|
|
39
|
+
* key alone, an attacker could grind keys offline until one lands on a chosen
|
|
40
|
+
* code (cheap at 10^6); with the daemon's nonce mixed in, there is nothing to
|
|
41
|
+
* grind against before asking.
|
|
42
|
+
*/
|
|
43
|
+
export declare function pairingCode(jwk: PublicJwk, daemonNonce: string): string;
|
|
44
|
+
export declare function requestPairing(origin: string, jwkIn: unknown, labelIn: unknown): Promise<{
|
|
45
|
+
pairing_id: string;
|
|
46
|
+
code: string;
|
|
47
|
+
expires_at: string;
|
|
48
|
+
}>;
|
|
49
|
+
export declare function pairingStatus(id: string, origin: string): {
|
|
50
|
+
status: 'pending' | 'approved' | 'unknown';
|
|
51
|
+
};
|
|
52
|
+
/** CLI only. Never reachable over HTTP. */
|
|
53
|
+
export declare function approveByCode(code: string): Promise<Pairing>;
|
|
54
|
+
/**
|
|
55
|
+
* The native macOS dialog's Allow (pairDialog.ts). Never reachable over HTTP:
|
|
56
|
+
* it is called only from the daemon after a local click. It approves the exact
|
|
57
|
+
* request the dialog showed, by id AND code, so a request that was replaced
|
|
58
|
+
* while the dialog was open is not approved by it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function approvePendingLocally(id: string, code: string): Promise<Pairing>;
|
|
61
|
+
/** CLI, or a signed request from the pairing itself. */
|
|
62
|
+
export declare function revokePairing(id: string): Promise<boolean>;
|
|
63
|
+
/** Test seam. */
|
|
64
|
+
export declare function _setPairingClock(fn: (() => number) | null): void;
|
|
65
|
+
export declare function issueNonces(pairingId: unknown, origin: string, countIn: unknown): {
|
|
66
|
+
nonces: string[];
|
|
67
|
+
expires_at: string;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Exactly what the browser signs. The body is not included: replay is stopped
|
|
71
|
+
* by the single-use nonce, and anything able to rewrite a loopback request in
|
|
72
|
+
* flight is already past every boundary this could add.
|
|
73
|
+
*/
|
|
74
|
+
export declare function signingPayload(method: string, pathAndQuery: string, origin: string, pairingId: string, nonce: string, iat: number): string;
|
|
75
|
+
/** The pairing id a request was verified under, if it was. */
|
|
76
|
+
export declare function pairingOf(req: IncomingMessage): string | undefined;
|
|
77
|
+
export declare function hasPairingHeaders(req: IncomingMessage): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Verify a signed request. Order is the ADR's: loopback, origin allowlist,
|
|
80
|
+
* pairing approved and bound to this origin, freshness, nonce (burned before
|
|
81
|
+
* the signature check, so a bad signature still spends it), signature.
|
|
82
|
+
*/
|
|
83
|
+
export declare function verifyPairedRequest(req: IncomingMessage, pathAndQuery: string, allowedOrigins: string[]): string;
|
|
84
|
+
/** Test seam. */
|
|
85
|
+
export declare function _resetPairing(): void;
|
|
86
|
+
//# sourceMappingURL=pairing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairing.d.ts","sourceRoot":"","sources":["../../src/pty/pairing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Browser pairing (ADR-0012 in this repo; decibel-hq ADR-0012 / EPIC-0015 ph 2)
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Deployed HQ is an https page with no server of its own on this machine, so
|
|
5
|
+
// nothing can inject the daemon's bearer for it, and POL-0002 forbids putting
|
|
6
|
+
// one in the page. Instead the page holds a NON-EXTRACTABLE ECDSA P-256 key
|
|
7
|
+
// and signs each request; the daemon holds only public keys.
|
|
8
|
+
//
|
|
9
|
+
// 1. POST /pair/request {public_key_jwk, label} → pending, with a 6-digit
|
|
10
|
+
// code = H(thumbprint(pubkey) || daemon_nonce). HQ shows the code.
|
|
11
|
+
// 2. The human approves on this machine: on macOS a native dialog showing
|
|
12
|
+
// the same code (pairDialog.ts, ISS-0228), elsewhere
|
|
13
|
+
// `decibel-tools pair approve <code>`. NO HTTP ROUTE APPROVES — that is
|
|
14
|
+
// the whole gate. A compromised HQ can ask to pair; it cannot say yes.
|
|
15
|
+
// 3. POST /pair/challenge → single-use daemon nonces. Each request is then
|
|
16
|
+
// signed over (method, path, origin, pairing id, nonce, iat) and carried
|
|
17
|
+
// in X-Pairing-* headers.
|
|
18
|
+
//
|
|
19
|
+
// Store: ~/.decibel/pairings.yaml, mode 0600, public keys only. The CLI and the
|
|
20
|
+
// daemon are different processes and both write it, so every write is locked
|
|
21
|
+
// and atomic, and the daemon re-reads it when its mtime changes — which is how
|
|
22
|
+
// a CLI revoke reaches the daemon without any HTTP route.
|
|
23
|
+
// ============================================================================
|
|
24
|
+
import { createHash, createPublicKey, randomBytes, verify as cryptoVerify } from 'crypto';
|
|
25
|
+
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'fs';
|
|
26
|
+
import { homedir } from 'os';
|
|
27
|
+
import { join } from 'path';
|
|
28
|
+
import YAML from 'yaml';
|
|
29
|
+
import { writeFileAtomic } from '../lib/atomicWrite.js';
|
|
30
|
+
import { withFileLock } from '../lib/fileLock.js';
|
|
31
|
+
import { SessionError } from './errors.js';
|
|
32
|
+
import { isAllowedOrigin, isLoopbackPeer } from './boundary.js';
|
|
33
|
+
export const PENDING_TTL_MS = 10 * 60_000;
|
|
34
|
+
/** Approved pairings idle this long expire (Ben, 2026-09-25). */
|
|
35
|
+
export const IDLE_EXPIRY_MS = 30 * 24 * 60 * 60_000;
|
|
36
|
+
export const NONCE_TTL_MS = 60_000;
|
|
37
|
+
/** Signed requests must be this fresh, in either direction. */
|
|
38
|
+
export const IAT_SKEW_MS = 60_000;
|
|
39
|
+
const MAX_PENDING_PER_ORIGIN = 3;
|
|
40
|
+
const MAX_PENDING_TOTAL = 10;
|
|
41
|
+
const MAX_NONCES_PER_CHALLENGE = 20;
|
|
42
|
+
/** last_used is written at most this often per pairing. */
|
|
43
|
+
const LAST_USED_WRITE_MS = 10 * 60_000;
|
|
44
|
+
// ----------------------------------------------------------------------------
|
|
45
|
+
// Paths (per call, so tests can move HOME)
|
|
46
|
+
// ----------------------------------------------------------------------------
|
|
47
|
+
export function pairingsPath() {
|
|
48
|
+
return join(homedir(), '.decibel', 'pairings.yaml');
|
|
49
|
+
}
|
|
50
|
+
function lockPath() {
|
|
51
|
+
return pairingsPath() + '.lock';
|
|
52
|
+
}
|
|
53
|
+
// ----------------------------------------------------------------------------
|
|
54
|
+
// Store I/O
|
|
55
|
+
// ----------------------------------------------------------------------------
|
|
56
|
+
/**
|
|
57
|
+
* Cache key: inode + size + mtime, never mtime alone. $HOME here is HFS+, whose
|
|
58
|
+
* mtime has ONE-SECOND resolution, so a CLI approve landing in the same second
|
|
59
|
+
* as the daemon's last read left the daemon holding a stale "pending" — found
|
|
60
|
+
* live, not in tests. Every writer replaces the file by atomic rename, which
|
|
61
|
+
* always yields a new inode, so the inode alone would do; size and mtime also
|
|
62
|
+
* catch an in-place edit.
|
|
63
|
+
*/
|
|
64
|
+
let cache = null;
|
|
65
|
+
function readStore() {
|
|
66
|
+
const p = pairingsPath();
|
|
67
|
+
if (!existsSync(p)) {
|
|
68
|
+
cache = null;
|
|
69
|
+
return { pairings: [] };
|
|
70
|
+
}
|
|
71
|
+
const st = statSync(p);
|
|
72
|
+
const key = `${st.ino}:${st.size}:${st.mtimeMs}`;
|
|
73
|
+
if (cache && cache.key === key)
|
|
74
|
+
return cache.store;
|
|
75
|
+
// An unparseable store must fail loudly, not read as "no pairings": the
|
|
76
|
+
// latter would silently un-pair every browser and hide the damage.
|
|
77
|
+
const parsed = YAML.parse(readFileSync(p, 'utf-8'));
|
|
78
|
+
const store = { pairings: Array.isArray(parsed?.pairings) ? parsed.pairings : [] };
|
|
79
|
+
cache = { key, store };
|
|
80
|
+
return store;
|
|
81
|
+
}
|
|
82
|
+
async function mutate(fn) {
|
|
83
|
+
const p = pairingsPath();
|
|
84
|
+
mkdirSync(join(homedir(), '.decibel'), { recursive: true });
|
|
85
|
+
return withFileLock(lockPath(), async () => {
|
|
86
|
+
cache = null;
|
|
87
|
+
const store = prune(readStore());
|
|
88
|
+
const result = fn(store);
|
|
89
|
+
if (!existsSync(p))
|
|
90
|
+
writeFileSync(p, '', { mode: 0o600 });
|
|
91
|
+
await writeFileAtomic(p, YAML.stringify(store));
|
|
92
|
+
cache = null;
|
|
93
|
+
return result;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/** Drop expired pending requests and idle approved pairings. */
|
|
97
|
+
function prune(store, now = Date.now()) {
|
|
98
|
+
store.pairings = store.pairings.filter((p) => {
|
|
99
|
+
if (p.status === 'pending')
|
|
100
|
+
return now - Date.parse(p.requested_at) < PENDING_TTL_MS;
|
|
101
|
+
const last = Date.parse(p.last_used ?? p.approved_at ?? p.requested_at);
|
|
102
|
+
return now - last < IDLE_EXPIRY_MS;
|
|
103
|
+
});
|
|
104
|
+
return store;
|
|
105
|
+
}
|
|
106
|
+
export function listPairings() {
|
|
107
|
+
return prune({ pairings: [...readStore().pairings] }).pairings;
|
|
108
|
+
}
|
|
109
|
+
function activePairing(id) {
|
|
110
|
+
return listPairings().find((p) => p.id === id && p.status === 'approved');
|
|
111
|
+
}
|
|
112
|
+
export function isPairingActive(id) {
|
|
113
|
+
return !!activePairing(id);
|
|
114
|
+
}
|
|
115
|
+
// ----------------------------------------------------------------------------
|
|
116
|
+
// Keys and codes
|
|
117
|
+
// ----------------------------------------------------------------------------
|
|
118
|
+
const B64URL = /^[A-Za-z0-9_-]{43}$/;
|
|
119
|
+
/**
|
|
120
|
+
* A P-256 PUBLIC key and nothing else. A JWK carrying `d` is a private key: the
|
|
121
|
+
* page is supposed to hold a non-extractable key, so receiving one means
|
|
122
|
+
* something is badly wrong, and it is refused rather than stored.
|
|
123
|
+
*/
|
|
124
|
+
export function validatePublicJwk(v) {
|
|
125
|
+
const j = v;
|
|
126
|
+
if (!j || typeof j !== 'object')
|
|
127
|
+
throw new SessionError(400, 'BAD_KEY', 'public_key_jwk is required.');
|
|
128
|
+
if ('d' in j)
|
|
129
|
+
throw new SessionError(400, 'BAD_KEY', 'That is a PRIVATE key. Send only the public half; the private key must never leave the browser.');
|
|
130
|
+
if (j.kty !== 'EC' || j.crv !== 'P-256')
|
|
131
|
+
throw new SessionError(400, 'BAD_KEY', 'Only ECDSA P-256 keys are accepted.');
|
|
132
|
+
if (typeof j.x !== 'string' || typeof j.y !== 'string' || !B64URL.test(j.x) || !B64URL.test(j.y)) {
|
|
133
|
+
throw new SessionError(400, 'BAD_KEY', 'Malformed EC coordinates.');
|
|
134
|
+
}
|
|
135
|
+
const jwk = { kty: 'EC', crv: 'P-256', x: j.x, y: j.y };
|
|
136
|
+
try {
|
|
137
|
+
createPublicKey({ key: jwk, format: 'jwk' });
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
throw new SessionError(400, 'BAD_KEY', 'Not a valid P-256 point.');
|
|
141
|
+
}
|
|
142
|
+
return jwk;
|
|
143
|
+
}
|
|
144
|
+
/** RFC 7638 thumbprint. */
|
|
145
|
+
export function thumbprint(jwk) {
|
|
146
|
+
return createHash('sha256')
|
|
147
|
+
.update(JSON.stringify({ crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }))
|
|
148
|
+
.digest('base64url');
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* The code both sides show. Derived from the key AND a daemon nonce: from the
|
|
152
|
+
* key alone, an attacker could grind keys offline until one lands on a chosen
|
|
153
|
+
* code (cheap at 10^6); with the daemon's nonce mixed in, there is nothing to
|
|
154
|
+
* grind against before asking.
|
|
155
|
+
*/
|
|
156
|
+
export function pairingCode(jwk, daemonNonce) {
|
|
157
|
+
const h = createHash('sha256').update(thumbprint(jwk)).update(daemonNonce).digest();
|
|
158
|
+
return String(h.readUInt32BE(0) % 1_000_000).padStart(6, '0');
|
|
159
|
+
}
|
|
160
|
+
// ----------------------------------------------------------------------------
|
|
161
|
+
// Request / status / approve / revoke
|
|
162
|
+
// ----------------------------------------------------------------------------
|
|
163
|
+
export async function requestPairing(origin, jwkIn, labelIn) {
|
|
164
|
+
const jwk = validatePublicJwk(jwkIn);
|
|
165
|
+
const label = typeof labelIn === 'string' ? labelIn.replace(/[\r\n\t]/g, ' ').trim().slice(0, 80) : '';
|
|
166
|
+
return mutate((store) => {
|
|
167
|
+
const pending = store.pairings.filter((p) => p.status === 'pending');
|
|
168
|
+
if (pending.length >= MAX_PENDING_TOTAL || pending.filter((p) => p.origin === origin).length >= MAX_PENDING_PER_ORIGIN) {
|
|
169
|
+
throw new SessionError(429, 'TOO_MANY_PENDING', 'Too many pairing requests are waiting. Approve or let them expire (10 min) first.');
|
|
170
|
+
}
|
|
171
|
+
// Re-requesting with the same key replaces the old pending request.
|
|
172
|
+
const tp = thumbprint(jwk);
|
|
173
|
+
store.pairings = store.pairings.filter((p) => !(p.status === 'pending' && thumbprint(p.public_key_jwk) === tp));
|
|
174
|
+
const taken = new Set(store.pairings.filter((p) => p.status === 'pending').map((p) => p.code));
|
|
175
|
+
let code = '';
|
|
176
|
+
for (let i = 0; i < 20 && (!code || taken.has(code)); i++)
|
|
177
|
+
code = pairingCode(jwk, randomBytes(16).toString('hex'));
|
|
178
|
+
if (taken.has(code))
|
|
179
|
+
throw new SessionError(503, 'CODE_COLLISION', 'Could not allocate a pairing code; try again.');
|
|
180
|
+
const now = new Date();
|
|
181
|
+
const p = {
|
|
182
|
+
id: `pr_${randomBytes(9).toString('hex')}`,
|
|
183
|
+
origin,
|
|
184
|
+
label: label || 'HQ',
|
|
185
|
+
public_key_jwk: jwk,
|
|
186
|
+
status: 'pending',
|
|
187
|
+
code,
|
|
188
|
+
requested_at: now.toISOString(),
|
|
189
|
+
};
|
|
190
|
+
store.pairings.push(p);
|
|
191
|
+
return { pairing_id: p.id, code, expires_at: new Date(now.getTime() + PENDING_TTL_MS).toISOString() };
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
export function pairingStatus(id, origin) {
|
|
195
|
+
const p = listPairings().find((x) => x.id === id);
|
|
196
|
+
// A pairing is only reported to the origin it belongs to.
|
|
197
|
+
if (!p || p.origin !== origin)
|
|
198
|
+
return { status: 'unknown' };
|
|
199
|
+
return { status: p.status };
|
|
200
|
+
}
|
|
201
|
+
/** CLI only. Never reachable over HTTP. */
|
|
202
|
+
export async function approveByCode(code) {
|
|
203
|
+
if (!/^\d{6}$/.test(code))
|
|
204
|
+
throw new Error('A pairing code is 6 digits.');
|
|
205
|
+
return mutate((store) => {
|
|
206
|
+
const p = store.pairings.find((x) => x.status === 'pending' && x.code === code);
|
|
207
|
+
if (!p)
|
|
208
|
+
throw new Error(`No pending pairing request with code ${code} (requests expire after 10 minutes).`);
|
|
209
|
+
p.status = 'approved';
|
|
210
|
+
p.approved_at = new Date().toISOString();
|
|
211
|
+
delete p.code;
|
|
212
|
+
return { ...p };
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* The native macOS dialog's Allow (pairDialog.ts). Never reachable over HTTP:
|
|
217
|
+
* it is called only from the daemon after a local click. It approves the exact
|
|
218
|
+
* request the dialog showed, by id AND code, so a request that was replaced
|
|
219
|
+
* while the dialog was open is not approved by it.
|
|
220
|
+
*/
|
|
221
|
+
export async function approvePendingLocally(id, code) {
|
|
222
|
+
return mutate((store) => {
|
|
223
|
+
const p = store.pairings.find((x) => x.id === id && x.status === 'pending' && x.code === code);
|
|
224
|
+
if (!p)
|
|
225
|
+
throw new Error('That pairing request is no longer pending (expired, replaced or already answered).');
|
|
226
|
+
p.status = 'approved';
|
|
227
|
+
p.approved_at = new Date().toISOString();
|
|
228
|
+
delete p.code;
|
|
229
|
+
return { ...p };
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/** CLI, or a signed request from the pairing itself. */
|
|
233
|
+
export async function revokePairing(id) {
|
|
234
|
+
return mutate((store) => {
|
|
235
|
+
const before = store.pairings.length;
|
|
236
|
+
store.pairings = store.pairings.filter((p) => p.id !== id);
|
|
237
|
+
return store.pairings.length < before;
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
// ----------------------------------------------------------------------------
|
|
241
|
+
// Nonces and signed requests
|
|
242
|
+
// ----------------------------------------------------------------------------
|
|
243
|
+
const nonces = new Map();
|
|
244
|
+
let clock = Date.now;
|
|
245
|
+
/** Test seam. */
|
|
246
|
+
export function _setPairingClock(fn) {
|
|
247
|
+
clock = fn ?? Date.now;
|
|
248
|
+
}
|
|
249
|
+
function sweepNonces() {
|
|
250
|
+
const t = clock();
|
|
251
|
+
for (const [n, rec] of nonces)
|
|
252
|
+
if (rec.expiresAt <= t)
|
|
253
|
+
nonces.delete(n);
|
|
254
|
+
}
|
|
255
|
+
export function issueNonces(pairingId, origin, countIn) {
|
|
256
|
+
if (typeof pairingId !== 'string')
|
|
257
|
+
throw new SessionError(400, 'BAD_REQUEST', 'pairing_id is required.');
|
|
258
|
+
const p = activePairing(pairingId);
|
|
259
|
+
if (!p || p.origin !== origin)
|
|
260
|
+
throw new SessionError(403, 'NOT_PAIRED', 'No approved pairing with that id for this origin.');
|
|
261
|
+
const count = Math.min(Math.max(1, Math.floor(Number(countIn) || 1)), MAX_NONCES_PER_CHALLENGE);
|
|
262
|
+
sweepNonces();
|
|
263
|
+
const expiresAt = clock() + NONCE_TTL_MS;
|
|
264
|
+
const out = [];
|
|
265
|
+
for (let i = 0; i < count; i++) {
|
|
266
|
+
const n = randomBytes(24).toString('base64url');
|
|
267
|
+
nonces.set(n, { pairingId, expiresAt });
|
|
268
|
+
out.push(n);
|
|
269
|
+
}
|
|
270
|
+
return { nonces: out, expires_at: new Date(expiresAt).toISOString() };
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Exactly what the browser signs. The body is not included: replay is stopped
|
|
274
|
+
* by the single-use nonce, and anything able to rewrite a loopback request in
|
|
275
|
+
* flight is already past every boundary this could add.
|
|
276
|
+
*/
|
|
277
|
+
export function signingPayload(method, pathAndQuery, origin, pairingId, nonce, iat) {
|
|
278
|
+
return ['decibel-pair-v1', method.toUpperCase(), pathAndQuery, origin, pairingId, nonce, String(iat)].join('\n');
|
|
279
|
+
}
|
|
280
|
+
const pairedRequests = new WeakMap();
|
|
281
|
+
/** The pairing id a request was verified under, if it was. */
|
|
282
|
+
export function pairingOf(req) {
|
|
283
|
+
return pairedRequests.get(req);
|
|
284
|
+
}
|
|
285
|
+
export function hasPairingHeaders(req) {
|
|
286
|
+
return typeof req.headers['x-pairing-id'] === 'string';
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Verify a signed request. Order is the ADR's: loopback, origin allowlist,
|
|
290
|
+
* pairing approved and bound to this origin, freshness, nonce (burned before
|
|
291
|
+
* the signature check, so a bad signature still spends it), signature.
|
|
292
|
+
*/
|
|
293
|
+
export function verifyPairedRequest(req, pathAndQuery, allowedOrigins) {
|
|
294
|
+
const h = (k) => (typeof req.headers[k] === 'string' ? req.headers[k] : '');
|
|
295
|
+
const origin = h('origin');
|
|
296
|
+
if (!isLoopbackPeer(req))
|
|
297
|
+
throw new SessionError(403, 'FORBIDDEN', 'not a loopback peer');
|
|
298
|
+
if (!isAllowedOrigin(origin, allowedOrigins))
|
|
299
|
+
throw new SessionError(403, 'FORBIDDEN', 'origin not allowed');
|
|
300
|
+
const pairingId = h('x-pairing-id');
|
|
301
|
+
const nonce = h('x-pairing-nonce');
|
|
302
|
+
const iat = Number(h('x-pairing-iat'));
|
|
303
|
+
const sig = h('x-pairing-sig');
|
|
304
|
+
if (!pairingId || !nonce || !Number.isFinite(iat) || !sig) {
|
|
305
|
+
throw new SessionError(401, 'BAD_SIGNATURE', 'X-Pairing-Id, -Nonce, -Iat and -Sig are all required.');
|
|
306
|
+
}
|
|
307
|
+
const p = activePairing(pairingId);
|
|
308
|
+
if (!p || p.origin !== origin)
|
|
309
|
+
throw new SessionError(401, 'NOT_PAIRED', 'No approved pairing with that id for this origin.');
|
|
310
|
+
if (Math.abs(clock() - iat) > IAT_SKEW_MS)
|
|
311
|
+
throw new SessionError(401, 'STALE_REQUEST', 'X-Pairing-Iat is outside the allowed window.');
|
|
312
|
+
sweepNonces();
|
|
313
|
+
const rec = nonces.get(nonce);
|
|
314
|
+
nonces.delete(nonce);
|
|
315
|
+
if (!rec || rec.pairingId !== pairingId)
|
|
316
|
+
throw new SessionError(401, 'BAD_NONCE', 'Unknown, reused or expired nonce.');
|
|
317
|
+
const payload = signingPayload(req.method || 'GET', pathAndQuery, origin, pairingId, nonce, iat);
|
|
318
|
+
let ok = false;
|
|
319
|
+
try {
|
|
320
|
+
ok = cryptoVerify('sha256', Buffer.from(payload, 'utf-8'), { key: createPublicKey({ key: p.public_key_jwk, format: 'jwk' }), dsaEncoding: 'ieee-p1363' }, Buffer.from(sig, 'base64url'));
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
ok = false;
|
|
324
|
+
}
|
|
325
|
+
if (!ok)
|
|
326
|
+
throw new SessionError(401, 'BAD_SIGNATURE', 'Signature does not verify.');
|
|
327
|
+
pairedRequests.set(req, pairingId);
|
|
328
|
+
touch(p);
|
|
329
|
+
return pairingId;
|
|
330
|
+
}
|
|
331
|
+
const lastTouched = new Map();
|
|
332
|
+
function touch(p) {
|
|
333
|
+
const now = clock();
|
|
334
|
+
const last = lastTouched.get(p.id) ?? Date.parse(p.last_used ?? '') ?? 0;
|
|
335
|
+
if (now - (Number.isFinite(last) ? last : 0) < LAST_USED_WRITE_MS)
|
|
336
|
+
return;
|
|
337
|
+
lastTouched.set(p.id, now);
|
|
338
|
+
mutate((store) => {
|
|
339
|
+
const q = store.pairings.find((x) => x.id === p.id);
|
|
340
|
+
if (q)
|
|
341
|
+
q.last_used = new Date(now).toISOString();
|
|
342
|
+
}).catch(() => undefined);
|
|
343
|
+
}
|
|
344
|
+
/** Test seam. */
|
|
345
|
+
export function _resetPairing() {
|
|
346
|
+
nonces.clear();
|
|
347
|
+
lastTouched.clear();
|
|
348
|
+
cache = null;
|
|
349
|
+
clock = Date.now;
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=pairing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairing.js","sourceRoot":"","sources":["../../src/pty/pairing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
+
import type { Duplex } from 'stream';
|
|
3
|
+
/** How long a minted attach token stays usable. Deliberately short. */
|
|
4
|
+
export declare const ATTACH_TOKEN_TTL_MS = 30000;
|
|
5
|
+
/** HQ dev server, through the Vite proxy (decibel-hq EPIC-0015 phase 1). */
|
|
6
|
+
export declare const DEFAULT_SESSION_ORIGINS: string[];
|
|
7
|
+
export interface SessionAuthConfig {
|
|
8
|
+
token?: string;
|
|
9
|
+
allowedOrigins: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function sessionAuthConfig(): SessionAuthConfig;
|
|
12
|
+
/** Test seam. */
|
|
13
|
+
export declare function _setSessionAuthConfig(c: SessionAuthConfig | null): void;
|
|
14
|
+
/** Test seam. */
|
|
15
|
+
export declare function _setClock(fn: (() => number) | null): void;
|
|
16
|
+
export declare function outstandingTokens(): number;
|
|
17
|
+
/** The routes this module gates itself. GET /sessions and /sessions/last-fleet are NOT among them. */
|
|
18
|
+
export declare function isSessionWritePath(path: string): boolean;
|
|
19
|
+
export declare function isSessionAttachPath(path: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Handle a session write route or its preflight. Called by httpServer.ts for
|
|
22
|
+
* any path where isSessionWritePath() is true, before the daemon's own auth
|
|
23
|
+
* gate (which knows nothing of the sessions bearer).
|
|
24
|
+
*/
|
|
25
|
+
export declare function handleSessionWrite(req: IncomingMessage, res: ServerResponse, path: string): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* POST /chat (decibel-hq EPIC-0016): send as the HQ chat peer. Same gate as
|
|
28
|
+
* the session writes: it puts text into other sessions.
|
|
29
|
+
*/
|
|
30
|
+
export declare function handleChatWrite(req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Signed requests from a paired browser (ADR-0012 in this repo). httpServer.ts
|
|
33
|
+
* calls this once per request, before rate limiting and auth. A verified
|
|
34
|
+
* request is marked (pairingOf) and stands in for a bearer everywhere after.
|
|
35
|
+
* A request that CLAIMS a pairing and fails verification is refused outright
|
|
36
|
+
* rather than falling through as anonymous. Returns false when it refused.
|
|
37
|
+
*/
|
|
38
|
+
export declare function applyPairingAuth(req: IncomingMessage, res: ServerResponse, url: URL): boolean;
|
|
39
|
+
export declare function isPairPath(path: string): boolean;
|
|
40
|
+
export declare function handlePair(req: IncomingMessage, res: ServerResponse, path: string): Promise<void>;
|
|
41
|
+
export declare function closeRevokedSockets(): number;
|
|
42
|
+
/**
|
|
43
|
+
* Handle an upgrade on /sessions/<key>/attach. The caller (httpServer.ts)
|
|
44
|
+
* routes here only for that path; anything else it refuses itself.
|
|
45
|
+
*/
|
|
46
|
+
export declare function handleSessionUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer, url: URL): Promise<void>;
|
|
47
|
+
/** Close every live attach socket (daemon shutdown). */
|
|
48
|
+
export declare function closeAllAttachSockets(): void;
|
|
49
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/pty/routes.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AA0CrC,uEAAuE;AACvE,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAG1C,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,UAAqD,CAAC;AAoB1F,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAWD,wBAAgB,iBAAiB,IAAI,iBAAiB,CAWrD;AACD,iBAAiB;AACjB,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAGvE;AAcD,iBAAiB;AACjB,wBAAgB,SAAS,CAAC,EAAE,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,CAEzD;AACD,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAcD,sGAAsG;AACtG,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AA8ED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+D/G;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9F;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAkB7F;AAUD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDvG;AAiCD,wBAAgB,mBAAmB,IAAI,MAAM,CAkB5C;AAuBD;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAkItH;AAED,wDAAwD;AACxD,wBAAgB,qBAAqB,IAAI,IAAI,CAS5C"}
|