@glubean/cli 0.8.3 → 0.9.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.
@@ -0,0 +1,322 @@
1
+ import { resolve } from "node:path";
2
+ import { stat } from "node:fs/promises";
3
+ import { loadProjectEnv } from "@glubean/runner";
4
+ import { buildProjections } from "./dry-run.js";
5
+ import { findProjectConfig } from "./run.js";
6
+ import { resolveToken, resolveProjectId, resolveApiUrl } from "../lib/auth.js";
7
+ import { resolveEnvFileName, SensitiveActiveEnvError } from "../lib/active_env.js";
8
+ const colors = {
9
+ reset: "\x1b[0m",
10
+ bold: "\x1b[1m",
11
+ dim: "\x1b[2m",
12
+ green: "\x1b[32m",
13
+ yellow: "\x1b[33m",
14
+ blue: "\x1b[34m",
15
+ red: "\x1b[31m",
16
+ };
17
+ /** Strip credential-bearing URL parts (query / fragment / userinfo) before a URL
18
+ * leaves the machine — mirrors the cloud's server-side sanitizer (defense in
19
+ * depth: the dry-run projector already placeholders ctx.secrets to `<KEY>`). */
20
+ function sanitizeUrl(url) {
21
+ try {
22
+ const u = new URL(url);
23
+ u.username = "";
24
+ u.password = "";
25
+ u.search = "";
26
+ u.hash = "";
27
+ return u.toString();
28
+ }
29
+ catch {
30
+ return url.split("#")[0].split("?")[0].replace(/(\/\/)[^/@]*@/, "$1");
31
+ }
32
+ }
33
+ /**
34
+ * `glubean sync` — sync the repo's test-definition projections (declared
35
+ * metadata + dry-run shape) to Glubean Cloud for team review. PROJECT-scoped:
36
+ * the projection is generated from SOURCE CODE, so it's one set per codebase
37
+ * regardless of how many targets it runs against. The upload is the COMPLETE
38
+ * source snapshot — the server replaces the project's projections with it
39
+ * (removed tests are deleted). Distinct from `glubean run --upload` (run
40
+ * evidence).
41
+ */
42
+ export async function syncCommand(options = {}) {
43
+ const dir = options.dir ? resolve(options.dir) : process.cwd();
44
+ // Resolve auth/env from the PROJECT ROOT (so root .env.* / .glubean/active-env
45
+ // are honored even when --dir points at a nested scan dir) — parity with run.
46
+ const { rootDir } = await findProjectConfig(dir);
47
+ console.log(`\n${colors.bold}${colors.blue}🔄 Glubean Sync (test-definition projection)${colors.reset}\n`);
48
+ // Validate an EXPLICIT --env-file FIRST — before the (expensive, user-code-
49
+ // running) projection — so a typo fails fast. A missing explicit env file
50
+ // would otherwise load empty and let global/process credentials upload to the
51
+ // WRONG project (parity with run/load). Default: the active env (or .env).
52
+ // GLU-88: resolveEnvFileName throws SensitiveActiveEnvError instead of
53
+ // silently returning a prod-like active-env file — surface it as a clear,
54
+ // actionable error (mirrors run/load) rather than silently syncing
55
+ // projections against prod.
56
+ const userSpecifiedEnvFile = !!options.envFile;
57
+ let envFileName;
58
+ if (userSpecifiedEnvFile) {
59
+ envFileName = options.envFile;
60
+ }
61
+ else {
62
+ try {
63
+ envFileName = await resolveEnvFileName(rootDir);
64
+ }
65
+ catch (err) {
66
+ if (err instanceof SensitiveActiveEnvError) {
67
+ console.error(`${colors.red}Sync failed: ${err.message}${colors.reset}`);
68
+ process.exit(1);
69
+ }
70
+ throw err;
71
+ }
72
+ }
73
+ if (userSpecifiedEnvFile) {
74
+ try {
75
+ await stat(resolve(rootDir, envFileName));
76
+ }
77
+ catch {
78
+ console.error(`${colors.red}Sync failed: env file '${envFileName}' not found in ${rootDir}${colors.reset}`);
79
+ process.exit(1);
80
+ }
81
+ }
82
+ // ALWAYS project the WHOLE project (rootDir), never just --dir: the upload is a
83
+ // complete snapshot the server replaces, so scanning a subdirectory would make
84
+ // the server delete every test outside it. --dir only locates the project root.
85
+ const { projected, errors, warnings, emptyTestFiles, contracts, workflows, openapi, openapiFailed } = await buildProjections(rootDir);
86
+ // A file that failed to import / timed out has NO projection. Since sync is a
87
+ // full-snapshot replace, publishing now would DELETE the broken file's tests'
88
+ // projections (treating them as removed) — so abort and let the user fix +
89
+ // re-sync the complete set.
90
+ if (errors.length) {
91
+ console.error(`${colors.red}Sync aborted: ${errors.length} file(s) failed to project.${colors.reset}`);
92
+ for (const e of errors)
93
+ console.error(` ${colors.red}✗ ${e.file}: ${e.message}${colors.reset}`);
94
+ console.error(`${colors.dim}Fix these files and re-run — syncing now would drop their tests' projections.${colors.reset}`);
95
+ process.exit(1);
96
+ }
97
+ // A file the SCANNER couldn't turn into a projection is dropped BEFORE upload
98
+ // (it never shows in `errors`), yet its tests/contracts/workflows would vanish
99
+ // from this full snapshot and be DELETED on replace. All fatal: test extraction
100
+ // THREW ("Failed to extract metadata from"), a test file yielded ZERO exports
101
+ // (emptyTestFiles), or a contract/workflow file failed to import ("Contract
102
+ // import failed" / "Flow import failed" — leaves contractsProjection/workflows
103
+ // missing that file, so a full-replace would wipe its prior Cloud projection).
104
+ const dropped = [
105
+ ...warnings.filter((w) => w.startsWith("Failed to extract metadata from") ||
106
+ w.startsWith("Contract import failed") ||
107
+ w.startsWith("Flow import failed")),
108
+ ...emptyTestFiles.map((f) => `${f} — a Glubean test file with no extractable tests (syntax error, or tests removed/unrecognized?)`),
109
+ ];
110
+ if (dropped.length) {
111
+ console.error(`${colors.red}Sync aborted: ${dropped.length} file(s) would be dropped from the snapshot.${colors.reset}`);
112
+ for (const w of dropped)
113
+ console.error(` ${colors.red}✗ ${w}${colors.reset}`);
114
+ console.error(`${colors.dim}Fix these files and re-run — syncing now would delete their projections from Cloud.${colors.reset}`);
115
+ process.exit(1);
116
+ }
117
+ // Empty snapshot would CLEAR the project's projections — guard against an
118
+ // accidental run in the wrong/empty dir; require --allow-empty to actually wipe.
119
+ // "Empty" means NO specs of ANY kind (test + contract + workflow).
120
+ if (projected.length === 0 && contracts.length === 0 && workflows.length === 0 && !options.allowEmpty) {
121
+ console.log(`${colors.yellow}No tests, contracts, or workflows found.${colors.reset} ${colors.dim}Pass --allow-empty to clear the project's projections, or check the directory.${colors.reset}\n`);
122
+ return;
123
+ }
124
+ // Resolve cloud auth — PROJECT-scoped (no target: the projection is repo-level).
125
+ const { vars, secrets } = await loadProjectEnv(rootDir, envFileName);
126
+ const authOpts = { token: options.token, project: options.project, apiUrl: options.apiUrl };
127
+ const sources = { envFileVars: { ...vars, ...secrets } };
128
+ const token = await resolveToken(authOpts, sources, options.tokenEnv);
129
+ const projectId = await resolveProjectId(authOpts, sources);
130
+ const apiUrl = await resolveApiUrl(authOpts, sources);
131
+ if (!token) {
132
+ console.error(`${colors.red}Sync failed: no auth token.${colors.reset}\n` +
133
+ `${colors.dim}Create a project token (glb_…) in the dashboard (Project → Tokens), then run 'glubean login', set GLUBEAN_TOKEN / --token, or add it to .env.secrets.${colors.reset}`);
134
+ process.exit(1);
135
+ }
136
+ if (!projectId) {
137
+ console.error(`${colors.red}Sync failed: no project ID.${colors.reset}\n` +
138
+ `${colors.dim}Set --project / GLUBEAN_PROJECT_ID, or run 'glubean login'.${colors.reset}`);
139
+ process.exit(1);
140
+ }
141
+ if (!apiUrl) {
142
+ console.error(`${colors.red}Sync failed: no API URL (set --api-url / GLUBEAN_API_URL).${colors.reset}`);
143
+ process.exit(1);
144
+ }
145
+ const tests = projected.map((p) => ({
146
+ testId: p.testId,
147
+ description: p.description ?? null,
148
+ deprecated: p.deprecated ?? null,
149
+ requires: p.requires ?? null,
150
+ defaultRun: p.defaultRun ?? null,
151
+ tags: p.tags ?? [],
152
+ assertions: p.assertions,
153
+ endpoints: p.endpoints.map((e) => ({ ...e, url: sanitizeUrl(e.url) })),
154
+ assertionCount: p.assertionCount,
155
+ projectionComplete: p.projectionComplete,
156
+ incompleteReason: p.incompleteReason ?? null,
157
+ skipped: p.skipped ?? false,
158
+ // B3 T1.5 row provenance — a server that predates the field strips it
159
+ // (ingest zod is non-strict), so this is forward-compatible. NOT redacted
160
+ // below (like testId): idTemplate/rowKey are identity keys built from the
161
+ // same row values as the uploaded testId itself — masking them would break
162
+ // the rowKey === id join Cloud derive performs.
163
+ ...(p.each ? { each: p.each } : {}),
164
+ }));
165
+ // Redact outbound data before it leaves the machine (parity with run/load):
166
+ // a hardcoded credential in an assertion message / endpoint is masked (URL
167
+ // query/userinfo/fragment is already stripped above). Honor the PROJECT's
168
+ // redaction rules (glubean.yaml `defaults.redaction` — custom sensitiveKeys /
169
+ // customPatterns), not just the built-in defaults; FAIL CLOSED on invalid config.
170
+ const { redactValue, BUILTIN_SCOPES } = await import("@glubean/redaction");
171
+ const { loadProjectConfigV1, resolveRedactionConfig } = await import("../lib/config.js");
172
+ let redaction = resolveRedactionConfig(undefined); // built-in defaults
173
+ let hasConfig = false;
174
+ try {
175
+ await stat(resolve(rootDir, "glubean.yaml"));
176
+ hasConfig = true;
177
+ }
178
+ catch {
179
+ /* no glubean.yaml → built-in default redaction */
180
+ }
181
+ if (hasConfig) {
182
+ try {
183
+ const { config } = await loadProjectConfigV1(rootDir);
184
+ redaction = resolveRedactionConfig(config.defaults?.redaction);
185
+ }
186
+ catch (err) {
187
+ console.error(`${colors.red}Sync failed: invalid glubean.yaml redaction config — ${err?.message ?? String(err)}${colors.reset}`);
188
+ process.exit(1);
189
+ }
190
+ }
191
+ // The projection is a static blob with NO request/response scope to bind to, so
192
+ // fold the builtin SCOPE sensitive keys (cookie / set-cookie / authorization /
193
+ // token / …) into the global keys — otherwise header/query examples carried in a
194
+ // contract/workflow projection would upload in cleartext (run/load apply these
195
+ // per-scope; here there's no scope, so apply them everywhere).
196
+ const scopeKeys = [...new Set(BUILTIN_SCOPES.flatMap((s) => s.rules?.sensitiveKeys ?? []))];
197
+ const globalRules = {
198
+ ...redaction.globalRules,
199
+ sensitiveKeys: [...new Set([...(redaction.globalRules.sensitiveKeys ?? []), ...scopeKeys])],
200
+ };
201
+ const redactField = (v) => redactValue(v, {
202
+ globalRules,
203
+ replacementFormat: redaction.replacementFormat,
204
+ maxDepth: 64,
205
+ });
206
+ // The normalized contract/workflow `projection` is a TYPE/STRUCTURE blob (JSON
207
+ // schemas, node trees) — its object KEYS are field names (e.g. a schema property
208
+ // literally named `password`/`token`), NOT secrets. Key-based redaction would
209
+ // MASK those field names and destroy the schema projection — the most important
210
+ // part of a contract. So redact the projection with PATTERN rules ONLY (still
211
+ // catches secret-LOOKING literal values, e.g. a hardcoded `sk-…` default), never
212
+ // sensitiveKeys.
213
+ const structureRules = { ...redaction.globalRules, sensitiveKeys: [] };
214
+ const redactStructure = (v) => redactValue(v, {
215
+ globalRules: structureRules,
216
+ replacementFormat: redaction.replacementFormat,
217
+ maxDepth: 64,
218
+ });
219
+ // Redact ONLY the secret-bearing/free-text fields — NEVER `testId` (the stable
220
+ // join key with run evidence; redacting an id that matches a built-in pattern
221
+ // would break correlation and collapse distinct ids) or structural fields
222
+ // (requires/defaultRun/counts/flags).
223
+ const safeTests = tests.map((t) => ({
224
+ ...t,
225
+ description: t.description == null ? t.description : redactField(t.description),
226
+ deprecated: t.deprecated == null ? t.deprecated : redactField(t.deprecated),
227
+ incompleteReason: t.incompleteReason == null ? t.incompleteReason : redactField(t.incompleteReason),
228
+ assertions: redactField(t.assertions),
229
+ endpoints: redactField(t.endpoints),
230
+ }));
231
+ // Contracts/workflows: redact the free-text + the normalized `projection` body
232
+ // (schemas/descriptions/notes), preserve identity/structural fields.
233
+ const safeContracts = contracts.map((c) => ({
234
+ contractId: c.contractId,
235
+ protocol: c.protocol,
236
+ target: c.target ?? null,
237
+ description: c.description == null ? null : redactField(c.description),
238
+ deprecated: c.deprecated == null ? null : redactField(c.deprecated),
239
+ tags: c.tags ?? [],
240
+ caseCount: c.caseCount,
241
+ projection: redactStructure(c.projection),
242
+ projectionComplete: c.projectionComplete,
243
+ incompleteReason: c.incompleteReason ?? null,
244
+ }));
245
+ const safeWorkflows = workflows.map((w) => ({
246
+ workflowId: w.workflowId,
247
+ name: w.name ?? null,
248
+ description: w.description == null ? null : redactField(w.description),
249
+ tags: w.tags ?? [],
250
+ nodeCount: w.nodeCount,
251
+ projection: redactStructure(w.projection),
252
+ projectionComplete: w.projectionComplete,
253
+ incompleteReason: w.incompleteReason ?? null,
254
+ }));
255
+ // The OpenAPI doc is purely structural (paths + schemas). Redact it pattern-ONLY
256
+ // (same as the normalized projection): mask secret-LOOKING example/default values
257
+ // but PRESERVE schema field names — masking a `password`/`token` field name (a
258
+ // type, not a secret) would corrupt the schema. `null` when there are no HTTP
259
+ // contracts, so a full-replace clears any stale doc.
260
+ const safeOpenapi = openapi ? redactStructure(openapi) : null;
261
+ const base = `${apiUrl.replace(/\/+$/, "")}/v1/projects/${projectId}/projections`;
262
+ // Each kind is its OWN full-snapshot replace (an empty kind clears that kind's
263
+ // stale projections). POST all three; a failure on any aborts.
264
+ const post = async (kind, body, opts) => {
265
+ let res;
266
+ try {
267
+ res = await fetch(`${base}/${kind}`, {
268
+ method: "POST",
269
+ headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
270
+ body: JSON.stringify(body),
271
+ });
272
+ }
273
+ catch (err) {
274
+ console.error(`${colors.red}Sync failed (${kind}): ${err?.message ?? String(err)}${colors.reset}`);
275
+ process.exit(1);
276
+ }
277
+ if (!res.ok) {
278
+ // A server that predates this projection kind answers 404 — tolerate it (skip
279
+ // this kind) instead of failing a sync that already replaced the OTHER kinds, so
280
+ // a newer CLI keeps working against a not-yet-upgraded / self-hosted server.
281
+ if (opts?.tolerateMissingRoute && res.status === 404)
282
+ return { skipped: true };
283
+ const text = await res.text().catch(() => "");
284
+ console.error(`${colors.red}Sync failed (${kind}): ${res.status} ${text}${colors.reset}`);
285
+ if (res.status === 401 || res.status === 403) {
286
+ console.error(`${colors.dim}The token is invalid/expired or lacks runs:write. Create a project token in the dashboard and 'glubean login' (or set GLUBEAN_TOKEN).${colors.reset}`);
287
+ }
288
+ process.exit(1);
289
+ }
290
+ return (await res.json().catch(() => ({})));
291
+ };
292
+ const testRes = await post("test", { tests: safeTests });
293
+ const contractRes = await post("contract", { contracts: safeContracts });
294
+ const workflowRes = await post("workflow", { workflows: safeWorkflows });
295
+ // The OpenAPI doc is a project-level single snapshot (not a per-id replace) — one
296
+ // doc rendered from all HTTP contracts. POST it last; `null` clears a stale doc. Two
297
+ // ways it skips (best-effort, never aborts the whole sync): render FAILED (don't wipe
298
+ // a prior doc on a transient error), or the server predates the route (404 tolerated,
299
+ // so a newer CLI doesn't break sync against a not-yet-upgraded server).
300
+ const openapiRes = openapiFailed
301
+ ? { skipped: true }
302
+ : await post("openapi", { openapi: safeOpenapi }, { tolerateMissingRoute: true });
303
+ const line = (label, r, n) => {
304
+ const removed = r.deleted ? `${colors.dim} (${r.deleted} removed)${colors.reset}` : "";
305
+ return `${colors.green}✓ ${r.upserted ?? n} ${label}${colors.reset}${removed}`;
306
+ };
307
+ const pathCount = safeOpenapi ? Object.keys(safeOpenapi.paths ?? {}).length : 0;
308
+ const openapiLine = openapiFailed
309
+ ? `${colors.yellow}⚠ openapi skipped (render failed; kept previous)${colors.reset}`
310
+ : openapiRes?.skipped
311
+ ? `${colors.dim}· openapi not supported by this server (skipped)${colors.reset}`
312
+ : `${colors.green}✓ openapi${colors.reset}${colors.dim} (${pathCount} path${pathCount === 1 ? "" : "s"})${colors.reset}`;
313
+ console.log(`${line("test", testRes, safeTests.length)} ${line("contract", contractRes, safeContracts.length)} ${line("workflow", workflowRes, safeWorkflows.length)} ${openapiLine} ${colors.dim}→ project ${projectId}${colors.reset}`);
314
+ const partial = projected.filter((p) => !p.projectionComplete).length +
315
+ contracts.filter((c) => !c.projectionComplete).length +
316
+ workflows.filter((w) => !w.projectionComplete).length;
317
+ if (partial > 0) {
318
+ console.log(`${colors.yellow} ◐ ${partial} partial — use ctx.when()/switch()/while() (tests) or resolve opaque nodes/unprojectable schemas (workflows/contracts) for full projection${colors.reset}`);
319
+ }
320
+ console.log();
321
+ }
322
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,18 @@
5
5
  * Used by both the CLI `run` command and the MCP server to resolve
