@mycadet/gateway 0.12.10 → 0.13.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 (85) hide show
  1. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  2. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  3. package/node_modules/@mycadet/ces-client/src/http-credentials.ts +18 -1
  4. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  5. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  6. package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
  7. package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  8. package/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  9. package/openapi.json +1 -1
  10. package/package.json +1 -1
  11. package/src/__tests__/actor-token-revocation.test.ts +41 -34
  12. package/src/__tests__/contact-store-mirror-op-missing.test.ts +33 -70
  13. package/src/__tests__/contacts-mirror-op-reporter.test.ts +33 -89
  14. package/src/__tests__/credential-requests.test.ts +4 -4
  15. package/src/__tests__/devices-mine.test.ts +187 -0
  16. package/src/__tests__/edge-auth.test.ts +1 -20
  17. package/src/__tests__/edge-guardian-auth.test.ts +1 -17
  18. package/src/__tests__/feature-flag-resolver.test.ts +2 -30
  19. package/src/__tests__/feature-flag-watcher-callback.test.ts +0 -22
  20. package/src/__tests__/feature-flags-route.test.ts +2 -191
  21. package/src/__tests__/guardian-bootstrap-lookups.test.ts +22 -29
  22. package/src/__tests__/guardian-init-lockfile.test.ts +2 -2
  23. package/src/__tests__/guardian-integrity-reporter.test.ts +51 -82
  24. package/src/__tests__/guardian-integrity.test.ts +16 -20
  25. package/src/__tests__/handle-inbound-trust-verdict.test.ts +1 -14
  26. package/src/__tests__/ipc-feature-flag-routes.test.ts +0 -56
  27. package/src/__tests__/lum-2783-recovery-e2e.test.ts +0 -12
  28. package/src/__tests__/post-assistant-ready-deferred.test.ts +0 -18
  29. package/src/__tests__/refresh-device-binding.test.ts +0 -12
  30. package/src/__tests__/remote-web-pairing-token.test.ts +5 -15
  31. package/src/__tests__/runtime-client.test.ts +7 -7
  32. package/src/__tests__/speech-relay-websocket.test.ts +4 -4
  33. package/src/__tests__/trust-verdict-resolver-guardian-integrity.test.ts +30 -36
  34. package/src/__tests__/twilio-webhooks.test.ts +2 -2
  35. package/src/auth/actor-token-revocation.ts +34 -9
  36. package/src/auth/guardian-bootstrap.ts +1 -1
  37. package/src/cli/__tests__/pairing.test.ts +95 -0
  38. package/src/cli/index.ts +1 -1
  39. package/src/cli/pairing.ts +81 -6
  40. package/src/contacts-mirror-op-reporter.ts +19 -36
  41. package/src/db/connection.ts +0 -10
  42. package/src/feature-flag-resolver.ts +2 -7
  43. package/src/feature-flag-watcher.ts +1 -14
  44. package/src/guardian-integrity-reporter.ts +19 -47
  45. package/src/http/middleware/auth.ts +33 -27
  46. package/src/http/routes/auth-token.ts +1 -1
  47. package/src/http/routes/devices-mine.ts +103 -0
  48. package/src/http/routes/feature-flags.ts +1 -8
  49. package/src/http/routes/guardian-pin.ts +2 -11
  50. package/src/http/routes/ipc-runtime-proxy.ts +1 -1
  51. package/src/http/routes/live-voice-websocket.ts +1 -1
  52. package/src/http/routes/runtime-audio-stream.ts +1 -1
  53. package/src/http/routes/runtime-proxy.ts +2 -2
  54. package/src/http/routes/speech-relay-websocket.ts +2 -2
  55. package/src/http/routes/twilio-voice-webhook.test.ts +13 -13
  56. package/src/index.ts +11 -198
  57. package/src/ipc/feature-flag-handlers.ts +2 -9
  58. package/src/remote-web/pairing-challenge-store.ts +15 -0
  59. package/src/risk/command-registry/commands/assistant.ts +0 -24
  60. package/src/risk/command-registry.test.ts +2 -4
  61. package/src/schema.ts +44 -372
  62. package/src/__tests__/auth-fallback-count-tracker.test.ts +0 -92
  63. package/src/__tests__/auth-fallback-reporter.test.ts +0 -101
  64. package/src/__tests__/backup-worker-cloud-mode.test.ts +0 -44
  65. package/src/__tests__/backup-worker-export-timeout.test.ts +0 -164
  66. package/src/__tests__/migration-teleport-gcs-proxy.test.ts +0 -216
  67. package/src/__tests__/remote-feature-flag-sync.test.ts +0 -961
  68. package/src/auth-fallback-count-tracker.ts +0 -113
  69. package/src/auth-fallback-reporter.ts +0 -127
  70. package/src/backup/backup-key.ts +0 -138
  71. package/src/backup/backup-routes.ts +0 -161
  72. package/src/backup/backup-worker.ts +0 -425
  73. package/src/backup/list-snapshots.ts +0 -97
  74. package/src/backup/local-writer.ts +0 -87
  75. package/src/backup/offsite-writer.ts +0 -182
  76. package/src/backup/paths.ts +0 -113
  77. package/src/backup/stream-crypt.ts +0 -258
  78. package/src/device-id.ts +0 -18
  79. package/src/feature-flag-remote-store.ts +0 -166
  80. package/src/http/routes/migration-proxy.ts +0 -636
  81. package/src/internal-telemetry-client.ts +0 -39
  82. package/src/ipc/debug-export-handlers.test.ts +0 -102
  83. package/src/ipc/debug-export-handlers.ts +0 -81
  84. package/src/remote-feature-flag-sync.ts +0 -440
  85. package/src/watchdog-reporter.ts +0 -110
