@wave-ai-os/wave-cli 0.1.60 → 0.1.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.cjs +260 -212
  2. package/dist/index.js +260 -212
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2136,13 +2136,18 @@ function resolveFromSources(options, stdin, config, env) {
2136
2136
  normalize3(env.WAVE_API_URL),
2137
2137
  normalize3(config.baseUrl)
2138
2138
  );
2139
- const organizationId = firstDefined(
2140
- normalize3(options.organizationId),
2141
- normalize3(stdin.organizationId),
2142
- normalize3(env.WAVE_ORGANIZATION_ID),
2143
- normalize3(env.WAVE_ORG_ID),
2144
- normalize3(config.organizationId)
2145
- );
2139
+ const organizationCandidates = [
2140
+ { organizationId: normalize3(options.organizationId), source: "flag" },
2141
+ { organizationId: normalize3(stdin.organizationId), source: "stdin" },
2142
+ { organizationId: normalize3(env.WAVE_ORGANIZATION_ID), source: "env" },
2143
+ { organizationId: normalize3(env.WAVE_ORG_ID), source: "env" },
2144
+ { organizationId: normalize3(config.organizationId), source: "config" }
2145
+ ];
2146
+ const resolvedOrganization = organizationCandidates.find((candidate) => candidate.organizationId) ?? {
2147
+ organizationId: void 0,
2148
+ source: "none"
2149
+ };
2150
+ const organizationId = resolvedOrganization.organizationId;
2146
2151
  const timeoutMs = firstDefined(options.timeoutMs, stdin.timeoutMs, env.WAVE_TIMEOUT_MS, config.timeoutMs);
