@mycadet/gateway 0.12.11 → 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 (81) hide show
  1. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
  2. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
  3. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
  4. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
  5. package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
  6. package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
  7. package/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
  8. package/openapi.json +1 -1
  9. package/package.json +1 -1
  10. package/src/__tests__/actor-token-revocation.test.ts +41 -34
  11. package/src/__tests__/contact-store-mirror-op-missing.test.ts +33 -70
  12. package/src/__tests__/contacts-mirror-op-reporter.test.ts +33 -89
  13. package/src/__tests__/credential-requests.test.ts +4 -4
  14. package/src/__tests__/devices-mine.test.ts +187 -0
  15. package/src/__tests__/edge-auth.test.ts +1 -20
  16. package/src/__tests__/edge-guardian-auth.test.ts +1 -17
  17. package/src/__tests__/feature-flag-resolver.test.ts +2 -30
  18. package/src/__tests__/feature-flag-watcher-callback.test.ts +0 -22
  19. package/src/__tests__/feature-flags-route.test.ts +2 -191
  20. package/src/__tests__/guardian-bootstrap-lookups.test.ts +18 -25
  21. package/src/__tests__/guardian-integrity-reporter.test.ts +51 -82
  22. package/src/__tests__/guardian-integrity.test.ts +16 -20
  23. package/src/__tests__/handle-inbound-trust-verdict.test.ts +1 -14
  24. package/src/__tests__/ipc-feature-flag-routes.test.ts +0 -56
  25. package/src/__tests__/lum-2783-recovery-e2e.test.ts +0 -12
  26. package/src/__tests__/post-assistant-ready-deferred.test.ts +0 -18
  27. package/src/__tests__/refresh-device-binding.test.ts +0 -12
  28. package/src/__tests__/remote-web-pairing-token.test.ts +4 -14
  29. package/src/__tests__/runtime-client.test.ts +7 -7
  30. package/src/__tests__/speech-relay-websocket.test.ts +4 -4
  31. package/src/__tests__/trust-verdict-resolver-guardian-integrity.test.ts +30 -36
  32. package/src/__tests__/twilio-webhooks.test.ts +2 -2
  33. package/src/auth/actor-token-revocation.ts +34 -9
  34. package/src/cli/__tests__/pairing.test.ts +95 -0
  35. package/src/cli/index.ts +1 -1
  36. package/src/cli/pairing.ts +81 -6
  37. package/src/contacts-mirror-op-reporter.ts +19 -36
  38. package/src/db/connection.ts +0 -10
  39. package/src/feature-flag-resolver.ts +2 -7
  40. package/src/feature-flag-watcher.ts +1 -14
  41. package/src/guardian-integrity-reporter.ts +19 -47
  42. package/src/http/middleware/auth.ts +33 -27
  43. package/src/http/routes/auth-token.ts +1 -1
  44. package/src/http/routes/devices-mine.ts +103 -0
  45. package/src/http/routes/feature-flags.ts +1 -8
  46. package/src/http/routes/guardian-pin.ts +2 -11
  47. package/src/http/routes/ipc-runtime-proxy.ts +1 -1
  48. package/src/http/routes/live-voice-websocket.ts +1 -1
  49. package/src/http/routes/runtime-audio-stream.ts +1 -1
  50. package/src/http/routes/runtime-proxy.ts +2 -2
  51. package/src/http/routes/twilio-voice-webhook.test.ts +13 -13
  52. package/src/index.ts +11 -198
  53. package/src/ipc/feature-flag-handlers.ts +2 -9
  54. package/src/remote-web/pairing-challenge-store.ts +15 -0
  55. package/src/risk/command-registry/commands/assistant.ts +0 -24
  56. package/src/risk/command-registry.test.ts +2 -4
  57. package/src/schema.ts +44 -372
  58. package/src/__tests__/auth-fallback-count-tracker.test.ts +0 -92
  59. package/src/__tests__/auth-fallback-reporter.test.ts +0 -101
  60. package/src/__tests__/backup-worker-cloud-mode.test.ts +0 -44
  61. package/src/__tests__/backup-worker-export-timeout.test.ts +0 -164
  62. package/src/__tests__/migration-teleport-gcs-proxy.test.ts +0 -216
  63. package/src/__tests__/remote-feature-flag-sync.test.ts +0 -961
  64. package/src/auth-fallback-count-tracker.ts +0 -113
  65. package/src/auth-fallback-reporter.ts +0 -127
  66. package/src/backup/backup-key.ts +0 -138
  67. package/src/backup/backup-routes.ts +0 -161
  68. package/src/backup/backup-worker.ts +0 -425
  69. package/src/backup/list-snapshots.ts +0 -97
  70. package/src/backup/local-writer.ts +0 -87
  71. package/src/backup/offsite-writer.ts +0 -182
  72. package/src/backup/paths.ts +0 -113
  73. package/src/backup/stream-crypt.ts +0 -258
  74. package/src/device-id.ts +0 -18
  75. package/src/feature-flag-remote-store.ts +0 -166
  76. package/src/http/routes/migration-proxy.ts +0 -636
  77. package/src/internal-telemetry-client.ts +0 -39
  78. package/src/ipc/debug-export-handlers.test.ts +0 -102
  79. package/src/ipc/debug-export-handlers.ts +0 -81
  80. package/src/remote-feature-flag-sync.ts +0 -440
  81. 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
- }