@@ -1,166 +0,0 @@
1
- /**
2
- * Gateway-side remote feature flag store — file-backed persistence of
3
- * feature flag values pushed from the cloud.
4
- *
5
- * Mirrors the feature-flag-store.ts pattern: file path resolution via
6
- * getGatewaySecurityDir(), atomic writes (temp file + rename), 0o600
7
- * permissions, and module-level caching with manual invalidation.
8
- *
9
- * Unlike the local override store, writes replace the *entire* value map at
10
- * once (the cloud pushes a complete snapshot) and immediately update the
11
- * in-memory cache so no file watcher is needed.
12
- */
13
-
14
- import {
15
- chmodSync,
16
- existsSync,
17
- mkdirSync,
18
- readFileSync,
19
- renameSync,
20
- writeFileSync,
21
- } from "node:fs";
22
- import { dirname, join } from "node:path";
23
-
24
- import { getLogger } from "./logger.js";
25
- import { getGatewaySecurityDir } from "./paths.js";
26
-
27
- const log = getLogger("feature-flag-remote-store");
28
-
29
- // ---------------------------------------------------------------------------
30
- // Types
31
- // ---------------------------------------------------------------------------
32
-
33
- interface FeatureFlagFileData {
34
- version: 1;
35
- values: Record<string, boolean | string>;
36
- }
37
-
38
- // ---------------------------------------------------------------------------
39
- // File path
40
- // ---------------------------------------------------------------------------
41
-
42
- export function getRemoteFeatureFlagStorePath(): string {
43
- return join(getGatewaySecurityDir(), "feature-flags-remote.json");
44
- }
45
-
46
- // ---------------------------------------------------------------------------
47
- // Disk I/O with caching
48
- // ---------------------------------------------------------------------------
49
-
50
- let cachedRemoteValues: Record<string, boolean | string> | null = null;
51
-
52
- export function readRemoteFeatureFlags(): Record<string, boolean | string> {
53
- if (cachedRemoteValues != null) return cachedRemoteValues;
54
-
55
- const path = getRemoteFeatureFlagStorePath();
56
- if (!existsSync(path)) {
57
- cachedRemoteValues = {};
58
- return cachedRemoteValues;
59
- }
60
-
61
- try {
62
- const raw = readFileSync(path, "utf-8");
63
- const data = JSON.parse(raw) as FeatureFlagFileData;
64
-
65
- if (data.version !== 1) {
66
- log.warn(
67
- { version: data.version },
68
- "Unknown remote feature flag store version, returning empty values",
69
- );
70
- cachedRemoteValues = {};
71
- return cachedRemoteValues;
72
- }
73
-
74
- if (
75
- data.values &&
76
- typeof data.values === "object" &&
77
- !Array.isArray(data.values)
78
- ) {
79
- const filtered: Record<string, boolean | string> = {};
80
- for (const [k, v] of Object.entries(data.values)) {
81
- if (typeof v === "boolean" || typeof v === "string") filtered[k] = v;
82
- }
83
- cachedRemoteValues = filtered;
84
- } else {
85
- cachedRemoteValues = {};
86
- }
87
- return cachedRemoteValues;
88
- } catch (err) {
89
- log.error({ err }, "Failed to load remote feature flag store");
90
- cachedRemoteValues = {};
91
- return cachedRemoteValues;
92
- }
93
- }
94
-
95
- /**
96
- * Persist remote feature flags to disk and update the in-memory cache.
97
- * Returns `true` when the new values differ from the previous cache.
98
- */
99
- export function writeRemoteFeatureFlags(
100
- values: Record<string, boolean | string>,
101
- ): boolean {
102
- const path = getRemoteFeatureFlagStorePath();
103
- const dir = dirname(path);
104
- if (!existsSync(dir)) {
105
- mkdirSync(dir, { recursive: true });
106
- }
107
-
108
- const data: FeatureFlagFileData = { version: 1, values };
109
- const tmpPath = path + ".tmp." + process.pid;
110
- writeFileSync(tmpPath, JSON.stringify(data, null, 2), { mode: 0o600 });
111
- renameSync(tmpPath, path);
112
- chmodSync(path, 0o600);
113
-
114
- const changed = !shallowEqual(cachedRemoteValues, values);
115
- cachedRemoteValues = values;
116
-
117
- const msg = "Wrote remote feature flags";
118
- const meta = { count: Object.keys(values).length };
119
- if (changed) {
120
- log.info(meta, msg);
121
- } else {
122
- log.debug(meta, msg);
123
- }
124
-
125
- return changed;
126
- }
127
-
128
- /**
129
- * Returns `true` when the incoming flag snapshot matches what's already
130
- * cached. Only used for log-level gating — correctness doesn't depend on it.
131
- */
132
- function shallowEqual(
133
- a: Record<string, boolean | string> | null,
134
- b: Record<string, boolean | string>,
135
- ): boolean {
136
- if (a == null) return false;
137
- const aKeys = Object.keys(a);
138
- if (aKeys.length !== Object.keys(b).length) return false;
139
- for (const k of aKeys) {
140
- if (a[k] !== b[k]) return false;
141
- }
142
- return true;
143
- }
144
-
145
- /**
146
- * Clear the in-memory cache so the next `readRemoteFeatureFlags()` call
147
- * re-reads from disk. Useful in tests for resetting state between cases.
148
- */
149
- export function clearRemoteFeatureFlagStoreCache(): void {
150
- cachedRemoteValues = null;
151
- }
152
-
153
- /**
154
- * Re-read the remote feature flag file from disk into the in-memory cache.
155
- *
156
- * Called by the file watcher when `feature-flags-remote.json` changes on
157
- * disk (e.g. written by a separate process or a previous gateway instance).
158
- * This ensures the next `readRemoteFeatureFlags()` call returns fresh data
159
- * without requiring every read to hit disk.
160
- */
161
- export function refreshRemoteFeatureFlagStoreCache(): void {
162
- cachedRemoteValues = null;
163
- // Force a re-read into cache immediately so the next
164
- // readRemoteFeatureFlags() call picks up the new values.
165
- readRemoteFeatureFlags();
166
- }