wicked-crew 0.5.0 → 0.6.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 (116) hide show
  1. package/dist/api/audit.d.ts +57 -0
  2. package/dist/api/audit.d.ts.map +1 -0
  3. package/dist/api/audit.js +115 -0
  4. package/dist/api/audit.js.map +1 -0
  5. package/dist/api/auth.d.ts +192 -0
  6. package/dist/api/auth.d.ts.map +1 -0
  7. package/dist/api/auth.js +515 -0
  8. package/dist/api/auth.js.map +1 -0
  9. package/dist/api/gate-cache.d.ts +8 -0
  10. package/dist/api/gate-cache.d.ts.map +1 -1
  11. package/dist/api/gate-cache.js +10 -0
  12. package/dist/api/gate-cache.js.map +1 -1
  13. package/dist/api/open-path.d.ts +18 -0
  14. package/dist/api/open-path.d.ts.map +1 -0
  15. package/dist/api/open-path.js +79 -0
  16. package/dist/api/open-path.js.map +1 -0
  17. package/dist/api/routes.d.ts +112 -1
  18. package/dist/api/routes.d.ts.map +1 -1
  19. package/dist/api/routes.js +435 -16
  20. package/dist/api/routes.js.map +1 -1
  21. package/dist/api/seat-health.d.ts +55 -0
  22. package/dist/api/seat-health.d.ts.map +1 -0
  23. package/dist/api/seat-health.js +273 -0
  24. package/dist/api/seat-health.js.map +1 -0
  25. package/dist/api/seat-signin.d.ts +27 -0
  26. package/dist/api/seat-signin.d.ts.map +1 -0
  27. package/dist/api/seat-signin.js +143 -0
  28. package/dist/api/seat-signin.js.map +1 -0
  29. package/dist/api/server.d.ts +111 -3
  30. package/dist/api/server.d.ts.map +1 -1
  31. package/dist/api/server.js +236 -11
  32. package/dist/api/server.js.map +1 -1
  33. package/dist/cli/index.js +97 -3
  34. package/dist/cli/index.js.map +1 -1
  35. package/dist/cli/mcp.d.ts +14 -0
  36. package/dist/cli/mcp.d.ts.map +1 -0
  37. package/dist/cli/mcp.js +119 -0
  38. package/dist/cli/mcp.js.map +1 -0
  39. package/dist/core/adapter.d.ts +64 -1
  40. package/dist/core/adapter.d.ts.map +1 -1
  41. package/dist/core/adapter.js +162 -4
  42. package/dist/core/adapter.js.map +1 -1
  43. package/dist/core/types.d.ts +23 -361
  44. package/dist/core/types.d.ts.map +1 -1
  45. package/dist/core/types.js +11 -4
  46. package/dist/core/types.js.map +1 -1
  47. package/dist/interactive/bridge-pool.d.ts +71 -0
  48. package/dist/interactive/bridge-pool.d.ts.map +1 -0
  49. package/dist/interactive/bridge-pool.js +187 -0
  50. package/dist/interactive/bridge-pool.js.map +1 -0
  51. package/dist/interactive/bridge-root.d.ts +36 -0
  52. package/dist/interactive/bridge-root.d.ts.map +1 -0
  53. package/dist/interactive/bridge-root.js +48 -0
  54. package/dist/interactive/bridge-root.js.map +1 -0
  55. package/dist/interactive/draft-events.d.ts +144 -0
  56. package/dist/interactive/draft-events.d.ts.map +1 -0
  57. package/dist/interactive/draft-events.js +490 -0
  58. package/dist/interactive/draft-events.js.map +1 -0
  59. package/dist/interactive/edit-events.d.ts +172 -0
  60. package/dist/interactive/edit-events.d.ts.map +1 -0
  61. package/dist/interactive/edit-events.js +530 -0
  62. package/dist/interactive/edit-events.js.map +1 -0
  63. package/dist/interactive/ledger.d.ts +39 -0
  64. package/dist/interactive/ledger.d.ts.map +1 -0
  65. package/dist/interactive/ledger.js +93 -0
  66. package/dist/interactive/ledger.js.map +1 -0
  67. package/dist/interactive/proxy-routes.d.ts +39 -0
  68. package/dist/interactive/proxy-routes.d.ts.map +1 -0
  69. package/dist/interactive/proxy-routes.js +189 -0
  70. package/dist/interactive/proxy-routes.js.map +1 -0
  71. package/dist/interactive/ws-relay.d.ts +85 -0
  72. package/dist/interactive/ws-relay.d.ts.map +1 -0
  73. package/dist/interactive/ws-relay.js +191 -0
  74. package/dist/interactive/ws-relay.js.map +1 -0
  75. package/dist/projects/activity.d.ts +29 -0
  76. package/dist/projects/activity.d.ts.map +1 -0
  77. package/dist/projects/activity.js +172 -0
  78. package/dist/projects/activity.js.map +1 -0
  79. package/dist/projects/charter.d.ts +28 -0
  80. package/dist/projects/charter.d.ts.map +1 -0
  81. package/dist/projects/charter.js +53 -0
  82. package/dist/projects/charter.js.map +1 -0
  83. package/dist/projects/events.d.ts +55 -0
  84. package/dist/projects/events.d.ts.map +1 -0
  85. package/dist/projects/events.js +141 -0
  86. package/dist/projects/events.js.map +1 -0
  87. package/dist/projects/membership-index.d.ts +25 -0
  88. package/dist/projects/membership-index.d.ts.map +1 -0
  89. package/dist/projects/membership-index.js +46 -0
  90. package/dist/projects/membership-index.js.map +1 -0
  91. package/dist/projects/routes.d.ts +90 -0
  92. package/dist/projects/routes.d.ts.map +1 -0
  93. package/dist/projects/routes.js +388 -0
  94. package/dist/projects/routes.js.map +1 -0
  95. package/dist/projects/settings.d.ts +32 -0
  96. package/dist/projects/settings.d.ts.map +1 -0
  97. package/dist/projects/settings.js +64 -0
  98. package/dist/projects/settings.js.map +1 -0
  99. package/dist/qe/acceptance.d.ts +137 -0
  100. package/dist/qe/acceptance.d.ts.map +1 -0
  101. package/dist/qe/acceptance.js +249 -0
  102. package/dist/qe/acceptance.js.map +1 -0
  103. package/dist/qe/gate-events.d.ts +111 -0
  104. package/dist/qe/gate-events.d.ts.map +1 -0
  105. package/dist/qe/gate-events.js +168 -0
  106. package/dist/qe/gate-events.js.map +1 -0
  107. package/dist/qe/ledger.d.ts +100 -0
  108. package/dist/qe/ledger.d.ts.map +1 -0
  109. package/dist/qe/ledger.js +154 -0
  110. package/dist/qe/ledger.js.map +1 -0
  111. package/dist/studio/assets/index-CCwXa1cn.js +428 -0
  112. package/dist/studio/assets/index-HWxo0h41.css +32 -0
  113. package/dist/studio/index.html +2 -2
  114. package/package.json +10 -4
  115. package/dist/studio/assets/index-DaaUU8Ep.css +0 -32
  116. package/dist/studio/assets/index-Fu5DRC00.js +0 -423
