@wlfi-agent/cli 1.4.15 → 1.4.16

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 (80) hide show
  1. package/Cargo.lock +1 -0
  2. package/Cargo.toml +1 -1
  3. package/README.md +10 -2
  4. package/crates/vault-cli-admin/src/main.rs +21 -2
  5. package/crates/vault-cli-admin/src/tui.rs +634 -129
  6. package/crates/vault-cli-daemon/Cargo.toml +1 -0
  7. package/crates/vault-cli-daemon/src/bin/wlfi-agent-system-keychain.rs +122 -8
  8. package/crates/vault-cli-daemon/src/main.rs +24 -4
  9. package/crates/vault-cli-daemon/src/relay_sync.rs +155 -35
  10. package/crates/vault-cli-daemon/tests/system_keychain_helper_acl.rs +23 -18
  11. package/crates/vault-daemon/src/daemon_parts/api_impl_and_utils.rs +6 -0
  12. package/crates/vault-daemon/src/daemon_parts/types_api_rpc.rs +6 -0
  13. package/crates/vault-daemon/src/tests.rs +2 -2
  14. package/crates/vault-daemon/src/tests_parts/part4.rs +110 -0
  15. package/crates/vault-transport-unix/src/lib.rs +22 -3
  16. package/crates/vault-transport-xpc/src/lib.rs +20 -2
  17. package/dist/cli.cjs +20842 -25552
  18. package/dist/cli.cjs.map +1 -1
  19. package/package.json +5 -3
  20. package/packages/cache/.turbo/turbo-build.log +20 -20
  21. package/packages/cache/coverage/base.css +224 -0
  22. package/packages/cache/coverage/block-navigation.js +87 -0
  23. package/packages/cache/coverage/clover.xml +585 -0
  24. package/packages/cache/coverage/coverage-final.json +5 -0
  25. package/packages/cache/coverage/favicon.png +0 -0
  26. package/packages/cache/coverage/index.html +161 -0
  27. package/packages/cache/coverage/prettify.css +1 -0
  28. package/packages/cache/coverage/prettify.js +2 -0
  29. package/packages/cache/coverage/sort-arrow-sprite.png +0 -0
  30. package/packages/cache/coverage/sorter.js +210 -0
  31. package/packages/cache/coverage/src/client/index.html +116 -0
  32. package/packages/cache/coverage/src/client/index.ts.html +253 -0
  33. package/packages/cache/coverage/src/errors/index.html +116 -0
  34. package/packages/cache/coverage/src/errors/index.ts.html +244 -0
  35. package/packages/cache/coverage/src/index.html +116 -0
  36. package/packages/cache/coverage/src/index.ts.html +94 -0
  37. package/packages/cache/coverage/src/service/index.html +116 -0
  38. package/packages/cache/coverage/src/service/index.ts.html +2212 -0
  39. package/packages/cache/dist/{chunk-ALQ6H7KG.cjs → chunk-QF4XKEIA.cjs} +189 -45
  40. package/packages/cache/dist/chunk-QF4XKEIA.cjs.map +1 -0
  41. package/packages/cache/dist/{chunk-FGJEEF5N.js → chunk-QNK6GOTI.js} +182 -38
  42. package/packages/cache/dist/chunk-QNK6GOTI.js.map +1 -0
  43. package/packages/cache/dist/index.cjs +2 -2
  44. package/packages/cache/dist/index.js +1 -1
  45. package/packages/cache/dist/service/index.cjs +2 -2
  46. package/packages/cache/dist/service/index.d.cts +2 -0
  47. package/packages/cache/dist/service/index.d.ts +2 -0
  48. package/packages/cache/dist/service/index.js +1 -1
  49. package/packages/cache/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  50. package/packages/cache/src/service/index.test.ts +575 -0
  51. package/packages/cache/src/service/index.ts +234 -51
  52. package/packages/config/.turbo/turbo-build.log +17 -18
  53. package/packages/config/node_modules/.bin/tsc +2 -2
  54. package/packages/config/node_modules/.bin/tsserver +2 -2
  55. package/packages/config/node_modules/.bin/tsup +2 -2
  56. package/packages/config/node_modules/.bin/tsup-node +2 -2
  57. package/packages/rpc/.turbo/turbo-build.log +31 -32
  58. package/packages/rpc/node_modules/.bin/tsc +2 -2
  59. package/packages/rpc/node_modules/.bin/tsserver +2 -2
  60. package/packages/rpc/node_modules/.bin/tsup +2 -2
  61. package/packages/rpc/node_modules/.bin/tsup-node +2 -2
  62. package/packages/ui/.turbo/turbo-build.log +43 -44
  63. package/scripts/install-rust-binaries.mjs +164 -58
  64. package/src/cli.ts +51 -39
  65. package/src/lib/admin-passthrough.js +1 -0
  66. package/src/lib/admin-reset.js +1 -0
  67. package/src/lib/admin-reset.ts +26 -16
  68. package/src/lib/admin-setup.js +1 -0
  69. package/src/lib/admin-setup.ts +32 -20
  70. package/src/lib/agent-auth-revoke.js +1 -0
  71. package/src/lib/agent-auth-rotate.js +1 -0
  72. package/src/lib/agent-auth.js +1 -0
  73. package/src/lib/config-mutation.js +1 -0
  74. package/src/lib/launchd-assets.js +1 -0
  75. package/src/lib/launchd-assets.ts +29 -0
  76. package/src/lib/local-admin-access.js +1 -0
  77. package/src/lib/rust.ts +1 -1
  78. package/src/lib/status-repair-cli.js +1 -0
  79. package/packages/cache/dist/chunk-ALQ6H7KG.cjs.map +0 -1
  80. package/packages/cache/dist/chunk-FGJEEF5N.js.map +0 -1
@@ -21,6 +21,11 @@ import {
21
21
  assertTrustedRootPlannedPrivateFilePath,
22
22
  } from './fs-trust.js';
23
23
  import { DAEMON_PASSWORD_KEYCHAIN_SERVICE } from './keychain.js';
24
+ import {
25
+ LAUNCHD_INSTALL_SCRIPT_NAME,
26
+ LAUNCHD_RUNNER_SCRIPT_NAME,
27
+ resolveLaunchDaemonHelperScriptPath,
28
+ } from './launchd-assets.js';
24
29
  import { resolveCliNetworkProfile } from './network-selection.js';
25
30
  import { passthroughRustBinary, RustBinaryExitError, runRustBinary } from './rust.js';
26
31
  import { createSudoSession } from './sudo.js';
