fest-gateway 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +274 -0
  3. package/dist/cli/claude.js +326 -0
  4. package/dist/cli/claude.js.map +1 -0
  5. package/dist/cli/config.js +59 -0
  6. package/dist/cli/config.js.map +1 -0
  7. package/dist/cli/login.js +130 -0
  8. package/dist/cli/login.js.map +1 -0
  9. package/dist/cli/logout.js +20 -0
  10. package/dist/cli/logout.js.map +1 -0
  11. package/dist/cli/whoami.js +34 -0
  12. package/dist/cli/whoami.js.map +1 -0
  13. package/dist/server/adapters/anthropic.js +74 -0
  14. package/dist/server/adapters/anthropic.js.map +1 -0
  15. package/dist/server/adapters/fireworks.js +54 -0
  16. package/dist/server/adapters/fireworks.js.map +1 -0
  17. package/dist/server/adapters/index.js +16 -0
  18. package/dist/server/adapters/index.js.map +1 -0
  19. package/dist/server/adapters/registry.js +38 -0
  20. package/dist/server/adapters/registry.js.map +1 -0
  21. package/dist/server/adapters/rewrite.js +152 -0
  22. package/dist/server/adapters/rewrite.js.map +1 -0
  23. package/dist/server/adapters/url.js +24 -0
  24. package/dist/server/adapters/url.js.map +1 -0
  25. package/dist/server/api/auth.js +213 -0
  26. package/dist/server/api/auth.js.map +1 -0
  27. package/dist/server/api/live.js +108 -0
  28. package/dist/server/api/live.js.map +1 -0
  29. package/dist/server/api/models.js +129 -0
  30. package/dist/server/api/models.js.map +1 -0
  31. package/dist/server/api/oauth.js +300 -0
  32. package/dist/server/api/oauth.js.map +1 -0
  33. package/dist/server/api/routes.js +164 -0
  34. package/dist/server/api/routes.js.map +1 -0
  35. package/dist/server/api/routing-view.js +47 -0
  36. package/dist/server/api/routing-view.js.map +1 -0
  37. package/dist/server/auth/accounts.js +111 -0
  38. package/dist/server/auth/accounts.js.map +1 -0
  39. package/dist/server/auth/gateway-401.js +85 -0
  40. package/dist/server/auth/gateway-401.js.map +1 -0
  41. package/dist/server/auth/guard.js +74 -0
  42. package/dist/server/auth/guard.js.map +1 -0
  43. package/dist/server/auth/oauth.js +43 -0
  44. package/dist/server/auth/oauth.js.map +1 -0
  45. package/dist/server/auth/password.js +104 -0
  46. package/dist/server/auth/password.js.map +1 -0
  47. package/dist/server/auth/posture.js +145 -0
  48. package/dist/server/auth/posture.js.map +1 -0
  49. package/dist/server/auth/session.js +161 -0
  50. package/dist/server/auth/session.js.map +1 -0
  51. package/dist/server/bin/fest.js +589 -0
  52. package/dist/server/bin/fest.js.map +1 -0
  53. package/dist/server/config.js +109 -0
  54. package/dist/server/config.js.map +1 -0
  55. package/dist/server/credentials/provider.js +70 -0
  56. package/dist/server/credentials/provider.js.map +1 -0
  57. package/dist/server/credentials/resolve.js +89 -0
  58. package/dist/server/credentials/resolve.js.map +1 -0
  59. package/dist/server/http/body.js +66 -0
  60. package/dist/server/http/body.js.map +1 -0
  61. package/dist/server/http/errors.js +144 -0
  62. package/dist/server/http/errors.js.map +1 -0
  63. package/dist/server/http/headers.js +189 -0
  64. package/dist/server/http/headers.js.map +1 -0
  65. package/dist/server/http/pipe.js +97 -0
  66. package/dist/server/http/pipe.js.map +1 -0
  67. package/dist/server/http/server.js +226 -0
  68. package/dist/server/http/server.js.map +1 -0
  69. package/dist/server/http/sse.js +167 -0
  70. package/dist/server/http/sse.js.map +1 -0
  71. package/dist/server/http/static.js +138 -0
  72. package/dist/server/http/static.js.map +1 -0
  73. package/dist/server/ingest/live-bus.js +67 -0
  74. package/dist/server/ingest/live-bus.js.map +1 -0
  75. package/dist/server/ingest/sink.js +141 -0
  76. package/dist/server/ingest/sink.js.map +1 -0
  77. package/dist/server/log.js +31 -0
  78. package/dist/server/log.js.map +1 -0
  79. package/dist/server/pipeline/count-tokens.js +48 -0
  80. package/dist/server/pipeline/count-tokens.js.map +1 -0
  81. package/dist/server/pipeline/dispatch.js +138 -0
  82. package/dist/server/pipeline/dispatch.js.map +1 -0
  83. package/dist/server/pipeline/passthrough.js +392 -0
  84. package/dist/server/pipeline/passthrough.js.map +1 -0
  85. package/dist/server/pipeline/preflight.js +66 -0
  86. package/dist/server/pipeline/preflight.js.map +1 -0
  87. package/dist/server/pipeline/record.js +49 -0
  88. package/dist/server/pipeline/record.js.map +1 -0
  89. package/dist/server/pipeline/substitute.js +287 -0
  90. package/dist/server/pipeline/substitute.js.map +1 -0
  91. package/dist/server/routes/resolve.js +176 -0
  92. package/dist/server/routes/resolve.js.map +1 -0
  93. package/dist/server/routes/table.js +247 -0
  94. package/dist/server/routes/table.js.map +1 -0
  95. package/dist/server/routes/watch.js +101 -0
  96. package/dist/server/routes/watch.js.map +1 -0
  97. package/dist/server/secret/fingerprint.js +107 -0
  98. package/dist/server/secret/fingerprint.js.map +1 -0
  99. package/dist/server/secret/non-persistable.js +69 -0
  100. package/dist/server/secret/non-persistable.js.map +1 -0
  101. package/dist/server/store/audit.js +53 -0
  102. package/dist/server/store/audit.js.map +1 -0
  103. package/dist/server/store/bootstrap.js +53 -0
  104. package/dist/server/store/bootstrap.js.map +1 -0
  105. package/dist/server/store/db.js +157 -0
  106. package/dist/server/store/db.js.map +1 -0
  107. package/dist/server/store/ids.js +14 -0
  108. package/dist/server/store/ids.js.map +1 -0
  109. package/dist/server/store/migrations/001-init.sql +213 -0
  110. package/dist/server/store/migrations/002-feed-and-error-indexes.sql +26 -0
  111. package/dist/server/store/migrations/003-routing.sql +42 -0
  112. package/dist/server/store/migrations/004-admin-auth.sql +72 -0
  113. package/dist/server/store/migrations/005-notional-cost.sql +28 -0
  114. package/dist/server/store/queries.js +904 -0
  115. package/dist/server/store/queries.js.map +1 -0
  116. package/dist/server/store/retention.js +79 -0
  117. package/dist/server/store/retention.js.map +1 -0
  118. package/dist/server/store/seed.js +203 -0
  119. package/dist/server/store/seed.js.map +1 -0
  120. package/dist/server/store/tokens.js +133 -0
  121. package/dist/server/store/tokens.js.map +1 -0
  122. package/dist/server/store/write.js +330 -0
  123. package/dist/server/store/write.js.map +1 -0
  124. package/dist/server/usage/accumulator.js +209 -0
  125. package/dist/server/usage/accumulator.js.map +1 -0
  126. package/dist/server/usage/cost.js +57 -0
  127. package/dist/server/usage/cost.js.map +1 -0
  128. package/dist/server/usage/prices/catalog.js +136 -0
  129. package/dist/server/usage/prices/catalog.js.map +1 -0
  130. package/dist/server/usage/prices/refresh.js +125 -0
  131. package/dist/server/usage/prices/refresh.js.map +1 -0
  132. package/dist/server/usage/prices/snapshot.json.gz +0 -0
  133. package/dist/server/usage/prices/table.js +102 -0
  134. package/dist/server/usage/prices/table.js.map +1 -0
  135. package/dist/server/usage/pricing.js +103 -0
  136. package/dist/server/usage/pricing.js.map +1 -0
  137. package/dist/shared/api.js +19 -0
  138. package/dist/shared/api.js.map +1 -0
  139. package/dist/shared/base-models.js +28 -0
  140. package/dist/shared/base-models.js.map +1 -0
  141. package/dist/shared/demotion-vars.js +17 -0
  142. package/dist/shared/demotion-vars.js.map +1 -0
  143. package/dist/shared/series.js +50 -0
  144. package/dist/shared/series.js.map +1 -0
  145. package/dist/shared/types.js +40 -0
  146. package/dist/shared/types.js.map +1 -0
  147. package/dist/web/dist/assets/index-8HlKsJqt.css +2 -0
  148. package/dist/web/dist/assets/index-DQ7fyPVm.js +56 -0
  149. package/dist/web/dist/assets/index-DQ7fyPVm.js.map +1 -0
  150. package/dist/web/dist/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  151. package/dist/web/dist/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  152. package/dist/web/dist/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  153. package/dist/web/dist/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  154. package/dist/web/dist/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
  155. package/dist/web/dist/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  156. package/dist/web/dist/assets/inter-latin-700-normal-BLAVimhd.woff +0 -0
  157. package/dist/web/dist/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
  158. package/dist/web/dist/index.html +44 -0
  159. package/dist/web/dist/nearform-icon.svg +4 -0
  160. package/package.json +82 -0
  161. package/routes.example.json +22 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../server/auth/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,589 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Fest CLI.