@@ -0,0 +1,515 @@
1
+ /**
2
+ * The daemon's identity/actor seam (task #88, locked decision #6).
3
+ *
4
+ * LOCAL IS SACRED: the default deployment stays exactly what it was — a
5
+ * 127.0.0.1-bound daemon with loopback CORS and NO auth, where every request
6
+ * implicitly acts as the full-trust local operator. Nothing in this module
7
+ * runs a verifier, reads a token file, or changes a response in that mode; it
8
+ * only pins ONE actor shape onto the request so downstream code (audit trail,
9
+ * bus events, gate decisions) never branches on "was there auth".
10
+ *
11
+ * TEAM/HOSTED REQUIRES AUTH: `WICKED_RUNTIME=team` or `WICKED_CREW_AUTH=required`
12
+ * arms a bearer-token check on `/api/v1/*` and the `/ws` upgrade paths.
13
+ * Verification is pluggable behind {@link TokenVerifier}; v1 ships the static
14
+ * workload-token verifier (hashed-at-rest file, {@link loadTokenFile}) and the
15
+ * OIDC verifier SEAM ({@link OidcConfig} + {@link createOidcVerifier}), whose
16
+ * implementation is a named follow-up — configuring OIDC today fails the boot
17
+ * LOUDLY rather than pretending an IdP was consulted.
18
+ *
19
+ * Deny semantics: missing/unknown token in required mode → 401 (with
20
+ * `WWW-Authenticate: Bearer`); an authenticated actor below a route's rung on
21
+ * the trust ladder → 403. The ladder is {@link requiredTrust} — minimal and
22
+ * documented (docs/auth.md), not a per-route registry.
23
+ */
24
+ import { readFileSync, statSync } from 'node:fs';
25
+ import { homedir } from 'node:os';
26
+ import { join } from 'node:path';
27
+ import { constants, createHash, createPublicKey, verify as cryptoVerify } from 'node:crypto';
28
+ import { API_PREFIX } from './api-prefix.js';
29
+ /**
30
+ * The implicit full-trust local operator. `admin` is the ladder's top rung —
31
+ * the local single-operator deployment has exactly one human and no boundary
32
+ * to enforce between that human and the daemon, so "full trust" and "admin"
33
+ * are the same fact spelled once.
34
+ */
35
+ export const LOCAL_ACTOR = Object.freeze({
36
+ id: 'local',
37
+ kind: 'human',
38
+ trust: 'admin',
39
+ });
40
+ const TRUST_RANK = { observer: 0, operator: 1, admin: 2 };
41
+ const KINDS = new Set(['human', 'agent', 'system']);
42
+ const TRUSTS = new Set(['observer', 'operator', 'admin']);
43
+ /** True when `actor` sits at or above `min` on the ladder. */
44
+ export function trustAtLeast(actor, min) {
45
+ return TRUST_RANK[actor.trust] >= TRUST_RANK[min];
46
+ }
47
+ /**
48
+ * Resolve the daemon's auth mode. DENY-DOMINANT: `WICKED_RUNTIME=team` forces
49
+ * `required` and nothing can talk it back down — a team runtime with auth
50
+ * switched off is exactly the silently-ungoverned state this seam exists to
51
+ * prevent. Outside team runtime, `WICKED_CREW_AUTH` (`required`|`off`) is
52
+ * explicit; unset means the local default, off.
53
+ */
54
+ export function resolveAuthMode(env = process.env) {
55
+ if (env['WICKED_RUNTIME']?.trim().toLowerCase() === 'team')
56
+ return 'required';
57
+ const explicit = env['WICKED_CREW_AUTH']?.trim().toLowerCase();
58
+ if (explicit === undefined || explicit === '' || explicit === 'off')
59
+ return 'off';
60
+ if (explicit === 'required')
61
+ return 'required';
62
+ // An unknown value fails LOUD rather than defaulting to off: a typo'd
63
+ // `WICKED_CREW_AUTH=reqired` silently running unauthenticated is the worst
64
+ // possible reading of an operator's stated intent to authenticate.
65
+ throw new Error(`WICKED_CREW_AUTH must be 'required' or 'off' (got '${explicit}')`);
66
+ }
67
+ /** Where the workload-token file lives unless overridden. */
68
+ export function defaultTokensPath(env = process.env) {
69
+ return env['WICKED_CREW_TOKENS'] ?? join(homedir(), '.config', 'wicked-crew', 'tokens.json');
70
+ }
71
+ /** `sha256` hex of a presented token — the only form the daemon stores or compares. */
72
+ export function tokenHash(token) {
73
+ return createHash('sha256').update(token, 'utf8').digest('hex');
74
+ }
75
+ const SHA256_HEX = /^[0-9a-f]{64}$/;
76
+ /**
77
+ * Parse a tokens.json payload into a hash→actor map. FAILS CLOSED on any
78
+ * malformed entry: a typo'd trust level that silently skipped its entry would
79
+ * lock an operator out (or, worse, a hand-edit that half-parsed would demote
80
+ * someone) with nothing saying so. The error names the entry index and field.
81
+ */
82
+ export function parseTokenFile(json, source) {
83
+ let raw;
84
+ try {
85
+ raw = JSON.parse(json);
86
+ }
87
+ catch (err) {
88
+ throw new Error(`${source}: not valid JSON (${err instanceof Error ? err.message : String(err)})`);
89
+ }
90
+ const file = raw;
91
+ if (typeof file !== 'object' || file === null || !Array.isArray(file.tokens)) {
92
+ throw new Error(`${source}: expected { "version": 1, "tokens": [...] }`);
93
+ }
94
+ if (file.version !== undefined && file.version !== 1) {
95
+ throw new Error(`${source}: unsupported version ${JSON.stringify(file.version)} (this build reads version 1)`);
96
+ }
97
+ const map = new Map();
98
+ file.tokens.forEach((entry, i) => {
99
+ const e = entry;
100
+ const at = `${source}: tokens[${i}]`;
101
+ if (typeof e?.sha256 !== 'string' || !SHA256_HEX.test(e.sha256)) {
102
+ throw new Error(`${at}: 'sha256' must be 64 lowercase hex chars (sha256 of the token)`);
103
+ }
104
+ const a = e.actor;
105
+ if (typeof a?.id !== 'string' || a.id.length === 0 || a.id.length > 128) {
106
+ throw new Error(`${at}: 'actor.id' must be a non-empty string (≤128 chars)`);
107
+ }
108
+ if (typeof a.kind !== 'string' || !KINDS.has(a.kind)) {
109
+ throw new Error(`${at}: 'actor.kind' must be 'human' | 'agent' | 'system'`);
110
+ }
111
+ if (typeof a.trust !== 'string' || !TRUSTS.has(a.trust)) {
112
+ throw new Error(`${at}: 'actor.trust' must be 'observer' | 'operator' | 'admin'`);
113
+ }
114
+ if (map.has(e.sha256)) {
115
+ throw new Error(`${at}: duplicate token hash (also used by an earlier entry)`);
116
+ }
117
+ map.set(e.sha256, Object.freeze({ id: a.id, kind: a.kind, trust: a.trust }));
118
+ });
119
+ return map;
120
+ }
121
+ /**
122
+ * Load `tokens.json` from disk into a static verifier. A MISSING file is a
123
+ * loud warning, not a boot failure: the daemon still starts and every request
124
+ * 401s, which is the honest fail-closed posture (an unreachable daemon tells
125
+ * the operator less than one that answers "no tokens are registered").
126
+ * A PRESENT-but-malformed file fails the boot — see {@link parseTokenFile}.
127
+ */
128
+ export function loadTokenFile(path, warn) {
129
+ let json;
130
+ try {
131
+ json = readFileSync(path, 'utf8');
132
+ }
133
+ catch (err) {
134
+ if (err.code === 'ENOENT') {
135
+ warn(`[auth] required mode with NO token file at ${path} — every /api/v1 and /ws request will 401 ` +
136
+ `until tokens are registered (docs/auth.md § "Workload tokens")`);
137
+ return new Map();
138
+ }
139
+ throw new Error(`[auth] cannot read token file ${path}: ${err instanceof Error ? err.message : String(err)}`);
140
+ }
141
+ // Hashes, not tokens, live in this file — but its actor/trust mappings are
142
+ // still authorization state, so a group/world-writable file is worth a shout.
143
+ if (process.platform !== 'win32') {
144
+ try {
145
+ const mode = statSync(path).mode & 0o077;
146
+ if (mode !== 0) {
147
+ warn(`[auth] ${path} is group/world-accessible (mode ${(statSync(path).mode & 0o777).toString(8)}) — chmod 600 recommended`);
148
+ }
149
+ }
150
+ catch {
151
+ /* stat raced a delete; the read above already succeeded */
152
+ }
153
+ }
154
+ return parseTokenFile(json, path);
155
+ }
156
+ /** The static workload-token verifier: sha256 the presented token, look it up. */
157
+ export function createStaticVerifier(entries) {
158
+ return {
159
+ name: 'static-tokens',
160
+ verify: (token) => Promise.resolve(entries.get(tokenHash(token)) ?? null),
161
+ };
162
+ }
163
+ /** Where the auth config (OIDC seam) lives unless overridden. */
164
+ export function defaultAuthConfigPath(env = process.env) {
165
+ return env['WICKED_CREW_AUTH_CONFIG'] ?? join(homedir(), '.config', 'wicked-crew', 'auth.json');
166
+ }
167
+ /** Per-issuer JWKS cache: keys indexed by kid (or by alg when kid is absent). */
168
+ const JWKS_CACHE = new Map();
169
+ const JWKS_TTL_MS = 5 * 60 * 1000; // 5-min TTL; synchronous re-fetch on stale or unknown kid
170
+ function base64urlDecode(s) {
171
+ const pad = (4 - (s.length % 4)) % 4;
172
+ return Buffer.from(s.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat(pad), 'base64');
173
+ }
174
+ async function fetchJson(url) {
175
+ const res = await fetch(url, { signal: AbortSignal.timeout(10_000) });
176
+ if (!res.ok)
177
+ throw new Error(`HTTP ${res.status} fetching ${url}`);
178
+ return res.json();
179
+ }
180
+ async function fetchJwks(jwksUri) {
181
+ const doc = await fetchJson(jwksUri);
182
+ const map = new Map();
183
+ for (const key of doc.keys ?? []) {
184
+ if (key.use !== undefined && key.use !== 'sig')
185
+ continue;
186
+ // Index by kid; fall back to alg when kid is absent.
187
+ const index = key.kid ?? key.alg ?? key.kty;
188
+ map.set(index, key);
189
+ }
190
+ return map;
191
+ }
192
+ async function resolveJwksUri(config) {
193
+ if (config.jwksUri)
194
+ return config.jwksUri;
195
+ const discovery = await fetchJson(`${config.issuer.replace(/\/$/, '')}/.well-known/openid-configuration`);
196
+ return discovery.jwks_uri;
197
+ }
198
+ async function getJwk(config, kid, allowRefresh) {
199
+ const cached = JWKS_CACHE.get(config.issuer);
200
+ const stale = !cached || Date.now() - cached.fetchedAt > JWKS_TTL_MS;
201
+ if (cached && !stale) {
202
+ const hit = cached.keys.get(kid);
203
+ if (hit)
204
+ return hit;
205
+ if (!allowRefresh)
206
+ return null;
207
+ }
208
+ // Fetch (or re-fetch on stale/miss).
209
+ const uri = await resolveJwksUri(config);
210
+ const keys = await fetchJwks(uri);
211
+ JWKS_CACHE.set(config.issuer, { keys, fetchedAt: Date.now() });
212
+ return keys.get(kid) ?? null;
213
+ }
214
+ // Supported algorithm → hash algorithm pairs.
215
+ const ALG_HASH = {
216
+ RS256: 'SHA256', RS384: 'SHA384', RS512: 'SHA512',
217
+ ES256: 'SHA256', ES384: 'SHA384', ES512: 'SHA512',
218
+ PS256: 'SHA256', PS384: 'SHA384', PS512: 'SHA512',
219
+ };
220
+ function verifySignature(headerPayload, sig, jwk, alg) {
221
+ const hashAlg = ALG_HASH[alg];
222
+ if (!hashAlg)
223
+ return false;
224
+ try {
225
+ const key = createPublicKey({ key: jwk, format: 'jwk' });
226
+ const opts = alg.startsWith('PS')
227
+ ? { padding: constants.RSA_PKCS1_PSS_PADDING, saltLength: constants.RSA_PSS_SALTLEN_DIGEST }
228
+ : alg.startsWith('ES')
229
+ ? { dsaEncoding: 'ieee-p1363' }
230
+ : {};
231
+ return cryptoVerify(hashAlg, Buffer.from(headerPayload), { key, ...opts }, sig);
232
+ }
233
+ catch {
234
+ return false;
235
+ }
236
+ }
237
+ /**
238
+ * Verify a raw JWT string against the issuer's JWKS. Returns the decoded
239
+ * payload on success or throws a descriptive error on failure.
240
+ */
241
+ async function verifyJwt(token, config) {
242
+ const parts = token.split('.');
243
+ if (parts.length !== 3)
244
+ throw new Error('malformed JWT: expected 3 dot-separated parts');
245
+ let header;
246
+ let payload;
247
+ try {
248
+ header = JSON.parse(base64urlDecode(parts[0]).toString('utf8'));
249
+ payload = JSON.parse(base64urlDecode(parts[1]).toString('utf8'));
250
+ }
251
+ catch {
252
+ throw new Error('malformed JWT: header or payload is not valid base64url JSON');
253
+ }
254
+ const alg = header.alg ?? '';
255
+ if (!ALG_HASH[alg])
256
+ throw new Error(`unsupported JWT algorithm: ${alg}`);
257
+ const kid = header.kid ?? alg;
258
+ const sig = base64urlDecode(parts[2]);
259
+ const headerPayload = `${parts[0]}.${parts[1]}`;
260
+ // Try cached key first; re-fetch once on unknown kid.
261
+ const jwk = await getJwk(config, kid, true);
262
+ if (!jwk)
263
+ throw new Error(`no JWKS key found for kid=${JSON.stringify(kid)}`);
264
+ if (!verifySignature(headerPayload, sig, jwk, alg)) {
265
+ throw new Error('JWT signature verification failed');
266
+ }
267
+ // Claim validation.
268
+ const now = Math.floor(Date.now() / 1000);
269
+ if (typeof payload.iss !== 'string' || payload.iss !== config.issuer) {
270
+ throw new Error(`JWT issuer mismatch: expected ${config.issuer}, got ${JSON.stringify(payload.iss)}`);
271
+ }
272
+ const audList = Array.isArray(payload.aud) ? payload.aud : [payload.aud];
273
+ if (!audList.includes(config.audience)) {
274
+ throw new Error(`JWT audience mismatch: expected ${config.audience}, got ${JSON.stringify(payload.aud)}`);
275
+ }
276
+ if (typeof payload.exp !== 'number') {
277
+ throw new Error('JWT is missing required exp claim');
278
+ }
279
+ if (payload.exp <= now) {
280
+ throw new Error('JWT has expired (exp)');
281
+ }
282
+ if (typeof payload.nbf === 'number' && payload.nbf > now) {
283
+ throw new Error('JWT is not yet valid (nbf)');
284
+ }
285
+ return payload;
286
+ }
287
+ function mapOidcActor(payload, config) {
288
+ const idClaim = config.claims?.id ?? 'sub';
289
+ const rawId = payload[idClaim];
290
+ const id = typeof rawId === 'string' && rawId.length > 0 ? rawId : payload.sub ?? '';
291
+ if (!id)
292
+ throw new Error(`JWT has no value for id claim '${idClaim}' or 'sub'`);
293
+ const trustClaim = config.claims?.trust;
294
+ const rawTrust = trustClaim ? payload[trustClaim] : undefined;
295
+ const defaultTrust = config.defaultTrust ?? 'observer';
296
+ const rawTrustStr = String(rawTrust);
297
+ const trust = TRUSTS.has(rawTrustStr) ? rawTrustStr : defaultTrust;
298
+ return Object.freeze({ id, kind: 'human', trust });
299
+ }
300
+ /**
301
+ * Create an OIDC verifier that validates JWTs against the issuer's JWKS.
302
+ * Supports RS256/384/512, ES256/384/512, PS256/384/512. JWKS keys are cached
303
+ * per issuer with a 5-minute TTL and auto-refreshed on unknown kid.
304
+ */
305
+ export function createOidcVerifier(config) {
306
+ // Validate config at creation time — a misconfigured issuer URL is caught
307
+ // immediately at boot rather than silently during the first verification.
308
+ if (!config.issuer || !config.issuer.startsWith('https://')) {
309
+ throw new Error(`[auth] OIDC config: 'issuer' must be an https:// URL (got ${JSON.stringify(config.issuer)})`);
310
+ }
311
+ if (config.defaultTrust !== undefined && !TRUSTS.has(config.defaultTrust)) {
312
+ throw new Error(`[auth] OIDC config: 'defaultTrust' must be observer|operator|admin (got ${JSON.stringify(config.defaultTrust)})`);
313
+ }
314
+ if (!config.audience) {
315
+ throw new Error(`[auth] OIDC config: 'audience' is required`);
316
+ }
317
+ return {
318
+ name: 'oidc',
319
+ async verify(token) {
320
+ // A JWT has exactly 3 base64url segments separated by dots. Static
321
+ // workload tokens are opaque strings and won't have this shape — the
322
+ // verifier chain tries static-tokens first, so if we get called the
323
+ // token isn't a known workload token. But don't assume it's a JWT either.
324
+ if (!token.includes('.'))
325
+ return null; // clearly not a JWT; pass through
326
+ try {
327
+ const payload = await verifyJwt(token, config);
328
+ return mapOidcActor(payload, config);
329
+ }
330
+ catch {
331
+ // Any verification failure → null so the chain can try the next
332
+ // verifier (or 401 if none match). The deny-401 path logs the failure.
333
+ return null;
334
+ }
335
+ },
336
+ };
337
+ }
338
+ /** Resolve mode + verifier chain. Reads files ONLY in required mode. */
339
+ export function resolveAuth(options, warn) {
340
+ const mode = options?.mode ?? resolveAuthMode();
341
+ const originsEnv = process.env['WICKED_CREW_ALLOWED_ORIGINS'];
342
+ const allowedOrigins = options?.allowedOrigins ??
343
+ (originsEnv !== undefined && originsEnv.trim() !== ''
344
+ ? originsEnv.split(',').map((o) => o.trim()).filter(Boolean)
345
+ : null);
346
+ if (mode === 'off') {
347
+ // Local default: no verifier exists, no file is read, no request is denied.
348
+ return { mode, verifiers: [], allowedOrigins };
349
+ }
350
+ if (options?.verifiers !== undefined) {
351
+ return { mode, verifiers: options.verifiers, allowedOrigins };
352
+ }
353
+ const verifiers = [
354
+ createStaticVerifier(loadTokenFile(options?.tokensPath ?? defaultTokensPath(), warn)),
355
+ ];
356
+ // The OIDC seam: configuring it today is a LOUD boot failure, never a silent skip.
357
+ const configPath = options?.configPath ?? defaultAuthConfigPath();
358
+ let configJson = null;
359
+ try {
360
+ configJson = readFileSync(configPath, 'utf8');
361
+ }
362
+ catch (err) {
363
+ // ONLY a missing file is the ordinary case. An unreadable-but-present
364
+ // auth.json (EACCES, EISDIR, …) silently skipping a configured OIDC block
365
+ // would be exactly the quiet misconfiguration this seam refuses to be
366
+ // (Copilot, #250) — so anything else fails the boot, named.
367
+ if (err.code !== 'ENOENT') {
368
+ throw new Error(`[auth] cannot read ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
369
+ }
370
+ configJson = null; // no auth.json — the ordinary case
371
+ }
372
+ if (configJson !== null) {
373
+ let parsed;
374
+ try {
375
+ parsed = JSON.parse(configJson);
376
+ }
377
+ catch (err) {
378
+ throw new Error(`[auth] ${configPath} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
379
+ }
380
+ if (parsed.oidc !== undefined) {
381
+ verifiers.push(createOidcVerifier(parsed.oidc)); // throws — the declared seam
382
+ }
383
+ }
384
+ return { mode, verifiers, allowedOrigins };
385
+ }
386
+ // ── The trust ladder over routes ─────────────────────────────────────────────
387
+ /** `PATCH /projects/:id` (exactly one segment after /projects) — see {@link requiredTrust}. */
388
+ const PROJECT_DETAIL_PATH = new RegExp(`^${API_PREFIX}/projects/[^/]+$`);
389
+ /**
390
+ * Minimum trust for a request. Minimal by design (the task's rule: no
391
+ * deny-by-default registry over unknown routes):
392
+ *
393
+ * - `/ws/terminals` and any sub-path → `operator` (write-capable WS channel;
394
+ * inbound frames are raw PTY stdin regardless of the GET upgrade method)
395
+ * - reads (GET/HEAD) and the main `/ws` stream → `observer`
396
+ * - governance writes, settings writes, project archive/restore → `admin`
397
+ * - every other mutation (launch, gate, cancel, chats, terminals, repos,
398
+ * workflows, project CRUD/membership) → `operator`
399
+ *
400
+ * `body` is consulted for exactly one rule: `PATCH /projects/:id` is an
401
+ * `operator` rename/describe unless the patch carries `status` (archive or
402
+ * restore), which changes what the whole team can attach work to — `admin`.
403
+ */
404
+ export function requiredTrust(method, path, body) {
405
+ // /ws/terminals and any sub-path (e.g. /ws/terminals/:id) are write-capable WS
406
+ // channels — inbound frames are raw PTY stdin. The HTTP upgrade uses GET but the
407
+ // socket carries operator-level writes. Guard both with and without trailing slash.
408
+ if (path === '/ws/terminals' || path.startsWith('/ws/terminals/'))
409
+ return 'operator';
410
+ if (method === 'GET' || method === 'HEAD')
411
+ return 'observer';
412
+ if (path.startsWith(`${API_PREFIX}/governance/`))
413
+ return 'admin';
414
+ if (path === `${API_PREFIX}/settings`)
415
+ return 'admin';
416
+ if (method === 'PATCH' &&
417
+ PROJECT_DETAIL_PATH.test(path) &&
418
+ typeof body === 'object' &&
419
+ body !== null &&
420
+ 'status' in body) {
421
+ return 'admin';
422
+ }
423
+ return 'operator';
424
+ }
425
+ /** Path without the query string. */
426
+ function pathOf(req) {
427
+ const url = req.raw.url ?? req.url;
428
+ const q = url.indexOf('?');
429
+ return q >= 0 ? url.slice(0, q) : url;
430
+ }
431
+ /** True for the paths the auth boundary covers: the API and the WS upgrades. */
432
+ export function isProtectedPath(path) {
433
+ return (path === API_PREFIX ||
434
+ path.startsWith(`${API_PREFIX}/`) ||
435
+ path === '/ws' ||
436
+ path.startsWith('/ws/'));
437
+ }
438
+ /**
439
+ * Extract the presented bearer token. `Authorization: Bearer <t>` everywhere;
440
+ * the `/ws` upgrade paths ALSO accept `?access_token=` (RFC 6750 §2.3),
441
+ * because the browser `WebSocket` constructor cannot set headers. Header wins
442
+ * when both are present.
443
+ */
444
+ export function extractToken(req, path) {
445
+ const header = req.headers.authorization;
446
+ if (typeof header === 'string') {
447
+ const m = /^Bearer\s+(\S+)$/i.exec(header.trim());
448
+ if (m)
449
+ return m[1] ?? null;
450
+ return null; // a malformed Authorization header is not a token
451
+ }
452
+ if (path === '/ws' || path.startsWith('/ws/')) {
453
+ const raw = req.query?.access_token;
454
+ const first = Array.isArray(raw) ? raw[0] : raw;
455
+ if (typeof first === 'string' && first !== '')
456
+ return first;
457
+ }
458
+ return null;
459
+ }
460
+ async function deny401(reply, error) {
461
+ await reply
462
+ .code(401)
463
+ .header('WWW-Authenticate', 'Bearer realm="wicked-crew"')
464
+ .send({ error });
465
+ }
466
+ /**
467
+ * Install the identity (401) and trust (403) hooks.
468
+ *
469
+ * Identity runs at `onRequest` — before body parsing, and (per
470
+ * `@fastify/websocket`) before the upgrade completes, so a bad token is an
471
+ * HTTP 401 on the wire for REST and WS alike. Trust runs at `preHandler`,
472
+ * where the parsed body exists (the one body-dependent rule is the project
473
+ * archive). Both scope to {@link isProtectedPath}; the SPA shell and its
474
+ * assets stay public so a hosted skin can load and ASK for a token.
475
+ */
476
+ export function registerAuthHooks(app, auth) {
477
+ app.decorateRequest('actor', null);
478
+ app.addHook('onRequest', async (req, reply) => {
479
+ const path = pathOf(req);
480
+ if (!isProtectedPath(path))
481
+ return;
482
+ if (auth.mode === 'off') {
483
+ req.actor = LOCAL_ACTOR;
484
+ return;
485
+ }
486
+ const token = extractToken(req, path);
487
+ if (token === null) {
488
+ return deny401(reply, 'Authentication required: send Authorization: Bearer <token>');
489
+ }
490
+ for (const verifier of auth.verifiers) {
491
+ const actor = await verifier.verify(token);
492
+ if (actor !== null) {
493
+ req.actor = actor;
494
+ return;
495
+ }
496
+ }
497
+ return deny401(reply, 'Invalid or unknown token');
498
+ });
499
+ app.addHook('preHandler', async (req, reply) => {
500
+ const path = pathOf(req);
501
+ if (!isProtectedPath(path))
502
+ return;
503
+ // `actor` is always set here: the onRequest hook either assigned it or
504
+ // already answered 401 (which skips the rest of the lifecycle).
505
+ const need = requiredTrust(req.method, path, req.body);
506
+ if (!trustAtLeast(req.actor, need)) {
507
+ // RETURN the reply — the idiomatic guarantee that the lifecycle stops
508
+ // here and the route handler is never reached (Copilot, #250).
509
+ return reply.code(403).send({
510
+ error: `Insufficient trust: this action requires '${need}' (you are '${req.actor.trust}')`,
511
+ });
512
+ }
513
+ });
514
+ }
515
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,aAAa,CAAC;AAG7F,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAe7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAU,MAAM,CAAC,MAAM,CAAC;IAC9C,EAAE,EAAE,OAAO;IACX,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,OAAO;CACf,CAAU,CAAC;AAEZ,MAAM,UAAU,GAA+B,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AACtF,MAAM,KAAK,GAAwB,IAAI,GAAG,CAAY,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AACpF,MAAM,MAAM,GAAwB,IAAI,GAAG,CAAa,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AAE3F,8DAA8D;AAC9D,MAAM,UAAU,YAAY,CAAC,KAAY,EAAE,GAAe;IACxD,OAAO,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;IAClE,IAAI,GAAG,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM;QAAE,OAAO,UAAU,CAAC;IAC9E,MAAM,QAAQ,GAAG,GAAG,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/D,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE,IAAI,QAAQ,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAClF,IAAI,QAAQ,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IAC/C,sEAAsE;IACtE,2EAA2E;IAC3E,mEAAmE;IACnE,MAAM,IAAI,KAAK,CAAC,sDAAsD,QAAQ,IAAI,CAAC,CAAC;AACtF,CAAC;AAiBD,6DAA6D;AAC7D,MAAM,UAAU,iBAAiB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACpE,OAAO,GAAG,CAAC,oBAAoB,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AAC/F,CAAC;AAWD,uFAAuF;AACvF,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,GAAG,gBAAgB,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,MAAc;IACzD,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,qBAAqB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrG,CAAC;IACD,MAAM,IAAI,GAAG,GAA8C,CAAC;IAC5D,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,8CAA8C,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,yBAAyB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC;IACjH,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAiB,CAAC;IACrC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAc,EAAE,CAAS,EAAE,EAAE;QAChD,MAAM,CAAC,GAAG,KAAgC,CAAC;QAC3C,MAAM,EAAE,GAAG,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC;QACrC,IAAI,OAAO,CAAC,EAAE,MAAM,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,iEAAiE,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,CAAC,KAAmC,CAAC;QAChD,IAAI,OAAO,CAAC,EAAE,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACxE,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,sDAAsD,CAAC,CAAC;QAC/E,CAAC;QACD,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,qDAAqD,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,2DAA2D,CAAC,CAAC;QACpF,CAAC;QACD,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,wDAAwD,CAAC,CAAC;QACjF,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAU,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,IAA2B;IACrE,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,IAAI,CACF,8CAA8C,IAAI,4CAA4C;gBAC5F,gEAAgE,CACnE,CAAC;YACF,OAAO,IAAI,GAAG,EAAE,CAAC;QACnB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChH,CAAC;IACD,2EAA2E;IAC3E,8EAA8E;IAC9E,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC;YACzC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,IAAI,CAAC,UAAU,IAAI,oCAAoC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC;YAC/H,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,2DAA2D;QAC7D,CAAC;IACH,CAAC;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,oBAAoB,CAAC,OAA2B;IAC9D,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC;KAC1E,CAAC;AACJ,CAAC;AAyBD,iEAAiE;AACjE,MAAM,UAAU,qBAAqB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACxE,OAAO,GAAG,CAAC,yBAAyB,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;AAClG,CAAC;AAqBD,iFAAiF;AACjF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyD,CAAC;AACpF,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,0DAA0D;AAE7F,SAAS,eAAe,CAAC,CAAS;IAChC,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC1F,CAAC;AAED,KAAK,UAAU,SAAS,CAAI,GAAW;IACrC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtE,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC,CAAC;IACnE,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,OAAe;IACtC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAe,OAAO,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAe,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QACjC,IAAI,GAAG,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK,KAAK;YAAE,SAAS;QACzD,qDAAqD;QACrD,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;QAC5C,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,MAAkB;IAC9C,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC;IAC1C,MAAM,SAAS,GAAG,MAAM,SAAS,CAC/B,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,mCAAmC,CACvE,CAAC;IACF,OAAO,SAAS,CAAC,QAAQ,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,MAAM,CACnB,MAAkB,EAClB,GAAW,EACX,YAAqB;IAErB,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,WAAW,CAAC;IACrE,IAAI,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QACpB,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;IACjC,CAAC;IACD,qCAAqC;IACrC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IAClC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC/D,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AAC/B,CAAC;AAED,8CAA8C;AAC9C,MAAM,QAAQ,GAA2B;IACvC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ;IACjD,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ;IACjD,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ;CAClD,CAAC;AAEF,SAAS,eAAe,CAAC,aAAqB,EAAE,GAAW,EAAE,GAAQ,EAAE,GAAW;IAChF,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,eAAe,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;YAC/B,CAAC,CAAE,EAAE,OAAO,EAAE,SAAS,CAAC,qBAAqB,EAAE,UAAU,EAAE,SAAS,CAAC,sBAAsB,EAAa;YACxG,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;gBACpB,CAAC,CAAE,EAAE,WAAW,EAAE,YAAY,EAAa;gBAC3C,CAAC,CAAE,EAAa,CAAC;QACrB,OAAO,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;IAClF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAWD;;;GAGG;AACH,KAAK,UAAU,SAAS,CAAC,KAAa,EAAE,MAAkB;IACxD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAEzF,IAAI,MAAsC,CAAC;IAC3C,IAAI,OAAmB,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAkB,CAAC;QAClF,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAe,CAAC;IAClF,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAC;IAEzE,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC;IAC9B,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;IACvC,MAAM,aAAa,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhD,sDAAsD;IACtD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5C,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAE9E,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,oBAAoB;IACpB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1C,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,iCAAiC,MAAM,CAAC,MAAM,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxG,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,CAAC,QAAQ,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5G,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,OAAmB,EAAE,MAAkB;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,KAAK,CAAC;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,EAAE,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;IACrF,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,OAAO,YAAY,CAAC,CAAC;IAEhF,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IACxC,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9D,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,UAAU,CAAC;IACvD,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,KAAK,GAAe,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAE,WAA0B,CAAC,CAAC,CAAC,YAAY,CAAC;IAE/F,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAU,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAkB;IACnD,0EAA0E;IAC1E,0EAA0E;IAC1E,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,6DAA6D,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjH,CAAC;IACD,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,2EAA2E,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACrI,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,KAAK,CAAC,MAAM,CAAC,KAAa;YACxB,mEAAmE;YACnE,qEAAqE;YACrE,oEAAoE;YACpE,0EAA0E;YAC1E,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC,CAAC,kCAAkC;YACzE,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC/C,OAAO,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,gEAAgE;gBAChE,uEAAuE;gBACvE,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAkCD,wEAAwE;AACxE,MAAM,UAAU,WAAW,CAAC,OAAgC,EAAE,IAA2B;IACvF,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,CAAC;IAChD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC9D,MAAM,cAAc,GAClB,OAAO,EAAE,cAAc;QACvB,CAAC,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE;YACnD,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;YAC5D,CAAC,CAAC,IAAI,CAAC,CAAC;IACZ,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,4EAA4E;QAC5E,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC;IAChE,CAAC;IACD,MAAM,SAAS,GAAoB;QACjC,oBAAoB,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,EAAE,IAAI,CAAC,CAAC;KACtF,CAAC;IACF,mFAAmF;IACnF,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,qBAAqB,EAAE,CAAC;IAClE,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,IAAI,CAAC;QACH,UAAU,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,sEAAsE;QACtE,0EAA0E;QAC1E,sEAAsE;QACtE,4DAA4D;QAC5D,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CACb,sBAAsB,UAAU,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACxF,CAAC;QACJ,CAAC;QACD,UAAU,GAAG,IAAI,CAAC,CAAC,mCAAmC;IACxD,CAAC;IACD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,IAAI,MAA6B,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAA0B,CAAC;QAC3D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,UAAU,UAAU,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjH,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,6BAA6B;QAChF,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AAC7C,CAAC;AAED,gFAAgF;AAEhF,+FAA+F;AAC/F,MAAM,mBAAmB,GAAG,IAAI,MAAM,CAAC,IAAI,UAAU,kBAAkB,CAAC,CAAC;AAEzE;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,IAAY,EAAE,IAAa;IACvE,+EAA+E;IAC/E,iFAAiF;IACjF,oFAAoF;IACpF,IAAI,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,UAAU,CAAC;IACrF,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,UAAU,CAAC;IAC7D,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,UAAU,cAAc,CAAC;QAAE,OAAO,OAAO,CAAC;IACjE,IAAI,IAAI,KAAK,GAAG,UAAU,WAAW;QAAE,OAAO,OAAO,CAAC;IACtD,IACE,MAAM,KAAK,OAAO;QAClB,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;QAC9B,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACb,QAAQ,IAAI,IAAI,EAChB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,qCAAqC;AACrC,SAAS,MAAM,CAAC,GAAmB;IACjC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;IACnC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACxC,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,CACL,IAAI,KAAK,UAAU;QACnB,IAAI,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,CAAC;QACjC,IAAI,KAAK,KAAK;QACd,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CACxB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAmB,EAAE,IAAY;IAC5D,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IACzC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC3B,OAAO,IAAI,CAAC,CAAC,kDAAkD;IACjE,CAAC;IACD,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAI,GAAG,CAAC,KAA0D,EAAE,YAAY,CAAC;QAC1F,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC;IAC9D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,KAAmB,EAAE,KAAa;IACvD,MAAM,KAAK;SACR,IAAI,CAAC,GAAG,CAAC;SACT,MAAM,CAAC,kBAAkB,EAAE,4BAA4B,CAAC;SACxD,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACrB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAoB,EAAE,IAAkB;IACxE,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,IAAwB,CAAC,CAAC;IAEvD,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;YAAE,OAAO;QACnC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACxB,GAAG,CAAC,KAAK,GAAG,WAAW,CAAC;YACxB,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO,OAAO,CAAC,KAAK,EAAE,6DAA6D,CAAC,CAAC;QACvF,CAAC;QACD,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC;gBAClB,OAAO;YACT,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC,KAAK,EAAE,0BAA0B,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;YAAE,OAAO;QACnC,uEAAuE;QACvE,gEAAgE;QAChE,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;YACnC,sEAAsE;YACtE,+DAA+D;YAC/D,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBAC1B,KAAK,EAAE,6CAA6C,IAAI,eAAe,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI;aAC3F,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -48,6 +48,14 @@ export declare class GateCache {
48
48
  rebuild(runId: string, events: CoreEvent[]): GateCacheEntry | undefined;
49
49
  /** The cached open gate for a run, if any. */
50
50
  get(runId: string): GateCacheEntry | undefined;
51
+ /**
52
+ * Adopt an entry hydrated from the DURABLE `interaction_requests` table (DES-PROJECT-001
53
+ * §5.3). With that table, this cache is finally what its own comments always claimed — a
54
+ * latency layer over durable truth: the route reads the table on a miss and parks the result
55
+ * here so the next poll is a map hit. `rebuild` (event-log replay) remains the fallback for
56
+ * engines predating the table.
57
+ */
58
+ adopt(runId: string, entry: GateCacheEntry): void;
51
59
  /** Drop cache entries whose run is no longer `awaiting_human` (self-healing on reconcile). */
52
60
  reconcile(views: SessionView[]): void;
53
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"gate-cache.d.ts","sourceRoot":"","sources":["../../src/api/gate-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/D,0CAA0C;AAC1C,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB;AA+CD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAE7D,8CAA8C;IAC9C,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAI9B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,cAAc,GAAG,SAAS;IAQvE,8CAA8C;IAC9C,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI9C,8FAA8F;IAC9F,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI;CAQtC"}
1
+ {"version":3,"file":"gate-cache.d.ts","sourceRoot":"","sources":["../../src/api/gate-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/D,0CAA0C;AAC1C,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB;AA+CD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAE7D,8CAA8C;IAC9C,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAI9B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,cAAc,GAAG,SAAS;IAQvE,8CAA8C;IAC9C,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI9C;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI;IAIjD,8FAA8F;IAC9F,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI;CAQtC"}
@@ -92,6 +92,16 @@ export class GateCache {
92
92
  get(runId) {
93
93
  return this.entries.get(runId);
94
94
  }
95
+ /**
96
+ * Adopt an entry hydrated from the DURABLE `interaction_requests` table (DES-PROJECT-001
97
+ * §5.3). With that table, this cache is finally what its own comments always claimed — a
98
+ * latency layer over durable truth: the route reads the table on a miss and parks the result
99
+ * here so the next poll is a map hit. `rebuild` (event-log replay) remains the fallback for
100
+ * engines predating the table.
101
+ */
102
+ adopt(runId, entry) {
103
+ this.entries.set(runId, entry);
104
+ }
95
105
  /** Drop cache entries whose run is no longer `awaiting_human` (self-healing on reconcile). */
96
106
  reconcile(views) {
97
107
  const awaiting = new Set(views.filter((v) => v.session.status === 'awaiting_human').map((v) => v.session.id));
@@ -1 +1 @@
1
- {"version":3,"file":"gate-cache.js","sourceRoot":"","sources":["../../src/api/gate-cache.ts"],"names":[],"mappings":"AAcA;;;;;;;GAOG;AACH,SAAS,UAAU,CAAC,KAAgB;IAClC,OAAO,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACtF,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,IAAI,CAAC,OAAoC,EAAE,KAAgB;IAClE,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO;IAClC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,eAAe;YAClB,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACtE,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE;oBACnB,GAAG,EAAE,KAAK,CAAC,GAAG;oBACd,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,SAAS,EAAE,MAAM;oBACjB,UAAU,EAAE,UAAU,CAAC,KAAK,CAAC;iBAC9B,CAAC,CAAC;YACL,CAAC;YACD,MAAM;QACR,KAAK,SAAS,CAAC;QACf,KAAK,kBAAkB,CAAC;QACxB,KAAK,cAAc,CAAC;QACpB,KAAK,eAAe;YAClB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACxB,MAAM;QACR;YACE,MAAM;IACV,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,SAAS;IACH,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAE7D,8CAA8C;IAC9C,MAAM,CAAC,KAAgB;QACrB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,KAAa,EAAE,MAAmB;QACxC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;QACnD,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC1C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,8CAA8C;IAC9C,GAAG,CAAC,KAAa;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,8FAA8F;IAC9F,SAAS,CAAC,KAAoB;QAC5B,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CACpF,CAAC;QACF,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"gate-cache.js","sourceRoot":"","sources":["../../src/api/gate-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Is `target` inside `root` (or `root` itself), after normalization? Traversal-safe: the check is
3
+ * on the RESOLVED relative path's first segment, so `/root/../evil` never passes, and a sibling
4
+ * whose name merely starts with dots (`/a/..hidden`) is not wrongly excluded.
5
+ */
6
+ export declare function isInsideRoot(root: string, target: string): boolean;
7
+ /** The platform's opener invocation. Exported for tests; args are always a real argv array. */
8
+ export declare function platformOpenCommand(target: string): {
9
+ cmd: string;
10
+ args: string[];
11
+ };
12
+ /**
13
+ * Spawn the platform opener, detached, and resolve on SPAWN success (the OS accepted the process —
14
+ * what the opener then does with the path is the desktop environment's business). Rejects when the
15
+ * opener binary itself cannot be spawned, which the route reports as 502.
16
+ */
17
+ export declare function openWithSystemDefault(target: string): Promise<void>;
18
+ //# sourceMappingURL=open-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-path.d.ts","sourceRoot":"","sources":["../../src/api/open-path.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CA2BlE;AAED,+FAA+F;AAC/F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAWnF;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnE"}