2147
2152
  const debug = firstDefined(
2148
2153
  options.debug,
@@ -2231,6 +2236,7 @@ function resolveFromSources(options, stdin, config, env) {
2231
2236
  const resolvedAuth = resolveAuthToken(options, stdin, config, env);
2232
2237
  return {
2233
2238
  organizationId,
2239
+ organizationIdSource: resolvedOrganization.source,
2234
2240
  runtimeOptions: {
2235
2241
  token: resolvedAuth.token,
2236
2242
  tokenSource: resolvedAuth.token ? resolvedAuth.source : "none",
@@ -2440,6 +2446,140 @@ function registerGraphqlSearchCommand(command, config) {
2440
2446
  });
2441
2447
  }
2442
2448
 
2449
+ // src/authClient.ts
2450
+ import { randomUUID as randomUUID2 } from "crypto";
2451
+
2452
+ // src/redaction.ts
2453
+ var TOKENISH_PATTERNS = [
2454
+ /\b(?:cli|wave|token|secret|bearer)[A-Za-z0-9._~+/=-]{8,}\b/gi,
2455
+ /\b[A-Za-z0-9._~+/=-]{24,}\b/g
2456
+ ];
2457
+ function redactOne(value) {
2458
+ if (value.length <= 8) {
2459
+ return "[redacted]";
2460
+ }
2461
+ return `${value.slice(0, 4)}...[redacted]...${value.slice(-4)}`;
2462
+ }
2463
+ function redactSecrets(input, knownSecrets = []) {
2464
+ let output = input;
2465
+ for (const secret of knownSecrets) {
2466
+ if (!secret) continue;
2467
+ output = output.split(secret).join(redactOne(secret));
2468
+ }
2469
+ for (const pattern of TOKENISH_PATTERNS) {
2470
+ output = output.replace(pattern, (match) => redactOne(match));
2471
+ }
2472
+ return output;
2473
+ }
2474
+ function redactUnknown(input, knownSecrets = []) {
2475
+ if (typeof input === "string") {
2476
+ return redactSecrets(input, knownSecrets);
2477
+ }
2478
+ if (Array.isArray(input)) {
2479
+ return input.map((entry2) => redactUnknown(entry2, knownSecrets));
2480
+ }
2481
+ if (!input || typeof input !== "object") {
2482
+ return input;
2483
+ }
2484
+ const output = {};
2485
+ for (const [key, value] of Object.entries(input)) {
2486
+ if (/token|secret|authorization|bearer/i.test(key)) {
2487
+ output[key] = typeof value === "string" ? redactSecrets(value, knownSecrets) : "[redacted]";
2488
+ continue;
2489
+ }
2490
+ output[key] = redactUnknown(value, knownSecrets);
2491
+ }
2492
+ return output;
2493
+ }
2494
+
2495
+ // src/authClient.ts
2496
+ function parseJsonSafely2(input) {
2497
+ try {
2498
+ return JSON.parse(input);
2499
+ } catch {
2500
+ return null;
2501
+ }
2502
+ }
2503
+ function graphqlErrors(payload, knownSecrets) {
2504
+ const errors = payload.errors;
2505
+ if (!Array.isArray(errors) || errors.length === 0) return null;
2506
+ return {
2507
+ code: "upstream_error",
2508
+ message: "GraphQL request failed.",
2509
+ status: 400,
2510
+ details: {
2511
+ errors: redactUnknown(errors, knownSecrets)
2512
+ }
2513
+ };
2514
+ }
2515
+ async function authGraphqlRequest(params) {
2516
+ const requestId = randomUUID2();
2517
+ const controller = new AbortController();
2518
+ const timeoutId = setTimeout(() => controller.abort(), params.timeoutMs);
2519
+ const knownSecrets = [params.token, ...params.knownSecrets ?? []].filter(
2520
+ (secret) => typeof secret === "string" && secret.length > 0
2521
+ );
2522
+ try {
2523
+ const url = new URL("/graphql", params.baseUrl);
2524
+ const response = await fetch(url, {
2525
+ method: "POST",
2526
+ headers: {
2527
+ Accept: "application/json",
2528
+ "Content-Type": "application/json",
2529
+ "X-Origin": "wave-cli",
2530
+ "X-Request-Id": requestId,
2531
+ ...params.token ? { Authorization: `Bearer ${params.token}` } : {}
2532
+ },
2533
+ body: JSON.stringify({ query: params.query, variables: params.variables ?? {} }),
2534
+ signal: controller.signal
2535
+ });
2536
+ const responseRequestId = response.headers.get("x-request-id") ?? requestId;
2537
+ const text = await response.text();
2538
+ const payload = text ? parseJsonSafely2(text) : null;
2539
+ const graph = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
2540
+ const gqlError = graphqlErrors(graph, knownSecrets);
2541
+ if (gqlError) {
2542
+ return { ok: false, error: gqlError, requestId: responseRequestId };
2543
+ }
2544
+ if (!response.ok) {
2545
+ return {
2546
+ ok: false,
2547
+ requestId: responseRequestId,
2548
+ error: {
2549
+ code: `http_${response.status}`,
2550
+ message: "Auth request failed.",
2551
+ status: response.status,
2552
+ details: { body: redactUnknown(graph, knownSecrets) }
2553
+ }
2554
+ };
2555
+ }
2556
+ const data = graph.data && typeof graph.data === "object" && !Array.isArray(graph.data) ? graph.data : {};
2557
+ return {
2558
+ ok: true,
2559
+ result: {
2560
+ status: response.status,
2561
+ requestId: responseRequestId,
2562
+ data
2563
+ }
2564
+ };
2565
+ } catch (error) {
2566
+ const message = error instanceof Error ? error.message : "Network error.";
2567
+ const timedOut = error instanceof Error && error.name === "AbortError";
2568
+ return {
2569
+ ok: false,
2570
+ requestId,
2571
+ error: {
2572
+ code: timedOut ? "timeout" : "network_error",
2573
+ message: redactSecrets(timedOut ? "Auth request timed out." : message, knownSecrets),
2574
+ status: timedOut ? 408 : 503,
2575
+ details: {}
2576
+ }
2577
+ };
2578
+ } finally {
2579
+ clearTimeout(timeoutId);
2580
+ }
2581
+ }
2582
+
2443
2583
  // src/commands/tasks.ts
2444
2584
  var projectIdSchema = z2.string().min(1);
2445
2585
  var idSchema = z2.string().min(1);
@@ -2468,6 +2608,44 @@ function parseTaskUpdateJson(raw) {
2468
2608
  function parseLabelIds(raw) {
2469
2609
  return raw.split(",").map((labelId) => labelId.trim()).filter((labelId) => labelId.length > 0);
2470
2610
  }
2611
+ function asRecord3(value) {
2612
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2613
+ return null;
2614
+ }
2615
+ return value;
2616
+ }
2617
+ function asNonEmptyString2(value) {
2618
+ if (typeof value !== "string") {
2619
+ return void 0;
2620
+ }
2621
+ const trimmed = value.trim();
2622
+ return trimmed.length > 0 ? trimmed : void 0;
2623
+ }
2624
+ async function resolveTaskReadOrganizationId(params) {
2625
+ const resolvedOrganizationId = asNonEmptyString2(params.organizationId);
2626
+ if (params.organizationIdSource === "flag" && resolvedOrganizationId) {
2627
+ return resolvedOrganizationId;
2628
+ }
2629
+ const baseUrl = asNonEmptyString2(params.runtimeOptions.baseUrl);
2630
+ const token = asNonEmptyString2(params.runtimeOptions.token);
2631
+ if (baseUrl && token) {
2632
+ const result = await authGraphqlRequest({
2633
+ baseUrl,
2634
+ token,
2635
+ timeoutMs: typeof params.runtimeOptions.timeoutMs === "number" ? params.runtimeOptions.timeoutMs : 1e4,
2636
+ query: "query WaveCliTaskReadOrganization { cliAuthStatus { authenticated baseAuthStatus organization { id slug } } }"
2637
+ });
2638
+ if (result.ok) {
2639
+ const status = asRecord3(result.result.data.cliAuthStatus);
2640
+ const organization = status ? asRecord3(status.organization) : null;
2641
+ const organizationId = organization ? asNonEmptyString2(organization.id) : void 0;
2642
+ if (organizationId) {
2643
+ return organizationId;
2644
+ }
2645
+ }
2646
+ }
2647
+ return resolveOrganizationId(resolvedOrganizationId);
2648
+ }
2471
2649
  function registerTaskCommands(program) {
2472
2650
  const tasks = program.command("tasks").description("Task operations");
2473
2651
  tasks.command("list").option("--project-id <projectId>").option("--page <page>").option("--per <per>").option("--team-id <teamId>").option("--team-ids <teamIds>").option("--member-id <memberId>").option("--meeting-id <meetingId>").option("--field-name <fieldName>").option("--field-value <fieldValue>").option("--field-blank <fieldBlank>").option("--open <open>").option("--rank-direction <rankDirection>").option("--include-archived <includeArchived>").action(async (opts, cmd) => {
@@ -2504,7 +2682,11 @@ function registerTaskCommands(program) {
2504
2682
  tasks.command("show").requiredOption("--id <id>").action(async (opts, cmd) => {
2505
2683
  const parsed = idSchema.parse(opts.id);
2506
2684
  const context = await resolveCommandContext(cmd.optsWithGlobals());
2507
- const organizationId = resolveOrganizationId(context.organizationId);
2685
+ const organizationId = await resolveTaskReadOrganizationId({
2686
+ organizationId: context.organizationId,
2687
+ organizationIdSource: context.organizationIdSource,
2688
+ runtimeOptions: context.runtimeOptions
2689
+ });
2508
2690
  await runGraphqlQueryCommand({
2509
2691
  command: "tasks.show",
2510
2692
  runtimeOptions: context.runtimeOptions,
@@ -3406,16 +3588,16 @@ var displayPreferenceAttributesSelectionSet = "attributes { id viewType favorite
3406
3588
  var filterPreferenceAttributesSelectionSet = "attributes { id filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId }";
3407
3589
  var healthUpdateSummarySelectionSet = "id type value memberId status createdAt updatedAt updatableType updatableId parentUpdateId emojis { id name memberId } resources { ...ResourceSummaryFull }";
3408
3590
  var projectShowFullSelectionSet = `{ id type name slug description status priority createdAt updatedAt startDate targetDate archivedAt memberId organizationId teamIds emoji { id name memberId } backgroundImage { backgroundType gradientStart gradientEnd gradientDegrees color imageUrl image { url lowUrl } } favorites { id memberId } resources { ...ResourceSummaryFull } displayPreference { id type ${displayPreferenceAttributesSelectionSet} viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId } filterPreferences { id type ${filterPreferenceAttributesSelectionSet} filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId } healthUpdates { ${healthUpdateSummarySelectionSet} replies { ${healthUpdateSummarySelectionSet} replies { id type } } } } fragment ResourceSummaryFull on ResourceSummary { id resourceType slug url skillId skill { id name slug emoji scope description } metadata { urlName imageUrl siteName providerName mediaType skillId skillName skillSlug skillScope skillEmoji skillDescription } attachment { id fileKey filename url } content { id name slug type firstChildSlug childCount } }`;
3409
- function asRecord3(value) {
3591
+ function asRecord4(value) {
3410
3592
  return value && typeof value === "object" ? value : null;
3411
3593
  }
3412
3594
  function toNonEmptyString(value) {
3413
3595
  return typeof value === "string" && value.trim() !== "" ? value : void 0;
3414
3596
  }
3415
3597
  function normalizeProjectRowForDisplay(row) {
3416
- const record = asRecord3(row);
3598
+ const record = asRecord4(row);
3417
3599
  if (!record) return row;
3418
- const attributes = asRecord3(record.attributes);
3600
+ const attributes = asRecord4(record.attributes);
3419
3601
  const topLevelName = toNonEmptyString(record.name);
3420
3602
  const topLevelTitle = toNonEmptyString(record.title);
3421
3603
  const attributeName = toNonEmptyString(attributes?.name);
@@ -3430,7 +3612,7 @@ function normalizeProjectRowForDisplay(row) {
3430
3612
  };
3431
3613
  }
3432
3614
  function normalizeProjectsListForDisplay(payload) {
3433
- const record = asRecord3(payload);
3615
+ const record = asRecord4(payload);
3434
3616
  if (!record || !Array.isArray(record.data)) return payload;
3435
3617
  return {
3436
3618
  ...record,
@@ -3638,7 +3820,7 @@ var MEETING_STATUSES = /* @__PURE__ */ new Set(["upcoming", "active", "completed
3638
3820
  var MEETING_REPEATS = /* @__PURE__ */ new Set(["never", "weekly", "biweekly", "monthly", "quarterly"]);
3639
3821
  var createHelp2 = buildDataJsonHelp("meeting", "create") ?? 'JSON object for meeting or {"meeting": {...}}';
3640
3822
  var updateHelp2 = buildDataJsonHelp("meeting", "update") ?? 'JSON object for meeting or {"meeting": {...}}';
3641
- function asNonEmptyString2(value) {
3823
+ function asNonEmptyString3(value) {
3642
3824
  if (typeof value !== "string") {
3643
3825
  return void 0;
3644
3826
  }
@@ -3696,7 +3878,7 @@ function normalizeMeetingCreateBody(body) {
3696
3878
  });
3697
3879
  }
3698
3880
  const meeting = { ...entity };
3699
- const type = asNonEmptyString2(meeting.type);
3881
+ const type = asNonEmptyString3(meeting.type);
3700
3882
  if (!type || !MEETING_TYPES.has(type)) {
3701
3883
  throw new CliError({
3702
3884
  message: "Invalid meeting.type. Use one of: TeamMeeting, OneOnOneMeeting.",
@@ -3706,8 +3888,8 @@ function normalizeMeetingCreateBody(body) {
3706
3888
  details: { field: "meeting.type", allowed: Array.from(MEETING_TYPES) }
3707
3889
  });
3708
3890
  }
3709
- const memberId = asNonEmptyString2(meeting.member_id);
3710
- const date = asNonEmptyString2(meeting.date);
3891
+ const memberId = asNonEmptyString3(meeting.member_id);
3892
+ const date = asNonEmptyString3(meeting.date);
3711
3893
  const startTime = toFiniteNumber(meeting.start_time, "meeting.start_time");
3712
3894
  const missingRequired = [];
3713
3895
  if (!memberId) missingRequired.push("member_id");
@@ -3722,7 +3904,7 @@ function normalizeMeetingCreateBody(body) {
3722
3904
  details: { requiredFields: ["member_id", "date", "start_time"], rootKey: "meeting" }
3723
3905
  });
3724
3906
  }
3725
- const status = asNonEmptyString2(meeting.status);
3907
+ const status = asNonEmptyString3(meeting.status);
3726
3908
  if (status && !MEETING_STATUSES.has(status)) {
3727
3909
  throw new CliError({
3728
3910
  message: "Invalid meeting.status. Use one of: upcoming, active, completed.",
@@ -3732,7 +3914,7 @@ function normalizeMeetingCreateBody(body) {
3732
3914
  details: { field: "meeting.status", allowed: Array.from(MEETING_STATUSES) }
3733
3915
  });
3734
3916
  }
3735
- const repeats = asNonEmptyString2(meeting.repeats) ?? "never";
3917
+ const repeats = asNonEmptyString3(meeting.repeats) ?? "never";
3736
3918
  if (!MEETING_REPEATS.has(repeats)) {
3737
3919
  throw new CliError({
3738
3920
  message: "Invalid meeting.repeats. Use one of: never, weekly, biweekly, monthly, quarterly.",
@@ -4021,7 +4203,7 @@ var SKILL_SELECTION = `{
4021
4203
  createdAt
4022
4204
  updatedAt
4023
4205
  }`;
4024
- function asRecord4(value) {
4206
+ function asRecord5(value) {
4025
4207
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
4026
4208
  }
4027
4209
  function findSkillById(id) {
@@ -4029,7 +4211,7 @@ function findSkillById(id) {
4029
4211
  if (!Array.isArray(payload)) {
4030
4212
  return null;
4031
4213
  }
4032
- return payload.find((entry2) => String(asRecord4(entry2)?.id ?? "") === id) ?? null;
4214
+ return payload.find((entry2) => String(asRecord5(entry2)?.id ?? "") === id) ?? null;
4033
4215
  };
4034
4216
  }
4035
4217
  function registerSkillCommands(program) {
@@ -4421,7 +4603,7 @@ function normalizeTodosCreateBody(body) {
4421
4603
  }
4422
4604
  return { ...body, todo };
4423
4605
  }
4424
- function asNonEmptyString3(value) {
4606
+ function asNonEmptyString4(value) {
4425
4607
  if (typeof value !== "string") {
4426
4608
  return void 0;
4427
4609
  }
@@ -4429,7 +4611,7 @@ function asNonEmptyString3(value) {
4429
4611
  return trimmed.length > 0 ? trimmed : void 0;
4430
4612
  }
4431
4613
  function validateEnumField(params) {
4432
- const value = asNonEmptyString3(params.rawValue);
4614
+ const value = asNonEmptyString4(params.rawValue);
4433
4615
  if (!value) {
4434
4616
  return void 0;
4435
4617
  }
@@ -4463,7 +4645,7 @@ function normalizeKnowledgeCreateBody(body) {
4463
4645
  message: "Invalid content.status. Use one of: draft, published."
4464
4646
  });
4465
4647
  content.status = status ?? "draft";
4466
- const memberId = asNonEmptyString3(content.member_id);
4648
+ const memberId = asNonEmptyString4(content.member_id);
4467
4649
  if (!memberId) {
4468
4650
  throwMissingRequiredCreateFields("content", ["member_id"]);
4469
4651
  }
@@ -4472,7 +4654,7 @@ function normalizeKnowledgeCreateBody(body) {
4472
4654
  }
4473
4655
  function normalizeNewsCreateBody(body) {
4474
4656
  const headline = ensureEntityObject(body, "headline");
4475
- const memberId = asNonEmptyString3(headline.member_id);
4657
+ const memberId = asNonEmptyString4(headline.member_id);
4476
4658
  if (!memberId) {
4477
4659
  throwMissingRequiredCreateFields("headline", ["member_id"]);
4478
4660
  }
@@ -4501,14 +4683,14 @@ function normalizeNewsCreateBody(body) {
4501
4683
  }
4502
4684
  function normalizeQuestionsCreateBody(body) {
4503
4685
  const question = ensureEntityObject(body, "question");
4504
- const summary = asNonEmptyString3(question.summary);
4505
- const currentName = asNonEmptyString3(question.name);
4686
+ const summary = asNonEmptyString4(question.summary);
4687
+ const currentName = asNonEmptyString4(question.name);
4506
4688
  if (!currentName && summary) {
4507
4689
  question.name = summary;
4508
4690
  }
4509
4691
  delete question.summary;
4510
- const name = asNonEmptyString3(question.name);
4511
- const memberId = asNonEmptyString3(question.member_id);
4692
+ const name = asNonEmptyString4(question.name);
4693
+ const memberId = asNonEmptyString4(question.member_id);
4512
4694
  const missing = [];
4513
4695
  if (!name) missing.push("name");
4514
4696
  if (!memberId) missing.push("member_id");
@@ -4530,13 +4712,13 @@ function normalizeQuestionsCreateBody(body) {
4530
4712
  }
4531
4713
  function normalizeQuestionsUpdateBody(body) {
4532
4714
  const question = ensureEntityObject(body, "question");
4533
- const summary = asNonEmptyString3(question.summary);
4534
- const currentName = asNonEmptyString3(question.name);
4715
+ const summary = asNonEmptyString4(question.summary);
4716
+ const currentName = asNonEmptyString4(question.name);
4535
4717
  if (!currentName && summary) {
4536
4718
  question.name = summary;
4537
4719
  }
4538
4720
  delete question.summary;
4539
- const name = asNonEmptyString3(question.name);
4721
+ const name = asNonEmptyString4(question.name);
4540
4722
  if (name) {
4541
4723
  question.name = name;
4542
4724
  }
@@ -4553,9 +4735,9 @@ function normalizeQuestionsUpdateBody(body) {
4553
4735
  }
4554
4736
  function normalizePulseCreateBody(body) {
4555
4737
  const healthUpdate = ensureEntityObject(body, "health_update");
4556
- const healthUpdatableId = asNonEmptyString3(healthUpdate.health_updatable_id) ?? asNonEmptyString3(healthUpdate.updatable_id);
4557
- const healthUpdatableType = asNonEmptyString3(healthUpdate.health_updatable_type) ?? asNonEmptyString3(healthUpdate.updatable_type);
4558
- const memberId = asNonEmptyString3(healthUpdate.member_id);
4738
+ const healthUpdatableId = asNonEmptyString4(healthUpdate.health_updatable_id) ?? asNonEmptyString4(healthUpdate.updatable_id);
4739
+ const healthUpdatableType = asNonEmptyString4(healthUpdate.health_updatable_type) ?? asNonEmptyString4(healthUpdate.updatable_type);
4740
+ const memberId = asNonEmptyString4(healthUpdate.member_id);
4559
4741
  const status = validateEnumField({
4560
4742
  rawValue: healthUpdate.status,
4561
4743
  field: "health_update.status",
@@ -4580,8 +4762,8 @@ function normalizePulseCreateBody(body) {
4580
4762
  }
4581
4763
  function normalizeSurveysCreateBody(body) {
4582
4764
  const survey = ensureEntityObject(body, "survey");
4583
- const title = asNonEmptyString3(survey.title);
4584
- const currentName = asNonEmptyString3(survey.name);
4765
+ const title = asNonEmptyString4(survey.title);
4766
+ const currentName = asNonEmptyString4(survey.name);
4585
4767
  if (!currentName && title) {
4586
4768
  survey.name = title;
4587
4769
  }
@@ -4610,8 +4792,8 @@ function normalizeSurveysCreateBody(body) {
4610
4792
  }
4611
4793
  function normalizeSurveysUpdateBody(body) {
4612
4794
  const survey = ensureEntityObject(body, "survey");
4613
- const title = asNonEmptyString3(survey.title);
4614
- const currentName = asNonEmptyString3(survey.name);
4795
+ const title = asNonEmptyString4(survey.title);
4796
+ const currentName = asNonEmptyString4(survey.name);
4615
4797
  if (!currentName && title) {
4616
4798
  survey.name = title;
4617
4799
  }
@@ -4638,8 +4820,8 @@ function normalizeSurveysUpdateBody(body) {
4638
4820
  }
4639
4821
  function normalizeFeedbacksCreateBody(body) {
4640
4822
  const feedback = ensureEntityObject(body, "feedback");
4641
- const title = asNonEmptyString3(feedback.title);
4642
- const currentName = asNonEmptyString3(feedback.name);
4823
+ const title = asNonEmptyString4(feedback.title);
4824
+ const currentName = asNonEmptyString4(feedback.name);
4643
4825
  if (!currentName && title) {
4644
4826
  feedback.name = title;
4645
4827
  }
@@ -4656,7 +4838,7 @@ function normalizeFeedbacksCreateBody(body) {
4656
4838
  allowed: FEEDBACK_QUARTERS,
4657
4839
  message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
4658
4840
  });
4659
- const year = asNonEmptyString3(feedback.year);
4841
+ const year = asNonEmptyString4(feedback.year);
4660
4842
  const missing = [];
4661
4843
  if (!name) missing.push("name");
4662
4844
  if (!quarter) missing.push("quarter");
@@ -4671,8 +4853,8 @@ function normalizeFeedbacksCreateBody(body) {
4671
4853
  }
4672
4854
  function normalizeFeedbacksUpdateBody(body) {
4673
4855
  const feedback = ensureEntityObject(body, "feedback");
4674
- const title = asNonEmptyString3(feedback.title);
4675
- const currentName = asNonEmptyString3(feedback.name);
4856
+ const title = asNonEmptyString4(feedback.title);
4857
+ const currentName = asNonEmptyString4(feedback.name);
4676
4858
  if (!currentName && title) {
4677
4859
  feedback.name = title;
4678
4860
  }
@@ -4699,14 +4881,14 @@ function normalizeFeedbacksUpdateBody(body) {
4699
4881
  }
4700
4882
  function normalizeAccountabilityCreateBody(body) {
4701
4883
  const responsibility = ensureEntityObject(body, "responsibility");
4702
- const summary = asNonEmptyString3(responsibility.summary);
4703
- const currentName = asNonEmptyString3(responsibility.name);
4884
+ const summary = asNonEmptyString4(responsibility.summary);
4885
+ const currentName = asNonEmptyString4(responsibility.name);
4704
4886
  if (!currentName && summary) {
4705
4887
  responsibility.name = summary;
4706
4888
  }
4707
4889
  delete responsibility.summary;
4708
- const name = asNonEmptyString3(responsibility.name);
4709
- const memberId = asNonEmptyString3(responsibility.member_id);
4890
+ const name = asNonEmptyString4(responsibility.name);
4891
+ const memberId = asNonEmptyString4(responsibility.member_id);
4710
4892
  const missing = [];
4711
4893
  if (!name) missing.push("name");
4712
4894
  if (!memberId) missing.push("member_id");
@@ -4721,8 +4903,8 @@ function normalizeAccountabilityCreateBody(body) {
4721
4903
  }
4722
4904
  function normalizeAccountabilityUpdateBody(body) {
4723
4905
  const responsibility = ensureEntityObject(body, "responsibility");
4724
- const summary = asNonEmptyString3(responsibility.summary);
4725
- const currentName = asNonEmptyString3(responsibility.name);
4906
+ const summary = asNonEmptyString4(responsibility.summary);
4907
+ const currentName = asNonEmptyString4(responsibility.name);
4726
4908
  if (!currentName && summary) {
4727
4909
  responsibility.name = summary;
4728
4910
  }
@@ -4754,7 +4936,7 @@ function parseSmartKpiViewCreateBody(raw) {
4754
4936
  }
4755
4937
  function normalizeSmartKpiViewCreateBody(body) {
4756
4938
  const smartKpiView = ensureEntityObject(body, "smart_kpi_view");
4757
- const name = asNonEmptyString3(smartKpiView.name);
4939
+ const name = asNonEmptyString4(smartKpiView.name);
4758
4940
  if (!name) {
4759
4941
  throwMissingRequiredCreateFields("smart_kpi_view", ["name"]);
4760
4942
  }
@@ -4792,9 +4974,9 @@ function buildKpisCreateMutation(params) {
4792
4974
  });
4793
4975
  }
4794
4976
  const smartKpi = { ...entity };
4795
- const name = asNonEmptyString3(smartKpi.name);
4796
- const smartKpiViewId = asNonEmptyString3(smartKpi.smart_kpi_view_id);
4797
- const measurableGroupId = asNonEmptyString3(smartKpi.measurable_group_id);
4977
+ const name = asNonEmptyString4(smartKpi.name);
4978
+ const smartKpiViewId = asNonEmptyString4(smartKpi.smart_kpi_view_id);
4979
+ const measurableGroupId = asNonEmptyString4(smartKpi.measurable_group_id);
4798
4980
  const hasAllowedName = typeof name === "string" && SMART_KPI_NAME_SET.has(name);
4799
4981
  if (!name) {
4800
4982
  throw new CliError({
@@ -4814,7 +4996,7 @@ function buildKpisCreateMutation(params) {
4814
4996
  measurable_type: "number",
4815
4997
  condition: "greater_than_or_equal_to"
4816
4998
  };
4817
- const notes = asNonEmptyString3(smartKpi.notes);
4999
+ const notes = asNonEmptyString4(smartKpi.notes);
4818
5000
  if (notes) {
4819
5001
  measurable.notes = notes;
4820
5002
  }
@@ -5217,7 +5399,7 @@ function ensureRootObject(body, rootKey) {
5217
5399
  }
5218
5400
  return { ...root };
5219
5401
  }
5220
- function asNonEmptyString4(value) {
5402
+ function asNonEmptyString5(value) {
5221
5403
  if (typeof value !== "string") {
5222
5404
  return void 0;
5223
5405
  }
@@ -5227,7 +5409,7 @@ function asNonEmptyString4(value) {
5227
5409
  function normalizeOrganizationUpdateBody(body) {
5228
5410
  const organization = ensureRootObject(body, "organization");
5229
5411
  const detail = isRecord3(organization.organization_detail_attributes) ? { ...organization.organization_detail_attributes } : {};
5230
- const workspaceName = asNonEmptyString4(organization.workspace_name);
5412
+ const workspaceName = asNonEmptyString5(organization.workspace_name);
5231
5413
  if (workspaceName) {
5232
5414
  detail.workspace_name = workspaceName;
5233
5415
  }
@@ -5240,7 +5422,7 @@ function normalizeOrganizationUpdateBody(body) {
5240
5422
  function normalizeOrganizationMetaProfileUpdateBody(body) {
5241
5423
  const root = ensureRootObject(body, "organization_meta_profile");
5242
5424
  const profile = isRecord3(root.profile) ? { ...root.profile } : {};
5243
- const title = asNonEmptyString4(root.title);
5425
+ const title = asNonEmptyString5(root.title);
5244
5426
  if (title) {
5245
5427
  const companyIdentity = isRecord3(profile.company_identity) ? { ...profile.company_identity } : {};
5246
5428
  companyIdentity.one_sentence_summary = title;
@@ -5270,7 +5452,7 @@ function normalizeOrganizationMetaProfileUpdateBody(body) {
5270
5452
  function normalizeKeyMetricMetaProfileUpdateBody(body) {
5271
5453
  const root = ensureRootObject(body, "key_metric_meta_profile");
5272
5454
  const profile = isRecord3(root.profile) ? { ...root.profile } : {};
5273
- const annualRevenue = asNonEmptyString4(root.annual_revenue);
5455
+ const annualRevenue = asNonEmptyString5(root.annual_revenue);
5274
5456
  if (annualRevenue) {
5275
5457
  const financial = isRecord3(profile.financial) ? { ...profile.financial } : {};
5276
5458
  financial.revenue = annualRevenue;
@@ -5441,7 +5623,7 @@ function ensureRootObject2(body, rootKey) {
5441
5623
  }
5442
5624
  return { ...root };
5443
5625
  }
5444
- function asNonEmptyString5(value) {
5626
+ function asNonEmptyString6(value) {
5445
5627
  if (typeof value !== "string") {
5446
5628
  return void 0;
5447
5629
  }
@@ -5469,8 +5651,8 @@ function normalizeStrategicPlanUpdateBody(body) {
5469
5651
  }
5470
5652
  function normalizeStrategicObjectiveUpdateBody(body) {
5471
5653
  const strategicObjective = ensureRootObject2(body, "strategic_objective");
5472
- const title = asNonEmptyString5(strategicObjective.title);
5473
- if (!asNonEmptyString5(strategicObjective.summary) && title) {
5654
+ const title = asNonEmptyString6(strategicObjective.title);
5655
+ if (!asNonEmptyString6(strategicObjective.summary) && title) {
5474
5656
  strategicObjective.summary = title;
5475
5657
  }
5476
5658
  delete strategicObjective.title;
@@ -5493,8 +5675,8 @@ function normalizeStrategicObjectiveUpdateBody(body) {
5493
5675
  }
5494
5676
  function normalizeAnnualObjectiveCreateBody(body) {
5495
5677
  const annualObjective = ensureRootObject2(body, "annual_objective");
5496
- const title = asNonEmptyString5(annualObjective.title);
5497
- if (!asNonEmptyString5(annualObjective.name) && title) {
5678
+ const title = asNonEmptyString6(annualObjective.title);
5679
+ if (!asNonEmptyString6(annualObjective.name) && title) {
5498
5680
  annualObjective.name = title;
5499
5681
  }
5500
5682
  delete annualObjective.title;
@@ -5502,8 +5684,8 @@ function normalizeAnnualObjectiveCreateBody(body) {
5502
5684
  }
5503
5685
  function normalizeQuarterlyObjectiveCreateBody(body) {
5504
5686
  const quarterlyObjective = ensureRootObject2(body, "quarterly_objective");
5505
- const title = asNonEmptyString5(quarterlyObjective.title);
5506
- if (!asNonEmptyString5(quarterlyObjective.name) && title) {
5687
+ const title = asNonEmptyString6(quarterlyObjective.title);
5688
+ if (!asNonEmptyString6(quarterlyObjective.name) && title) {
5507
5689
  quarterlyObjective.name = title;
5508
5690
  }
5509
5691
  delete quarterlyObjective.title;
@@ -6304,7 +6486,7 @@ import { z as z16 } from "zod";
6304
6486
 
6305
6487
  // src/internalOptions.ts
6306
6488
  var INTERNAL_OPTIONS_KEY = "__waveInternalOptions";
6307
- function asRecord5(value) {
6489
+ function asRecord6(value) {
6308
6490
  if (!value || typeof value !== "object" || Array.isArray(value)) {
6309
6491
  return null;
6310
6492
  }
@@ -6318,7 +6500,7 @@ function setInternalCliOptions(program, options) {
6318
6500
  function getInternalCliOptions(command) {
6319
6501
  let current = command;
6320
6502
  while (current) {
6321
- const record = asRecord5(current[INTERNAL_OPTIONS_KEY]);
6503
+ const record = asRecord6(current[INTERNAL_OPTIONS_KEY]);
6322
6504
  if (record) {
6323
6505
  return {
6324
6506
  enableRetryOnEmptyPhrase: record.enableRetryOnEmptyPhrase === true
@@ -9963,142 +10145,6 @@ function registerOsmdCommands(program) {
9963
10145
 
9964
10146
  // src/commands/auth.ts
9965
10147
  import { spawn } from "child_process";
9966
-
9967
- // src/authClient.ts
9968
- import { randomUUID as randomUUID2 } from "crypto";
9969
-
9970
- // src/redaction.ts
9971
- var TOKENISH_PATTERNS = [
9972
- /\b(?:cli|wave|token|secret|bearer)[A-Za-z0-9._~+/=-]{8,}\b/gi,
9973
- /\b[A-Za-z0-9._~+/=-]{24,}\b/g
9974
- ];
9975
- function redactOne(value) {
9976
- if (value.length <= 8) {
9977
- return "[redacted]";
9978
- }
9979
- return `${value.slice(0, 4)}...[redacted]...${value.slice(-4)}`;
9980
- }
9981
- function redactSecrets(input, knownSecrets = []) {
9982
- let output = input;
9983
- for (const secret of knownSecrets) {
9984
- if (!secret) continue;
9985
- output = output.split(secret).join(redactOne(secret));
9986
- }
9987
- for (const pattern of TOKENISH_PATTERNS) {
9988
- output = output.replace(pattern, (match) => redactOne(match));
9989
- }
9990
- return output;
9991
- }
9992
- function redactUnknown(input, knownSecrets = []) {
9993
- if (typeof input === "string") {
9994
- return redactSecrets(input, knownSecrets);
9995
- }
9996
- if (Array.isArray(input)) {
9997
- return input.map((entry2) => redactUnknown(entry2, knownSecrets));
9998
- }
9999
- if (!input || typeof input !== "object") {
10000
- return input;
10001
- }
10002
- const output = {};
10003
- for (const [key, value] of Object.entries(input)) {
10004
- if (/token|secret|authorization|bearer/i.test(key)) {
10005
- output[key] = typeof value === "string" ? redactSecrets(value, knownSecrets) : "[redacted]";
10006
- continue;
10007
- }
10008
- output[key] = redactUnknown(value, knownSecrets);
10009
- }
10010
- return output;
10011
- }
10012
-
10013
- // src/authClient.ts
10014
- function parseJsonSafely2(input) {
10015
- try {
10016
- return JSON.parse(input);
10017
- } catch {
10018
- return null;
10019
- }
10020
- }
10021
- function graphqlErrors(payload, knownSecrets) {
10022
- const errors = payload.errors;
10023
- if (!Array.isArray(errors) || errors.length === 0) return null;
10024
- return {
10025
- code: "upstream_error",
10026
- message: "GraphQL request failed.",
10027
- status: 400,
10028
- details: {
10029
- errors: redactUnknown(errors, knownSecrets)
10030
- }
10031
- };
10032
- }
10033
- async function authGraphqlRequest(params) {
10034
- const requestId = randomUUID2();
10035
- const controller = new AbortController();
10036
- const timeoutId = setTimeout(() => controller.abort(), params.timeoutMs);
10037
- const knownSecrets = [params.token, ...params.knownSecrets ?? []].filter(
10038
- (secret) => typeof secret === "string" && secret.length > 0
10039
- );
10040
- try {
10041
- const url = new URL("/graphql", params.baseUrl);
10042
- const response = await fetch(url, {
10043
- method: "POST",
10044
- headers: {
10045
- Accept: "application/json",
10046
- "Content-Type": "application/json",
10047
- "X-Origin": "wave-cli",
10048
- "X-Request-Id": requestId,
10049
- ...params.token ? { Authorization: `Bearer ${params.token}` } : {}
10050
- },
10051
- body: JSON.stringify({ query: params.query, variables: params.variables ?? {} }),
10052
- signal: controller.signal
10053
- });
10054
- const responseRequestId = response.headers.get("x-request-id") ?? requestId;
10055
- const text = await response.text();
10056
- const payload = text ? parseJsonSafely2(text) : null;
10057
- const graph = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
10058
- const gqlError = graphqlErrors(graph, knownSecrets);
10059
- if (gqlError) {
10060
- return { ok: false, error: gqlError, requestId: responseRequestId };
10061
- }
10062
- if (!response.ok) {
10063
- return {
10064
- ok: false,
10065
- requestId: responseRequestId,
10066
- error: {
10067
- code: `http_${response.status}`,
10068
- message: "Auth request failed.",
10069
- status: response.status,
10070
- details: { body: redactUnknown(graph, knownSecrets) }
10071
- }
10072
- };
10073
- }
10074
- const data = graph.data && typeof graph.data === "object" && !Array.isArray(graph.data) ? graph.data : {};
10075
- return {
10076
- ok: true,
10077
- result: {
10078
- status: response.status,
10079
- requestId: responseRequestId,
10080
- data
10081
- }
10082
- };
10083
- } catch (error) {
10084
- const message = error instanceof Error ? error.message : "Network error.";
10085
- const timedOut = error instanceof Error && error.name === "AbortError";
10086
- return {
10087
- ok: false,
10088
- requestId,
10089
- error: {
10090
- code: timedOut ? "timeout" : "network_error",
10091
- message: redactSecrets(timedOut ? "Auth request timed out." : message, knownSecrets),
10092
- status: timedOut ? 408 : 503,
10093
- details: {}
10094
- }
10095
- };
10096
- } finally {
10097
- clearTimeout(timeoutId);
10098
- }
10099
- }
10100
-
10101
- // src/commands/auth.ts
10102
10148
  var DEFAULT_LOGIN_TIMEOUT_MS = 12e4;
10103
10149
  var DEFAULT_POLL_INTERVAL_MS = 2e3;
10104
10150
  function envelope(params) {
@@ -10126,7 +10172,7 @@ function positiveInt2(raw, fallback) {
10126
10172
  function requestTimeoutMs(totalTimeoutMs) {
10127
10173
  return Math.max(1e3, Math.min(totalTimeoutMs, 1e4));
10128
10174
  }
10129
- function asRecord6(value) {
10175
+ function asRecord7(value) {
10130
10176
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
10131
10177
  }
10132
10178
  function asString(value) {
@@ -10173,9 +10219,9 @@ function cliTokenFromPoll(payload) {
10173
10219
  return asString(payload.cliToken) ?? asString(payload.cli_token) ?? asString(payload.token);
10174
10220
  }
10175
10221
  function unwrapMutationResult(value) {
10176
- const record = asRecord6(value);
10222
+ const record = asRecord7(value);
10177
10223
  if (!record) return null;
10178
- const data = asRecord6(record.data);
10224
+ const data = asRecord7(record.data);
10179
10225
  if (data && (Object.prototype.hasOwnProperty.call(record, "ok") || Object.prototype.hasOwnProperty.call(record, "errors") || Object.prototype.hasOwnProperty.call(record, "errorCode") || Object.prototype.hasOwnProperty.call(record, "error_code"))) {
10180
10226
  return data;
10181
10227
  }
@@ -10239,7 +10285,7 @@ async function runTokenLogin(cmd, opts) {
10239
10285
  exitCode: mapStatusToExitCode(status.error.status)
10240
10286
  });
10241
10287
  }
10242
- const statusData = asRecord6(status.result.data.cliAuthStatus) ?? {};
10288
+ const statusData = asRecord7(status.result.data.cliAuthStatus) ?? {};
10243
10289
  const storage = await writeStoredToken(token, baseUrl);
10244
10290
  const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
10245
10291
  return printEnvelopeAndExit({
@@ -10456,7 +10502,7 @@ async function runLogout(cmd) {
10456
10502
  });
10457
10503
  if (result.ok) {
10458
10504
  requestId = result.result.requestId;
10459
- const payload = asRecord6(result.result.data.revokeCliToken) ?? {};
10505
+ const payload = asRecord7(result.result.data.revokeCliToken) ?? {};
10460
10506
  revokedRemote = payload.ok !== false;
10461
10507
  } else {
10462
10508
  requestId = result.requestId;
@@ -10519,7 +10565,8 @@ async function runAuthStatus(cmd) {
10519
10565
  exitCode: mapStatusToExitCode(result.error.status)
10520
10566
  });
10521
10567
  }
10522
- const status = asRecord6(result.result.data.cliAuthStatus) ?? {};
10568
+ const status = asRecord7(result.result.data.cliAuthStatus) ?? {};
10569
+ const baseAuthStatus = status.baseAuthStatus;
10523
10570
  return printEnvelopeAndExit({
10524
10571
  envelope: envelope({
10525
10572
  ok: true,
@@ -10528,6 +10575,7 @@ async function runAuthStatus(cmd) {
10528
10575
  requestId: result.result.requestId,
10529
10576
  data: {
10530
10577
  authenticated: Boolean(status.authenticated),
10578
+ baseAuthStatus: typeof baseAuthStatus === "string" ? baseAuthStatus : null,
10531
10579
  baseUrl,
10532
10580
  tokenSource,
10533
10581
  member: redactUnknown(status.member, [token]) ?? null,
@@ -12168,11 +12216,11 @@ function sanitizePlannerJson(value) {
12168
12216
  }
12169
12217
  return output;
12170
12218
  }
12171
- function asRecord7(value) {
12219
+ function asRecord8(value) {
12172
12220
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
12173
12221
  }
12174
12222
  function readPlannerStateKey(value, keys) {
12175
- const record = asRecord7(value);
12223
+ const record = asRecord8(value);
12176
12224
  if (!record) {
12177
12225
  return null;
12178
12226
  }
@@ -15797,7 +15845,7 @@ function attachDiscoveryHelp(program) {
15797
15845
  }
15798
15846
 
15799
15847
  // src/version.ts
15800
- var CLI_VERSION = "0.1.60";
15848
+ var CLI_VERSION = "0.1.61";
15801
15849
 
15802
15850
  // src/cli.ts
15803
15851
  function buildCli(options) {