4
+ *
5
+ * Server operator commands (need FEST_* server env, run on the host):
6
+ * fest serve run the gateway
7
+ * fest migrate apply schema migrations
8
+ * fest token create <email> [name] mint an identity token (shown once)
9
+ * fest token list
10
+ * fest token revoke <token-id>
11
+ * fest admin create <email> [--role owner|admin|member] [--password-stdin]
12
+ * grant dashboard sign-in (password shown once)
13
+ * fest admin list
14
+ * fest admin passwd <email> [--password-stdin]
15
+ * fest admin disable <email> | fest admin enable <email>
16
+ * fest seed [--requests N] [--hours N] [--force]
17
+ * synthetic traffic, for looking at the
18
+ * dashboard without a live session
19
+ * fest seed --reset discard the database, then seed it fresh
20
+ * fest seed --clear discard the database and stop
21
+ *
22
+ * Developer commands (run on your own machine, no server env needed):
23
+ * fest login [--provider google|github] [--server <url>]
24
+ * sign in via OAuth, store a token in ~/.fest
25
+ * fest whoami show the locally stored login
26
+ * fest claude [gw] [-- claude args...]
27
+ * run `claude` pointed at your Fest gateway.
28
+ * Posture is auto-detected: your own Anthropic
29
+ * login pays if you have one, org credentials
30
+ * if you do not. `gw` forces org credentials
31
+ * and the gateway model menu.
32
+ * fest logout forget the local login
33
+ */
34
+ import { mkdir, rm } from "node:fs/promises";
35
+ import { dirname } from "node:path";
36
+ import { loadConfig, describeConfig } from "../config.js";
37
+ import { createUsageSink } from "../ingest/sink.js";
38
+ import { createLiveBus } from "../ingest/live-bus.js";
39
+ import { createServer } from "../http/server.js";
40
+ import { log, setLogLevel } from "../log.js";
41
+ import { openStore, migrate } from "../store/db.js";
42
+ import { ensureOrg, ensureUser, findUserByEmail } from "../store/bootstrap.js";
43
+ import { createToken, listTokens, revokeToken, resolveToken, createLastUsedTracker } from "../store/tokens.js";
44
+ import { grantDashboardAccess, hasAnyOwner, normaliseEmail } from "../auth/accounts.js";
45
+ import { revokeUserSessions } from "../auth/session.js";
46
+ import { isLoopbackHost } from "../auth/guard.js";
47
+ import { generatePassword } from "../auth/password.js";
48
+ import { recordAudit } from "../store/audit.js";
49
+ import { createRequestWriter } from "../store/write.js";
50
+ import { startRetention, DEFAULT_RETENTION } from "../store/retention.js";
51
+ import { loadPrices, startPriceRefresh, pricingOptionsFromEnv } from "../usage/prices/refresh.js";
52
+ import { seed, existingRequestCount, isDefaultDatabase } from "../store/seed.js";
53
+ import { parseRouteTable, EMPTY_ROUTE_TABLE } from "../routes/table.js";
54
+ import { watchRoutes } from "../routes/watch.js";
55
+ import { readFile } from "node:fs/promises";
56
+ import { runLogin } from "../../cli/login.js";
57
+ import { runWhoami } from "../../cli/whoami.js";
58
+ import { runClaude } from "../../cli/claude.js";
59
+ import { runLogout } from "../../cli/logout.js";
60
+ import { readCliConfig } from "../../cli/config.js";
61
+ const out = (s) => void process.stdout.write(s + "\n");
62
+ async function withStore(cfg) {
63
+ await mkdir(dirname(cfg.dbPath), { recursive: true });
64
+ const store = openStore(cfg.dbPath);
65
+ // Migrations run before anything else touches the schema, so a fresh volume
66
+ // and an upgraded one behave identically.
67
+ const { applied, version } = migrate(store);
68
+ if (applied > 0)
69
+ log.info("migrations applied", { applied, version });
70
+ return store;
71
+ }
72
+ /**
73
+ * Load and validate the routing table at BOOT, not on first use.
74
+ *
75
+ * A config error must stop the process here, where an operator is watching,
76
+ * rather than surfacing as a failed request to a developer hours later. And a
77
+ * table that fails to parse must never degrade to "no routing": that would
78
+ * silently send substituted traffic back onto developers' subscriptions, which
79
+ * is the exact silent-billing-substitution failure this phase is designed
80
+ * against.
81
+ */
82
+ async function loadRoutes(cfg) {
83
+ if (cfg.routesPath === null)
84
+ return EMPTY_ROUTE_TABLE;
85
+ const text = await readFile(cfg.routesPath, "utf8");
86
+ const table = parseRouteTable(text);
87
+ log.info("routing table loaded", {
88
+ path: cfg.routesPath,
89
+ version: table.version,
90
+ routes: table.routes.length,
91
+ upstreams: [...table.upstreams.keys()],
92
+ });
93
+ return table;
94
+ }
95
+ async function cmdServe(cfg) {
96
+ const routes = await loadRoutes(cfg);
97
+ // Edits to routes.json take effect without a restart. `node --watch` only
98
+ // tracks imported .ts files, so without this an edit appeared to do nothing —
99
+ // which reads as "my config is wrong" rather than "it has not been loaded".
100
+ const routeWatcher = cfg.routesPath === null ? null : watchRoutes(cfg.routesPath, routes);
101
+ const store = await withStore(cfg);
102
+ const org = ensureOrg(store);
103
+ /**
104
+ * Refuse to serve an unauthenticated dashboard off loopback.
105
+ *
106
+ * The API exposes every developer's usage. On 127.0.0.1 that is a
107
+ * single-developer trial and asking for a password first would be friction
108
+ * for no one's benefit; on any other interface it is a data leak waiting for
109
+ * someone to find the port. Failing at boot — where an operator is watching —
110
+ * beats failing as a quiet exposure nobody notices.
111
+ */
112
+ if (!isLoopbackHost(cfg.host) && !hasAnyOwner(store, org.id)) {
113
+ store.close();
114
+ throw new Error(`refusing to listen on ${cfg.host} with no owner account.\n` +
115
+ "The dashboard would serve every developer's usage to anyone who finds the port.\n" +
116
+ "Create one first:\n" +
117
+ " node server/bin/fest.ts admin create you@corp.test\n" +
118
+ " (in Docker: docker compose run --rm fest admin create you@corp.test)\n" +
119
+ "or bind to loopback (FEST_HOST=127.0.0.1) for a single-developer trial.");
120
+ }
121
+ // Prices load synchronously from the vendored snapshot before the first
122
+ // request can arrive, so a call is never metered against an empty table. The
123
+ // refresh that follows is best-effort and off the hot path — see
124
+ // usage/prices/refresh.ts for why boot must never wait on it.
125
+ const pricing = pricingOptionsFromEnv(cfg.dbPath);
126
+ loadPrices(pricing);
127
+ const priceRefresh = startPriceRefresh(pricing);
128
+ const writer = createRequestWriter(store);
129
+ const lastUsed = createLastUsedTracker(store);
130
+ // Hourly sweep, on a timer rather than at boot: a restart loop must not turn
131
+ // into a delete loop.
132
+ const retention = startRetention(store, DEFAULT_RETENTION);
133
+ await mkdir(dirname(cfg.usageLogPath), { recursive: true });
134
+ const bus = createLiveBus();
135
+ const sink = createUsageSink({
136
+ path: cfg.usageLogPath,
137
+ // The store is the system of record; JSONL stays as a cheap, greppable
138
+ // trail. Pricing and persistence both happen here in the flush, never on
139
+ // the request path.
140
+ //
141
+ // The live feed is published AFTER the write, so a dashboard never shows a
142
+ // row that then fails to persist. A throwing write requeues the batch and
143
+ // publishes on the retry instead, which is the right way round: the feed
144
+ // may lag the truth, but it must not contradict it.
145
+ onBatch: (records) => {
146
+ writer.writeBatch(org.id, records);
147
+ bus.publish(records);
148
+ },
149
+ });
150
+ const server = createServer({
151
+ config: cfg,
152
+ sink,
153
+ bus,
154
+ routes: routeWatcher === null ? routes : () => routeWatcher.current(),
155
+ orgId: org.id,
156
+ store,
157
+ resolveIdentity: (raw) => resolveToken(store, raw),
158
+ touchToken: (id) => lastUsed.touch(id),
159
+ });
160
+ /**
161
+ * How long an in-flight request may keep the process alive on shutdown.
162
+ *
163
+ * Long enough not to guillotine a developer mid-turn; short enough that
164
+ * `node --watch` feels like a restart rather than a hang.
165
+ */
166
+ const DRAIN_GRACE_MS = 5_000;
167
+ let shuttingDown = false;
168
+ const shutdown = (signal) => {
169
+ if (shuttingDown)
170
+ return;
171
+ shuttingDown = true;
172
+ log.info("shutting down", { signal });
173
+ const finish = () => {
174
+ void sink.close().then(() => {
175
+ retention.stop();
176
+ priceRefresh.stop();
177
+ routeWatcher?.stop();
178
+ lastUsed.stop();
179
+ store.close();
180
+ log.info("drained", { sink: sink.stats() });
181
+ process.exit(0);
182
+ });
183
+ };
184
+ server.close(finish);
185
+ // `server.close()` stops accepting but WAITS for every open connection.
186
+ // An SSE stream never ends by itself, so a single open dashboard would
187
+ // block shutdown indefinitely — which under `node --watch` looks like a
188
+ // restart stuck on "Waiting for graceful termination". Hang up on the
189
+ // dashboards explicitly; they reconnect on their own.
190
+ bus.closeAll();
191
+ server.closeIdleConnections();
192
+ // Whatever is left is a request genuinely in flight. Give it a bounded
193
+ // grace period, then stop waiting: a developer's next keystroke restarting
194
+ // the server matters more than the tail of one turn, and the sink has
195
+ // already been told to drain.
196
+ const forced = setTimeout(() => {
197
+ log.warn("shutdown grace expired; closing remaining connections", {
198
+ afterMs: DRAIN_GRACE_MS,
199
+ });
200
+ server.closeAllConnections();
201
+ finish();
202
+ }, DRAIN_GRACE_MS);
203
+ forced.unref();
204
+ };
205
+ process.on("SIGINT", () => shutdown("SIGINT"));
206
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
207
+ server.listen(cfg.port, cfg.host, () => {
208
+ log.info("fest listening", describeConfig(cfg));
209
+ out(`fest: http://${cfg.host}:${cfg.port} -> ${cfg.upstreamBaseUrl}\n` +
210
+ ` db: ${cfg.dbPath} identity required: ${cfg.requireIdentity}\n` +
211
+ ` retention: requests ${DEFAULT_RETENTION.requestDays}d, rollups ${DEFAULT_RETENTION.rollupDays}d\n` +
212
+ ` routing: ${routes.routes.length === 0
213
+ ? "none — every request passes through on the caller's own credential"
214
+ : `${routes.routes.length} route(s) via ${cfg.routesPath} (v${routes.version})`}\n` +
215
+ `point Claude Code at it with:\n` +
216
+ ` ANTHROPIC_BASE_URL=http://${cfg.host}:${cfg.port}/t/<your-token>\n` +
217
+ `and do NOT set ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN (either disables your subscription)`);
218
+ });
219
+ }
220
+ async function cmdToken(cfg, argv) {
221
+ const store = await withStore(cfg);
222
+ const org = ensureOrg(store);
223
+ const sub = argv[0] ?? "list";
224
+ if (sub === "create") {
225
+ const email = argv[1];
226
+ if (email === undefined)
227
+ throw new Error("usage: fest token create <email> [name]");
228
+ const user = ensureUser(store, { orgId: org.id, email, role: "member" });
229
+ const created = createToken(store, { orgId: org.id, userId: user.id, name: argv[2] ?? "" });
230
+ recordAudit(store, {
231
+ orgId: org.id,
232
+ actorLabel: "cli",
233
+ action: "token.create",
234
+ target: created.id,
235
+ outcome: "ok",
236
+ detail: { user: user.email, name: argv[2] ?? "" },
237
+ });
238
+ out(`token id : ${created.id}`);
239
+ out(`user : ${user.email}`);
240
+ out("");
241
+ // Shown exactly once: only the hash is stored.
242
+ out(` ${created.raw}`);
243
+ out("");
244
+ out("This is the only time the token is shown. Use it as:");
245
+ out(` ANTHROPIC_BASE_URL=http://${cfg.host}:${cfg.port}/t/${created.raw}`);
246
+ }
247
+ else if (sub === "list") {
248
+ const rows = listTokens(store, org.id);
249
+ if (rows.length === 0)
250
+ out("(no tokens)");
251
+ for (const r of rows) {
252
+ const state = r.revokedAt !== null ? "revoked" : "active";
253
+ out(`${r.id} ${r.displayPrefix}… ${state.padEnd(7)} user=${r.userId} ` +
254
+ `last-used=${r.lastUsedAt === null ? "never" : new Date(r.lastUsedAt).toISOString()} ${r.name}`);
255
+ }
256
+ }
257
+ else if (sub === "revoke") {
258
+ const id = argv[1];
259
+ if (id === undefined)
260
+ throw new Error("usage: fest token revoke <token-id>");
261
+ const revoked = revokeToken(store, org.id, id);
262
+ recordAudit(store, {
263
+ orgId: org.id,
264
+ actorLabel: "cli",
265
+ action: "token.revoke",
266
+ target: id,
267
+ outcome: revoked ? "ok" : "denied",
268
+ });
269
+ out(revoked ? `revoked ${id}` : `not found or already revoked: ${id}`);
270
+ }
271
+ else {
272
+ throw new Error(`unknown token subcommand: ${sub}`);
273
+ }
274
+ store.close();
275
+ }
276
+ /**
277
+ * Read a password from stdin when asked to, otherwise generate one.
278
+ *
279
+ * Never from a command-line argument: `fest admin create x --password hunter2`
280
+ * puts the password in the shell history, in `ps` output for every user on the
281
+ * box, and often in a CI log. `--password-stdin` is the automation path; the
282
+ * default is a generated password shown once, which is the one most operators
283
+ * should take.
284
+ */
285
+ async function readPassword(argv) {
286
+ if (!argv.includes("--password-stdin"))
287
+ return { password: generatePassword(), generated: true };
288
+ const chunks = [];
289
+ for await (const chunk of process.stdin)
290
+ chunks.push(chunk);
291
+ const password = Buffer.concat(chunks).toString("utf8").replace(/\r?\n$/, "");
292
+ if (password === "")
293
+ throw new Error("--password-stdin was given but stdin was empty");
294
+ return { password, generated: false };
295
+ }
296
+ function flagValue(argv, name) {
297
+ const i = argv.indexOf(`--${name}`);
298
+ return i === -1 ? undefined : argv[i + 1];
299
+ }
300
+ /**
301
+ * Did this user already have console access — a password of their own —
302
+ * before this call? `ensureUser` also runs for metering-only rows (an
303
+ * identity token, or an OAuth self-service login that never went through
304
+ * `admin create`), so "a row exists" is not the same question.
305
+ */
306
+ function hadConsoleAccess(store, userId) {
307
+ const row = store.db.prepare(`SELECT password_hash FROM users WHERE id = ?`).get(userId);
308
+ return row !== undefined && row.password_hash !== null;
309
+ }
310
+ async function cmdAdmin(cfg, argv) {
311
+ const store = await withStore(cfg);
312
+ const org = ensureOrg(store);
313
+ const sub = argv[0] ?? "list";
314
+ try {
315
+ if (sub === "create" || sub === "passwd") {
316
+ const email = argv[1];
317
+ if (email === undefined)
318
+ throw new Error(`usage: fest admin ${sub} <email> [--role R] [--password-stdin]`);
319
+ const roleFlag = flagValue(argv, "role");
320
+ if (roleFlag !== undefined && !["owner", "admin", "member"].includes(roleFlag)) {
321
+ throw new Error("--role must be owner, admin or member");
322
+ }
323
+ /**
324
+ * An existing user keeps their role unless `--role` says otherwise.
325
+ *
326
+ * Found by running it: `admin passwd` on the only owner silently demoted
327
+ * them to `admin`, which left the deployment with no owner — and an
328
+ * ownerless deployment on loopback serves the API unauthenticated. A
329
+ * routine password rotation therefore turned the dashboard's auth off.
330
+ * Changing a password must change exactly the password.
331
+ *
332
+ * Only when the user is new to the CONSOLE does the default apply, and
333
+ * then the FIRST such account is the owner whatever it asked for: a
334
+ * deployment with only an `admin` has nobody able to grant the owner
335
+ * role afterwards. A metering-only row (minted by `fest token create`,
336
+ * or by an OAuth `fest login` that never touched the console) does not
337
+ * count as "existing" for this purpose — granting it console access for
338
+ * the first time is exactly the bootstrap case, not a rotation to
339
+ * protect.
340
+ */
341
+ const existing = findUserByEmail(store, org.id, normaliseEmail(email));
342
+ const existingConsoleRole = existing !== null && hadConsoleAccess(store, existing.id) ? existing.role : undefined;
343
+ const role = (roleFlag ?? existingConsoleRole ?? (hasAnyOwner(store, org.id) ? "admin" : "owner"));
344
+ const { password, generated } = await readPassword(argv);
345
+ const user = await grantDashboardAccess(store, {
346
+ orgId: org.id,
347
+ email,
348
+ password,
349
+ role,
350
+ });
351
+ recordAudit(store, {
352
+ orgId: org.id,
353
+ actorLabel: "cli",
354
+ action: sub === "create" ? "admin.create" : "admin.passwd",
355
+ target: user.email,
356
+ outcome: "ok",
357
+ detail: { role },
358
+ });
359
+ out(`user : ${user.email}`);
360
+ out(`role : ${user.role}`);
361
+ if (generated) {
362
+ out("");
363
+ // Shown exactly once: only the scrypt hash is stored.
364
+ out(` ${password}`);
365
+ out("");
366
+ out("This is the only time the password is shown. Store it in a password manager.");
367
+ }
368
+ else {
369
+ out("password set from stdin");
370
+ }
371
+ out("Existing sessions for this user have been signed out.");
372
+ return;
373
+ }
374
+ if (sub === "list") {
375
+ const rows = store.db
376
+ .prepare(`SELECT email, role, password_hash IS NOT NULL AS can_sign_in, disabled_at, password_set_at
377
+ FROM users WHERE org_id = ? ORDER BY role, email`)
378
+ .all(org.id);
379
+ if (rows.length === 0)
380
+ out("(no users)");
381
+ for (const r of rows) {
382
+ const state = r["disabled_at"] !== null ? "disabled" : Number(r["can_sign_in"]) === 1 ? "sign-in" : "metered-only";
383
+ out(`${String(r["email"]).padEnd(32)} ${String(r["role"]).padEnd(7)} ${state}`);
384
+ }
385
+ return;
386
+ }
387
+ if (sub === "disable" || sub === "enable") {
388
+ const email = argv[1];
389
+ if (email === undefined)
390
+ throw new Error(`usage: fest admin ${sub} <email>`);
391
+ const disabling = sub === "disable";
392
+ const res = store.db
393
+ .prepare(`UPDATE users SET disabled_at = ? WHERE org_id = ? AND email = ?`)
394
+ .run(disabling ? Date.now() : null, org.id, normaliseEmail(email));
395
+ if (Number(res.changes) === 0)
396
+ throw new Error(`no such user: ${email}`);
397
+ // Disabling has to take effect now, not at the next sign-in. A live
398
+ // cookie outliving the account is the whole reason this command exists.
399
+ if (disabling) {
400
+ const user = store.db
401
+ .prepare(`SELECT id FROM users WHERE org_id = ? AND email = ?`)
402
+ .get(org.id, normaliseEmail(email));
403
+ if (user !== undefined)
404
+ revokeUserSessions(store, user.id);
405
+ }
406
+ recordAudit(store, {
407
+ orgId: org.id,
408
+ actorLabel: "cli",
409
+ action: disabling ? "admin.disable" : "admin.enable",
410
+ target: normaliseEmail(email),
411
+ outcome: "ok",
412
+ });
413
+ out(`${disabling ? "disabled" : "enabled"} ${normaliseEmail(email)}`);
414
+ return;
415
+ }
416
+ throw new Error(`unknown admin subcommand: ${sub}`);
417
+ }
418
+ finally {
419
+ store.close();
420
+ }
421
+ }
422
+ function intFlag(argv, name) {
423
+ const i = argv.indexOf(`--${name}`);
424
+ if (i === -1)
425
+ return undefined;
426
+ const n = Number(argv[i + 1]);
427
+ if (!Number.isInteger(n) || n <= 0)
428
+ throw new Error(`--${name} needs a positive integer`);
429
+ return n;
430
+ }
431
+ /**
432
+ * Discard a database entirely, rather than deleting rows from it.
433
+ *
434
+ * Unlink and not `DELETE FROM`: once synthetic and observed rows share a table
435
+ * there is no honest predicate that separates them, so a partial wipe would
436
+ * have to guess. Removing the file is total and unambiguous — you know exactly
437
+ * what you have afterwards, which is nothing.
438
+ *
439
+ * Refuses the default database without `--force`, because the one thing this
440
+ * command must never do is silently destroy a real record of a team's usage on
441
+ * the way to showing someone a demo.
442
+ */
443
+ async function discardDatabase(cfg, force) {
444
+ if (isDefaultDatabase(cfg.dbPath) && !force) {
445
+ throw new Error(`refusing to delete the default database (${cfg.dbPath}).\n` +
446
+ "That is where real traffic is recorded. Point at a scratch database:\n" +
447
+ " npm run demo:clean (uses ./data/demo.db)\n" +
448
+ " FEST_DB=./data/scratch.db node server/bin/fest.ts seed --clear\n" +
449
+ "or pass --force if you genuinely mean this one.");
450
+ }
451
+ // The -wal and -shm siblings hold committed pages. Leaving them behind next
452
+ // to a deleted main file is how a "cleared" database comes back populated.
453
+ await Promise.all([cfg.dbPath, `${cfg.dbPath}-wal`, `${cfg.dbPath}-shm`].map((f) => rm(f, { force: true })));
454
+ }
455
+ async function cmdSeed(cfg, argv) {
456
+ const force = argv.includes("--force");
457
+ const clear = argv.includes("--clear");
458
+ const reset = argv.includes("--reset");
459
+ if (clear || reset) {
460
+ await discardDatabase(cfg, force);
461
+ out(`discarded ${cfg.dbPath}`);
462
+ if (clear)
463
+ return;
464
+ }
465
+ const store = await withStore(cfg);
466
+ const existing = existingRequestCount(store);
467
+ // Invented numbers must never be blended into observed ones. A dashboard is
468
+ // only worth anything if you can trust that what it shows was measured.
469
+ if (existing > 0 && !force) {
470
+ store.close();
471
+ throw new Error(`${cfg.dbPath} already holds ${existing} request(s).\n` +
472
+ "Seeding would mix synthetic rows into real traffic. Either start clean:\n" +
473
+ " npm run demo (scratch database, reset each time)\n" +
474
+ " node server/bin/fest.ts seed --reset\n" +
475
+ "or pass --force if you are certain this database is disposable.");
476
+ }
477
+ const requests = intFlag(argv, "requests");
478
+ const hours = intFlag(argv, "hours");
479
+ const result = seed(store, {
480
+ ...(requests === undefined ? {} : { requests }),
481
+ ...(hours === undefined ? {} : { hours }),
482
+ });
483
+ store.close();
484
+ out(`seeded ${result.written} synthetic requests into ${cfg.dbPath}`);
485
+ out(`developers: ${result.users.join(", ")}`);
486
+ out("");
487
+ out("These rows are INVENTED. Discard them with --clear before trusting any");
488
+ out("number in this database.");
489
+ }
490
+ function printHelp() {
491
+ out("server operator:\n" +
492
+ " fest serve | migrate |\n" +
493
+ " seed [--requests N] [--hours N] [--reset | --clear] [--force] |\n" +
494
+ " token create <email> [name] | token list | token revoke <id> |\n" +
495
+ " admin create <email> [--role R] [--password-stdin] | admin list |\n" +
496
+ " admin passwd <email> | admin disable <email> | admin enable <email>\n" +
497
+ "\n" +
498
+ "developer (run on your own machine, no server env needed):\n" +
499
+ " fest login [--provider google|github] [--server <url>]\n" +
500
+ " fest whoami\n" +
501
+ " fest claude [gw] [-- claude args...] (gw: force org credentials + gateway models)\n" +
502
+ " fest logout");
503
+ }
504
+ async function cmdLogin(argv) {
505
+ const providerFlag = flagValue(argv, "provider") ?? "google";
506
+ if (providerFlag !== "google" && providerFlag !== "github") {
507
+ throw new Error("--provider must be google or github");
508
+ }
509
+ const serverFlag = flagValue(argv, "server");
510
+ const serverUrl = serverFlag ?? (await readCliConfig())?.serverUrl;
511
+ if (serverUrl === undefined) {
512
+ throw new Error("usage: fest login --server <url> [--provider google|github]\n(--server is required the first time)");
513
+ }
514
+ await runLogin({ provider: providerFlag, serverUrl });
515
+ }
516
+ /**
517
+ * Commands a developer runs on their own machine. Dispatched before
518
+ * `loadConfig()` is ever called: a laptop has no reason to have any FEST_*
519
+ * server env var set, and these commands must not imply otherwise.
520
+ */
521
+ const CLIENT_COMMANDS = new Set(["login", "whoami", "claude", "logout"]);
522
+ async function main() {
523
+ const argv = process.argv.slice(2);
524
+ const cmd = argv[0] ?? "help";
525
+ if (CLIENT_COMMANDS.has(cmd)) {
526
+ switch (cmd) {
527
+ case "login":
528
+ await cmdLogin(argv.slice(1));
529
+ return;
530
+ case "whoami":
531
+ await runWhoami();
532
+ return;
533
+ case "claude": {
534
+ let claudeArgs = argv.slice(1);
535
+ // `gw` is the one word this subcommand owns, and only before `--`:
536
+ // `fest claude -- gw` still forwards `gw` to the child.
537
+ const posture = claudeArgs[0] === "gw" ? "key" : "auto";
538
+ if (posture === "key")
539
+ claudeArgs = claudeArgs.slice(1);
540
+ // `fest claude -- --resume` and `fest claude --resume` are both fine:
541
+ // apart from `gw` this subcommand defines no flags of its own, so a
542
+ // leading `--` is only ever there by convention and is stripped rather
543
+ // than forwarded.
544
+ if (claudeArgs[0] === "--")
545
+ claudeArgs = claudeArgs.slice(1);
546
+ await runClaude(claudeArgs, posture);
547
+ return;
548
+ }
549
+ case "logout":
550
+ await runLogout();
551
+ return;
552
+ }
553
+ }
554
+ if (cmd === "help" || cmd === "--help" || cmd === "-h") {
555
+ printHelp();
556
+ return;
557
+ }
558
+ const cfg = loadConfig();
559
+ setLogLevel(cfg.logLevel);
560
+ switch (cmd) {
561
+ case "serve":
562
+ await cmdServe(cfg);
563
+ return;
564
+ case "migrate": {
565
+ const store = await withStore(cfg);
566
+ ensureOrg(store);
567
+ const version = store.db.prepare("PRAGMA user_version").get();
568
+ out(`migrated: ${cfg.dbPath} (user_version=${Object.values(version)[0]})`);
569
+ store.close();
570
+ return;
571
+ }
572
+ case "token":
573
+ await cmdToken(cfg, argv.slice(1));
574
+ return;
575
+ case "admin":
576
+ await cmdAdmin(cfg, argv.slice(1));
577
+ return;
578
+ case "seed":
579
+ await cmdSeed(cfg, argv.slice(1));
580
+ return;
581
+ default:
582
+ throw new Error(`unknown command: ${cmd}`);
583
+ }
584
+ }
585
+ main().catch((err) => {
586
+ process.stderr.write(`fest: ${err instanceof Error ? err.message : String(err)}\n`);
587
+ process.exit(1);
588
+ });
589
+ //# sourceMappingURL=fest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fest.js","sourceRoot":"","sources":["../../../server/bin/fest.ts"],"names":[],"mappings":"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"}