6
6
  * which `.env.<name>` file to load when no explicit `--env-file` is given.
7
7
  */
8
+ /**
9
+ * Thrown by `resolveEnvFileName` when the active env resolves to a
10
+ * sensitive (prod-like) name. Callers MUST catch this and surface an
11
+ * actionable error — never fall through to silently loading the file
12
+ * anyway. Explicit `--env-file .env.prod` bypasses `resolveEnvFileName`
13
+ * entirely (call sites branch on `userSpecifiedEnvFile` first), so this
14
+ * only blocks the *implicit* path.
15
+ */
16
+ export declare class SensitiveActiveEnvError extends Error {
17
+ readonly envName: string;
18
+ constructor(envName: string);
19
+ }
8
20
  /**
9
21
  * Read the active environment name from `.glubean/active-env`.
10
22
  * Returns `undefined` if the file doesn't exist or is empty.
@@ -23,7 +35,10 @@ export declare function clearActiveEnv(projectRoot: string): Promise<void>;
23
35
  *
24
36
  * Priority:
25
37
  * 1. Explicit `--env-file` flag (pass-through, not handled here)
26
- * 2. `.glubean/active-env` → `.env.<name>`
38
+ * 2. `.glubean/active-env` → `.env.<name>` — UNLESS `<name>` is a sensitive
39
+ * (prod-like) name, in which case this throws `SensitiveActiveEnvError`
40
+ * instead of silently returning it (GLU-88). Every caller must handle
41
+ * that error explicitly.
27
42
  * 3. Default `.env`
28
43
  */