@@ -639,7 +644,7 @@ function resolveRustBinDir(config: WlfiConfig): string {
639
644
  function resolveSourceLaunchDaemonPaths(config: WlfiConfig): LaunchDaemonAssetPaths {
640
645
  const rustBinDir = resolveRustBinDir(config);
641
646
  return {
642
- runnerPath: path.join(rustBinDir, 'run-wlfi-agent-daemon.sh'),
647
+ runnerPath: path.join(rustBinDir, LAUNCHD_RUNNER_SCRIPT_NAME),
643
648
  daemonBin: path.join(
644
649
  rustBinDir,
645
650
  `wlfi-agent-daemon${process.platform === 'win32' ? '.exe' : ''}`,
@@ -662,20 +667,8 @@ export function resolveManagedLaunchDaemonPaths(): LaunchDaemonAssetPaths {
662
667
  };
663
668
  }
664
669
 
665
- function resolveLaunchDaemonInstallScriptPath(): string {
666
- const candidates = [
667
- path.resolve(__dirname, '../scripts/launchd/install-user-daemon.sh'),
668
- path.resolve(__dirname, '../../scripts/launchd/install-user-daemon.sh'),
669
- path.resolve(process.cwd(), 'scripts/launchd/install-user-daemon.sh'),
670
- ];
671
-
672
- for (const candidate of candidates) {
673
- if (fs.existsSync(candidate)) {
674
- return candidate;
675
- }
676
- }
677
-
678
- return candidates[0];
670
+ function resolveLaunchDaemonInstallScriptPath(config: WlfiConfig): string {
671
+ return resolveLaunchDaemonHelperScriptPath(LAUNCHD_INSTALL_SCRIPT_NAME, config);
679
672
  }
680
673
 
681
674
  function filesHaveIdenticalContents(leftPath: string, rightPath: string): boolean {
@@ -718,23 +711,24 @@ export function assertManagedDaemonInstallPreconditions(
718
711
  deps.assertTrustedRootPlannedDaemonSocketPath ?? assertTrustedRootPlannedDaemonSocketPath;
719
712
  const trustStateFilePath =
720
713
  deps.assertTrustedRootPlannedPrivateFilePath ?? assertTrustedRootPlannedPrivateFilePath;
721
- const installScript = (deps.resolveInstallScriptPath ?? resolveLaunchDaemonInstallScriptPath)();
714
+ const installScript =
715
+ (deps.resolveInstallScriptPath ?? (() => resolveLaunchDaemonInstallScriptPath(config)))();
722
716
  const sourcePaths = resolveSourceLaunchDaemonPaths(config);
723
717
  const managedPaths = resolveManagedLaunchDaemonPaths();
724
718
 
725
719
  if (!existsSync(sourcePaths.runnerPath)) {
726
720
  throw new Error(
727
- `daemon runner is not installed at ${sourcePaths.runnerPath}; rerun npm run install:rust-binaries`,
721
+ `daemon runner is not installed at ${sourcePaths.runnerPath}; reinstall @wlfi-agent/cli`,
728
722
  );
729
723
  }
730
724
  if (!existsSync(sourcePaths.daemonBin)) {
731
725
  throw new Error(
732
- `daemon binary is not installed at ${sourcePaths.daemonBin}; rerun npm run install:rust-binaries`,
726
+ `daemon binary is not installed at ${sourcePaths.daemonBin}; reinstall @wlfi-agent/cli`,
733
727
  );
734
728
  }
735
729
  if (!existsSync(sourcePaths.keychainHelperBin)) {
736
730
  throw new Error(
737
- `daemon keychain helper is not installed at ${sourcePaths.keychainHelperBin}; rerun npm run install:rust-binaries`,
731
+ `daemon keychain helper is not installed at ${sourcePaths.keychainHelperBin}; reinstall @wlfi-agent/cli`,
738
732
  );
739
733
  }
740
734
  if (!existsSync(installScript)) {
@@ -927,6 +921,17 @@ function plistContainsValue(plistContents: string, value: string): boolean {
927
921
  return plistContents.includes(`<string>${value}</string>`);
928
922
  }
929
923
 
924
+ export function launchDaemonPlistValue(
925
+ plistContents: string,
926
+ key: string,
927
+ ): string | null {
928
+ const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
929
+ const match = plistContents.match(
930
+ new RegExp(`<key>${escapedKey}</key>\\s*<string>([^<]+)</string>`, 'u'),
931
+ );
932
+ return match?.[1] ?? null;
933
+ }
934
+
930
935
  function resolveInstalledLaunchDaemonPaths(
931
936
  config: WlfiConfig,
932
937
  plistContents: string,
@@ -961,6 +966,7 @@ function isManagedDaemonInstallCurrent(
961
966
  const sourcePaths = resolveSourceLaunchDaemonPaths(config);
962
967
  const keychainAccount = os.userInfo().username;
963
968
  const expectedAdminUid = String(process.getuid?.() ?? process.geteuid?.() ?? 0);
969
+ const expectedAgentUid = String(process.getuid?.() ?? process.geteuid?.() ?? 0);
964
970
 
965
971
  if (!fs.existsSync(DEFAULT_LAUNCH_DAEMON_PLIST)) {
966
972
  return false;
@@ -1003,6 +1009,13 @@ function isManagedDaemonInstallCurrent(
1003
1009
  return false;
1004
1010
  }
1005
1011
 
1012
+ if (
1013
+ launchDaemonPlistValue(plistContents, 'WLFI_ALLOW_ADMIN_EUID') !== expectedAdminUid ||
1014
+ launchDaemonPlistValue(plistContents, 'WLFI_ALLOW_AGENT_EUID') !== expectedAgentUid
1015
+ ) {
1016
+ return false;
1017
+ }
1018
+
1006
1019
  return [
1007
1020
  DEFAULT_LAUNCH_DAEMON_LABEL,
1008
1021
  installedPaths.runnerPath,
@@ -1013,7 +1026,6 @@ function isManagedDaemonInstallCurrent(
1013
1026
  DAEMON_PASSWORD_KEYCHAIN_SERVICE,
1014
1027
  keychainAccount,
1015
1028
  DEFAULT_SIGNER_BACKEND,
1016
- expectedAdminUid,
1017
1029
  ].every((value) => plistContainsValue(plistContents, value));
1018
1030
  }
1019
1031
 
@@ -0,0 +1 @@
1
+ export * from './agent-auth-revoke.ts';
@@ -0,0 +1 @@
1
+ export * from './agent-auth-rotate.ts';
@@ -0,0 +1 @@
1
+ export * from './agent-auth.ts';
@@ -0,0 +1 @@
1
+ export * from './config-mutation.ts';
@@ -0,0 +1 @@
1
+ export * from './launchd-assets.ts';
@@ -0,0 +1,29 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { defaultRustBinDir, type WlfiConfig } from '../../packages/config/src/index.js';
4
+
5
+ export const LAUNCHD_RUNNER_SCRIPT_NAME = 'run-wlfi-agent-daemon.sh';
6
+ export const LAUNCHD_INSTALL_SCRIPT_NAME = 'install-user-daemon.sh';
7
+ export const LAUNCHD_UNINSTALL_SCRIPT_NAME = 'uninstall-user-daemon.sh';
8
+
9
+ function resolveRustBinDir(config?: WlfiConfig): string {
10
+ return path.resolve(config?.rustBinDir || defaultRustBinDir());
11
+ }
12
+
13
+ export function resolveLaunchDaemonHelperScriptPath(
14
+ scriptName: string,
15
+ config?: WlfiConfig,
16
+ ): string {
17
+ const candidates = [
18
+ path.join(resolveRustBinDir(config), scriptName),
19
+ path.resolve(process.cwd(), 'scripts/launchd', scriptName),
20
+ ];
21
+
22
+ for (const candidate of candidates) {
23
+ if (fs.existsSync(candidate)) {
24
+ return candidate;
25
+ }
26
+ }
27
+
28
+ return candidates[0];
29
+ }
@@ -0,0 +1 @@
1
+ export * from './local-admin-access.ts';
package/src/lib/rust.ts CHANGED
@@ -31,7 +31,7 @@ function ensureBinary(binaryName: RustBinaryName, config?: WlfiConfig): string {
31
31
  const resolved = resolveRustBinaryPath(binaryName, config ?? readConfig());
32
32
  if (!fs.existsSync(resolved)) {
33
33
  throw new Error(
34
- `${binaryName} is not installed at ${resolved}. Re-run npm install -g @wlfi-agent/cli or npm run install:rust-binaries.`,
34
+ `${binaryName} is not installed at ${resolved}. Re-run npm install -g @wlfi-agent/cli.`,
35
35
  );
36
36
  }
37
37
  assertTrustedExecutablePath(resolved);
@@ -0,0 +1 @@
1
+ export * from './status-repair-cli.ts';
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/hanzhi/Documents/WLFI/wlfi-agent-sdk/packages/cache/dist/chunk-ALQ6H7KG.cjs","../src/service/index.ts"],"names":[],"mappings":"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","file":"/Users/hanzhi/Documents/WLFI/wlfi-agent-sdk/packages/cache/dist/chunk-ALQ6H7KG.cjs","sourcesContent":[null,"import { createHash, randomBytes, randomUUID } from 'node:crypto';\nimport type Redis from 'ioredis';\nimport { getCacheClient } from '../client/index.js';\nimport { CacheError, cacheErrorCodes, toCacheError } from '../errors/index.js';\n\nexport const relayApprovalStatuses = [\n 'pending',\n 'approved',\n 'rejected',\n 'completed',\n 'expired',\n] as const;\nexport type RelayApprovalStatus = (typeof relayApprovalStatuses)[number];\n\nexport const relayUpdateStatuses = [\n 'pending',\n 'inflight',\n 'applied',\n 'rejected',\n 'failed',\n] as const;\nexport type RelayUpdateStatus = (typeof relayUpdateStatuses)[number];\n\nexport interface RelayDaemonProfile {\n daemonId: string;\n daemonPublicKey: string;\n ethereumAddress: string;\n label?: string;\n lastSeenAt: string;\n registeredAt: string;\n relayUrl?: string;\n signerBackend?: string;\n status: 'active' | 'paused';\n updatedAt: string;\n version?: string;\n}\n\nexport interface RelayPolicyRecord {\n action: string;\n amountMaxWei?: string;\n amountMinWei?: string;\n chainId?: number;\n daemonId: string;\n destination: string;\n metadata?: Record<string, string>;\n policyId: string;\n requiresManualApproval: boolean;\n scope: 'default' | 'override';\n tokenAddress?: string;\n updatedAt: string;\n}\n\nexport interface RelayAgentKeyRecord {\n agentKeyId: string;\n createdAt?: string;\n daemonId: string;\n label?: string;\n metadata?: Record<string, string>;\n status: 'active' | 'revoked';\n updatedAt: string;\n}\n\nexport interface RelayApprovalRequestRecord {\n agentKeyId?: string;\n amountWei?: string;\n approvalRequestId: string;\n chainId?: number;\n daemonId: string;\n destination: string;\n metadata?: Record<string, string>;\n network?: string;\n reason?: string;\n requestedAt: string;\n status: RelayApprovalStatus;\n tokenAddress?: string;\n transactionType: string;\n updatedAt: string;\n}\n\nexport interface RelayEncryptedPayload {\n aadBase64?: string;\n algorithm: string;\n ciphertextBase64: string;\n contentSha256Hex?: string;\n encapsulatedKeyBase64: string;\n nonceBase64: string;\n schemaVersion: number;\n}\n\nexport interface RelayUpdateFeedbackRecord {\n daemonId: string;\n details?: Record<string, string>;\n feedbackAt: string;\n message?: string;\n status: Extract<RelayUpdateStatus, 'applied' | 'failed' | 'rejected'>;\n updateId: string;\n}\n\nexport interface RelayEncryptedUpdateRecord {\n claimToken?: string;\n claimUntil?: string;\n createdAt: string;\n daemonId: string;\n feedback?: RelayUpdateFeedbackRecord;\n lastDeliveredAt?: string;\n metadata?: Record<string, string>;\n payload: RelayEncryptedPayload;\n status: RelayUpdateStatus;\n targetApprovalRequestId?: string;\n type: string;\n updateId: string;\n updatedAt: string;\n}\n\nexport interface SyncDaemonRegistrationInput {\n agentKeys?: RelayAgentKeyRecord[];\n approvalRequests?: RelayApprovalRequestRecord[];\n daemon: RelayDaemonProfile;\n policies?: RelayPolicyRecord[];\n}\n\nexport interface ApprovalRequestFilters {\n daemonId?: string;\n destination?: string;\n limit?: number;\n status?: RelayApprovalStatus;\n tokenAddress?: string;\n}\n\nexport interface CreateEncryptedUpdateInput {\n daemonId: string;\n metadata?: Record<string, string>;\n payload: RelayEncryptedPayload;\n targetApprovalRequestId?: string;\n type: string;\n updateId?: string;\n}\n\nexport interface ClaimEncryptedUpdatesInput {\n daemonId: string;\n leaseSeconds?: number;\n limit?: number;\n}\n\nexport interface SubmitUpdateFeedbackInput {\n claimToken: string;\n daemonId: string;\n details?: Record<string, string>;\n message?: string;\n status: Extract<RelayUpdateStatus, 'applied' | 'failed' | 'rejected'>;\n updateId: string;\n}\n\nexport interface ApprovalCapabilityFailureRecord {\n attempts: number;\n blockedUntil?: string;\n firstFailedAt: string;\n lastFailedAt: string;\n}\n\nexport interface RecordApprovalCapabilityFailureResult {\n attempts: number;\n blocked: boolean;\n blockedUntil: string | null;\n}\n\ninterface JsonCache {\n del(key: string): Promise<number>;\n get(key: string): Promise<string | null>;\n ping(): Promise<string>;\n quit(): Promise<string>;\n sadd(key: string, ...members: string[]): Promise<number>;\n set(key: string, value: string, mode?: 'NX' | 'XX'): Promise<'OK' | null>;\n smembers(key: string): Promise<string[]>;\n zadd(key: string, ...args: (string | number)[]): Promise<number>;\n zrange(key: string, start: number, stop: number, ...args: string[]): Promise<string[]>;\n zrem(key: string, ...members: string[]): Promise<number>;\n}\n\nconst defaultNamespace = 'wlfi:relay';\nconst activeApprovalUpdateScanLimit = 250;\nconst approvalCapabilityFailureWindowMs = 5 * 60 * 1000;\nconst approvalCapabilityMaxFailures = 5;\nconst approvalCapabilityBlockWindowMs = 10 * 60 * 1000;\n\nconst toIsoTimestamp = (value = new Date()): string => value.toISOString();\n\nconst dedupe = <T>(values: T[]): T[] => [...new Set(values)];\n\nconst matchesOptionalFilter = (\n value: string | undefined,\n expected: string | undefined,\n): boolean => {\n if (!expected) {\n return true;\n }\n\n return value?.toLowerCase() === expected.toLowerCase();\n};\n\nconst clampLimit = (limit: number | undefined, fallback: number, max: number): number => {\n if (!limit || Number.isNaN(limit)) {\n return fallback;\n }\n\n return Math.max(1, Math.min(limit, max));\n};\n\nconst createApprovalCapabilityToken = (): string => randomBytes(32).toString('hex');\n\nconst approvalCapabilityHash = (token: string): string =>\n createHash('sha256').update(token, 'utf8').digest('hex');\n\nexport class RelayCacheService {\n private readonly client: JsonCache;\n private readonly namespace: string;\n\n constructor(options: { client?: Redis; namespace?: string } = {}) {\n this.client = (options.client ?? getCacheClient()) as unknown as JsonCache;\n this.namespace = options.namespace ?? defaultNamespace;\n }\n\n async ping(): Promise<string> {\n try {\n return await this.client.ping();\n } catch (error) {\n throw toCacheError(error, { operation: 'ping' });\n }\n }\n\n async syncDaemonRegistration(input: SyncDaemonRegistrationInput): Promise<{\n agentKeyCount: number;\n approvalRequestCount: number;\n policyCount: number;\n }> {\n const profile = {\n ...input.daemon,\n lastSeenAt: input.daemon.lastSeenAt || toIsoTimestamp(),\n updatedAt: input.daemon.updatedAt || toIsoTimestamp(),\n } satisfies RelayDaemonProfile;\n\n try {\n await this.writeJson(this.daemonProfileKey(profile.daemonId), profile);\n await this.client.sadd(this.daemonIndexKey(), profile.daemonId);\n\n if (input.policies) {\n const policies = input.policies.map((policy) => ({\n ...policy,\n daemonId: profile.daemonId,\n }));\n await this.writeJson(this.daemonPoliciesKey(profile.daemonId), policies);\n }\n\n if (input.agentKeys) {\n const agentKeys = input.agentKeys.map((agentKey) => ({\n ...agentKey,\n daemonId: profile.daemonId,\n }));\n await this.writeJson(this.daemonAgentKeysKey(profile.daemonId), agentKeys);\n }\n\n if (input.approvalRequests) {\n for (const approvalRequest of input.approvalRequests) {\n const normalized = { ...approvalRequest, daemonId: profile.daemonId };\n await this.writeJson(this.approvalKey(normalized.approvalRequestId), normalized);\n await this.client.zadd(\n this.daemonApprovalsKey(profile.daemonId),\n Date.parse(normalized.requestedAt),\n normalized.approvalRequestId,\n );\n }\n }\n\n return {\n agentKeyCount: input.agentKeys?.length ?? 0,\n approvalRequestCount: input.approvalRequests?.length ?? 0,\n policyCount: input.policies?.length ?? 0,\n };\n } catch (error) {\n throw toCacheError(error, {\n key: this.daemonProfileKey(profile.daemonId),\n operation: 'syncDaemonRegistration',\n });\n }\n }\n\n async listDaemons(): Promise<RelayDaemonProfile[]> {\n const daemonIds = await this.client.smembers(this.daemonIndexKey());\n const profiles = await Promise.all(\n daemonIds.map((daemonId) =>\n this.readJson<RelayDaemonProfile>(this.daemonProfileKey(daemonId)),\n ),\n );\n\n return profiles.filter((profile): profile is RelayDaemonProfile => Boolean(profile));\n }\n\n async getDaemonProfile(daemonId: string): Promise<RelayDaemonProfile | null> {\n return await this.readJson<RelayDaemonProfile>(this.daemonProfileKey(daemonId));\n }\n\n async getDaemonPolicies(daemonId: string): Promise<RelayPolicyRecord[]> {\n return (await this.readJson<RelayPolicyRecord[]>(this.daemonPoliciesKey(daemonId))) ?? [];\n }\n\n async getDaemonAgentKeys(daemonId: string): Promise<RelayAgentKeyRecord[]> {\n return (await this.readJson<RelayAgentKeyRecord[]>(this.daemonAgentKeysKey(daemonId))) ?? [];\n }\n\n async getApprovalRequest(approvalRequestId: string): Promise<RelayApprovalRequestRecord | null> {\n return await this.readJson<RelayApprovalRequestRecord>(this.approvalKey(approvalRequestId));\n }\n\n async listApprovalRequests(\n filters: ApprovalRequestFilters = {},\n ): Promise<RelayApprovalRequestRecord[]> {\n const limit = clampLimit(filters.limit, 100, 500);\n const daemonIds = filters.daemonId\n ? [filters.daemonId]\n : await this.client.smembers(this.daemonIndexKey());\n const requestIdsByDaemon = await Promise.all(\n daemonIds.map((daemonId) =>\n this.client.zrange(this.daemonApprovalsKey(daemonId), 0, limit * 2, 'REV'),\n ),\n );\n const requestIds = dedupe(requestIdsByDaemon.flat()).slice(0, limit * 3);\n const requests = await Promise.all(\n requestIds.map((requestId) =>\n this.readJson<RelayApprovalRequestRecord>(this.approvalKey(requestId)),\n ),\n );\n\n return requests\n .filter((request): request is RelayApprovalRequestRecord => Boolean(request))\n .filter((request) => (filters.daemonId ? request.daemonId === filters.daemonId : true))\n .filter((request) => (filters.status ? request.status === filters.status : true))\n .filter((request) => matchesOptionalFilter(request.destination, filters.destination))\n .filter((request) => matchesOptionalFilter(request.tokenAddress, filters.tokenAddress))\n .sort((left, right) => Date.parse(right.requestedAt) - Date.parse(left.requestedAt))\n .slice(0, limit);\n }\n\n async createEncryptedUpdate(\n input: CreateEncryptedUpdateInput,\n ): Promise<RelayEncryptedUpdateRecord> {\n const updateId = input.updateId ?? randomUUID();\n const now = toIsoTimestamp();\n const record: RelayEncryptedUpdateRecord = {\n createdAt: now,\n daemonId: input.daemonId,\n metadata: input.metadata,\n payload: input.payload,\n status: 'pending',\n targetApprovalRequestId: input.targetApprovalRequestId,\n type: input.type,\n updateId,\n updatedAt: now,\n };\n\n await this.writeJson(this.updateKey(updateId), record);\n await this.client.zadd(this.daemonUpdatesKey(input.daemonId), Date.now(), updateId);\n\n return record;\n }\n\n async hasActiveApprovalUpdate(daemonId: string, approvalRequestId: string): Promise<boolean> {\n const updateIds = await this.client.zrange(\n this.daemonUpdatesKey(daemonId),\n 0,\n activeApprovalUpdateScanLimit,\n 'REV',\n );\n\n for (const updateId of updateIds) {\n const record = await this.readJson<RelayEncryptedUpdateRecord>(this.updateKey(updateId));\n if (!record) {\n continue;\n }\n\n if (\n record.type !== 'manual_approval_decision' ||\n record.targetApprovalRequestId !== approvalRequestId\n ) {\n continue;\n }\n\n if (record.status === 'pending' || record.status === 'inflight') {\n return true;\n }\n }\n\n return false;\n }\n\n async consumeApprovalCapability(\n approvalRequestId: string,\n capabilityHash: string,\n ): Promise<boolean> {\n try {\n const result = await this.client.set(\n this.approvalCapabilityConsumedKey(approvalRequestId, capabilityHash),\n toIsoTimestamp(),\n 'NX',\n );\n return result === 'OK';\n } catch (error) {\n throw toCacheError(error, {\n key: this.approvalCapabilityConsumedKey(approvalRequestId, capabilityHash),\n operation: 'consumeApprovalCapability',\n });\n }\n }\n\n async releaseApprovalCapabilityConsumption(\n approvalRequestId: string,\n capabilityHash: string,\n ): Promise<void> {\n try {\n await this.client.del(this.approvalCapabilityConsumedKey(approvalRequestId, capabilityHash));\n } catch (error) {\n throw toCacheError(error, {\n key: this.approvalCapabilityConsumedKey(approvalRequestId, capabilityHash),\n operation: 'releaseApprovalCapabilityConsumption',\n });\n }\n }\n\n async clearApprovalCapabilityFailures(approvalRequestId: string): Promise<void> {\n try {\n await this.client.del(this.approvalCapabilityFailuresKey(approvalRequestId));\n } catch (error) {\n throw toCacheError(error, {\n key: this.approvalCapabilityFailuresKey(approvalRequestId),\n operation: 'clearApprovalCapabilityFailures',\n });\n }\n }\n\n async recordApprovalCapabilityFailure(\n approvalRequestId: string,\n ): Promise<RecordApprovalCapabilityFailureResult> {\n const key = this.approvalCapabilityFailuresKey(approvalRequestId);\n const now = new Date();\n const nowMs = now.getTime();\n const existing = await this.readJson<ApprovalCapabilityFailureRecord>(key);\n\n if (existing?.blockedUntil && Date.parse(existing.blockedUntil) > nowMs) {\n return {\n attempts: existing.attempts,\n blocked: true,\n blockedUntil: existing.blockedUntil,\n };\n }\n\n const firstFailedAtMs = existing?.firstFailedAt\n ? Date.parse(existing.firstFailedAt)\n : Number.NaN;\n const withinWindow =\n Number.isFinite(firstFailedAtMs) &&\n nowMs - firstFailedAtMs <= approvalCapabilityFailureWindowMs;\n const attempts = withinWindow && existing ? existing.attempts + 1 : 1;\n const firstFailedAt = withinWindow && existing ? existing.firstFailedAt : now.toISOString();\n const blockedUntil =\n attempts >= approvalCapabilityMaxFailures\n ? new Date(nowMs + approvalCapabilityBlockWindowMs).toISOString()\n : undefined;\n\n await this.writeJson(key, {\n attempts,\n blockedUntil,\n firstFailedAt,\n lastFailedAt: now.toISOString(),\n } satisfies ApprovalCapabilityFailureRecord);\n\n return {\n attempts,\n blocked: blockedUntil !== undefined,\n blockedUntil: blockedUntil ?? null,\n };\n }\n\n async rotateApprovalCapability(approvalRequestId: string): Promise<RelayApprovalRequestRecord> {\n const key = this.approvalKey(approvalRequestId);\n const approval = await this.readJson<RelayApprovalRequestRecord>(key);\n\n if (!approval) {\n throw new CacheError({\n code: cacheErrorCodes.notFound,\n key,\n message: `Unknown approval '${approvalRequestId}'`,\n operation: 'rotateApprovalCapability',\n });\n }\n\n if (approval.status !== 'pending') {\n throw new CacheError({\n code: cacheErrorCodes.invalidPayload,\n key,\n message: `Approval '${approvalRequestId}' is '${approval.status}' and cannot accept a new secure approval link`,\n operation: 'rotateApprovalCapability',\n });\n }\n\n const capabilityToken = createApprovalCapabilityToken();\n const nextRecord: RelayApprovalRequestRecord = {\n ...approval,\n metadata: {\n ...(approval.metadata ?? {}),\n approvalCapabilityHash: approvalCapabilityHash(capabilityToken),\n approvalCapabilityToken: capabilityToken,\n },\n updatedAt: toIsoTimestamp(),\n };\n\n await this.writeJson(key, nextRecord);\n await this.clearApprovalCapabilityFailures(approvalRequestId);\n\n return nextRecord;\n }\n\n async claimEncryptedUpdates(\n input: ClaimEncryptedUpdatesInput,\n ): Promise<RelayEncryptedUpdateRecord[]> {\n const limit = clampLimit(input.limit, 25, 100);\n const leaseSeconds = clampLimit(input.leaseSeconds, 30, 300);\n const now = new Date();\n const nowMs = now.getTime();\n const claimUntil = new Date(nowMs + leaseSeconds * 1000).toISOString();\n const updateIds = await this.client.zrange(\n this.daemonUpdatesKey(input.daemonId),\n 0,\n limit * 4,\n 'REV',\n );\n const claimed: RelayEncryptedUpdateRecord[] = [];\n\n for (const updateId of updateIds) {\n if (claimed.length >= limit) {\n break;\n }\n\n const record = await this.readJson<RelayEncryptedUpdateRecord>(this.updateKey(updateId));\n if (!record) {\n continue;\n }\n\n if (\n record.status === 'applied' ||\n record.status === 'failed' ||\n record.status === 'rejected'\n ) {\n continue;\n }\n\n if (\n record.status === 'inflight' &&\n record.claimUntil &&\n Date.parse(record.claimUntil) > nowMs\n ) {\n continue;\n }\n\n const nextRecord: RelayEncryptedUpdateRecord = {\n ...record,\n claimToken: randomUUID(),\n claimUntil,\n lastDeliveredAt: now.toISOString(),\n status: 'inflight',\n updatedAt: now.toISOString(),\n };\n await this.writeJson(this.updateKey(updateId), nextRecord);\n claimed.push(nextRecord);\n }\n\n return claimed;\n }\n\n async submitUpdateFeedback(\n input: SubmitUpdateFeedbackInput,\n ): Promise<RelayEncryptedUpdateRecord> {\n const key = this.updateKey(input.updateId);\n const record = await this.readJson<RelayEncryptedUpdateRecord>(key);\n\n if (!record || record.daemonId !== input.daemonId) {\n throw new CacheError({\n code: cacheErrorCodes.notFound,\n key,\n message: `Unknown update '${input.updateId}' for daemon '${input.daemonId}'`,\n operation: 'submitUpdateFeedback',\n });\n }\n\n if (!record.claimToken || record.claimToken !== input.claimToken) {\n throw new CacheError({\n code: cacheErrorCodes.invalidPayload,\n key,\n message: `Claim token mismatch for update '${input.updateId}'`,\n operation: 'submitUpdateFeedback',\n });\n }\n\n const feedback: RelayUpdateFeedbackRecord = {\n daemonId: input.daemonId,\n details: input.details,\n feedbackAt: toIsoTimestamp(),\n message: input.message,\n status: input.status,\n updateId: input.updateId,\n };\n const nextRecord: RelayEncryptedUpdateRecord = {\n ...record,\n claimToken: undefined,\n claimUntil: undefined,\n feedback,\n status: input.status,\n updatedAt: toIsoTimestamp(),\n };\n\n await this.writeJson(key, nextRecord);\n return nextRecord;\n }\n\n async getEncryptedUpdate(updateId: string): Promise<RelayEncryptedUpdateRecord | null> {\n return await this.readJson<RelayEncryptedUpdateRecord>(this.updateKey(updateId));\n }\n\n async removeEncryptedUpdate(daemonId: string, updateId: string): Promise<void> {\n await this.client.zrem(this.daemonUpdatesKey(daemonId), updateId);\n await this.client.del(this.updateKey(updateId));\n }\n\n private readonly daemonIndexKey = (): string => `${this.namespace}:daemons`;\n private readonly daemonProfileKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:profile`;\n private readonly daemonPoliciesKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:policies`;\n private readonly daemonAgentKeysKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:agent-keys`;\n private readonly daemonApprovalsKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:approvals`;\n private readonly daemonUpdatesKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:updates`;\n private readonly approvalKey = (approvalRequestId: string): string =>\n `${this.namespace}:approval:${approvalRequestId}`;\n private readonly approvalCapabilityConsumedKey = (\n approvalRequestId: string,\n capabilityHash: string,\n ): string =>\n `${this.namespace}:approval:${approvalRequestId}:capability:${capabilityHash}:consumed`;\n private readonly approvalCapabilityFailuresKey = (approvalRequestId: string): string =>\n `${this.namespace}:approval:${approvalRequestId}:capability-failures`;\n private readonly updateKey = (updateId: string): string => `${this.namespace}:update:${updateId}`;\n\n private async readJson<T>(key: string): Promise<T | null> {\n try {\n const payload = await this.client.get(key);\n if (payload === null) {\n return null;\n }\n\n return JSON.parse(payload) as T;\n } catch (error) {\n throw toCacheError(error, { key, operation: 'readJson' });\n }\n }\n\n private async writeJson(key: string, value: unknown): Promise<void> {\n try {\n await this.client.set(key, JSON.stringify(value));\n } catch (error) {\n throw toCacheError(error, { key, operation: 'writeJson' });\n }\n }\n}\n\nexport const createRelayCacheService = (options: { client?: Redis; namespace?: string } = {}) => {\n return new RelayCacheService(options);\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/service/index.ts"],"sourcesContent":["import { createHash, randomBytes, randomUUID } from 'node:crypto';\nimport type Redis from 'ioredis';\nimport { getCacheClient } from '../client/index.js';\nimport { CacheError, cacheErrorCodes, toCacheError } from '../errors/index.js';\n\nexport const relayApprovalStatuses = [\n 'pending',\n 'approved',\n 'rejected',\n 'completed',\n 'expired',\n] as const;\nexport type RelayApprovalStatus = (typeof relayApprovalStatuses)[number];\n\nexport const relayUpdateStatuses = [\n 'pending',\n 'inflight',\n 'applied',\n 'rejected',\n 'failed',\n] as const;\nexport type RelayUpdateStatus = (typeof relayUpdateStatuses)[number];\n\nexport interface RelayDaemonProfile {\n daemonId: string;\n daemonPublicKey: string;\n ethereumAddress: string;\n label?: string;\n lastSeenAt: string;\n registeredAt: string;\n relayUrl?: string;\n signerBackend?: string;\n status: 'active' | 'paused';\n updatedAt: string;\n version?: string;\n}\n\nexport interface RelayPolicyRecord {\n action: string;\n amountMaxWei?: string;\n amountMinWei?: string;\n chainId?: number;\n daemonId: string;\n destination: string;\n metadata?: Record<string, string>;\n policyId: string;\n requiresManualApproval: boolean;\n scope: 'default' | 'override';\n tokenAddress?: string;\n updatedAt: string;\n}\n\nexport interface RelayAgentKeyRecord {\n agentKeyId: string;\n createdAt?: string;\n daemonId: string;\n label?: string;\n metadata?: Record<string, string>;\n status: 'active' | 'revoked';\n updatedAt: string;\n}\n\nexport interface RelayApprovalRequestRecord {\n agentKeyId?: string;\n amountWei?: string;\n approvalRequestId: string;\n chainId?: number;\n daemonId: string;\n destination: string;\n metadata?: Record<string, string>;\n network?: string;\n reason?: string;\n requestedAt: string;\n status: RelayApprovalStatus;\n tokenAddress?: string;\n transactionType: string;\n updatedAt: string;\n}\n\nexport interface RelayEncryptedPayload {\n aadBase64?: string;\n algorithm: string;\n ciphertextBase64: string;\n contentSha256Hex?: string;\n encapsulatedKeyBase64: string;\n nonceBase64: string;\n schemaVersion: number;\n}\n\nexport interface RelayUpdateFeedbackRecord {\n daemonId: string;\n details?: Record<string, string>;\n feedbackAt: string;\n message?: string;\n status: Extract<RelayUpdateStatus, 'applied' | 'failed' | 'rejected'>;\n updateId: string;\n}\n\nexport interface RelayEncryptedUpdateRecord {\n claimToken?: string;\n claimUntil?: string;\n createdAt: string;\n daemonId: string;\n feedback?: RelayUpdateFeedbackRecord;\n lastDeliveredAt?: string;\n metadata?: Record<string, string>;\n payload: RelayEncryptedPayload;\n status: RelayUpdateStatus;\n targetApprovalRequestId?: string;\n type: string;\n updateId: string;\n updatedAt: string;\n}\n\nexport interface SyncDaemonRegistrationInput {\n agentKeys?: RelayAgentKeyRecord[];\n approvalRequests?: RelayApprovalRequestRecord[];\n daemon: RelayDaemonProfile;\n policies?: RelayPolicyRecord[];\n}\n\nexport interface ApprovalRequestFilters {\n daemonId?: string;\n destination?: string;\n limit?: number;\n status?: RelayApprovalStatus;\n tokenAddress?: string;\n}\n\nexport interface CreateEncryptedUpdateInput {\n daemonId: string;\n metadata?: Record<string, string>;\n payload: RelayEncryptedPayload;\n targetApprovalRequestId?: string;\n type: string;\n updateId?: string;\n}\n\nexport interface ClaimEncryptedUpdatesInput {\n daemonId: string;\n leaseSeconds?: number;\n limit?: number;\n}\n\nexport interface SubmitUpdateFeedbackInput {\n claimToken: string;\n daemonId: string;\n details?: Record<string, string>;\n message?: string;\n status: Extract<RelayUpdateStatus, 'applied' | 'failed' | 'rejected'>;\n updateId: string;\n}\n\nexport interface ApprovalCapabilityFailureRecord {\n attempts: number;\n blockedUntil?: string;\n firstFailedAt: string;\n lastFailedAt: string;\n}\n\nexport interface RecordApprovalCapabilityFailureResult {\n attempts: number;\n blocked: boolean;\n blockedUntil: string | null;\n}\n\ninterface JsonCache {\n del(key: string): Promise<number>;\n get(key: string): Promise<string | null>;\n ping(): Promise<string>;\n quit(): Promise<string>;\n sadd(key: string, ...members: string[]): Promise<number>;\n set(key: string, value: string, mode?: 'NX' | 'XX'): Promise<'OK' | null>;\n smembers(key: string): Promise<string[]>;\n zadd(key: string, ...args: (string | number)[]): Promise<number>;\n zrange(key: string, start: number, stop: number, ...args: string[]): Promise<string[]>;\n zrem(key: string, ...members: string[]): Promise<number>;\n}\n\nconst defaultNamespace = 'wlfi:relay';\nconst activeApprovalUpdateScanLimit = 250;\nconst approvalCapabilityFailureWindowMs = 5 * 60 * 1000;\nconst approvalCapabilityMaxFailures = 5;\nconst approvalCapabilityBlockWindowMs = 10 * 60 * 1000;\n\nconst toIsoTimestamp = (value = new Date()): string => value.toISOString();\n\nconst dedupe = <T>(values: T[]): T[] => [...new Set(values)];\n\nconst matchesOptionalFilter = (\n value: string | undefined,\n expected: string | undefined,\n): boolean => {\n if (!expected) {\n return true;\n }\n\n return value?.toLowerCase() === expected.toLowerCase();\n};\n\nconst clampLimit = (limit: number | undefined, fallback: number, max: number): number => {\n if (!limit || Number.isNaN(limit)) {\n return fallback;\n }\n\n return Math.max(1, Math.min(limit, max));\n};\n\nconst createApprovalCapabilityToken = (): string => randomBytes(32).toString('hex');\n\nconst approvalCapabilityHash = (token: string): string =>\n createHash('sha256').update(token, 'utf8').digest('hex');\n\nexport class RelayCacheService {\n private readonly client: JsonCache;\n private readonly namespace: string;\n\n constructor(options: { client?: Redis; namespace?: string } = {}) {\n this.client = (options.client ?? getCacheClient()) as unknown as JsonCache;\n this.namespace = options.namespace ?? defaultNamespace;\n }\n\n async ping(): Promise<string> {\n try {\n return await this.client.ping();\n } catch (error) {\n throw toCacheError(error, { operation: 'ping' });\n }\n }\n\n async syncDaemonRegistration(input: SyncDaemonRegistrationInput): Promise<{\n agentKeyCount: number;\n approvalRequestCount: number;\n policyCount: number;\n }> {\n const profile = {\n ...input.daemon,\n lastSeenAt: input.daemon.lastSeenAt || toIsoTimestamp(),\n updatedAt: input.daemon.updatedAt || toIsoTimestamp(),\n } satisfies RelayDaemonProfile;\n\n try {\n await this.writeJson(this.daemonProfileKey(profile.daemonId), profile);\n await this.client.sadd(this.daemonIndexKey(), profile.daemonId);\n\n if (input.policies) {\n const policies = input.policies.map((policy) => ({\n ...policy,\n daemonId: profile.daemonId,\n }));\n await this.writeJson(this.daemonPoliciesKey(profile.daemonId), policies);\n }\n\n if (input.agentKeys) {\n const agentKeys = input.agentKeys.map((agentKey) => ({\n ...agentKey,\n daemonId: profile.daemonId,\n }));\n await this.writeJson(this.daemonAgentKeysKey(profile.daemonId), agentKeys);\n }\n\n if (input.approvalRequests) {\n for (const approvalRequest of input.approvalRequests) {\n const normalized = { ...approvalRequest, daemonId: profile.daemonId };\n await this.writeJson(this.approvalKey(normalized.approvalRequestId), normalized);\n await this.client.zadd(\n this.daemonApprovalsKey(profile.daemonId),\n Date.parse(normalized.requestedAt),\n normalized.approvalRequestId,\n );\n }\n }\n\n return {\n agentKeyCount: input.agentKeys?.length ?? 0,\n approvalRequestCount: input.approvalRequests?.length ?? 0,\n policyCount: input.policies?.length ?? 0,\n };\n } catch (error) {\n throw toCacheError(error, {\n key: this.daemonProfileKey(profile.daemonId),\n operation: 'syncDaemonRegistration',\n });\n }\n }\n\n async listDaemons(): Promise<RelayDaemonProfile[]> {\n const daemonIds = await this.client.smembers(this.daemonIndexKey());\n const profiles = await Promise.all(\n daemonIds.map((daemonId) =>\n this.readJson<RelayDaemonProfile>(this.daemonProfileKey(daemonId)),\n ),\n );\n\n return profiles.filter((profile): profile is RelayDaemonProfile => Boolean(profile));\n }\n\n async getDaemonProfile(daemonId: string): Promise<RelayDaemonProfile | null> {\n return await this.readJson<RelayDaemonProfile>(this.daemonProfileKey(daemonId));\n }\n\n async getDaemonPolicies(daemonId: string): Promise<RelayPolicyRecord[]> {\n return (await this.readJson<RelayPolicyRecord[]>(this.daemonPoliciesKey(daemonId))) ?? [];\n }\n\n async getDaemonAgentKeys(daemonId: string): Promise<RelayAgentKeyRecord[]> {\n return (await this.readJson<RelayAgentKeyRecord[]>(this.daemonAgentKeysKey(daemonId))) ?? [];\n }\n\n async getApprovalRequest(approvalRequestId: string): Promise<RelayApprovalRequestRecord | null> {\n return await this.readJson<RelayApprovalRequestRecord>(this.approvalKey(approvalRequestId));\n }\n\n async listApprovalRequests(\n filters: ApprovalRequestFilters = {},\n ): Promise<RelayApprovalRequestRecord[]> {\n const limit = clampLimit(filters.limit, 100, 500);\n const daemonIds = filters.daemonId\n ? [filters.daemonId]\n : await this.client.smembers(this.daemonIndexKey());\n const requestIdsByDaemon = await Promise.all(\n daemonIds.map((daemonId) =>\n this.client.zrange(this.daemonApprovalsKey(daemonId), 0, limit * 2, 'REV'),\n ),\n );\n const requestIds = dedupe(requestIdsByDaemon.flat()).slice(0, limit * 3);\n const requests = await Promise.all(\n requestIds.map((requestId) =>\n this.readJson<RelayApprovalRequestRecord>(this.approvalKey(requestId)),\n ),\n );\n\n return requests\n .filter((request): request is RelayApprovalRequestRecord => Boolean(request))\n .filter((request) => (filters.daemonId ? request.daemonId === filters.daemonId : true))\n .filter((request) => (filters.status ? request.status === filters.status : true))\n .filter((request) => matchesOptionalFilter(request.destination, filters.destination))\n .filter((request) => matchesOptionalFilter(request.tokenAddress, filters.tokenAddress))\n .sort((left, right) => Date.parse(right.requestedAt) - Date.parse(left.requestedAt))\n .slice(0, limit);\n }\n\n async createEncryptedUpdate(\n input: CreateEncryptedUpdateInput,\n ): Promise<RelayEncryptedUpdateRecord> {\n const updateId = input.updateId ?? randomUUID();\n const now = toIsoTimestamp();\n const record: RelayEncryptedUpdateRecord = {\n createdAt: now,\n daemonId: input.daemonId,\n metadata: input.metadata,\n payload: input.payload,\n status: 'pending',\n targetApprovalRequestId: input.targetApprovalRequestId,\n type: input.type,\n updateId,\n updatedAt: now,\n };\n\n await this.writeJson(this.updateKey(updateId), record);\n await this.client.zadd(this.daemonUpdatesKey(input.daemonId), Date.now(), updateId);\n\n return record;\n }\n\n async hasActiveApprovalUpdate(daemonId: string, approvalRequestId: string): Promise<boolean> {\n const updateIds = await this.client.zrange(\n this.daemonUpdatesKey(daemonId),\n 0,\n activeApprovalUpdateScanLimit,\n 'REV',\n );\n\n for (const updateId of updateIds) {\n const record = await this.readJson<RelayEncryptedUpdateRecord>(this.updateKey(updateId));\n if (!record) {\n continue;\n }\n\n if (\n record.type !== 'manual_approval_decision' ||\n record.targetApprovalRequestId !== approvalRequestId\n ) {\n continue;\n }\n\n if (record.status === 'pending' || record.status === 'inflight') {\n return true;\n }\n }\n\n return false;\n }\n\n async consumeApprovalCapability(\n approvalRequestId: string,\n capabilityHash: string,\n ): Promise<boolean> {\n try {\n const result = await this.client.set(\n this.approvalCapabilityConsumedKey(approvalRequestId, capabilityHash),\n toIsoTimestamp(),\n 'NX',\n );\n return result === 'OK';\n } catch (error) {\n throw toCacheError(error, {\n key: this.approvalCapabilityConsumedKey(approvalRequestId, capabilityHash),\n operation: 'consumeApprovalCapability',\n });\n }\n }\n\n async releaseApprovalCapabilityConsumption(\n approvalRequestId: string,\n capabilityHash: string,\n ): Promise<void> {\n try {\n await this.client.del(this.approvalCapabilityConsumedKey(approvalRequestId, capabilityHash));\n } catch (error) {\n throw toCacheError(error, {\n key: this.approvalCapabilityConsumedKey(approvalRequestId, capabilityHash),\n operation: 'releaseApprovalCapabilityConsumption',\n });\n }\n }\n\n async clearApprovalCapabilityFailures(approvalRequestId: string): Promise<void> {\n try {\n await this.client.del(this.approvalCapabilityFailuresKey(approvalRequestId));\n } catch (error) {\n throw toCacheError(error, {\n key: this.approvalCapabilityFailuresKey(approvalRequestId),\n operation: 'clearApprovalCapabilityFailures',\n });\n }\n }\n\n async recordApprovalCapabilityFailure(\n approvalRequestId: string,\n ): Promise<RecordApprovalCapabilityFailureResult> {\n const key = this.approvalCapabilityFailuresKey(approvalRequestId);\n const now = new Date();\n const nowMs = now.getTime();\n const existing = await this.readJson<ApprovalCapabilityFailureRecord>(key);\n\n if (existing?.blockedUntil && Date.parse(existing.blockedUntil) > nowMs) {\n return {\n attempts: existing.attempts,\n blocked: true,\n blockedUntil: existing.blockedUntil,\n };\n }\n\n const firstFailedAtMs = existing?.firstFailedAt\n ? Date.parse(existing.firstFailedAt)\n : Number.NaN;\n const withinWindow =\n Number.isFinite(firstFailedAtMs) &&\n nowMs - firstFailedAtMs <= approvalCapabilityFailureWindowMs;\n const attempts = withinWindow && existing ? existing.attempts + 1 : 1;\n const firstFailedAt = withinWindow && existing ? existing.firstFailedAt : now.toISOString();\n const blockedUntil =\n attempts >= approvalCapabilityMaxFailures\n ? new Date(nowMs + approvalCapabilityBlockWindowMs).toISOString()\n : undefined;\n\n await this.writeJson(key, {\n attempts,\n blockedUntil,\n firstFailedAt,\n lastFailedAt: now.toISOString(),\n } satisfies ApprovalCapabilityFailureRecord);\n\n return {\n attempts,\n blocked: blockedUntil !== undefined,\n blockedUntil: blockedUntil ?? null,\n };\n }\n\n async rotateApprovalCapability(approvalRequestId: string): Promise<RelayApprovalRequestRecord> {\n const key = this.approvalKey(approvalRequestId);\n const approval = await this.readJson<RelayApprovalRequestRecord>(key);\n\n if (!approval) {\n throw new CacheError({\n code: cacheErrorCodes.notFound,\n key,\n message: `Unknown approval '${approvalRequestId}'`,\n operation: 'rotateApprovalCapability',\n });\n }\n\n if (approval.status !== 'pending') {\n throw new CacheError({\n code: cacheErrorCodes.invalidPayload,\n key,\n message: `Approval '${approvalRequestId}' is '${approval.status}' and cannot accept a new secure approval link`,\n operation: 'rotateApprovalCapability',\n });\n }\n\n const capabilityToken = createApprovalCapabilityToken();\n const nextRecord: RelayApprovalRequestRecord = {\n ...approval,\n metadata: {\n ...(approval.metadata ?? {}),\n approvalCapabilityHash: approvalCapabilityHash(capabilityToken),\n approvalCapabilityToken: capabilityToken,\n },\n updatedAt: toIsoTimestamp(),\n };\n\n await this.writeJson(key, nextRecord);\n await this.clearApprovalCapabilityFailures(approvalRequestId);\n\n return nextRecord;\n }\n\n async claimEncryptedUpdates(\n input: ClaimEncryptedUpdatesInput,\n ): Promise<RelayEncryptedUpdateRecord[]> {\n const limit = clampLimit(input.limit, 25, 100);\n const leaseSeconds = clampLimit(input.leaseSeconds, 30, 300);\n const now = new Date();\n const nowMs = now.getTime();\n const claimUntil = new Date(nowMs + leaseSeconds * 1000).toISOString();\n const updateIds = await this.client.zrange(\n this.daemonUpdatesKey(input.daemonId),\n 0,\n limit * 4,\n 'REV',\n );\n const claimed: RelayEncryptedUpdateRecord[] = [];\n\n for (const updateId of updateIds) {\n if (claimed.length >= limit) {\n break;\n }\n\n const record = await this.readJson<RelayEncryptedUpdateRecord>(this.updateKey(updateId));\n if (!record) {\n continue;\n }\n\n if (\n record.status === 'applied' ||\n record.status === 'failed' ||\n record.status === 'rejected'\n ) {\n continue;\n }\n\n if (\n record.status === 'inflight' &&\n record.claimUntil &&\n Date.parse(record.claimUntil) > nowMs\n ) {\n continue;\n }\n\n const nextRecord: RelayEncryptedUpdateRecord = {\n ...record,\n claimToken: randomUUID(),\n claimUntil,\n lastDeliveredAt: now.toISOString(),\n status: 'inflight',\n updatedAt: now.toISOString(),\n };\n await this.writeJson(this.updateKey(updateId), nextRecord);\n claimed.push(nextRecord);\n }\n\n return claimed;\n }\n\n async submitUpdateFeedback(\n input: SubmitUpdateFeedbackInput,\n ): Promise<RelayEncryptedUpdateRecord> {\n const key = this.updateKey(input.updateId);\n const record = await this.readJson<RelayEncryptedUpdateRecord>(key);\n\n if (!record || record.daemonId !== input.daemonId) {\n throw new CacheError({\n code: cacheErrorCodes.notFound,\n key,\n message: `Unknown update '${input.updateId}' for daemon '${input.daemonId}'`,\n operation: 'submitUpdateFeedback',\n });\n }\n\n if (!record.claimToken || record.claimToken !== input.claimToken) {\n throw new CacheError({\n code: cacheErrorCodes.invalidPayload,\n key,\n message: `Claim token mismatch for update '${input.updateId}'`,\n operation: 'submitUpdateFeedback',\n });\n }\n\n const feedback: RelayUpdateFeedbackRecord = {\n daemonId: input.daemonId,\n details: input.details,\n feedbackAt: toIsoTimestamp(),\n message: input.message,\n status: input.status,\n updateId: input.updateId,\n };\n const nextRecord: RelayEncryptedUpdateRecord = {\n ...record,\n claimToken: undefined,\n claimUntil: undefined,\n feedback,\n status: input.status,\n updatedAt: toIsoTimestamp(),\n };\n\n await this.writeJson(key, nextRecord);\n return nextRecord;\n }\n\n async getEncryptedUpdate(updateId: string): Promise<RelayEncryptedUpdateRecord | null> {\n return await this.readJson<RelayEncryptedUpdateRecord>(this.updateKey(updateId));\n }\n\n async removeEncryptedUpdate(daemonId: string, updateId: string): Promise<void> {\n await this.client.zrem(this.daemonUpdatesKey(daemonId), updateId);\n await this.client.del(this.updateKey(updateId));\n }\n\n private readonly daemonIndexKey = (): string => `${this.namespace}:daemons`;\n private readonly daemonProfileKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:profile`;\n private readonly daemonPoliciesKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:policies`;\n private readonly daemonAgentKeysKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:agent-keys`;\n private readonly daemonApprovalsKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:approvals`;\n private readonly daemonUpdatesKey = (daemonId: string): string =>\n `${this.namespace}:daemon:${daemonId}:updates`;\n private readonly approvalKey = (approvalRequestId: string): string =>\n `${this.namespace}:approval:${approvalRequestId}`;\n private readonly approvalCapabilityConsumedKey = (\n approvalRequestId: string,\n capabilityHash: string,\n ): string =>\n `${this.namespace}:approval:${approvalRequestId}:capability:${capabilityHash}:consumed`;\n private readonly approvalCapabilityFailuresKey = (approvalRequestId: string): string =>\n `${this.namespace}:approval:${approvalRequestId}:capability-failures`;\n private readonly updateKey = (updateId: string): string => `${this.namespace}:update:${updateId}`;\n\n private async readJson<T>(key: string): Promise<T | null> {\n try {\n const payload = await this.client.get(key);\n if (payload === null) {\n return null;\n }\n\n return JSON.parse(payload) as T;\n } catch (error) {\n throw toCacheError(error, { key, operation: 'readJson' });\n }\n }\n\n private async writeJson(key: string, value: unknown): Promise<void> {\n try {\n await this.client.set(key, JSON.stringify(value));\n } catch (error) {\n throw toCacheError(error, { key, operation: 'writeJson' });\n }\n }\n}\n\nexport const createRelayCacheService = (options: { client?: Redis; namespace?: string } = {}) => {\n return new RelayCacheService(options);\n};\n"],"mappings":"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","names":[]}