@runcofactor/cli 0.15.2 → 0.17.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.
- package/dist/{account-62I7FG5G.js → account-ZSM2Q3RB.js} +6 -6
- package/dist/account-ZSM2Q3RB.js.map +1 -0
- package/dist/{api-catalog-CAJUASVC.js → api-catalog-MMPFWS52.js} +5 -5
- package/dist/{attachment-RL4AZUJE.js → attachment-NSYL5X3S.js} +5 -5
- package/dist/{augmentor-GAF3MFY6.js → augmentor-LSJLMJYP.js} +5 -5
- package/dist/{auth-DURHUZDW.js → auth-OYF5A4BY.js} +4 -2
- package/dist/{chunk-26U3DGUM.js → chunk-7YJTQCPX.js} +3 -5
- package/dist/chunk-7YJTQCPX.js.map +1 -0
- package/dist/{chunk-PXFDH6YL.js → chunk-A4ISG3VX.js} +55 -15
- package/dist/{chunk-PXFDH6YL.js.map → chunk-A4ISG3VX.js.map} +1 -1
- package/dist/{chunk-4NRDONSC.js → chunk-FGB6PS2T.js} +4 -4
- package/dist/chunk-FGB6PS2T.js.map +1 -0
- package/dist/{chunk-VKBTI5EF.js → chunk-GFP4UEUT.js} +3 -3
- package/dist/{chunk-IWKJQZJQ.js → chunk-GZVCNYR4.js} +55 -55
- package/dist/chunk-GZVCNYR4.js.map +1 -0
- package/dist/{chunk-G5SXUXSU.js → chunk-H7ZML5QL.js} +2 -2
- package/dist/{chunk-HKQ5XQAQ.js → chunk-HGPZ2QWV.js} +4 -4
- package/dist/{chunk-CJEKEW7R.js → chunk-IHCPMYKU.js} +3 -3
- package/dist/{chunk-UZ2ZA5A6.js → chunk-JZWJFG4M.js} +2 -2
- package/dist/{chunk-5R4HMSNX.js → chunk-MO5G5TP5.js} +17141 -16812
- package/dist/chunk-MO5G5TP5.js.map +1 -0
- package/dist/{chunk-CFJXYPTF.js → chunk-PVWG3V62.js} +13 -5
- package/dist/chunk-PVWG3V62.js.map +1 -0
- package/dist/{chunk-3CZU7XCS.js → chunk-PWZ4ULCB.js} +20 -14
- package/dist/chunk-PWZ4ULCB.js.map +1 -0
- package/dist/{chunk-ZXRVFFCY.js → chunk-VHVOTGBQ.js} +3 -3
- package/dist/{chunk-IGHDIWZU.js → chunk-VYTIJ6HJ.js} +17 -2
- package/dist/{chunk-IGHDIWZU.js.map → chunk-VYTIJ6HJ.js.map} +1 -1
- package/dist/{credential-JGVSEGVH.js → credential-WOATCWOU.js} +5 -5
- package/dist/{credential-template-CWWMOKB2.js → credential-template-Q3DQE2AH.js} +5 -5
- package/dist/{debug-workflow-BXRU72YZ.js → debug-workflow-ZNP5XZQF.js} +7 -7
- package/dist/{src-CV57ZD6I.js → dist-WW2S733L.js} +7 -9
- package/dist/{docs-PVBXPTGR.js → docs-XVU4LA7G.js} +5 -5
- package/dist/{doctor-RHMKD4W5.js → doctor-PGNHD3TI.js} +3 -3
- package/dist/{environment-WZKIO3R3.js → environment-MRDNWU47.js} +5 -5
- package/dist/{feature-flag-K5REGGDY.js → feature-flag-D3DQZ6DX.js} +11 -10
- package/dist/feature-flag-D3DQZ6DX.js.map +1 -0
- package/dist/index.js +144 -56
- package/dist/index.js.map +1 -1
- package/dist/{init-FFUZO5D7.js → init-DHWKUYIR.js} +10 -10
- package/dist/{install-XRKEQAFZ.js → install-DMEFGQHD.js} +5 -5
- package/dist/{issues-I3V6GEXU.js → issues-E4YQ4DVC.js} +5 -5
- package/dist/{knobs-6WLJMB44.js → knobs-NA6SPLHX.js} +5 -5
- package/dist/{list-PHC7VYNS.js → list-GJNGFQMC.js} +5 -5
- package/dist/{local-VGYRSW22.js → local-NSKOZHHA.js} +6 -6
- package/dist/{login-QPU2BKG2.js → login-AMSRVPXG.js} +10 -10
- package/dist/{mcp-LA452TOA.js → mcp-V4GKEL2J.js} +7 -8
- package/dist/{mcp-LA452TOA.js.map → mcp-V4GKEL2J.js.map} +1 -1
- package/dist/metrics-DM4YQQZN.js +367 -0
- package/dist/metrics-DM4YQQZN.js.map +1 -0
- package/dist/{product-RSZV5HMB.js → product-WGOLTBRI.js} +6 -5
- package/dist/product-WGOLTBRI.js.map +1 -0
- package/dist/{property-YP4GHQAR.js → property-B7QMGLVW.js} +5 -5
- package/dist/{psql-XGLBI6T7.js → psql-4JHPJ2CO.js} +3 -3
- package/dist/{record-KWKHP2ZY.js → record-LDNKS42Y.js} +6 -6
- package/dist/{record-KWKHP2ZY.js.map → record-LDNKS42Y.js.map} +1 -1
- package/dist/{redis-VJGCUJPV.js → redis-N44ZZ6VB.js} +3 -3
- package/dist/{release-NDRHPW6V.js → release-R7GKLEAI.js} +5 -5
- package/dist/{sandbox-OOCANWOG.js → sandbox-PLYUNOFX.js} +6 -6
- package/dist/{scenarios-2HRLCGFY.js → scenarios-WUUUKP2S.js} +5 -5
- package/dist/{session-M4ULYDYP.js → session-Y6RO7GFC.js} +15 -17
- package/dist/{session-M4ULYDYP.js.map → session-Y6RO7GFC.js.map} +1 -1
- package/dist/{skill-4DGPRDUC.js → skill-3SP7MAA4.js} +176 -15
- package/dist/skill-3SP7MAA4.js.map +1 -0
- package/dist/{spec-XZ2TKUFZ.js → spec-ESPA3H26.js} +5 -5
- package/dist/{src-HL7HEJIW.js → src-ECFPDE5X.js} +18 -2
- package/dist/src-ECFPDE5X.js.map +1 -0
- package/dist/{src-7LAXXTVG.js → src-OWPS5DCK.js} +63 -27
- package/dist/{src-7LAXXTVG.js.map → src-OWPS5DCK.js.map} +1 -1
- package/dist/{src-OU7544PM.js → src-PDYXACRP.js} +2 -2
- package/dist/{start-IYKF3C3X.js → start-KDDRLUFN.js} +8 -8
- package/dist/{tag-T45MMSCH.js → tag-DAGHQZAR.js} +6 -6
- package/dist/{task-MCUHAVTD.js → task-PRR75HI4.js} +5 -5
- package/dist/{test-suite-BICBRSBP.js → test-suite-O3UY7EER.js} +7 -7
- package/dist/{trace-2BAPMYAS.js → trace-BCSP7PCX.js} +5 -6
- package/dist/{triage-M3RZ2ASB.js → triage-2BKUBMMX.js} +6 -6
- package/dist/utilities-O3OO64T5.js +441 -0
- package/dist/utilities-O3OO64T5.js.map +1 -0
- package/dist/{workflow-ZGJU4QCV.js → workflow-76EKT3DS.js} +16 -21
- package/dist/workflow-76EKT3DS.js.map +1 -0
- package/dist/{workflow-cache-M4N325UT.js → workflow-cache-UDTTNIHT.js} +8 -8
- package/dist/{workflow-cache-M4N325UT.js.map → workflow-cache-UDTTNIHT.js.map} +1 -1
- package/dist/{workflow-debug-W4USZH35.js → workflow-debug-WO7D32EI.js} +8 -9
- package/dist/{workflow-debug-W4USZH35.js.map → workflow-debug-WO7D32EI.js.map} +1 -1
- package/dist/{workflow-proposals-5E3DTYZB.js → workflow-proposals-PGURJ6ZI.js} +7 -7
- package/package.json +3 -3
- package/dist/account-62I7FG5G.js.map +0 -1
- package/dist/chunk-26U3DGUM.js.map +0 -1
- package/dist/chunk-3CZU7XCS.js.map +0 -1
- package/dist/chunk-4NRDONSC.js.map +0 -1
- package/dist/chunk-5R4HMSNX.js.map +0 -1
- package/dist/chunk-CFJXYPTF.js.map +0 -1
- package/dist/chunk-IWKJQZJQ.js.map +0 -1
- package/dist/chunk-KRWRUU6R.js +0 -114
- package/dist/chunk-KRWRUU6R.js.map +0 -1
- package/dist/feature-flag-K5REGGDY.js.map +0 -1
- package/dist/pdf-extract-YHE54XU4.js +0 -13
- package/dist/product-RSZV5HMB.js.map +0 -1
- package/dist/skill-4DGPRDUC.js.map +0 -1
- package/dist/src-HL7HEJIW.js.map +0 -1
- package/dist/triage-M3RZ2ASB.js.map +0 -1
- package/dist/workflow-ZGJU4QCV.js.map +0 -1
- /package/dist/{api-catalog-CAJUASVC.js.map → api-catalog-MMPFWS52.js.map} +0 -0
- /package/dist/{attachment-RL4AZUJE.js.map → attachment-NSYL5X3S.js.map} +0 -0
- /package/dist/{augmentor-GAF3MFY6.js.map → augmentor-LSJLMJYP.js.map} +0 -0
- /package/dist/{auth-DURHUZDW.js.map → auth-OYF5A4BY.js.map} +0 -0
- /package/dist/{chunk-VKBTI5EF.js.map → chunk-GFP4UEUT.js.map} +0 -0
- /package/dist/{chunk-G5SXUXSU.js.map → chunk-H7ZML5QL.js.map} +0 -0
- /package/dist/{chunk-HKQ5XQAQ.js.map → chunk-HGPZ2QWV.js.map} +0 -0
- /package/dist/{chunk-CJEKEW7R.js.map → chunk-IHCPMYKU.js.map} +0 -0
- /package/dist/{chunk-UZ2ZA5A6.js.map → chunk-JZWJFG4M.js.map} +0 -0
- /package/dist/{chunk-ZXRVFFCY.js.map → chunk-VHVOTGBQ.js.map} +0 -0
- /package/dist/{credential-JGVSEGVH.js.map → credential-WOATCWOU.js.map} +0 -0
- /package/dist/{credential-template-CWWMOKB2.js.map → credential-template-Q3DQE2AH.js.map} +0 -0
- /package/dist/{debug-workflow-BXRU72YZ.js.map → debug-workflow-ZNP5XZQF.js.map} +0 -0
- /package/dist/{pdf-extract-YHE54XU4.js.map → dist-WW2S733L.js.map} +0 -0
- /package/dist/{docs-PVBXPTGR.js.map → docs-XVU4LA7G.js.map} +0 -0
- /package/dist/{doctor-RHMKD4W5.js.map → doctor-PGNHD3TI.js.map} +0 -0
- /package/dist/{environment-WZKIO3R3.js.map → environment-MRDNWU47.js.map} +0 -0
- /package/dist/{init-FFUZO5D7.js.map → init-DHWKUYIR.js.map} +0 -0
- /package/dist/{install-XRKEQAFZ.js.map → install-DMEFGQHD.js.map} +0 -0
- /package/dist/{issues-I3V6GEXU.js.map → issues-E4YQ4DVC.js.map} +0 -0
- /package/dist/{knobs-6WLJMB44.js.map → knobs-NA6SPLHX.js.map} +0 -0
- /package/dist/{list-PHC7VYNS.js.map → list-GJNGFQMC.js.map} +0 -0
- /package/dist/{local-VGYRSW22.js.map → local-NSKOZHHA.js.map} +0 -0
- /package/dist/{login-QPU2BKG2.js.map → login-AMSRVPXG.js.map} +0 -0
- /package/dist/{property-YP4GHQAR.js.map → property-B7QMGLVW.js.map} +0 -0
- /package/dist/{psql-XGLBI6T7.js.map → psql-4JHPJ2CO.js.map} +0 -0
- /package/dist/{redis-VJGCUJPV.js.map → redis-N44ZZ6VB.js.map} +0 -0
- /package/dist/{release-NDRHPW6V.js.map → release-R7GKLEAI.js.map} +0 -0
- /package/dist/{sandbox-OOCANWOG.js.map → sandbox-PLYUNOFX.js.map} +0 -0
- /package/dist/{scenarios-2HRLCGFY.js.map → scenarios-WUUUKP2S.js.map} +0 -0
- /package/dist/{spec-XZ2TKUFZ.js.map → spec-ESPA3H26.js.map} +0 -0
- /package/dist/{src-CV57ZD6I.js.map → src-PDYXACRP.js.map} +0 -0
- /package/dist/{start-IYKF3C3X.js.map → start-KDDRLUFN.js.map} +0 -0
- /package/dist/{src-OU7544PM.js.map → tag-DAGHQZAR.js.map} +0 -0
- /package/dist/{task-MCUHAVTD.js.map → task-PRR75HI4.js.map} +0 -0
- /package/dist/{test-suite-BICBRSBP.js.map → test-suite-O3UY7EER.js.map} +0 -0
- /package/dist/{tag-T45MMSCH.js.map → trace-BCSP7PCX.js.map} +0 -0
- /package/dist/{trace-2BAPMYAS.js.map → triage-2BKUBMMX.js.map} +0 -0
- /package/dist/{workflow-proposals-5E3DTYZB.js.map → workflow-proposals-PGURJ6ZI.js.map} +0 -0
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
apiFetch,
|
|
4
4
|
exitOnFailure,
|
|
5
5
|
isTerminalFailure
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PWZ4ULCB.js";
|
|
7
7
|
import {
|
|
8
8
|
getArgValue
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VYTIJ6HJ.js";
|
|
10
10
|
import {
|
|
11
11
|
getCanaryTmpDir
|
|
12
12
|
} from "./chunk-JWHYXEA2.js";
|
|
13
13
|
import {
|
|
14
14
|
VALID_MACRO_NAMES
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-GZVCNYR4.js";
|
|
16
16
|
|
|
17
17
|
// src/cli-helpers.ts
|
|
18
18
|
import fs from "fs/promises";
|
|
@@ -27,6 +27,8 @@ function toLifecycleLabel(stage) {
|
|
|
27
27
|
switch (stage) {
|
|
28
28
|
case "baking":
|
|
29
29
|
return "baking";
|
|
30
|
+
case "internal":
|
|
31
|
+
return "internal";
|
|
30
32
|
case "deprecated":
|
|
31
33
|
return "deprecated";
|
|
32
34
|
case "ready_for_cleanup":
|
|
@@ -35,7 +37,13 @@ function toLifecycleLabel(stage) {
|
|
|
35
37
|
return "active";
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
|
-
function parseLifecycleStage(argv, allowedStages = [
|
|
40
|
+
function parseLifecycleStage(argv, allowedStages = [
|
|
41
|
+
"active",
|
|
42
|
+
"baking",
|
|
43
|
+
"internal",
|
|
44
|
+
"deprecated",
|
|
45
|
+
"ready_for_cleanup"
|
|
46
|
+
]) {
|
|
39
47
|
const stage = getArgValue(argv, "--stage");
|
|
40
48
|
if (!stage || !allowedStages.includes(stage)) {
|
|
41
49
|
console.error(`Error: --stage is required and must be one of: ${allowedStages.join(", ")}`);
|
|
@@ -356,4 +364,4 @@ export {
|
|
|
356
364
|
uploadStorageState,
|
|
357
365
|
fetchList
|
|
358
366
|
};
|
|
359
|
-
//# sourceMappingURL=chunk-
|
|
367
|
+
//# sourceMappingURL=chunk-PVWG3V62.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-helpers.ts"],"sourcesContent":["/**\n * Shared CLI helpers for superadmin management commands (knobs, feature-flags).\n */\n\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { getCanaryTmpDir } from '@chatsdet/tmp';\nimport { VALID_MACRO_NAMES } from '@chatsdet/types';\nimport { getArgValue } from './auth.js';\nimport { apiFetch, exitOnFailure, isTerminalFailure } from './api-fetch.js';\n\nexport type LifecycleStage =\n | 'active'\n | 'baking'\n | 'internal'\n | 'deprecated'\n | 'ready_for_cleanup';\n\n/** Stages knobs may use — `baking` (the oven) and `internal` are flag-only. */\nexport const KNOB_LIFECYCLE_STAGES: LifecycleStage[] = [\n 'active',\n 'deprecated',\n 'ready_for_cleanup',\n];\n\nexport function toLifecycleLabel(stage: LifecycleStage): string {\n switch (stage) {\n case 'baking':\n return 'baking';\n case 'internal':\n return 'internal';\n case 'deprecated':\n return 'deprecated';\n case 'ready_for_cleanup':\n return 'ready_for_cleanup';\n default:\n return 'active';\n }\n}\n\nexport function parseLifecycleStage(\n argv: string[],\n allowedStages: LifecycleStage[] = [\n 'active',\n 'baking',\n 'internal',\n 'deprecated',\n 'ready_for_cleanup',\n ]\n): LifecycleStage {\n const stage = getArgValue(argv, '--stage');\n if (!stage || !allowedStages.includes(stage as LifecycleStage)) {\n console.error(`Error: --stage is required and must be one of: ${allowedStages.join(', ')}`);\n process.exit(1);\n }\n return stage as LifecycleStage;\n}\n\nexport async function apiRequest<T extends { ok: boolean; error?: string }>(\n apiUrl: string,\n token: string,\n method: string,\n path: string,\n body?: Record<string, unknown>,\n options?: { timeoutMs?: number }\n): Promise<T> {\n const result = await apiFetch(`${apiUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n token,\n ...(options?.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),\n ...(body ? { body: JSON.stringify(body) } : {}),\n });\n\n if (!result.ok) {\n const { failure } = result;\n // Terminal kinds (auth/proxy/TLS) surface the full diagnostic and exit;\n // http-error falls through so the caller can pretty-print structured\n // user errors (unresolved vars, invalid macros, etc.).\n if (isTerminalFailure(failure)) exitOnFailure(failure);\n const text = failure.body ?? '';\n let errorMessage = failure.message;\n let parsed: Record<string, unknown> | null = null;\n try {\n const data = JSON.parse(text);\n if (data && typeof data === 'object') {\n parsed = data as Record<string, unknown>;\n if (typeof parsed.error === 'string') errorMessage = parsed.error;\n }\n } catch {\n /* keep failure.message */\n }\n return { ...parsed, ok: false, error: errorMessage } as T;\n }\n\n try {\n return (await result.response.json()) as T;\n } catch {\n return { ok: false, error: `Invalid JSON response (${result.response.status})` } as T;\n }\n}\n\ntype UnresolvedRef = {\n nodeId?: string;\n nodeType?: string;\n field?: string;\n variable: string;\n};\n\n/**\n * Render a structured `userError` response from the workflow API into a\n * multi-line, actionable message. Recognizes `WORKFLOW_UNRESOLVED_VARIABLES`\n * and falls back to `✖ {code}: {message}` for other codes. Returns `null` if\n * the response body isn't a recognized structured error.\n */\nexport function renderWorkflowUserError(result: Record<string, unknown>): string | null {\n const code = typeof result.code === 'string' ? result.code : null;\n const message = typeof result.error === 'string' ? result.error : null;\n if (!code) return null;\n\n if (code === 'WORKFLOW_VALIDATION_FAILED') {\n type ValidationIssue = {\n nodeId?: string | null;\n nodeType?: string | null;\n field?: string;\n message?: string;\n severity?: 'error' | 'warning';\n };\n const issues = Array.isArray(result.issues) ? (result.issues as ValidationIssue[]) : [];\n const errors = issues.filter((i) => (i.severity ?? 'error') === 'error');\n const warnings = issues.filter((i) => i.severity === 'warning');\n\n const lines: string[] = [\n `✖ Validation failed (${errors.length} error${errors.length === 1 ? '' : 's'}` +\n (warnings.length > 0\n ? `, ${warnings.length} warning${warnings.length === 1 ? '' : 's'}`\n : '') +\n ')',\n ];\n if (message) lines.push(` ${message}`);\n\n // Group by nodeId (null = flow-level).\n const byNode = new Map<string, ValidationIssue[]>();\n for (const issue of issues) {\n const key = issue.nodeId ?? '__flow__';\n const arr = byNode.get(key) ?? [];\n arr.push(issue);\n byNode.set(key, arr);\n }\n for (const [nodeKey, nodeIssues] of byNode) {\n const heading =\n nodeKey === '__flow__'\n ? 'Flow'\n : `Node ${nodeKey}${nodeIssues[0]?.nodeType ? ` (${nodeIssues[0].nodeType})` : ''}`;\n lines.push(` ${heading}:`);\n for (const issue of nodeIssues) {\n const sev = issue.severity === 'warning' ? '⚠' : '•';\n const field = issue.field ? `${issue.field} — ` : '';\n lines.push(` ${sev} ${field}${issue.message ?? ''}`);\n }\n }\n return lines.join('\\n');\n }\n\n if (code === 'WORKFLOW_UNRESOLVED_VARIABLES') {\n const lines: string[] = [`✖ ${code}`];\n if (message) lines.push(` ${message}`);\n const refs = Array.isArray(result.refs) ? (result.refs as UnresolvedRef[]) : [];\n const variables = Array.isArray(result.variables)\n ? (result.variables as string[])\n : refs.map((r) => r.variable);\n\n if (refs.length > 0) {\n lines.push(' Unresolved references:');\n for (const ref of refs) {\n const loc = ref.field && ref.nodeId ? ` (node ${ref.nodeId}, ${ref.field})` : '';\n lines.push(` • $var.${ref.variable}${loc}`);\n }\n } else if (variables.length > 0) {\n lines.push(' Unresolved:');\n for (const v of variables) lines.push(` • $var.${v}`);\n }\n\n const macroHints = variables.filter((v) => VALID_MACRO_NAMES.has(v.toUpperCase()));\n if (macroHints.length > 0) {\n lines.push(' Hint: these look like macro names, not variables:');\n for (const v of macroHints) {\n lines.push(` $var.${v} → $${v.toUpperCase()}()`);\n }\n }\n return lines.join('\\n');\n }\n\n if (code === 'WORKFLOW_INVALID_INPUT_VALUES') {\n const lines: string[] = [`✖ ${code}`];\n if (message) lines.push(` ${message}`);\n const issues = Array.isArray(result.issues)\n ? (result.issues as Array<{\n key?: string;\n value?: string;\n reason?: string;\n variables?: string[];\n }>)\n : [];\n for (const issue of issues) {\n const key = issue.key ?? '?';\n const value = issue.value ?? '';\n if (issue.reason === 'self_referential') {\n lines.push(` • ${key}: self-referential → ${value}`);\n lines.push(` Use a literal or point at a different upstream variable.`);\n } else if (issue.reason === 'macro_name_used_as_var') {\n lines.push(` • ${key}: macro name used as $var → ${value}`);\n for (const v of issue.variables ?? []) {\n lines.push(` $var.${v} → $${v.toUpperCase()}()`);\n }\n } else {\n lines.push(` • ${key}: ${issue.reason ?? 'invalid'} → ${value}`);\n }\n }\n return lines.join('\\n');\n }\n\n if (code === 'WORKFLOW_INVALID_MACRO') {\n const lines: string[] = [`✖ ${code}`];\n if (message) lines.push(` ${message}`);\n const invalid = Array.isArray(result.invalid) ? (result.invalid as string[]) : [];\n const valid = Array.isArray(result.valid) ? (result.valid as string[]) : [];\n if (invalid.length > 0) {\n lines.push(` Invalid macro(s): ${invalid.map((n) => `$${n}()`).join(', ')}`);\n }\n if (valid.length > 0) {\n lines.push(` Valid macros: ${valid.map((n) => `$${n}()`).join(', ')}`);\n }\n return lines.join('\\n');\n }\n\n return `✖ ${code}${message ? `: ${message}` : ''}`;\n}\n\nexport async function downloadStorageState(opts: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n prefix?: string;\n}): Promise<string | undefined> {\n const tmpFile = path.join(getCanaryTmpDir(), `${opts.prefix ?? 'canary-ss'}-${Date.now()}.json`);\n try {\n const res = await fetch(\n `${opts.apiUrl}/org/properties/${opts.propertyId}/credentials/${opts.credentialId}/storage-state/download`,\n {\n headers: { Authorization: `Bearer ${opts.token}` },\n redirect: 'follow',\n }\n );\n if (res.ok) {\n const body = await res.text();\n await fs.writeFile(tmpFile, body, 'utf-8');\n return tmpFile;\n }\n } catch {\n // Caller handles missing storage state\n }\n return undefined;\n}\n\n/* ── Credential selection ─────────────────────────────────────────────── */\n\nexport interface CredentialListItem {\n id: string;\n name: string;\n propertyId: string;\n propertyName?: string;\n propertyBaseUrl?: string;\n environmentId?: string | null;\n environmentName?: string | null;\n storageStateS3Key?: string | null;\n isDefault?: boolean;\n isEphemeral?: boolean;\n}\n\n/**\n * Fetch org credentials and let the user pick one interactively.\n *\n * @param credentialArg - Credential name or ID to auto-select, or undefined for interactive\n * @returns The selected credential, or null if none found / invalid selection\n */\nexport async function selectCredential(\n apiUrl: string,\n token: string,\n credentialArg?: string\n): Promise<CredentialListItem | null> {\n const credentials = await fetchList<CredentialListItem>(\n apiUrl,\n token,\n '/org/credentials',\n 'items'\n );\n\n if (credentials.length === 0) {\n console.error('No credentials found. Create one first in the web app.');\n return null;\n }\n\n if (credentialArg) {\n const match = credentials.find(\n (c) => c.id === credentialArg || c.name.toLowerCase() === credentialArg.toLowerCase()\n );\n if (!match) {\n console.error(`Credential \"${credentialArg}\" not found.`);\n console.error('Available credentials:');\n for (const c of credentials) {\n const env = c.environmentName ? ` — ${c.environmentName}` : '';\n const baseUrl = c.propertyBaseUrl ? ` — ${c.propertyBaseUrl}` : '';\n console.error(` - ${c.name} [${c.propertyName ?? c.propertyId}${env}${baseUrl}]`);\n }\n return null;\n }\n return match;\n }\n\n // Interactive selection\n console.log('\\nSelect a credential:\\n');\n const labels = credentials.map((c) => {\n const property = c.propertyName ?? c.propertyId;\n const env = c.environmentName ? ` — ${c.environmentName}` : '';\n const baseUrl = c.propertyBaseUrl ? ` — ${c.propertyBaseUrl}` : '';\n return `${c.name} [${property}${env}${baseUrl}]`;\n });\n\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n for (let i = 0; i < labels.length; i++) {\n console.log(` ${i + 1}. ${labels[i]}`);\n }\n rl.question('\\nEnter number: ', (ans) => {\n rl.close();\n resolve(ans.trim());\n });\n });\n\n const idx = parseInt(answer, 10) - 1;\n if (isNaN(idx) || idx < 0 || idx >= credentials.length) {\n console.error('Invalid selection.');\n return null;\n }\n\n return credentials[idx];\n}\n\n/* ── Property selection ──────────────────────────────────────────────── */\n\ninterface PropertyListItem {\n id: string;\n name: string;\n baseUrl: string;\n}\n\nexport async function fetchProperties(apiUrl: string, token: string): Promise<PropertyListItem[]> {\n return fetchList<PropertyListItem>(apiUrl, token, '/org/properties', 'items');\n}\n\n/**\n * Read the application/property selector flag. `--application` is the user-facing\n * name; `--property` is kept as a backwards-compat alias (read second). Internally\n * this is still a \"property\" — the rename is cosmetic.\n */\nexport function getApplicationArg(argv: string[]): string | undefined {\n return getArgValue(argv, '--application') ?? getArgValue(argv, '--property');\n}\n\n/**\n * Read the application/property UUID flag. `--application-id` is the user-facing\n * name; `--property-id` is kept as a backwards-compat alias.\n */\nexport function getApplicationIdArg(argv: string[]): string | undefined {\n return getArgValue(argv, '--application-id') ?? getArgValue(argv, '--property-id');\n}\n\nexport async function selectProperty(\n apiUrl: string,\n token: string,\n hint?: string\n): Promise<PropertyListItem | null> {\n const properties = await fetchProperties(apiUrl, token);\n\n if (properties.length === 0) {\n console.error('No applications found. Create one first in the web app.');\n return null;\n }\n\n if (hint) {\n const match = properties.find(\n (p) => p.id === hint || p.name.toLowerCase() === hint.toLowerCase()\n );\n if (!match) {\n console.error(`Application \"${hint}\" not found.`);\n console.error('Available applications:');\n for (const p of properties) {\n console.error(` - ${p.name} (${p.baseUrl})`);\n }\n return null;\n }\n return match;\n }\n\n if (properties.length === 1) {\n console.log(`Auto-selected application: ${properties[0].name}`);\n return properties[0];\n }\n\n return promptChoice(\n 'Select an application:',\n properties.map((p) => ({ label: `${p.name} — ${p.baseUrl}`, value: p }))\n );\n}\n\n/* ── Interactive prompt helpers ──────────────────────────────────────── */\n\nexport async function promptInput(question: string, defaultValue?: string): Promise<string> {\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;\n const answer = await new Promise<string>((resolve) => {\n rl.question(prompt, (ans) => {\n rl.close();\n resolve(ans.trim());\n });\n });\n return answer || defaultValue || '';\n}\n\nexport async function promptChoice<T>(\n question: string,\n options: Array<{ label: string; value: T }>\n): Promise<T | null> {\n console.log(`\\n${question}\\n`);\n for (let i = 0; i < options.length; i++) {\n console.log(` ${i + 1}. ${options[i].label}`);\n }\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n rl.question('\\nEnter number: ', (ans) => {\n rl.close();\n resolve(ans.trim());\n });\n });\n\n const idx = parseInt(answer, 10) - 1;\n if (isNaN(idx) || idx < 0 || idx >= options.length) {\n console.error('Invalid selection.');\n return null;\n }\n return options[idx].value;\n}\n\nexport async function uploadStorageState(opts: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n storageState: unknown;\n}): Promise<{ ok: boolean; s3Key?: string; error?: string }> {\n const result = await apiFetch(\n `${opts.apiUrl}/org/properties/${opts.propertyId}/credentials/${opts.credentialId}/storage-state/upload`,\n {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${opts.token}`,\n 'Content-Type': 'application/json',\n },\n token: opts.token,\n body: JSON.stringify({ storageState: opts.storageState }),\n }\n );\n\n if (!result.ok) exitOnFailure(result.failure);\n\n return (await result.response.json()) as { ok: boolean; s3Key?: string; error?: string };\n}\n\nexport async function fetchList<T>(\n apiUrl: string,\n token: string,\n path: string,\n listKey: string\n): Promise<T[]> {\n const result = await apiFetch(`${apiUrl}${path}`, {\n headers: { Authorization: `Bearer ${token}` },\n token,\n });\n\n if (!result.ok) exitOnFailure(result.failure);\n\n const json = (await result.response.json()) as Record<string, unknown>;\n\n if (!json.ok) {\n console.error(`Error: ${json.error}`);\n process.exit(1);\n }\n\n return (json[listKey] as T[]) ?? [];\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -23,7 +23,21 @@ function isSuperadminToken(token) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// src/api-fetch.ts
|
|
26
|
+
import process2 from "process";
|
|
27
|
+
|
|
28
|
+
// src/debug.ts
|
|
26
29
|
import process from "process";
|
|
30
|
+
function isDebug() {
|
|
31
|
+
return process.env.CANARY_DEBUG === "1" || process.env.CANARY_DEBUG === "true" || process.argv.includes("--debug");
|
|
32
|
+
}
|
|
33
|
+
function debug(line) {
|
|
34
|
+
if (isDebug()) {
|
|
35
|
+
process.stderr.write(`[canary-debug] ${line}
|
|
36
|
+
`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/api-fetch.ts
|
|
27
41
|
var CANARY_REQUEST_ID_HEADER = "x-canary-request-id";
|
|
28
42
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
29
43
|
var JWT_EXP_SKEW_SEC = 60;
|
|
@@ -34,15 +48,6 @@ function redactUrl(url) {
|
|
|
34
48
|
const q = url.indexOf("?");
|
|
35
49
|
return q === -1 ? url : `${url.slice(0, q)}?[redacted]`;
|
|
36
50
|
}
|
|
37
|
-
function isDebug() {
|
|
38
|
-
return process.env.CANARY_DEBUG === "1" || process.env.CANARY_DEBUG === "true" || process.argv.includes("--debug");
|
|
39
|
-
}
|
|
40
|
-
function debug(line) {
|
|
41
|
-
if (isDebug()) {
|
|
42
|
-
process.stderr.write(`[canary-debug] ${line}
|
|
43
|
-
`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
51
|
var TLS_CODES = /* @__PURE__ */ new Set([
|
|
47
52
|
"UNABLE_TO_VERIFY_LEAF_SIGNATURE",
|
|
48
53
|
"UNABLE_TO_GET_ISSUER_CERT",
|
|
@@ -85,7 +90,7 @@ function maybeWarnPlaintextAuth(url, hasAuthHeader2) {
|
|
|
85
90
|
return;
|
|
86
91
|
}
|
|
87
92
|
warnedAboutPlaintext = true;
|
|
88
|
-
|
|
93
|
+
process2.stderr.write(
|
|
89
94
|
`[canary] WARNING: sending Authorization over plaintext http:// (${url}). Your API token may be exposed to the network. Use https:// in CANARY_API_URL.
|
|
90
95
|
`
|
|
91
96
|
);
|
|
@@ -243,13 +248,13 @@ function isTerminalFailure(failure) {
|
|
|
243
248
|
return failure.kind !== "http-error";
|
|
244
249
|
}
|
|
245
250
|
function exitOnFailure(failure) {
|
|
246
|
-
|
|
251
|
+
process2.stderr.write(`Error: ${failure.message}
|
|
247
252
|
`);
|
|
248
253
|
if (isDebug() && failure.body && failure.kind !== "html-body") {
|
|
249
|
-
|
|
254
|
+
process2.stderr.write(`[canary-debug] body: ${failure.body}
|
|
250
255
|
`);
|
|
251
256
|
}
|
|
252
|
-
|
|
257
|
+
process2.exit(1);
|
|
253
258
|
}
|
|
254
259
|
async function fetchOrExit(url, init = {}) {
|
|
255
260
|
const result = await apiFetch(url, init);
|
|
@@ -262,6 +267,7 @@ async function fetchOrExit(url, init = {}) {
|
|
|
262
267
|
}
|
|
263
268
|
|
|
264
269
|
export {
|
|
270
|
+
debug,
|
|
265
271
|
decodeJwtPayload,
|
|
266
272
|
isSuperadminToken,
|
|
267
273
|
apiFetch,
|
|
@@ -269,4 +275,4 @@ export {
|
|
|
269
275
|
exitOnFailure,
|
|
270
276
|
fetchOrExit
|
|
271
277
|
};
|
|
272
|
-
//# sourceMappingURL=chunk-
|
|
278
|
+
//# sourceMappingURL=chunk-PWZ4ULCB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/jwt.ts","../src/api-fetch.ts","../src/debug.ts"],"sourcesContent":["/**\n * JWT payload decoder for CLI superadmin detection.\n *\n * Decodes the payload section of a JWT locally (no signature verification,\n * no network calls). Used to conditionally show superadmin CLI commands.\n *\n * @module\n */\n\n/**\n * Decode the payload (second segment) of a JWT without verifying the signature.\n * Returns the parsed JSON object, or `null` if the token is malformed.\n */\nexport function decodeJwtPayload(token: string): Record<string, unknown> | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) return null;\n\n const base64 = parts[1]!.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const json = Buffer.from(base64, \"base64\").toString(\"utf8\");\n const payload: unknown = JSON.parse(json);\n\n if (typeof payload !== \"object\" || payload === null || Array.isArray(payload)) {\n return null;\n }\n return payload as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n/**\n * Returns `true` when the JWT's `is_superadmin` claim is exactly `true`.\n * Returns `false` for any invalid, missing, or non-superadmin token.\n */\nexport function isSuperadminToken(token: string | null | undefined): boolean {\n if (!token) return false;\n const payload = decodeJwtPayload(token);\n return payload?.is_superadmin === true;\n}\n","/**\n * Central fetch wrapper for the Canary CLI.\n *\n * Exists to classify failures so corporate-proxy interference (Zscaler,\n * Netskope, Cloudflare Access, etc.) is distinguishable from real auth\n * expiry. Every non-2xx or transport error gets a specific, actionable\n * message instead of the historical blanket \"session may have expired.\"\n *\n * Set CANARY_DEBUG=1 (or pass --debug to the CLI) to log every request\n * and its classification — this is what affected users should share\n * with us or their IT/Zscaler admin.\n */\n\nimport process from 'node:process';\nimport { debug, isDebug } from './debug.js';\nimport { decodeJwtPayload } from './jwt.js';\n\n/** Header every canary API response carries. Absence => response did not come from our API. */\nconst CANARY_REQUEST_ID_HEADER = 'x-canary-request-id';\n\n/** Default per-request timeout. Zscaler-half-opened sockets have been observed\n * hanging indefinitely; the CLI should give up and classify rather than hang. */\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Treat a JWT exp within this grace window as still valid — tolerates the\n * typical handful of seconds of client-clock skew so we don't mislabel a\n * 30-second-fast clock as `token-revoked`. */\nconst JWT_EXP_SKEW_SEC = 60;\n\n/**\n * Best-effort scrub of `Bearer <token>` and bare three-segment JWTs from\n * error text before we print it. Doctor output is explicitly coached to be\n * shared with IT — if a proxy block page reflects the Authorization header,\n * we do not want the token in that paste.\n */\nfunction redactSecrets(text: string): string {\n return text\n .replace(/Bearer\\s+[A-Za-z0-9._-]+/gi, 'Bearer [redacted]')\n .replace(/\\beyJ[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{6,}\\b/g, '[redacted-jwt]');\n}\n\n/** Strip query string — query params sometimes carry one-time tokens. */\nfunction redactUrl(url: string): string {\n const q = url.indexOf('?');\n return q === -1 ? url : `${url.slice(0, q)}?[redacted]`;\n}\n\nexport type FailureKind =\n | 'tls'\n | 'network'\n | 'html-body'\n | 'proxy-injected-4xx'\n | 'token-revoked'\n | 'token-expired'\n | 'unauthorized'\n | 'http-error';\n\nexport interface ClassifiedFailure {\n kind: FailureKind;\n status: number | null;\n url: string;\n message: string;\n /**\n * Response body text. Full body for `http-error` (so callers can parse\n * structured error payloads); truncated snippet for proxy/TLS failures\n * where the body is likely an HTML block page.\n */\n body?: string;\n /** Best-effort content-type. */\n contentType?: string;\n /** Raw error object for transport failures. */\n cause?: unknown;\n /**\n * Value of `x-canary-request-id` on the response, if any. Present means\n * the response came from our API (even for `token-revoked` / `token-expired`\n * / `unauthorized`); absent means the response was injected or the request\n * never reached us.\n */\n requestId?: string | null;\n}\n\n/**\n * Node/undici TLS error codes that indicate a MITM proxy (Zscaler et al.)\n * is intercepting HTTPS without the user trusting the proxy's root CA.\n */\nconst TLS_CODES = new Set([\n 'UNABLE_TO_VERIFY_LEAF_SIGNATURE',\n 'UNABLE_TO_GET_ISSUER_CERT',\n 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',\n 'SELF_SIGNED_CERT_IN_CHAIN',\n 'DEPTH_ZERO_SELF_SIGNED_CERT',\n 'CERT_HAS_EXPIRED',\n 'CERT_UNTRUSTED',\n 'ERR_TLS_CERT_ALTNAME_INVALID',\n 'CERT_SIGNATURE_FAILURE',\n]);\n\nfunction extractErrorCode(err: unknown): string | null {\n if (!err || typeof err !== 'object') return null;\n const withCode = err as { code?: unknown; cause?: unknown };\n if (typeof withCode.code === 'string') return withCode.code;\n if (withCode.cause) return extractErrorCode(withCode.cause);\n return null;\n}\n\nfunction looksLikeHtml(body: string, contentType: string | null): boolean {\n if (contentType && contentType.toLowerCase().includes('text/html')) return true;\n const trimmed = body.trimStart();\n return trimmed.startsWith('<!') || trimmed.startsWith('<html') || trimmed.startsWith('<HTML');\n}\n\n/** Decode JWT `exp` and compare to now (with a small skew grace); null if undecodable. */\nfunction jwtExpStatus(token: string | undefined): 'expired' | 'valid' | 'unknown' {\n if (!token) return 'unknown';\n const payload = decodeJwtPayload(token);\n const exp = payload && typeof payload.exp === 'number' ? (payload.exp as number) : null;\n if (exp === null) return 'unknown';\n const nowSec = Math.floor(Date.now() / 1000);\n return exp < nowSec - JWT_EXP_SKEW_SEC ? 'expired' : 'valid';\n}\n\n/** Warn once per process when sending Authorization to a non-local http:// URL. */\nlet warnedAboutPlaintext = false;\nfunction maybeWarnPlaintextAuth(url: string, hasAuthHeader: boolean): void {\n if (!hasAuthHeader || warnedAboutPlaintext) return;\n if (!url.startsWith('http://')) return;\n try {\n const host = new URL(url).hostname;\n if (host === 'localhost' || host === '127.0.0.1' || host === '::1') return;\n } catch {\n return;\n }\n warnedAboutPlaintext = true;\n process.stderr.write(\n `[canary] WARNING: sending Authorization over plaintext http:// (${url}). ` +\n 'Your API token may be exposed to the network. Use https:// in CANARY_API_URL.\\n'\n );\n}\n\nfunction hasAuthHeader(init: RequestInit): boolean {\n const h = init.headers;\n if (!h) return false;\n if (h instanceof Headers) return h.has('authorization');\n if (Array.isArray(h)) return h.some(([k]) => k.toLowerCase() === 'authorization');\n return Object.keys(h).some((k) => k.toLowerCase() === 'authorization');\n}\n\n/**\n * Wrap global `fetch` with classification. Always resolves — never throws —\n * so callers can make a single uniform decision from the returned shape.\n */\nexport async function apiFetch(\n url: string,\n init: RequestInit & { token?: string; timeoutMs?: number } = {}\n): Promise<\n | { ok: true; response: Response; requestId: string | null }\n | { ok: false; failure: ClassifiedFailure }\n> {\n const { token, timeoutMs, ...fetchInit } = init;\n maybeWarnPlaintextAuth(url, hasAuthHeader(fetchInit));\n debug(`→ ${fetchInit.method ?? 'GET'} ${redactUrl(url)}`);\n\n // Merge caller-supplied signal with our timeout so both can abort.\n // timeoutMs <= 0 disables the timeout (use for long-lived SSE streams).\n const timeout = timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const timeoutSignal = timeout > 0 ? AbortSignal.timeout(timeout) : null;\n const effectiveSignal =\n fetchInit.signal && timeoutSignal\n ? AbortSignal.any([fetchInit.signal, timeoutSignal])\n : (fetchInit.signal ?? timeoutSignal ?? undefined);\n\n let response: Response;\n try {\n response = await fetch(url, { ...fetchInit, signal: effectiveSignal });\n } catch (err) {\n const isTimeout =\n (err as { name?: string })?.name === 'TimeoutError' ||\n Boolean(timeoutSignal?.aborted);\n if (isTimeout) {\n const msg = `Request to ${redactUrl(url)} timed out after ${timeout}ms.`;\n debug(`✖ network timeout`);\n return {\n ok: false,\n failure: { kind: 'network', status: null, url, message: msg, cause: err },\n };\n }\n const code = extractErrorCode(err);\n if (code && TLS_CODES.has(code)) {\n const msg = [\n `TLS verification failed talking to ${redactUrl(url)} (${code}).`,\n 'A corporate proxy (Zscaler, Netskope, ZPA, Cloudflare Access) is likely intercepting HTTPS.',\n 'Fixes: point Node at the proxy\\'s root CA with',\n ' NODE_EXTRA_CA_CERTS=/path/to/corporate-root.pem canary …',\n 'or on Node 20+ enable the system trust store with',\n ' NODE_OPTIONS=--use-system-ca canary …',\n ].join('\\n');\n debug(`✖ tls ${code}`);\n return { ok: false, failure: { kind: 'tls', status: null, url, message: msg, cause: err } };\n }\n const msg = `Network error reaching ${redactUrl(url)}: ${String((err as Error).message ?? err)}`;\n debug(`✖ network ${msg}`);\n return { ok: false, failure: { kind: 'network', status: null, url, message: msg, cause: err } };\n }\n\n const requestId = response.headers.get(CANARY_REQUEST_ID_HEADER);\n const contentType = response.headers.get('content-type');\n debug(`← ${response.status} ${redactUrl(url)} (ct=${contentType ?? 'n/a'} rid=${requestId ?? 'none'})`);\n\n if (response.ok) {\n return { ok: true, response, requestId };\n }\n\n // Read body once so we can classify and still return something useful.\n // Scrub secrets before constructing user-facing `snippet`; `bodyText` is\n // kept intact for callers that parse structured JSON error bodies.\n const bodyText = await response.clone().text().catch(() => '');\n const snippet = redactSecrets(bodyText.slice(0, 200));\n\n // HTML on a JSON endpoint => proxy block page or captive portal.\n if (looksLikeHtml(bodyText, contentType)) {\n return {\n ok: false,\n failure: {\n kind: 'html-body',\n status: response.status,\n url,\n contentType: contentType ?? undefined,\n requestId,\n body: snippet,\n message: [\n `Got an HTML response from ${url} (status ${response.status}).`,\n 'A corporate proxy block page or captive portal is intercepting this request — the',\n 'response did not come from the Canary API.',\n 'Check that your proxy (e.g. Zscaler) allowlists the API hostname, and that any',\n 'required sign-in to the proxy itself is current.',\n snippet ? `First bytes: ${snippet.replace(/\\s+/g, ' ')}` : '',\n ]\n .filter(Boolean)\n .join('\\n'),\n },\n };\n }\n\n // 401/403 without our header => not our response.\n if ((response.status === 401 || response.status === 403) && !requestId) {\n return {\n ok: false,\n failure: {\n kind: 'proxy-injected-4xx',\n status: response.status,\n url,\n contentType: contentType ?? undefined,\n requestId,\n body: snippet,\n message: [\n `Got ${response.status} from ${url} but the response is missing the \\`${CANARY_REQUEST_ID_HEADER}\\` header.`,\n 'This response was almost certainly injected by a corporate proxy (Zscaler, Netskope,',\n 'Cloudflare Access) rather than returned by our API — retrying \"canary login\" will not fix it.',\n 'Ask your IT team to allowlist the API host, or re-auth to the proxy and try again.',\n ].join('\\n'),\n },\n };\n }\n\n if (response.status === 401) {\n const jwtStatus = jwtExpStatus(token);\n if (jwtStatus === 'valid') {\n return {\n ok: false,\n failure: {\n kind: 'token-revoked',\n status: 401,\n url,\n requestId,\n body: snippet,\n message: [\n 'Server rejected a token that is still valid locally (unexpired JWT).',\n 'Likely causes: the token was revoked, the server\\'s signing key rotated, or the',\n 'user/org was deactivated. `canary login` will issue a fresh token.',\n ].join('\\n'),\n },\n };\n }\n if (jwtStatus === 'expired') {\n return {\n ok: false,\n failure: {\n kind: 'token-expired',\n status: 401,\n url,\n requestId,\n body: snippet,\n message: 'Your stored token has expired. Run: canary login',\n },\n };\n }\n return {\n ok: false,\n failure: {\n kind: 'unauthorized',\n status: 401,\n url,\n requestId,\n body: snippet,\n message: 'Unauthorized. Run: canary login',\n },\n };\n }\n\n return {\n ok: false,\n failure: {\n kind: 'http-error',\n status: response.status,\n url,\n contentType: contentType ?? undefined,\n requestId,\n body: bodyText,\n message: `${response.status} ${response.statusText}${snippet ? `: ${snippet}` : ''}`,\n },\n };\n}\n\n/**\n * Kinds of failure the user can't recover from by retrying the same call —\n * no token on disk, proxy interception, TLS mismatch, rejected JWT. Callers\n * should `exitOnFailure` immediately for these. `http-error` is excluded\n * because the caller often needs to pretty-print a structured error body.\n */\nexport function isTerminalFailure(failure: ClassifiedFailure): boolean {\n return failure.kind !== 'http-error';\n}\n\n/**\n * Print a classified failure and exit(1). Use from command handlers that\n * have no way to recover — matches the historical behavior of the various\n * `if (res.status === 401) { console.error(...); process.exit(1); }` blocks.\n */\nexport function exitOnFailure(failure: ClassifiedFailure): never {\n process.stderr.write(`Error: ${failure.message}\\n`);\n if (isDebug() && failure.body && failure.kind !== 'html-body') {\n process.stderr.write(`[canary-debug] body: ${failure.body}\\n`);\n }\n process.exit(1);\n}\n\n/**\n * Drop-in for `fetch()` in CLI call sites that parse the body themselves:\n * exits the process for terminal failures (TLS/proxy/unauthorized) so the\n * user sees a diagnostic, and returns a Response otherwise — whether 2xx\n * or an HTTP error (so the caller can still inspect .status / .json()).\n */\nexport async function fetchOrExit(\n url: string,\n init: RequestInit & { token?: string; timeoutMs?: number } = {}\n): Promise<Response> {\n const result = await apiFetch(url, init);\n if (result.ok) return result.response;\n if (isTerminalFailure(result.failure)) exitOnFailure(result.failure);\n // http-error: reconstruct a Response the caller can json() / read status on.\n return new Response(result.failure.body ?? '', {\n status: result.failure.status ?? 500,\n headers: result.failure.contentType\n ? { 'content-type': result.failure.contentType }\n : undefined,\n });\n}\n","import process from 'node:process';\n\n/**\n * Whether verbose CLI diagnostics are enabled. Opt-in only, so normal runs stay\n * quiet — set CANARY_DEBUG=1 (or =true) or pass --debug. Diagnostics always go\n * to stderr so they never pollute stdout-piped (`--json`) output.\n */\nexport function isDebug(): boolean {\n return (\n process.env.CANARY_DEBUG === '1' ||\n process.env.CANARY_DEBUG === 'true' ||\n process.argv.includes('--debug')\n );\n}\n\n/** Write a diagnostic line to stderr, but only when debug mode is enabled. */\nexport function debug(line: string): void {\n if (isDebug()) {\n process.stderr.write(`[canary-debug] ${line}\\n`);\n }\n}\n"],"mappings":";;;AAaO,SAAS,iBAAiB,OAA+C;AAC9E,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,UAAM,SAAS,MAAM,CAAC,EAAG,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AAC7D,UAAM,OAAO,OAAO,KAAK,QAAQ,QAAQ,EAAE,SAAS,MAAM;AAC1D,UAAM,UAAmB,KAAK,MAAM,IAAI;AAExC,QAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,MAAM,QAAQ,OAAO,GAAG;AAC7E,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,kBAAkB,OAA2C;AAC3E,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,iBAAiB,KAAK;AACtC,SAAO,SAAS,kBAAkB;AACpC;;;AC1BA,OAAOA,cAAa;;;ACbpB,OAAO,aAAa;AAOb,SAAS,UAAmB;AACjC,SACE,QAAQ,IAAI,iBAAiB,OAC7B,QAAQ,IAAI,iBAAiB,UAC7B,QAAQ,KAAK,SAAS,SAAS;AAEnC;AAGO,SAAS,MAAM,MAAoB;AACxC,MAAI,QAAQ,GAAG;AACb,YAAQ,OAAO,MAAM,kBAAkB,IAAI;AAAA,CAAI;AAAA,EACjD;AACF;;;ADFA,IAAM,2BAA2B;AAIjC,IAAM,qBAAqB;AAK3B,IAAM,mBAAmB;AAQzB,SAAS,cAAc,MAAsB;AAC3C,SAAO,KACJ,QAAQ,8BAA8B,mBAAmB,EACzD,QAAQ,mEAAmE,gBAAgB;AAChG;AAGA,SAAS,UAAU,KAAqB;AACtC,QAAM,IAAI,IAAI,QAAQ,GAAG;AACzB,SAAO,MAAM,KAAK,MAAM,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC;AAC5C;AAwCA,IAAM,YAAY,oBAAI,IAAI;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,iBAAiB,KAA6B;AACrD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,WAAW;AACjB,MAAI,OAAO,SAAS,SAAS,SAAU,QAAO,SAAS;AACvD,MAAI,SAAS,MAAO,QAAO,iBAAiB,SAAS,KAAK;AAC1D,SAAO;AACT;AAEA,SAAS,cAAc,MAAc,aAAqC;AACxE,MAAI,eAAe,YAAY,YAAY,EAAE,SAAS,WAAW,EAAG,QAAO;AAC3E,QAAM,UAAU,KAAK,UAAU;AAC/B,SAAO,QAAQ,WAAW,IAAI,KAAK,QAAQ,WAAW,OAAO,KAAK,QAAQ,WAAW,OAAO;AAC9F;AAGA,SAAS,aAAa,OAA4D;AAChF,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,iBAAiB,KAAK;AACtC,QAAM,MAAM,WAAW,OAAO,QAAQ,QAAQ,WAAY,QAAQ,MAAiB;AACnF,MAAI,QAAQ,KAAM,QAAO;AACzB,QAAM,SAAS,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC3C,SAAO,MAAM,SAAS,mBAAmB,YAAY;AACvD;AAGA,IAAI,uBAAuB;AAC3B,SAAS,uBAAuB,KAAaC,gBAA8B;AACzE,MAAI,CAACA,kBAAiB,qBAAsB;AAC5C,MAAI,CAAC,IAAI,WAAW,SAAS,EAAG;AAChC,MAAI;AACF,UAAM,OAAO,IAAI,IAAI,GAAG,EAAE;AAC1B,QAAI,SAAS,eAAe,SAAS,eAAe,SAAS,MAAO;AAAA,EACtE,QAAQ;AACN;AAAA,EACF;AACA,yBAAuB;AACvB,EAAAC,SAAQ,OAAO;AAAA,IACb,mEAAmE,GAAG;AAAA;AAAA,EAExE;AACF;AAEA,SAAS,cAAc,MAA4B;AACjD,QAAM,IAAI,KAAK;AACf,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,aAAa,QAAS,QAAO,EAAE,IAAI,eAAe;AACtD,MAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,YAAY,MAAM,eAAe;AAChF,SAAO,OAAO,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,eAAe;AACvE;AAMA,eAAsB,SACpB,KACA,OAA6D,CAAC,GAI9D;AACA,QAAM,EAAE,OAAO,WAAW,GAAG,UAAU,IAAI;AAC3C,yBAAuB,KAAK,cAAc,SAAS,CAAC;AACpD,QAAM,UAAK,UAAU,UAAU,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE;AAIxD,QAAM,UAAU,aAAa;AAC7B,QAAM,gBAAgB,UAAU,IAAI,YAAY,QAAQ,OAAO,IAAI;AACnE,QAAM,kBACJ,UAAU,UAAU,gBAChB,YAAY,IAAI,CAAC,UAAU,QAAQ,aAAa,CAAC,IAChD,UAAU,UAAU,iBAAiB;AAE5C,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,KAAK,EAAE,GAAG,WAAW,QAAQ,gBAAgB,CAAC;AAAA,EACvE,SAAS,KAAK;AACZ,UAAM,YACH,KAA2B,SAAS,kBACrC,QAAQ,eAAe,OAAO;AAChC,QAAI,WAAW;AACb,YAAMC,OAAM,cAAc,UAAU,GAAG,CAAC,oBAAoB,OAAO;AACnE,YAAM,wBAAmB;AACzB,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,SAAS,EAAE,MAAM,WAAW,QAAQ,MAAM,KAAK,SAASA,MAAK,OAAO,IAAI;AAAA,MAC1E;AAAA,IACF;AACA,UAAM,OAAO,iBAAiB,GAAG;AACjC,QAAI,QAAQ,UAAU,IAAI,IAAI,GAAG;AAC/B,YAAMA,OAAM;AAAA,QACV,sCAAsC,UAAU,GAAG,CAAC,KAAK,IAAI;AAAA,QAC7D;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,EAAE,KAAK,IAAI;AACX,YAAM,cAAS,IAAI,EAAE;AACrB,aAAO,EAAE,IAAI,OAAO,SAAS,EAAE,MAAM,OAAO,QAAQ,MAAM,KAAK,SAASA,MAAK,OAAO,IAAI,EAAE;AAAA,IAC5F;AACA,UAAM,MAAM,0BAA0B,UAAU,GAAG,CAAC,KAAK,OAAQ,IAAc,WAAW,GAAG,CAAC;AAC9F,UAAM,kBAAa,GAAG,EAAE;AACxB,WAAO,EAAE,IAAI,OAAO,SAAS,EAAE,MAAM,WAAW,QAAQ,MAAM,KAAK,SAAS,KAAK,OAAO,IAAI,EAAE;AAAA,EAChG;AAEA,QAAM,YAAY,SAAS,QAAQ,IAAI,wBAAwB;AAC/D,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;AACvD,QAAM,UAAK,SAAS,MAAM,IAAI,UAAU,GAAG,CAAC,QAAQ,eAAe,KAAK,QAAQ,aAAa,MAAM,GAAG;AAEtG,MAAI,SAAS,IAAI;AACf,WAAO,EAAE,IAAI,MAAM,UAAU,UAAU;AAAA,EACzC;AAKA,QAAM,WAAW,MAAM,SAAS,MAAM,EAAE,KAAK,EAAE,MAAM,MAAM,EAAE;AAC7D,QAAM,UAAU,cAAc,SAAS,MAAM,GAAG,GAAG,CAAC;AAGpD,MAAI,cAAc,UAAU,WAAW,GAAG;AACxC,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ,SAAS;AAAA,QACjB;AAAA,QACA,aAAa,eAAe;AAAA,QAC5B;AAAA,QACA,MAAM;AAAA,QACN,SAAS;AAAA,UACP,6BAA6B,GAAG,YAAY,SAAS,MAAM;AAAA,UAC3D;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,gBAAgB,QAAQ,QAAQ,QAAQ,GAAG,CAAC,KAAK;AAAA,QAC7D,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAGA,OAAK,SAAS,WAAW,OAAO,SAAS,WAAW,QAAQ,CAAC,WAAW;AACtE,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ,SAAS;AAAA,QACjB;AAAA,QACA,aAAa,eAAe;AAAA,QAC5B;AAAA,QACA,MAAM;AAAA,QACN,SAAS;AAAA,UACP,OAAO,SAAS,MAAM,SAAS,GAAG,sCAAsC,wBAAwB;AAAA,UAChG;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,KAAK;AAC3B,UAAM,YAAY,aAAa,KAAK;AACpC,QAAI,cAAc,SAAS;AACzB,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,SAAS;AAAA,UACP,MAAM;AAAA,UACN,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,SAAS;AAAA,YACP;AAAA,YACA;AAAA,YACA;AAAA,UACF,EAAE,KAAK,IAAI;AAAA,QACb;AAAA,MACF;AAAA,IACF;AACA,QAAI,cAAc,WAAW;AAC3B,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,SAAS;AAAA,UACP,MAAM;AAAA,UACN,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,QAAQ,SAAS;AAAA,MACjB;AAAA,MACA,aAAa,eAAe;AAAA,MAC5B;AAAA,MACA,MAAM;AAAA,MACN,SAAS,GAAG,SAAS,MAAM,IAAI,SAAS,UAAU,GAAG,UAAU,KAAK,OAAO,KAAK,EAAE;AAAA,IACpF;AAAA,EACF;AACF;AAQO,SAAS,kBAAkB,SAAqC;AACrE,SAAO,QAAQ,SAAS;AAC1B;AAOO,SAAS,cAAc,SAAmC;AAC/D,EAAAD,SAAQ,OAAO,MAAM,UAAU,QAAQ,OAAO;AAAA,CAAI;AAClD,MAAI,QAAQ,KAAK,QAAQ,QAAQ,QAAQ,SAAS,aAAa;AAC7D,IAAAA,SAAQ,OAAO,MAAM,wBAAwB,QAAQ,IAAI;AAAA,CAAI;AAAA,EAC/D;AACA,EAAAA,SAAQ,KAAK,CAAC;AAChB;AAQA,eAAsB,YACpB,KACA,OAA6D,CAAC,GAC3C;AACnB,QAAM,SAAS,MAAM,SAAS,KAAK,IAAI;AACvC,MAAI,OAAO,GAAI,QAAO,OAAO;AAC7B,MAAI,kBAAkB,OAAO,OAAO,EAAG,eAAc,OAAO,OAAO;AAEnE,SAAO,IAAI,SAAS,OAAO,QAAQ,QAAQ,IAAI;AAAA,IAC7C,QAAQ,OAAO,QAAQ,UAAU;AAAA,IACjC,SAAS,OAAO,QAAQ,cACpB,EAAE,gBAAgB,OAAO,QAAQ,YAAY,IAC7C;AAAA,EACN,CAAC;AACH;","names":["process","hasAuthHeader","process","msg"]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
apiRequest
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PVWG3V62.js";
|
|
5
5
|
import {
|
|
6
6
|
getArgValue,
|
|
7
7
|
hasFlag,
|
|
8
8
|
resolveConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VYTIJ6HJ.js";
|
|
10
10
|
|
|
11
11
|
// src/triage.ts
|
|
12
12
|
import process from "process";
|
|
@@ -268,4 +268,4 @@ export {
|
|
|
268
268
|
isTriageEnabledForExecution,
|
|
269
269
|
runTriage
|
|
270
270
|
};
|
|
271
|
-
//# sourceMappingURL=chunk-
|
|
271
|
+
//# sourceMappingURL=chunk-VHVOTGBQ.js.map
|
|
@@ -155,6 +155,20 @@ async function resolveConfig(argv) {
|
|
|
155
155
|
async function resolveOptionalConfig(argv) {
|
|
156
156
|
return resolveConfigInternal(argv, { required: false });
|
|
157
157
|
}
|
|
158
|
+
async function resolveAuthSource(argv) {
|
|
159
|
+
const env = getArgValue(argv, "--env");
|
|
160
|
+
if (env && !ENV_URLS[env]) return "none";
|
|
161
|
+
const profile = env ? envToProfile(env) : void 0;
|
|
162
|
+
if (getArgValue(argv, "--token")) return "flag";
|
|
163
|
+
if (profile) {
|
|
164
|
+
if (await readStoredToken(profile)) return "stored";
|
|
165
|
+
if (readBrandEnv("CANARY_API_TOKEN")) return "env";
|
|
166
|
+
return "none";
|
|
167
|
+
}
|
|
168
|
+
if (readBrandEnv("CANARY_API_TOKEN")) return "env";
|
|
169
|
+
if (await readStoredToken()) return "stored";
|
|
170
|
+
return "none";
|
|
171
|
+
}
|
|
158
172
|
|
|
159
173
|
export {
|
|
160
174
|
getArgValue,
|
|
@@ -168,6 +182,7 @@ export {
|
|
|
168
182
|
readAllStoredTokens,
|
|
169
183
|
saveAuth,
|
|
170
184
|
resolveConfig,
|
|
171
|
-
resolveOptionalConfig
|
|
185
|
+
resolveOptionalConfig,
|
|
186
|
+
resolveAuthSource
|
|
172
187
|
};
|
|
173
|
-
//# sourceMappingURL=chunk-
|
|
188
|
+
//# sourceMappingURL=chunk-VYTIJ6HJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { readBrandEnv } from './brand.js';\n\ntype StoredAuth = {\n token?: string;\n apiUrl?: string;\n orgId?: string;\n orgName?: string;\n};\n\n/** Multi-profile auth file format */\ntype MultiProfileAuth = {\n profiles: Record<string, StoredAuth>;\n default: string;\n};\n\n/** Legacy flat format (single profile) */\ntype LegacyAuth = StoredAuth;\n\nconst AUTH_DIR = path.join(os.homedir(), '.config', 'canary-cli');\nconst AUTH_FILE = path.join(AUTH_DIR, 'auth.json');\n\n/* ── Shared argv helpers ─────────────────────────────────────────────── */\n\nexport function getArgValue(argv: string[], key: string): string | undefined {\n const index = argv.indexOf(key);\n if (index === -1 || index >= argv.length - 1) return undefined;\n return argv[index + 1];\n}\n\nexport function hasFlag(argv: string[], ...flags: string[]): boolean {\n return flags.some((flag) => argv.includes(flag));\n}\n\n/* ── Environment / profile mapping ───────────────────────────────────── */\n\n/** Map --env values to profile names for multi-profile auth storage */\nexport function envToProfile(env: string): string {\n if (env === 'prod' || env === 'production') return 'production';\n if (env === 'dev') return 'dev';\n if (env === 'local') return 'local';\n return env;\n}\n\nconst VALID_ENVS = ['prod', 'dev', 'local'];\n\n/** Environment URL mappings shared across CLI commands */\nexport const ENV_URLS: Record<string, { api: string; app: string }> = {\n prod: {\n api: 'https://api.trycanary.ai',\n app: 'https://app.trycanary.ai',\n },\n production: {\n api: 'https://api.trycanary.ai',\n app: 'https://app.trycanary.ai',\n },\n dev: {\n api: 'https://api.dev.trycanary.ai',\n app: 'https://app.dev.trycanary.ai',\n },\n local: {\n api: 'http://localhost:3000',\n app: 'http://localhost:5173',\n },\n};\n\n/** Derive the web-app URL that corresponds to a given API URL. */\nexport function resolveAppUrl(apiUrl: string): string {\n for (const env of Object.values(ENV_URLS)) {\n if (env.api === apiUrl) return env.app;\n }\n // Fallback for custom API URLs: replace \"api.\" at protocol boundary or \"/api\" path\n return apiUrl.replace(/(:\\/\\/)api\\./, '$1app.').replace(/:3000\\b/, ':5173');\n}\n\nfunction isMultiProfile(data: unknown): data is MultiProfileAuth {\n return typeof data === 'object' && data !== null && 'profiles' in data;\n}\n\n/** Read the raw auth file and normalize to multi-profile format */\nasync function readAuthFile(): Promise<MultiProfileAuth | null> {\n try {\n const content = await fs.readFile(AUTH_FILE, 'utf8');\n const data = JSON.parse(content) as unknown;\n\n if (isMultiProfile(data)) {\n return data;\n }\n\n // Legacy flat format — treat as the \"default\" profile\n const legacy = data as LegacyAuth;\n return {\n profiles: { default: legacy },\n default: 'default',\n };\n } catch {\n return null;\n }\n}\n\nexport async function readStoredAuth(profile?: string): Promise<StoredAuth | null> {\n const auth = await readAuthFile();\n if (!auth) return null;\n\n const key = profile ?? auth.default;\n return auth.profiles[key] ?? null;\n}\n\nexport async function readStoredToken(profile?: string): Promise<string | null> {\n const auth = await readStoredAuth(profile);\n return auth?.token ?? null;\n}\n\nexport async function readStoredApiUrl(profile?: string): Promise<string | null> {\n const auth = await readStoredAuth(profile);\n return auth?.apiUrl ?? null;\n}\n\n/** Return all stored tokens across every profile */\nexport async function readAllStoredTokens(): Promise<string[]> {\n const auth = await readAuthFile();\n if (!auth) return [];\n return Object.values(auth.profiles)\n .map((p) => p.token)\n .filter((t): t is string => !!t);\n}\n\nexport async function saveAuth(auth: StoredAuth, profile?: string): Promise<string> {\n await fs.mkdir(AUTH_DIR, { recursive: true, mode: 0o700 });\n\n // Read existing file (may be legacy or multi-profile)\n let existing: MultiProfileAuth;\n try {\n const content = await fs.readFile(AUTH_FILE, 'utf8');\n const data = JSON.parse(content) as unknown;\n\n if (isMultiProfile(data)) {\n existing = data;\n } else {\n // Migrate legacy flat format into profiles.default\n existing = {\n profiles: { default: data as LegacyAuth },\n default: 'default',\n };\n }\n } catch {\n existing = { profiles: {}, default: 'default' };\n }\n\n const key = profile ?? 'default';\n existing.profiles[key] = auth;\n\n // Set default to this profile if no default exists yet\n if (!existing.profiles[existing.default]) {\n existing.default = key;\n }\n\n await fs.writeFile(AUTH_FILE, JSON.stringify(existing, null, 2), {\n encoding: 'utf8',\n mode: 0o600,\n });\n return AUTH_FILE;\n}\n\n/* ── Shared config resolution ────────────────────────────────────────── */\n\ntype ResolvedConfig = { apiUrl: string; token: string };\n\nasync function resolveConfigInternal(\n argv: string[],\n opts: { required: boolean }\n): Promise<ResolvedConfig | null> {\n const env = getArgValue(argv, '--env');\n const profile = env ? envToProfile(env) : undefined;\n\n if (env && !ENV_URLS[env]) {\n if (opts.required) {\n console.error(`Unknown environment: ${env}`);\n console.error(`Valid environments: ${VALID_ENVS.join(', ')}`);\n process.exit(1);\n }\n return null;\n }\n\n const storedApiUrl = await readStoredApiUrl(profile);\n const apiUrl =\n getArgValue(argv, '--api-url') ??\n (env ? ENV_URLS[env].api : undefined) ??\n readBrandEnv('CANARY_API_URL') ??\n storedApiUrl ??\n 'https://api.trycanary.ai';\n\n const explicitToken = getArgValue(argv, '--token');\n\n let token: string | null;\n if (explicitToken) {\n token = explicitToken;\n } else if (profile) {\n token = (await readStoredToken(profile)) ?? readBrandEnv('CANARY_API_TOKEN') ?? null;\n if (!token && opts.required) {\n console.error(`Error: No token found for \"${env}\" profile.`);\n console.error(`Run: canary login --env ${env}`);\n process.exit(1);\n }\n } else {\n token = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken()) ?? null;\n if (!token && opts.required) {\n console.error('Error: No API token found.');\n console.error('Run: canary login');\n process.exit(1);\n }\n }\n\n return token ? { apiUrl, token } : null;\n}\n\n/**\n * Resolve API URL and auth token from argv flags, env vars, and stored profiles.\n * Used by knobs, feature-flag, release, and debug-session commands.\n */\nexport async function resolveConfig(argv: string[]): Promise<ResolvedConfig> {\n return (await resolveConfigInternal(argv, { required: true }))!;\n}\n\nexport async function resolveOptionalConfig(argv: string[]): Promise<ResolvedConfig | null> {\n return resolveConfigInternal(argv, { required: false });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/auth.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { readBrandEnv } from './brand.js';\n\ntype StoredAuth = {\n token?: string;\n apiUrl?: string;\n orgId?: string;\n orgName?: string;\n};\n\n/** Multi-profile auth file format */\ntype MultiProfileAuth = {\n profiles: Record<string, StoredAuth>;\n default: string;\n};\n\n/** Legacy flat format (single profile) */\ntype LegacyAuth = StoredAuth;\n\nconst AUTH_DIR = path.join(os.homedir(), '.config', 'canary-cli');\nconst AUTH_FILE = path.join(AUTH_DIR, 'auth.json');\n\n/* ── Shared argv helpers ─────────────────────────────────────────────── */\n\nexport function getArgValue(argv: string[], key: string): string | undefined {\n const index = argv.indexOf(key);\n if (index === -1 || index >= argv.length - 1) return undefined;\n return argv[index + 1];\n}\n\nexport function hasFlag(argv: string[], ...flags: string[]): boolean {\n return flags.some((flag) => argv.includes(flag));\n}\n\n/* ── Environment / profile mapping ───────────────────────────────────── */\n\n/** Map --env values to profile names for multi-profile auth storage */\nexport function envToProfile(env: string): string {\n if (env === 'prod' || env === 'production') return 'production';\n if (env === 'dev') return 'dev';\n if (env === 'local') return 'local';\n return env;\n}\n\nconst VALID_ENVS = ['prod', 'dev', 'local'];\n\n/** Environment URL mappings shared across CLI commands */\nexport const ENV_URLS: Record<string, { api: string; app: string }> = {\n prod: {\n api: 'https://api.trycanary.ai',\n app: 'https://app.trycanary.ai',\n },\n production: {\n api: 'https://api.trycanary.ai',\n app: 'https://app.trycanary.ai',\n },\n dev: {\n api: 'https://api.dev.trycanary.ai',\n app: 'https://app.dev.trycanary.ai',\n },\n local: {\n api: 'http://localhost:3000',\n app: 'http://localhost:5173',\n },\n};\n\n/** Derive the web-app URL that corresponds to a given API URL. */\nexport function resolveAppUrl(apiUrl: string): string {\n for (const env of Object.values(ENV_URLS)) {\n if (env.api === apiUrl) return env.app;\n }\n // Fallback for custom API URLs: replace \"api.\" at protocol boundary or \"/api\" path\n return apiUrl.replace(/(:\\/\\/)api\\./, '$1app.').replace(/:3000\\b/, ':5173');\n}\n\nfunction isMultiProfile(data: unknown): data is MultiProfileAuth {\n return typeof data === 'object' && data !== null && 'profiles' in data;\n}\n\n/** Read the raw auth file and normalize to multi-profile format */\nasync function readAuthFile(): Promise<MultiProfileAuth | null> {\n try {\n const content = await fs.readFile(AUTH_FILE, 'utf8');\n const data = JSON.parse(content) as unknown;\n\n if (isMultiProfile(data)) {\n return data;\n }\n\n // Legacy flat format — treat as the \"default\" profile\n const legacy = data as LegacyAuth;\n return {\n profiles: { default: legacy },\n default: 'default',\n };\n } catch {\n return null;\n }\n}\n\nexport async function readStoredAuth(profile?: string): Promise<StoredAuth | null> {\n const auth = await readAuthFile();\n if (!auth) return null;\n\n const key = profile ?? auth.default;\n return auth.profiles[key] ?? null;\n}\n\nexport async function readStoredToken(profile?: string): Promise<string | null> {\n const auth = await readStoredAuth(profile);\n return auth?.token ?? null;\n}\n\nexport async function readStoredApiUrl(profile?: string): Promise<string | null> {\n const auth = await readStoredAuth(profile);\n return auth?.apiUrl ?? null;\n}\n\n/** Return all stored tokens across every profile */\nexport async function readAllStoredTokens(): Promise<string[]> {\n const auth = await readAuthFile();\n if (!auth) return [];\n return Object.values(auth.profiles)\n .map((p) => p.token)\n .filter((t): t is string => !!t);\n}\n\nexport async function saveAuth(auth: StoredAuth, profile?: string): Promise<string> {\n await fs.mkdir(AUTH_DIR, { recursive: true, mode: 0o700 });\n\n // Read existing file (may be legacy or multi-profile)\n let existing: MultiProfileAuth;\n try {\n const content = await fs.readFile(AUTH_FILE, 'utf8');\n const data = JSON.parse(content) as unknown;\n\n if (isMultiProfile(data)) {\n existing = data;\n } else {\n // Migrate legacy flat format into profiles.default\n existing = {\n profiles: { default: data as LegacyAuth },\n default: 'default',\n };\n }\n } catch {\n existing = { profiles: {}, default: 'default' };\n }\n\n const key = profile ?? 'default';\n existing.profiles[key] = auth;\n\n // Set default to this profile if no default exists yet\n if (!existing.profiles[existing.default]) {\n existing.default = key;\n }\n\n await fs.writeFile(AUTH_FILE, JSON.stringify(existing, null, 2), {\n encoding: 'utf8',\n mode: 0o600,\n });\n return AUTH_FILE;\n}\n\n/* ── Shared config resolution ────────────────────────────────────────── */\n\ntype ResolvedConfig = { apiUrl: string; token: string };\n\nasync function resolveConfigInternal(\n argv: string[],\n opts: { required: boolean }\n): Promise<ResolvedConfig | null> {\n const env = getArgValue(argv, '--env');\n const profile = env ? envToProfile(env) : undefined;\n\n if (env && !ENV_URLS[env]) {\n if (opts.required) {\n console.error(`Unknown environment: ${env}`);\n console.error(`Valid environments: ${VALID_ENVS.join(', ')}`);\n process.exit(1);\n }\n return null;\n }\n\n const storedApiUrl = await readStoredApiUrl(profile);\n const apiUrl =\n getArgValue(argv, '--api-url') ??\n (env ? ENV_URLS[env].api : undefined) ??\n readBrandEnv('CANARY_API_URL') ??\n storedApiUrl ??\n 'https://api.trycanary.ai';\n\n const explicitToken = getArgValue(argv, '--token');\n\n let token: string | null;\n if (explicitToken) {\n token = explicitToken;\n } else if (profile) {\n token = (await readStoredToken(profile)) ?? readBrandEnv('CANARY_API_TOKEN') ?? null;\n if (!token && opts.required) {\n console.error(`Error: No token found for \"${env}\" profile.`);\n console.error(`Run: canary login --env ${env}`);\n process.exit(1);\n }\n } else {\n token = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken()) ?? null;\n if (!token && opts.required) {\n console.error('Error: No API token found.');\n console.error('Run: canary login');\n process.exit(1);\n }\n }\n\n return token ? { apiUrl, token } : null;\n}\n\n/**\n * Resolve API URL and auth token from argv flags, env vars, and stored profiles.\n * Used by knobs, feature-flag, release, and debug-session commands.\n */\nexport async function resolveConfig(argv: string[]): Promise<ResolvedConfig> {\n return (await resolveConfigInternal(argv, { required: true }))!;\n}\n\nexport async function resolveOptionalConfig(argv: string[]): Promise<ResolvedConfig | null> {\n return resolveConfigInternal(argv, { required: false });\n}\n\n/**\n * Where the effective auth token would come from for this invocation:\n * - `flag` — explicit `--token`\n * - `env` — CANARY_API_TOKEN / COFACTOR_API_TOKEN\n * - `stored` — an interactive `canary login` session in auth.json\n * - `none` — no token resolvable\n *\n * Mirrors the precedence in `resolveConfigInternal` exactly (which differs by\n * whether a profile is selected). `stored` is the only \"logged in interactively\"\n * source; `flag`/`env` are API-key style auth used by CI/automation.\n */\nexport async function resolveAuthSource(\n argv: string[]\n): Promise<'flag' | 'env' | 'stored' | 'none'> {\n const env = getArgValue(argv, '--env');\n if (env && !ENV_URLS[env]) return 'none';\n const profile = env ? envToProfile(env) : undefined;\n\n if (getArgValue(argv, '--token')) return 'flag';\n\n if (profile) {\n // With a profile, stored auth wins over the env var.\n if (await readStoredToken(profile)) return 'stored';\n if (readBrandEnv('CANARY_API_TOKEN')) return 'env';\n return 'none';\n }\n\n // Without a profile, the env var wins over stored auth.\n if (readBrandEnv('CANARY_API_TOKEN')) return 'env';\n if (await readStoredToken()) return 'stored';\n return 'none';\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,19 +3,19 @@ import {
|
|
|
3
3
|
apiRequest,
|
|
4
4
|
fetchProperties,
|
|
5
5
|
getApplicationArg
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PVWG3V62.js";
|
|
7
7
|
import {
|
|
8
8
|
apiFetch,
|
|
9
9
|
exitOnFailure
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PWZ4ULCB.js";
|
|
11
11
|
import {
|
|
12
12
|
getArgValue,
|
|
13
13
|
hasFlag,
|
|
14
14
|
resolveConfig
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-VYTIJ6HJ.js";
|
|
16
16
|
import "./chunk-32P26BZT.js";
|
|
17
17
|
import "./chunk-JWHYXEA2.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-GZVCNYR4.js";
|
|
19
19
|
import "./chunk-VKVL7WBN.js";
|
|
20
20
|
|
|
21
21
|
// src/credential.ts
|
|
@@ -451,4 +451,4 @@ async function runCredential(argv) {
|
|
|
451
451
|
export {
|
|
452
452
|
runCredential
|
|
453
453
|
};
|
|
454
|
-
//# sourceMappingURL=credential-
|
|
454
|
+
//# sourceMappingURL=credential-WOATCWOU.js.map
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
apiRequest,
|
|
4
4
|
fetchProperties,
|
|
5
5
|
getApplicationArg
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-PVWG3V62.js";
|
|
7
|
+
import "./chunk-PWZ4ULCB.js";
|
|
8
8
|
import {
|
|
9
9
|
getArgValue,
|
|
10
10
|
hasFlag,
|
|
11
11
|
resolveConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-VYTIJ6HJ.js";
|
|
13
13
|
import "./chunk-32P26BZT.js";
|
|
14
14
|
import "./chunk-JWHYXEA2.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-GZVCNYR4.js";
|
|
16
16
|
import "./chunk-VKVL7WBN.js";
|
|
17
17
|
|
|
18
18
|
// src/credential-template.ts
|
|
@@ -290,4 +290,4 @@ async function runCredentialTemplate(argv) {
|
|
|
290
290
|
export {
|
|
291
291
|
runCredentialTemplate
|
|
292
292
|
};
|
|
293
|
-
//# sourceMappingURL=credential-template-
|
|
293
|
+
//# sourceMappingURL=credential-template-Q3DQE2AH.js.map
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
downloadStorageState
|
|
4
|
+
} from "./chunk-PVWG3V62.js";
|
|
5
|
+
import "./chunk-PWZ4ULCB.js";
|
|
2
6
|
import {
|
|
3
7
|
acquireCloudLock,
|
|
4
8
|
createSessionWithRelay,
|
|
5
9
|
deleteSession,
|
|
6
10
|
releaseCloudLock
|
|
7
11
|
} from "./chunk-J6SH7GQT.js";
|
|
8
|
-
import {
|
|
9
|
-
downloadStorageState
|
|
10
|
-
} from "./chunk-CFJXYPTF.js";
|
|
11
|
-
import "./chunk-3CZU7XCS.js";
|
|
12
12
|
import {
|
|
13
13
|
getArgValue,
|
|
14
14
|
hasFlag,
|
|
15
15
|
resolveConfig
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-VYTIJ6HJ.js";
|
|
17
17
|
import "./chunk-32P26BZT.js";
|
|
18
18
|
import "./chunk-JWHYXEA2.js";
|
|
19
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-GZVCNYR4.js";
|
|
20
20
|
import "./chunk-VKVL7WBN.js";
|
|
21
21
|
|
|
22
22
|
// src/debug-workflow.ts
|
|
@@ -257,4 +257,4 @@ async function runDebugWorkflow(argv) {
|
|
|
257
257
|
export {
|
|
258
258
|
runDebugWorkflow
|
|
259
259
|
};
|
|
260
|
-
//# sourceMappingURL=debug-workflow-
|
|
260
|
+
//# sourceMappingURL=debug-workflow-ZNP5XZQF.js.map
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
compareEditingContexts,
|
|
35
35
|
compareSnapshots,
|
|
36
36
|
computeFingerprint,
|
|
37
|
+
consoleLogger,
|
|
37
38
|
cropImage,
|
|
38
39
|
decodeV2Value,
|
|
39
40
|
detectGrid,
|
|
@@ -60,6 +61,8 @@ import {
|
|
|
60
61
|
extractIndexedDB,
|
|
61
62
|
extractLinks,
|
|
62
63
|
extractLinksFromTree,
|
|
64
|
+
extractPdfText,
|
|
65
|
+
extractPdfTextFromBuffer,
|
|
63
66
|
extractSemanticHint,
|
|
64
67
|
extractSnapshotYaml,
|
|
65
68
|
extractTablesFromSnapshot,
|
|
@@ -107,22 +110,17 @@ import {
|
|
|
107
110
|
restoreIndexedDB,
|
|
108
111
|
searchElements,
|
|
109
112
|
setCdpScreencastLogger,
|
|
113
|
+
setPdfExtractLogger,
|
|
110
114
|
setSnapshotAnalyzerLogger,
|
|
111
115
|
sortMatchesByContext,
|
|
112
116
|
withBrowserLaunchRetry,
|
|
113
117
|
withRecoveryNotice,
|
|
114
118
|
withRecoveryNoticeMCP,
|
|
115
119
|
withToolTimeout
|
|
116
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-MO5G5TP5.js";
|
|
117
121
|
import "./chunk-JWHYXEA2.js";
|
|
118
|
-
import "./chunk-
|
|
122
|
+
import "./chunk-GZVCNYR4.js";
|
|
119
123
|
import "./chunk-6LEZCKKV.js";
|
|
120
|
-
import {
|
|
121
|
-
consoleLogger,
|
|
122
|
-
extractPdfText,
|
|
123
|
-
extractPdfTextFromBuffer,
|
|
124
|
-
setPdfExtractLogger
|
|
125
|
-
} from "./chunk-KRWRUU6R.js";
|
|
126
124
|
import "./chunk-VKVL7WBN.js";
|
|
127
125
|
export {
|
|
128
126
|
BROWSER_LIFECYCLE_TOOLS,
|
|
@@ -244,4 +242,4 @@ export {
|
|
|
244
242
|
withRecoveryNoticeMCP,
|
|
245
243
|
withToolTimeout
|
|
246
244
|
};
|
|
247
|
-
//# sourceMappingURL=
|
|
245
|
+
//# sourceMappingURL=dist-WW2S733L.js.map
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
apiRequest
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-PVWG3V62.js";
|
|
5
|
+
import "./chunk-PWZ4ULCB.js";
|
|
6
6
|
import {
|
|
7
7
|
getArgValue,
|
|
8
8
|
hasFlag,
|
|
9
9
|
resolveConfig
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-VYTIJ6HJ.js";
|
|
11
11
|
import "./chunk-32P26BZT.js";
|
|
12
12
|
import {
|
|
13
13
|
getSubDir
|
|
14
14
|
} from "./chunk-JWHYXEA2.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-GZVCNYR4.js";
|
|
16
16
|
import "./chunk-VKVL7WBN.js";
|
|
17
17
|
|
|
18
18
|
// src/docs.ts
|
|
@@ -448,4 +448,4 @@ async function runDocs(argv) {
|
|
|
448
448
|
export {
|
|
449
449
|
runDocs
|
|
450
450
|
};
|
|
451
|
-
//# sourceMappingURL=docs-
|
|
451
|
+
//# sourceMappingURL=docs-XVU4LA7G.js.map
|
|
@@ -2,13 +2,13 @@ import { createRequire as __cr } from "module"; const require = __cr(import.meta
|
|
|
2
2
|
import {
|
|
3
3
|
apiFetch,
|
|
4
4
|
decodeJwtPayload
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-PWZ4ULCB.js";
|
|
6
6
|
import {
|
|
7
7
|
ENV_URLS,
|
|
8
8
|
envToProfile,
|
|
9
9
|
getArgValue,
|
|
10
10
|
readStoredAuth
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-VYTIJ6HJ.js";
|
|
12
12
|
import {
|
|
13
13
|
readBrandEnv
|
|
14
14
|
} from "./chunk-32P26BZT.js";
|
|
@@ -133,4 +133,4 @@ async function runAuthDoctor(argv) {
|
|
|
133
133
|
export {
|
|
134
134
|
runAuthDoctor
|
|
135
135
|
};
|
|
136
|
-
//# sourceMappingURL=doctor-
|
|
136
|
+
//# sourceMappingURL=doctor-PGNHD3TI.js.map
|
|
@@ -2,16 +2,16 @@ import { createRequire as __cr } from "module"; const require = __cr(import.meta
|
|
|
2
2
|
import {
|
|
3
3
|
apiRequest,
|
|
4
4
|
fetchProperties
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-PVWG3V62.js";
|
|
6
|
+
import "./chunk-PWZ4ULCB.js";
|
|
7
7
|
import {
|
|
8
8
|
getArgValue,
|
|
9
9
|
hasFlag,
|
|
10
10
|
resolveConfig
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-VYTIJ6HJ.js";
|
|
12
12
|
import "./chunk-32P26BZT.js";
|
|
13
13
|
import "./chunk-JWHYXEA2.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-GZVCNYR4.js";
|
|
15
15
|
import "./chunk-VKVL7WBN.js";
|
|
16
16
|
|
|
17
17
|
// src/environment.ts
|
|
@@ -218,4 +218,4 @@ async function runEnvironment(argv) {
|
|
|
218
218
|
export {
|
|
219
219
|
runEnvironment
|
|
220
220
|
};
|
|
221
|
-
//# sourceMappingURL=environment-
|
|
221
|
+
//# sourceMappingURL=environment-MRDNWU47.js.map
|