29
44
  export declare function resolveEnvFileName(projectRoot: string): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"active_env.d.ts","sourceRoot":"","sources":["../../src/lib/active_env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH;;;GAGG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvE;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAMjB"}
1
+ {"version":3,"file":"active_env.d.ts","sourceRoot":"","sources":["../../src/lib/active_env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4BH;;;;;;;GAOG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;aACpB,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM;CAW5C;AAMD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CASjB"}
@@ -9,6 +9,45 @@ import { resolve } from "node:path";
9
9
  import { readFile, writeFile, mkdir, unlink } from "node:fs/promises";
10
10
  const ACTIVE_ENV_DIR = ".glubean";
11
11
  const ACTIVE_ENV_FILE = "active-env";
12
+ /**
13
+ * GLU-88: env names that must NEVER be picked up silently through the
14
+ * `.glubean/active-env` fallback. `.glubean/active-env` is a persistent,
15
+ * un-TTL'd, un-warned sticky file — a `glubean env use prod` run once (e.g.
16
+ * to debug something) stays in effect for every future `glubean run` /
17
+ * `sync` / `load` in that directory until someone remembers to `glubean env
18
+ * reset`. For an ordinary named env (staging, dev, ci) that stickiness is
19
+ * the whole point of the feature. For a *production* env it's a footgun:
20
+ * a later, unrelated `--upload` silently ships data to prod with no
21
+ * confirmation and (today) no way to delete it server-side. Matched
22
+ * case-insensitively against the trimmed active-env name; deliberately an
23
+ * exact-match denylist (not a substring/regex sweep) to avoid false
24
+ * positives on names like "preprod-mirror".
25
+ */
26
+ const SENSITIVE_ENV_NAMES = new Set(["prod", "production"]);
27
+ function isSensitiveEnvName(name) {
28
+ return SENSITIVE_ENV_NAMES.has(name.trim().toLowerCase());
29
+ }
30
+ /**
31
+ * Thrown by `resolveEnvFileName` when the active env resolves to a
32
+ * sensitive (prod-like) name. Callers MUST catch this and surface an
33
+ * actionable error — never fall through to silently loading the file
34
+ * anyway. Explicit `--env-file .env.prod` bypasses `resolveEnvFileName`
35
+ * entirely (call sites branch on `userSpecifiedEnvFile` first), so this
36
+ * only blocks the *implicit* path.
37
+ */
38
+ export class SensitiveActiveEnvError extends Error {
39
+ envName;
40
+ constructor(envName) {
41
+ super(`Active environment is "${envName}" (set via \`glubean env use ${envName}\`, ` +
42
+ `recorded in .glubean/active-env), which looks like a production ` +
43
+ `environment. Refusing to load it implicitly — GLU-88 hardens exactly ` +
44
+ `this case (a stale active-env silently routing an unrelated run to prod). ` +
45
+ `Pass \`--env-file .env.${envName}\` to use it explicitly, or run ` +
46
+ `\`glubean env reset\` to clear the active environment and fall back to .env.`);
47
+ this.envName = envName;
48
+ this.name = "SensitiveActiveEnvError";
49
+ }
50
+ }
12
51
  function activeEnvPath(projectRoot) {
13
52
  return resolve(projectRoot, ACTIVE_ENV_DIR, ACTIVE_ENV_FILE);
14
53
  }
@@ -50,12 +89,18 @@ export async function clearActiveEnv(projectRoot) {
50
89
  *
51
90
  * Priority:
52
91
  * 1. Explicit `--env-file` flag (pass-through, not handled here)
53
- * 2. `.glubean/active-env` → `.env.<name>`
92
+ * 2. `.glubean/active-env` → `.env.<name>` — UNLESS `<name>` is a sensitive
93
+ * (prod-like) name, in which case this throws `SensitiveActiveEnvError`
94
+ * instead of silently returning it (GLU-88). Every caller must handle
95
+ * that error explicitly.
54
96
  * 3. Default `.env`
55
97
  */
56
98
  export async function resolveEnvFileName(projectRoot) {
57
99
  const activeEnv = await readActiveEnv(projectRoot);
58
100
  if (activeEnv) {
101
+ if (isSensitiveEnvName(activeEnv)) {
102
+ throw new SensitiveActiveEnvError(activeEnv);
103
+ }
59
104
  return `.env.${activeEnv}`;
60
105
  }
61
106
  return ".env";
@@ -1 +1 @@
1
- {"version":3,"file":"active_env.js","sourceRoot":"","sources":["../../src/lib/active_env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEtE,MAAM,cAAc,GAAG,UAAU,CAAC;AAClC,MAAM,eAAe,GAAG,YAAY,CAAC;AAErC,SAAS,aAAa,CAAC,WAAmB;IACxC,OAAO,OAAO,CAAC,WAAW,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAmB;IAEnB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC3B,OAAO,GAAG,IAAI,SAAS,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAmB,EACnB,OAAe;IAEf,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACjD,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,WAAmB;IAEnB,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IACnD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,QAAQ,SAAS,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"active_env.js","sourceRoot":"","sources":["../../src/lib/active_env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEtE,MAAM,cAAc,GAAG,UAAU,CAAC;AAClC,MAAM,eAAe,GAAG,YAAY,CAAC;AAErC;;;;;;;;;;;;;GAaG;AACH,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;AAE5D,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACpB;IAA5B,YAA4B,OAAe;QACzC,KAAK,CACH,0BAA0B,OAAO,gCAAgC,OAAO,MAAM;YAC5E,kEAAkE;YAClE,uEAAuE;YACvE,4EAA4E;YAC5E,0BAA0B,OAAO,kCAAkC;YACnE,8EAA8E,CACjF,CAAC;QARwB,YAAO,GAAP,OAAO,CAAQ;QASzC,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,SAAS,aAAa,CAAC,WAAmB;IACxC,OAAO,OAAO,CAAC,WAAW,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAmB;IAEnB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC3B,OAAO,GAAG,IAAI,SAAS,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAmB,EACnB,OAAe;IAEf,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACjD,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,WAAmB;IAEnB,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IACnD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,uBAAuB,CAAC,SAAS,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,QAAQ,SAAS,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * only-selectors.ts — pure, unit-testable builders for the B2 M3 `{id, rowIndex}`
3
+ * "only" selector protocol at the CLI surface.
4
+ *
5
+ * Two entry points:
6
+ * - `buildOnlySelectorsFromFlags` — the single validation gate for the
7
+ * `--only-id` / `--row` / `--rerun-failed` flag combination. Returns the
8
+ * selector set for the explicit (`--only-id`/`--row`) path, or a clear error.
9
+ * - `deriveRerunSelectors` — turns a prior `last-run.result.json` into the
10
+ * failed-subset selectors + the distinct files those failures live in.
11
+ *
12
+ * The protocol shape (`OnlySelector`) and matching/collection semantics
13
+ * (`collectFailedSelectors`) are reused from `@glubean/runner` so the CLI, the
14
+ * SDK runner, and the cloud harness all speak ONE protocol.
15
+ */
16
+ import { type OnlySelector } from "@glubean/runner";
17
+ export interface OnlyFlags {
18
+ onlyId?: string[];
19
+ row?: number;
20
+ rerunFailed?: boolean;
21
+ }
22
+ export type BuildSelectorsResult = {
23
+ ok: true;
24
+ selectors: OnlySelector[];
25
+ } | {
26
+ ok: false;
27
+ error: string;
28
+ };
29
+ /**
30
+ * Validate the flag combination and build selectors for the explicit
31
+ * `--only-id` / `--row` path.
32
+ *
33
+ * Validation:
34
+ * - `--rerun-failed` is mutually exclusive with `--only-id` / `--row`.
35
+ * - `--row` requires EXACTLY one `--only-id` (it pins a single `.each` row).
36
+ *
37
+ * Returns `{ selectors: [] }` for the conflict-free `--rerun-failed` case — the
38
+ * caller sources the actual selectors from the last run via `deriveRerunSelectors`.
39
+ */
40
+ export declare function buildOnlySelectorsFromFlags(opts: OnlyFlags): BuildSelectorsResult;
41
+ /**
42
+ * Derive the `--rerun-failed` selector set + the distinct files those failures
43
+ * came from, off a prior run's `last-run.result.json` `tests` array.
44
+ *
45
+ * `selectors` reuses `collectFailedSelectors` (failed records with an id → bare
46
+ * `{id}` or row-pinned `{id, rowIndex}`). `files` is the de-duplicated list of
47
+ * `filePath`s of failed records (declaration order preserved) so the caller can
48
+ * narrow discovery to only the files that actually contained a failure.
49
+ */
50
+ export declare function deriveRerunSelectors(lastRun: {
51
+ tests: Array<{
52
+ testId?: string;
53
+ rowIndex?: number;
54
+ filePath?: string;
55
+ success: boolean;
56
+ }>;
57
+ }): {
58
+ selectors: OnlySelector[];
59
+ files: string[];
60
+ };
61
+ //# sourceMappingURL=only-selectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"only-selectors.d.ts","sourceRoot":"","sources":["../../src/lib/only-selectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE5E,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,YAAY,EAAE,CAAA;CAAE,GACvC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,SAAS,GAAG,oBAAoB,CAiCjF;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,KAAK,EAAE,KAAK,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC3F,GAAG;IAAE,SAAS,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAcjD"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * only-selectors.ts — pure, unit-testable builders for the B2 M3 `{id, rowIndex}`
3
+ * "only" selector protocol at the CLI surface.
4
+ *
5
+ * Two entry points:
6
+ * - `buildOnlySelectorsFromFlags` — the single validation gate for the
7
+ * `--only-id` / `--row` / `--rerun-failed` flag combination. Returns the
8
+ * selector set for the explicit (`--only-id`/`--row`) path, or a clear error.
9
+ * - `deriveRerunSelectors` — turns a prior `last-run.result.json` into the
10
+ * failed-subset selectors + the distinct files those failures live in.
11
+ *
12
+ * The protocol shape (`OnlySelector`) and matching/collection semantics
13
+ * (`collectFailedSelectors`) are reused from `@glubean/runner` so the CLI, the
14
+ * SDK runner, and the cloud harness all speak ONE protocol.
15
+ */
16
+ import { collectFailedSelectors } from "@glubean/runner";
17
+ /**
18
+ * Validate the flag combination and build selectors for the explicit
19
+ * `--only-id` / `--row` path.
20
+ *
21
+ * Validation:
22
+ * - `--rerun-failed` is mutually exclusive with `--only-id` / `--row`.
23
+ * - `--row` requires EXACTLY one `--only-id` (it pins a single `.each` row).
24
+ *
25
+ * Returns `{ selectors: [] }` for the conflict-free `--rerun-failed` case — the
26
+ * caller sources the actual selectors from the last run via `deriveRerunSelectors`.
27
+ */
28
+ export function buildOnlySelectorsFromFlags(opts) {
29
+ const onlyId = opts.onlyId ?? [];
30
+ const hasRow = opts.row !== undefined;
31
+ const rerun = !!opts.rerunFailed;
32
+ // --rerun-failed reuses the last run's failed set; it can't be combined with
33
+ // an explicit --only-id / --row target.
34
+ if (rerun && (onlyId.length > 0 || hasRow)) {
35
+ return {
36
+ ok: false,
37
+ error: "--rerun-failed cannot be combined with --only-id or --row (it reuses the last run's failed set).",
38
+ };
39
+ }
40
+ // --row pins a single .each row, so it needs exactly one --only-id to attach to.
41
+ if (hasRow && onlyId.length !== 1) {
42
+ return {
43
+ ok: false,
44
+ error: onlyId.length === 0
45
+ ? "--row requires --only-id (the id whose .each row you want to isolate)."
46
+ : `--row requires exactly one --only-id (got ${onlyId.length}). Drop --row to run multiple ids.`,
47
+ };
48
+ }
49
+ // Conflict-free rerun mode: no flag-derived selectors — they come from the file.
50
+ if (rerun)
51
+ return { ok: true, selectors: [] };
52
+ if (hasRow) {
53
+ return { ok: true, selectors: [{ id: onlyId[0], rowIndex: opts.row }] };
54
+ }
55
+ return { ok: true, selectors: onlyId.map((id) => ({ id })) };
56
+ }
57
+ /**
58
+ * Derive the `--rerun-failed` selector set + the distinct files those failures
59
+ * came from, off a prior run's `last-run.result.json` `tests` array.
60
+ *
61
+ * `selectors` reuses `collectFailedSelectors` (failed records with an id → bare
62
+ * `{id}` or row-pinned `{id, rowIndex}`). `files` is the de-duplicated list of
63
+ * `filePath`s of failed records (declaration order preserved) so the caller can
64
+ * narrow discovery to only the files that actually contained a failure.
65
+ */
66
+ export function deriveRerunSelectors(lastRun) {
67
+ const tests = lastRun.tests ?? [];
68
+ const selectors = collectFailedSelectors(tests.map((t) => ({ id: t.testId, rowIndex: t.rowIndex, success: t.success })));
69
+ const files = [];
70
+ const seen = new Set();
71
+ for (const t of tests) {
72
+ if (t.success === false && t.filePath && !seen.has(t.filePath)) {
73
+ seen.add(t.filePath);
74
+ files.push(t.filePath);
75
+ }
76
+ }
77
+ return { selectors, files };
78
+ }
79
+ //# sourceMappingURL=only-selectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"only-selectors.js","sourceRoot":"","sources":["../../src/lib/only-selectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,sBAAsB,EAAqB,MAAM,iBAAiB,CAAC;AAY5E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAAe;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC;IACtC,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;IAEjC,6EAA6E;IAC7E,wCAAwC;IACxC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EACH,kGAAkG;SACrG,CAAC;IACJ,CAAC;IAED,iFAAiF;IACjF,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EACH,MAAM,CAAC,MAAM,KAAK,CAAC;gBACjB,CAAC,CAAC,wEAAwE;gBAC1E,CAAC,CAAC,6CAA6C,MAAM,CAAC,MAAM,oCAAoC;SACrG,CAAC;IACJ,CAAC;IAED,iFAAiF;IACjF,IAAI,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;IAE9C,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAI,EAAE,CAAC,EAAE,CAAC;IAC5E,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;AAC/D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAEpC;IACC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,sBAAsB,CACtC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAC/E,CAAC;IACF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC"}