@odla-ai/cli 0.25.19 → 0.25.21

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/index.cjs CHANGED
@@ -142,22 +142,22 @@ function readJsonFile(path) {
142
142
  return null;
143
143
  }
144
144
  }
145
- function writePrivateJson(path, value) {
146
- writePrivateText(path, `${JSON.stringify(value, null, 2)}
145
+ function writePrivateJson(path, value2) {
146
+ writePrivateText(path, `${JSON.stringify(value2, null, 2)}
147
147
  `);
148
148
  }
149
149
  function readCredentials(path) {
150
150
  if (!(0, import_node_fs.existsSync)(path)) return null;
151
- let value;
151
+ let value2;
152
152
  try {
153
- value = JSON.parse((0, import_node_fs.readFileSync)(path, "utf8"));
153
+ value2 = JSON.parse((0, import_node_fs.readFileSync)(path, "utf8"));
154
154
  } catch {
155
155
  throw new Error(`credentials file ${path} is not valid JSON; fix or remove it before provisioning`);
156
156
  }
157
- if (!value || typeof value !== "object" || typeof value.appId !== "string" || !value.envs || typeof value.envs !== "object") {
157
+ if (!value2 || typeof value2 !== "object" || typeof value2.appId !== "string" || !value2.envs || typeof value2.envs !== "object") {
158
158
  throw new Error(`credentials file ${path} has an invalid shape; fix or remove it before provisioning`);
159
159
  }
160
- return value;
160
+ return value2;
161
161
  }
162
162
  function mergeCredential(current, update) {
163
163
  const next = current ?? {
@@ -452,8 +452,8 @@ function stillPending(pending, email) {
452
452
  { retryable: true }
453
453
  );
454
454
  }
455
- function handshakeEmail(value, cached) {
456
- const email = (value ?? import_node_process3.default.env.ODLA_USER_EMAIL ?? cached ?? "").trim().toLowerCase();
455
+ function handshakeEmail(value2, cached) {
456
+ const email = (value2 ?? import_node_process3.default.env.ODLA_USER_EMAIL ?? cached ?? "").trim().toLowerCase();
457
457
  if (email.length > 254 || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
458
458
  throw new Error("a fresh odla handshake requires --email <account> or ODLA_USER_EMAIL");
459
459
  }
@@ -477,10 +477,10 @@ function handshakeUrl(platformUrl, userCode) {
477
477
  url.searchParams.set("code", userCode);
478
478
  return url.toString();
479
479
  }
480
- function platformAudience(value) {
480
+ function platformAudience(value2) {
481
481
  let url;
482
482
  try {
483
- url = new URL(value);
483
+ url = new URL(value2);
484
484
  } catch {
485
485
  throw new Error("platform must be an absolute URL");
486
486
  }
@@ -499,22 +499,22 @@ var import_node_process4 = __toESM(require("process"), 1);
499
499
  var MAX_BYTES = 64 * 1024;
500
500
  async function secretInputValue(options, kind = "credential") {
501
501
  if (options.fromEnv && options.stdin) throw new Error("choose exactly one of --from-env or --stdin");
502
- let value;
503
- if (options.fromEnv) value = import_node_process4.default.env[options.fromEnv];
504
- else if (options.stdin) value = await (options.readStdin ?? (() => readSecretStream(kind)))();
502
+ let value2;
503
+ if (options.fromEnv) value2 = import_node_process4.default.env[options.fromEnv];
504
+ else if (options.stdin) value2 = await (options.readStdin ?? (() => readSecretStream(kind)))();
505
505
  else throw new Error(`${kind} input required: use --from-env <NAME> or --stdin; values are never accepted as arguments`);
506
- value = value?.replace(/[\r\n]+$/, "");
507
- if (!value) throw new Error(options.fromEnv ? `environment variable ${options.fromEnv} is empty or unset` : `stdin ${kind} is empty`);
508
- if (new TextEncoder().encode(value).byteLength > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
509
- return value;
506
+ value2 = value2?.replace(/[\r\n]+$/, "");
507
+ if (!value2) throw new Error(options.fromEnv ? `environment variable ${options.fromEnv} is empty or unset` : `stdin ${kind} is empty`);
508
+ if (new TextEncoder().encode(value2).byteLength > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
509
+ return value2;
510
510
  }
511
511
  async function readSecretStream(kind, stream = import_node_process4.default.stdin) {
512
- let value = "";
512
+ let value2 = "";
513
513
  for await (const chunk of stream) {
514
- value += String(chunk);
515
- if (value.length > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
514
+ value2 += String(chunk);
515
+ if (value2.length > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
516
516
  }
517
- return value;
517
+ return value2;
518
518
  }
519
519
 
520
520
  // src/admin-ai-auth.ts
@@ -549,6 +549,7 @@ function audienceBoundEnvToken(token, platform) {
549
549
  return token;
550
550
  }
551
551
  var SCOPE_PURPOSE = {
552
+ "platform:status:read": "read the platform fleet health and deployment snapshot",
552
553
  "platform:runbook:write": "add or edit odla's operational runbooks",
553
554
  "platform:ai:policy:write": "change System AI model routing",
554
555
  "platform:ai:policy:read": "read System AI model routing",
@@ -652,13 +653,13 @@ function apiError(status, body) {
652
653
  const message2 = error && typeof error.message === "string" ? error.message : isRecord(body) && typeof body.message === "string" ? body.message : "request failed";
653
654
  return `read System AI admin changes failed (${status}): ${message2}`;
654
655
  }
655
- function timestamp(value) {
656
- if (typeof value !== "number" || !Number.isFinite(value)) return String(value ?? "");
657
- const date = new Date(value);
656
+ function timestamp(value2) {
657
+ if (typeof value2 !== "number" || !Number.isFinite(value2)) return String(value2 ?? "");
658
+ const date = new Date(value2);
658
659
  return Number.isFinite(date.valueOf()) ? date.toISOString() : "";
659
660
  }
660
- function isRecord(value) {
661
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
661
+ function isRecord(value2) {
662
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
662
663
  }
663
664
 
664
665
  // src/admin-ai-policy.ts
@@ -668,11 +669,11 @@ var SYSTEM_AI_PURPOSES = [
668
669
  "security.validation",
669
670
  "runbook.answer"
670
671
  ];
671
- function requireSystemAiPurpose(value) {
672
- if (!SYSTEM_AI_PURPOSES.includes(value)) {
672
+ function requireSystemAiPurpose(value2) {
673
+ if (!SYSTEM_AI_PURPOSES.includes(value2)) {
673
674
  throw new Error(`purpose must be one of: ${SYSTEM_AI_PURPOSES.join(", ")}`);
674
675
  }
675
- return value;
676
+ return value2;
676
677
  }
677
678
 
678
679
  // src/admin-ai-usage.ts
@@ -694,11 +695,11 @@ async function readAdminAiUsage(request2) {
694
695
  if (request2.json) request2.stdout.log(JSON.stringify(body, null, 2));
695
696
  else printUsage(body, request2.stdout);
696
697
  }
697
- function usageLimit(value) {
698
- if (!Number.isSafeInteger(value) || value < 1 || value > 500) {
698
+ function usageLimit(value2) {
699
+ if (!Number.isSafeInteger(value2) || value2 < 1 || value2 > 500) {
699
700
  throw new Error("usage limit must be an integer from 1 to 500");
700
701
  }
701
- return value;
702
+ return value2;
702
703
  }
703
704
  function printUsage(body, out) {
704
705
  const aggregates = isRecord2(body) && isRecord2(body.aggregates) && Array.isArray(body.aggregates.byStatus) ? body.aggregates.byStatus.filter(isRecord2) : [];
@@ -734,15 +735,15 @@ when app/env run actor purpose/role route / policy tokens cost status`);
734
735
  ].join(" "));
735
736
  }
736
737
  }
737
- function numeric(value) {
738
- return typeof value === "number" && Number.isFinite(value) ? value : 0;
738
+ function numeric(value2) {
739
+ return typeof value2 === "number" && Number.isFinite(value2) ? value2 : 0;
739
740
  }
740
- function formatMicrousd(value) {
741
- return typeof value === "number" && Number.isFinite(value) ? `$${(value / 1e6).toFixed(6)}` : "unpriced";
741
+ function formatMicrousd(value2) {
742
+ return typeof value2 === "number" && Number.isFinite(value2) ? `$${(value2 / 1e6).toFixed(6)}` : "unpriced";
742
743
  }
743
- function timestamp2(value) {
744
- if (typeof value !== "number" || !Number.isFinite(value)) return String(value ?? "");
745
- const date = new Date(value);
744
+ function timestamp2(value2) {
745
+ if (typeof value2 !== "number" || !Number.isFinite(value2)) return String(value2 ?? "");
746
+ const date = new Date(value2);
746
747
  return Number.isFinite(date.valueOf()) ? date.toISOString() : "";
747
748
  }
748
749
  async function responseBody2(res) {
@@ -759,8 +760,8 @@ function apiError2(action, status, body) {
759
760
  const message2 = error && typeof error.message === "string" ? error.message : isRecord2(body) && typeof body.message === "string" ? body.message : "request failed";
760
761
  return `${action} failed (${status}): ${message2}`;
761
762
  }
762
- function isRecord2(value) {
763
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
763
+ function isRecord2(value2) {
764
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
764
765
  }
765
766
 
766
767
  // src/admin-ai.ts
@@ -805,11 +806,11 @@ async function adminAi(options) {
805
806
  }
806
807
  if (options.action === "credential-set") {
807
808
  const provider = requireProvider(options.credentialProvider);
808
- const value = await secretInputValue(options);
809
+ const value2 = await secretInputValue(options);
809
810
  const res2 = await doFetch(`${platform}/registry/platform/ai-credentials/${encodeURIComponent(provider)}`, {
810
811
  method: "PUT",
811
812
  headers,
812
- body: JSON.stringify({ value })
813
+ body: JSON.stringify({ value: value2 })
813
814
  });
814
815
  const body2 = await responseBody3(res2);
815
816
  if (!res2.ok) throw new Error(apiError3(`store ${provider} platform credential`, res2.status, body2));
@@ -909,11 +910,11 @@ async function adminAi(options) {
909
910
  const policy = isRecord3(response2) && isRecord3(response2.policy) ? response2.policy : isRecord3(response2) ? response2 : {};
910
911
  out.log(options.json ? JSON.stringify({ policy }, null, 2) : `updated ${purpose}: ${String(policy.provider ?? "unchanged")}/${String(policy.model ?? "unchanged")}`);
911
912
  }
912
- function requireProvider(value) {
913
- if (value !== "anthropic" && value !== "openai" && value !== "google") {
913
+ function requireProvider(value2) {
914
+ if (value2 !== "anthropic" && value2 !== "openai" && value2 !== "google") {
914
915
  throw new Error("provider must be one of: anthropic, openai, google");
915
916
  }
916
- return value;
917
+ return value2;
917
918
  }
918
919
  function policyArray(body) {
919
920
  if (isRecord3(body) && Array.isArray(body.policies)) return body.policies.filter(isRecord3);
@@ -924,7 +925,7 @@ function catalogModels(body) {
924
925
  if (!isRecord3(body) || !isRecord3(body.catalog) || !Array.isArray(body.catalog.models)) {
925
926
  throw new Error("platform returned an invalid System AI model catalog");
926
927
  }
927
- return body.catalog.models.filter((value) => isRecord3(value) && typeof value.id === "string" && typeof value.provider === "string");
928
+ return body.catalog.models.filter((value2) => isRecord3(value2) && typeof value2.id === "string" && typeof value2.provider === "string");
928
929
  }
929
930
  async function responseBody3(res) {
930
931
  const text = await res.text();
@@ -940,8 +941,8 @@ function apiError3(action, status, body) {
940
941
  const message2 = error && typeof error.message === "string" ? error.message : isRecord3(body) && typeof body.message === "string" ? body.message : "request failed";
941
942
  return `${action} failed (${status}): ${message2}`;
942
943
  }
943
- function isRecord3(value) {
944
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
944
+ function isRecord3(value2) {
945
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
945
946
  }
946
947
 
947
948
  // src/argv.ts
@@ -965,10 +966,10 @@ function parseArgv(argv) {
965
966
  addOption(options, rawName, arg.slice(eq + 1));
966
967
  continue;
967
968
  }
968
- const value = argv[i + 1];
969
- if (value !== void 0 && !value.startsWith("--")) {
969
+ const value2 = argv[i + 1];
970
+ if (value2 !== void 0 && !value2.startsWith("--")) {
970
971
  i++;
971
- addOption(options, rawName, value);
972
+ addOption(options, rawName, value2);
972
973
  } else {
973
974
  addOption(options, rawName, true);
974
975
  }
@@ -984,39 +985,39 @@ function assertArgs(parsed, allowedOptions2, maxPositionals) {
984
985
  throw new Error(`unexpected argument "${parsed.positionals[maxPositionals]}"; run "odla-ai help"`);
985
986
  }
986
987
  }
987
- function requiredString(value, name) {
988
- const result = stringOpt(value);
988
+ function requiredString(value2, name) {
989
+ const result = stringOpt(value2);
989
990
  if (!result) throw new Error(`${name} is required`);
990
991
  return result;
991
992
  }
992
- function stringOpt(value) {
993
- if (typeof value === "string") return value;
994
- if (Array.isArray(value)) return value[value.length - 1];
993
+ function stringOpt(value2) {
994
+ if (typeof value2 === "string") return value2;
995
+ if (Array.isArray(value2)) return value2[value2.length - 1];
995
996
  return void 0;
996
997
  }
997
- function listOpt(value) {
998
- if (value === void 0 || typeof value === "boolean") return void 0;
999
- const values = Array.isArray(value) ? value : [value];
998
+ function listOpt(value2) {
999
+ if (value2 === void 0 || typeof value2 === "boolean") return void 0;
1000
+ const values = Array.isArray(value2) ? value2 : [value2];
1000
1001
  return values.flatMap((item) => item.split(",")).map((item) => item.trim()).filter(Boolean);
1001
1002
  }
1002
- function boolOpt(value) {
1003
- if (typeof value === "boolean") return value;
1004
- if (typeof value === "string" && (value === "true" || value === "false")) return value === "true";
1005
- if (value === void 0) return void 0;
1003
+ function boolOpt(value2) {
1004
+ if (typeof value2 === "boolean") return value2;
1005
+ if (typeof value2 === "string" && (value2 === "true" || value2 === "false")) return value2 === "true";
1006
+ if (value2 === void 0) return void 0;
1006
1007
  throw new Error("boolean option must be true or false");
1007
1008
  }
1008
- function numberOpt(value, flag) {
1009
- if (value === void 0) return void 0;
1010
- const raw = stringOpt(value);
1009
+ function numberOpt(value2, flag) {
1010
+ if (value2 === void 0) return void 0;
1011
+ const raw = stringOpt(value2);
1011
1012
  const parsed = raw === void 0 ? Number.NaN : Number(raw);
1012
1013
  if (!Number.isSafeInteger(parsed) || parsed < 1) throw new Error(`${flag} requires a positive integer`);
1013
1014
  return parsed;
1014
1015
  }
1015
- function addOption(options, name, value) {
1016
+ function addOption(options, name, value2) {
1016
1017
  const current = options[name];
1017
- if (current === void 0) options[name] = value;
1018
- else if (Array.isArray(current)) current.push(String(value));
1019
- else options[name] = [String(current), String(value)];
1018
+ if (current === void 0) options[name] = value2;
1019
+ else if (Array.isArray(current)) current.push(String(value2));
1020
+ else options[name] = [String(current), String(value2)];
1020
1021
  }
1021
1022
 
1022
1023
  // src/operator-context.ts
@@ -1028,6 +1029,7 @@ var import_node_process8 = __toESM(require("process"), 1);
1028
1029
  var import_node_fs4 = require("fs");
1029
1030
  var import_node_path4 = require("path");
1030
1031
  var import_node_url = require("url");
1032
+ var import_apps = require("@odla-ai/apps");
1031
1033
 
1032
1034
  // src/integration-validation.ts
1033
1035
  function validateIntegrations(cfg, path, defaultServices) {
@@ -1082,17 +1084,17 @@ function validateProbes(integration, at) {
1082
1084
  }
1083
1085
  }
1084
1086
  }
1085
- function isRecord4(value) {
1086
- return value !== null && typeof value === "object" && !Array.isArray(value);
1087
+ function isRecord4(value2) {
1088
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
1087
1089
  }
1088
- function safeText(value, max) {
1089
- return typeof value === "string" && value.trim().length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
1090
+ function safeText(value2, max) {
1091
+ return typeof value2 === "string" && value2.trim().length > 0 && value2.length <= max && !/[\u0000-\u001f\u007f]/.test(value2);
1090
1092
  }
1091
- function safeProbePath(value) {
1092
- return typeof value === "string" && /^\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/.test(value);
1093
+ function safeProbePath(value2) {
1094
+ return typeof value2 === "string" && /^\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/.test(value2);
1093
1095
  }
1094
- function validId(value) {
1095
- return typeof value === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value);
1096
+ function validId(value2) {
1097
+ return typeof value2 === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value2);
1096
1098
  }
1097
1099
  function unique(values) {
1098
1100
  return [...new Set(values.filter(Boolean))];
@@ -1115,6 +1117,7 @@ async function loadProjectConfig(configPath = "odla.config.mjs") {
1115
1117
  const dbEndpoint = trimSlash(process.env.ODLA_DB_ENDPOINT || raw.dbEndpoint || platformUrl);
1116
1118
  const envs = unique2(raw.envs?.length ? raw.envs : DEFAULT_ENVS);
1117
1119
  const services = unique2(raw.services?.length ? raw.services : DEFAULT_SERVICES);
1120
+ validateServices(services, resolved);
1118
1121
  validateCalendarConfig(raw, envs, services, resolved);
1119
1122
  const local = {
1120
1123
  tokenFile: (0, import_node_path4.resolve)(rootDir, raw.local?.tokenFile ?? ".odla/dev-token.json"),
@@ -1133,10 +1136,10 @@ async function loadProjectConfig(configPath = "odla.config.mjs") {
1133
1136
  local
1134
1137
  };
1135
1138
  }
1136
- async function resolveDataExport(cfg, value, names) {
1137
- if (value === void 0 || value === null || value === false) return void 0;
1138
- if (typeof value !== "string") return value;
1139
- const target = (0, import_node_path4.isAbsolute)(value) ? value : (0, import_node_path4.resolve)(cfg.rootDir, value);
1139
+ async function resolveDataExport(cfg, value2, names) {
1140
+ if (value2 === void 0 || value2 === null || value2 === false) return void 0;
1141
+ if (typeof value2 !== "string") return value2;
1142
+ const target = (0, import_node_path4.isAbsolute)(value2) ? value2 : (0, import_node_path4.resolve)(cfg.rootDir, value2);
1140
1143
  if (target.endsWith(".json")) {
1141
1144
  return JSON.parse((0, import_node_fs4.readFileSync)(target, "utf8"));
1142
1145
  }
@@ -1145,7 +1148,7 @@ async function resolveDataExport(cfg, value, names) {
1145
1148
  if (mod[name] !== void 0) return mod[name];
1146
1149
  }
1147
1150
  if (mod.default !== void 0) return mod.default;
1148
- throw new Error(`${value} did not export ${names.join(", ")} or default`);
1151
+ throw new Error(`${value2} did not export ${names.join(", ")} or default`);
1149
1152
  }
1150
1153
  function buildPlan(cfg) {
1151
1154
  const integrationSchema = cfg.integrations?.some((integration) => integration.schema) ?? false;
@@ -1179,9 +1182,9 @@ function calendarServiceConfig(cfg, env) {
1179
1182
  };
1180
1183
  }
1181
1184
  function calendarBookingPageUrl(cfg, env) {
1182
- const value = cfg.calendar?.google.bookingPageUrl?.[env];
1183
- if (value === void 0 || value === null) return value;
1184
- return new URL(value).toString();
1185
+ const value2 = cfg.calendar?.google.bookingPageUrl?.[env];
1186
+ if (value2 === void 0 || value2 === null) return value2;
1187
+ return new URL(value2).toString();
1185
1188
  }
1186
1189
  function rulesFromSchema(schema) {
1187
1190
  const entities = serializedEntities(schema);
@@ -1195,10 +1198,10 @@ function serializedEntities(schema) {
1195
1198
  if (!entities || typeof entities !== "object" || Array.isArray(entities)) return [];
1196
1199
  return Object.keys(entities);
1197
1200
  }
1198
- function envValue(value) {
1199
- if (!value) return void 0;
1200
- if (value.startsWith("$")) return process.env[value.slice(1)];
1201
- return value;
1201
+ function envValue(value2) {
1202
+ if (!value2) return void 0;
1203
+ if (value2.startsWith("$")) return process.env[value2.slice(1)];
1204
+ return value2;
1202
1205
  }
1203
1206
  function validateRawConfig(raw, path) {
1204
1207
  if (!raw || typeof raw !== "object") throw new Error(`${path} must export an object`);
@@ -1254,8 +1257,8 @@ function validateCalendarConfig(cfg, envs, services, path) {
1254
1257
  if (!isRecord5(google.bookingCalendar)) throw new Error(`${path}: calendar.google.bookingCalendar must map env names to one calendar id`);
1255
1258
  const unknownBookingEnv = Object.keys(google.bookingCalendar).find((env) => !envs.includes(env));
1256
1259
  if (unknownBookingEnv) throw new Error(`${path}: calendar.google.bookingCalendar.${unknownBookingEnv} is not in config envs`);
1257
- for (const [env, value] of Object.entries(google.bookingCalendar)) {
1258
- if (!safeText2(value, 1024)) {
1260
+ for (const [env, value2] of Object.entries(google.bookingCalendar)) {
1261
+ if (!safeText2(value2, 1024)) {
1259
1262
  throw new Error(`${path}: calendar.google.bookingCalendar.${env} must be a calendar id`);
1260
1263
  }
1261
1264
  }
@@ -1264,45 +1267,57 @@ function validateCalendarConfig(cfg, envs, services, path) {
1264
1267
  if (!isRecord5(google.bookingPageUrl)) throw new Error(`${path}: calendar.google.bookingPageUrl must map env names to HTTPS URLs or null`);
1265
1268
  const unknownBookingEnv = Object.keys(google.bookingPageUrl).find((env) => !envs.includes(env));
1266
1269
  if (unknownBookingEnv) throw new Error(`${path}: calendar.google.bookingPageUrl.${unknownBookingEnv} is not in config envs`);
1267
- for (const [env, value] of Object.entries(google.bookingPageUrl)) {
1268
- if (value !== null && !safeHttpsUrl(value)) {
1270
+ for (const [env, value2] of Object.entries(google.bookingPageUrl)) {
1271
+ if (value2 !== null && !safeHttpsUrl(value2)) {
1269
1272
  throw new Error(`${path}: calendar.google.bookingPageUrl.${env} must be an HTTPS URL without credentials or fragment`);
1270
1273
  }
1271
1274
  }
1272
1275
  }
1273
- if (enabled && !services.includes("db")) throw new Error(`${path}: calendar service requires the db service`);
1274
1276
  }
1275
- function assertOnly(value, allowed, label) {
1276
- const extra = Object.keys(value).find((key) => !allowed.includes(key));
1277
+ function validateServices(services, path) {
1278
+ for (const service of services) {
1279
+ const definition = (0, import_apps.appServiceDefinition)(service);
1280
+ if (!definition) {
1281
+ throw new Error(`${path}: unknown service "${service}" (known: ${(0, import_apps.appServiceIds)().join(", ")})`);
1282
+ }
1283
+ for (const dependency of definition.requires) {
1284
+ if (!services.includes(dependency)) {
1285
+ throw new Error(`${path}: ${service} service requires the ${dependency} service`);
1286
+ }
1287
+ }
1288
+ }
1289
+ }
1290
+ function assertOnly(value2, allowed, label) {
1291
+ const extra = Object.keys(value2).find((key) => !allowed.includes(key));
1277
1292
  if (extra) throw new Error(`${label}.${extra} is not supported`);
1278
1293
  }
1279
- function isRecord5(value) {
1280
- return value !== null && typeof value === "object" && !Array.isArray(value);
1294
+ function isRecord5(value2) {
1295
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
1281
1296
  }
1282
- function safeText2(value, max) {
1283
- return typeof value === "string" && value.trim().length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
1297
+ function safeText2(value2, max) {
1298
+ return typeof value2 === "string" && value2.trim().length > 0 && value2.length <= max && !/[\u0000-\u001f\u007f]/.test(value2);
1284
1299
  }
1285
- function safeHttpsUrl(value) {
1286
- if (typeof value !== "string" || value.length > 2048) return false;
1300
+ function safeHttpsUrl(value2) {
1301
+ if (typeof value2 !== "string" || value2.length > 2048) return false;
1287
1302
  try {
1288
- const url = new URL(value);
1303
+ const url = new URL(value2);
1289
1304
  return url.protocol === "https:" && !url.username && !url.password && !url.hash;
1290
1305
  } catch {
1291
1306
  return false;
1292
1307
  }
1293
1308
  }
1294
- function validId2(value) {
1295
- return typeof value === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value);
1309
+ function validId2(value2) {
1310
+ return typeof value2 === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value2);
1296
1311
  }
1297
1312
  async function loadConfigModule(path) {
1298
1313
  if (path.endsWith(".json")) return JSON.parse((0, import_node_fs4.readFileSync)(path, "utf8"));
1299
1314
  const mod = await import(`${(0, import_node_url.pathToFileURL)(path).href}?t=${Date.now()}`);
1300
- const value = mod.default ?? mod.config;
1301
- if (typeof value === "function") return await value();
1302
- return value;
1315
+ const value2 = mod.default ?? mod.config;
1316
+ if (typeof value2 === "function") return await value2();
1317
+ return value2;
1303
1318
  }
1304
- function trimSlash(value) {
1305
- return value.replace(/\/+$/, "");
1319
+ function trimSlash(value2) {
1320
+ return value2.replace(/\/+$/, "");
1306
1321
  }
1307
1322
  function unique2(values) {
1308
1323
  return [...new Set(values.filter(Boolean))];
@@ -1328,8 +1343,8 @@ function resolveOperatorProfile(parsed) {
1328
1343
  }
1329
1344
  assertOperatorName(name, "context");
1330
1345
  const profiles = readOperatorProfiles(file);
1331
- const value = Object.hasOwn(profiles, name) ? profiles[name] : void 0;
1332
- if (!value) {
1346
+ const value2 = Object.hasOwn(profiles, name) ? profiles[name] : void 0;
1347
+ if (!value2) {
1333
1348
  throw new Error(
1334
1349
  `operator context "${name}" not found in ${file}; run "odla-ai context list" or save it first`
1335
1350
  );
@@ -1338,7 +1353,7 @@ function resolveOperatorProfile(parsed) {
1338
1353
  name,
1339
1354
  source: fromFlag ? "flag" : "environment",
1340
1355
  file,
1341
- value
1356
+ value: value2
1342
1357
  };
1343
1358
  }
1344
1359
  function listOperatorProfiles(file = operatorProfileFile()) {
@@ -1366,8 +1381,8 @@ function operatorCredentialFiles(selection) {
1366
1381
  scoped: (0, import_node_path5.join)(base, "admin-token.local.json")
1367
1382
  };
1368
1383
  }
1369
- function assertOperatorName(value, label) {
1370
- if (!/^[a-z0-9][a-z0-9-]*$/.test(value)) {
1384
+ function assertOperatorName(value2, label) {
1385
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(value2)) {
1371
1386
  throw new Error(
1372
1387
  `${label} must contain lowercase letters, numbers, and hyphens`
1373
1388
  );
@@ -1393,22 +1408,22 @@ function readOperatorProfiles(file) {
1393
1408
  );
1394
1409
  }
1395
1410
  const profiles = emptyProfiles();
1396
- for (const [name, value] of Object.entries(
1411
+ for (const [name, value2] of Object.entries(
1397
1412
  raw.profiles
1398
1413
  )) {
1399
1414
  assertOperatorName(name, "context");
1400
- profiles[name] = validateProfile(value, `operator context "${name}"`);
1415
+ profiles[name] = validateProfile(value2, `operator context "${name}"`);
1401
1416
  }
1402
1417
  return profiles;
1403
1418
  }
1404
1419
  function emptyProfiles() {
1405
1420
  return /* @__PURE__ */ Object.create(null);
1406
1421
  }
1407
- function validateProfile(value, label) {
1408
- if (!value || typeof value !== "object" || Array.isArray(value)) {
1422
+ function validateProfile(value2, label) {
1423
+ if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) {
1409
1424
  throw new Error(`${label} has an invalid shape`);
1410
1425
  }
1411
- const unknown = Object.keys(value).filter(
1426
+ const unknown = Object.keys(value2).filter(
1412
1427
  (key) => !["platform", "app", "environment"].includes(key)
1413
1428
  );
1414
1429
  if (unknown.length > 0) {
@@ -1416,7 +1431,7 @@ function validateProfile(value, label) {
1416
1431
  `${label} contains unsupported field(s): ${unknown.sort().join(", ")}; contexts store scope metadata only, never credentials`
1417
1432
  );
1418
1433
  }
1419
- const candidate = value;
1434
+ const candidate = value2;
1420
1435
  if (typeof candidate.platform !== "string") {
1421
1436
  throw new Error(`${label} needs an absolute platform URL`);
1422
1437
  }
@@ -1431,8 +1446,8 @@ function validateProfile(value, label) {
1431
1446
  ...environment2 ? { environment: environment2 } : {}
1432
1447
  };
1433
1448
  }
1434
- function clean(value) {
1435
- const normalized = value?.trim();
1449
+ function clean(value2) {
1450
+ const normalized = value2?.trim();
1436
1451
  return normalized || void 0;
1437
1452
  }
1438
1453
 
@@ -1525,8 +1540,8 @@ async function resolveOperatorContext(parsed, options = {}) {
1525
1540
  }
1526
1541
  };
1527
1542
  }
1528
- function clean2(value) {
1529
- const normalized = value?.trim();
1543
+ function clean2(value2) {
1544
+ const normalized = value2?.trim();
1530
1545
  return normalized || void 0;
1531
1546
  }
1532
1547
 
@@ -1594,7 +1609,7 @@ async function adminCommand(parsed, deps = {}) {
1594
1609
  }
1595
1610
 
1596
1611
  // src/tenant.ts
1597
- var import_apps = require("@odla-ai/apps");
1612
+ var import_apps2 = require("@odla-ai/apps");
1598
1613
  function resolveEnv(cfg, requested) {
1599
1614
  const env = requested ?? (cfg.envs.includes("dev") ? "dev" : cfg.envs[0]);
1600
1615
  if (!env || !cfg.envs.includes(env)) {
@@ -1604,7 +1619,7 @@ function resolveEnv(cfg, requested) {
1604
1619
  }
1605
1620
  function resolveTenant(cfg, requested) {
1606
1621
  const env = resolveEnv(cfg, requested);
1607
- return { env, tenant: (0, import_apps.tenantIdFor)(cfg.app.id, env) };
1622
+ return { env, tenant: (0, import_apps2.tenantIdFor)(cfg.app.id, env) };
1608
1623
  }
1609
1624
  function bothTenants(cfg) {
1610
1625
  for (const env of ["dev", "prod"]) {
@@ -1614,7 +1629,7 @@ function bothTenants(cfg) {
1614
1629
  );
1615
1630
  }
1616
1631
  }
1617
- return { sandbox: (0, import_apps.tenantIdFor)(cfg.app.id, "dev"), live: (0, import_apps.tenantIdFor)(cfg.app.id, "prod") };
1632
+ return { sandbox: (0, import_apps2.tenantIdFor)(cfg.app.id, "dev"), live: (0, import_apps2.tenantIdFor)(cfg.app.id, "prod") };
1618
1633
  }
1619
1634
 
1620
1635
  // src/agent-command.ts
@@ -2237,44 +2252,44 @@ var REPLACEMENTS = [
2237
2252
  [/\b(ghp|gho|github_pat)_[A-Za-z0-9_]+/g, "$1_[redacted]"],
2238
2253
  [/\bAKIA[A-Z0-9]{12,}/g, "AKIA[redacted]"]
2239
2254
  ];
2240
- function redactSecrets(value) {
2241
- let result = value;
2255
+ function redactSecrets(value2) {
2256
+ let result = value2;
2242
2257
  for (const [pattern, replacement] of REPLACEMENTS) result = result.replace(pattern, replacement);
2243
2258
  return result;
2244
2259
  }
2245
2260
  function redactingOutput(output) {
2246
- const redactArgs = (args) => args.map((value) => redactOutputValue(value, /* @__PURE__ */ new WeakMap()));
2261
+ const redactArgs = (args) => args.map((value2) => redactOutputValue(value2, /* @__PURE__ */ new WeakMap()));
2247
2262
  return {
2248
2263
  log: (...args) => output.log(...redactArgs(args)),
2249
2264
  error: (...args) => output.error(...redactArgs(args))
2250
2265
  };
2251
2266
  }
2252
- function redactOutputValue(value, seen) {
2253
- if (typeof value === "string") return redactSecrets(value);
2254
- if (value instanceof Error) {
2255
- const redacted = new Error(redactSecrets(value.message));
2256
- redacted.name = value.name;
2257
- if (value.stack) redacted.stack = redactSecrets(value.stack);
2267
+ function redactOutputValue(value2, seen) {
2268
+ if (typeof value2 === "string") return redactSecrets(value2);
2269
+ if (value2 instanceof Error) {
2270
+ const redacted = new Error(redactSecrets(value2.message));
2271
+ redacted.name = value2.name;
2272
+ if (value2.stack) redacted.stack = redactSecrets(value2.stack);
2258
2273
  return redacted;
2259
2274
  }
2260
- if (!value || typeof value !== "object") return value;
2261
- const prior = seen.get(value);
2275
+ if (!value2 || typeof value2 !== "object") return value2;
2276
+ const prior = seen.get(value2);
2262
2277
  if (prior) return prior;
2263
- if (Array.isArray(value)) {
2278
+ if (Array.isArray(value2)) {
2264
2279
  const next2 = [];
2265
- seen.set(value, next2);
2266
- for (const item of value) next2.push(redactOutputValue(item, seen));
2280
+ seen.set(value2, next2);
2281
+ for (const item of value2) next2.push(redactOutputValue(item, seen));
2267
2282
  return next2;
2268
2283
  }
2269
- const prototype = Object.getPrototypeOf(value);
2270
- if (prototype !== Object.prototype && prototype !== null) return value;
2284
+ const prototype = Object.getPrototypeOf(value2);
2285
+ if (prototype !== Object.prototype && prototype !== null) return value2;
2271
2286
  const next = {};
2272
- seen.set(value, next);
2273
- for (const [key, item] of Object.entries(value)) next[key] = redactOutputValue(item, seen);
2287
+ seen.set(value2, next);
2288
+ for (const [key, item] of Object.entries(value2)) next[key] = redactOutputValue(item, seen);
2274
2289
  return next;
2275
2290
  }
2276
- function looksSecret(value) {
2277
- return redactSecrets(value) !== value || value.includes("-----BEGIN");
2291
+ function looksSecret(value2) {
2292
+ return redactSecrets(value2) !== value2 || value2.includes("-----BEGIN");
2278
2293
  }
2279
2294
 
2280
2295
  // src/calendar-http.ts
@@ -2291,9 +2306,9 @@ async function readCalendarStatus(ctx) {
2291
2306
  }
2292
2307
  async function discoverGoogleCalendars(ctx) {
2293
2308
  const raw = await calendarJson(ctx, "/calendars", {});
2294
- const value = record(raw);
2295
- if (!value || !Array.isArray(value.calendars)) throw new Error("calendar discovery returned an invalid response");
2296
- return value.calendars.map((item, index) => {
2309
+ const value2 = record(raw);
2310
+ if (!value2 || !Array.isArray(value2.calendars)) throw new Error("calendar discovery returned an invalid response");
2311
+ return value2.calendars.map((item, index) => {
2297
2312
  const calendar = record(item);
2298
2313
  const id = textField(calendar?.id, 1024);
2299
2314
  if (!calendar || !id) throw new Error(`calendar discovery returned an invalid calendar at index ${index}`);
@@ -2315,10 +2330,10 @@ async function applyCalendarSettings(ctx, bookingPageUrl) {
2315
2330
  }
2316
2331
  async function startCalendarConnection(ctx) {
2317
2332
  const raw = await calendarJson(ctx, "/google/connect", { method: "POST", body: "{}" });
2318
- const value = wrapped(raw, "attempt");
2319
- const attemptId = textField(value.attemptId, 180);
2320
- const consentUrl = textField(value.consentUrl, 4096);
2321
- const expiresAt = timestamp3(value.expiresAt);
2333
+ const value2 = wrapped(raw, "attempt");
2334
+ const attemptId = textField(value2.attemptId, 180);
2335
+ const consentUrl = textField(value2.consentUrl, 4096);
2336
+ const expiresAt = timestamp3(value2.expiresAt);
2322
2337
  if (!attemptId || !consentUrl || expiresAt === void 0) throw new Error("calendar connect returned an invalid attempt");
2323
2338
  return { attemptId, consentUrl, expiresAt };
2324
2339
  }
@@ -2336,42 +2351,42 @@ async function requestCalendarDisconnect(ctx) {
2336
2351
  }
2337
2352
  function parseCalendarStatus(raw, env) {
2338
2353
  const outer = wrapped(raw, "calendar");
2339
- const value = record(outer.attempt) ?? record(outer.status) ?? outer;
2340
- const connection = record(value.connection) ?? {};
2341
- const config = record(value.config) ?? record(outer.config) ?? {};
2354
+ const value2 = record(outer.attempt) ?? record(outer.status) ?? outer;
2355
+ const connection = record(value2.connection) ?? {};
2356
+ const config = record(value2.config) ?? record(outer.config) ?? {};
2342
2357
  const googleConfig = record(config.google) ?? config;
2343
- const stateValue = calendarState(value.status ?? value.state ?? connection.status ?? connection.state);
2358
+ const stateValue = calendarState(value2.status ?? value2.state ?? connection.status ?? connection.state);
2344
2359
  if (!stateValue) {
2345
2360
  throw new Error("calendar status returned an invalid connection state");
2346
2361
  }
2347
- const providerValue = value.provider ?? connection.provider ?? config.provider ?? (config.google ? "google" : void 0);
2362
+ const providerValue = value2.provider ?? connection.provider ?? config.provider ?? (config.google ? "google" : void 0);
2348
2363
  if (providerValue !== void 0 && providerValue !== null && providerValue !== "google") {
2349
2364
  throw new Error("calendar status returned an unsupported provider");
2350
2365
  }
2351
- const accessValue = value.access ?? connection.access ?? config.access ?? googleConfig.access;
2366
+ const accessValue = value2.access ?? connection.access ?? config.access ?? googleConfig.access;
2352
2367
  if (accessValue !== void 0 && accessValue !== "book" && accessValue !== "read") {
2353
2368
  throw new Error("calendar status returned unsupported access");
2354
2369
  }
2355
- const errorValue = record(value.error) ?? record(connection.error);
2356
- const errorCode = textField(value.lastErrorCode, 128);
2357
- const bookingPageValue = Object.hasOwn(value, "bookingPageUrl") ? value.bookingPageUrl : Object.hasOwn(config, "bookingPageUrl") ? config.bookingPageUrl : googleConfig.bookingPageUrl;
2358
- const connected = typeof (value.connected ?? connection.connected) === "boolean" ? Boolean(value.connected ?? connection.connected) : ["healthy", "degraded"].includes(stateValue);
2359
- const bookingCalendarId = textField(value.bookingCalendarId ?? config.bookingCalendarId, 1024);
2370
+ const errorValue = record(value2.error) ?? record(connection.error);
2371
+ const errorCode = textField(value2.lastErrorCode, 128);
2372
+ const bookingPageValue = Object.hasOwn(value2, "bookingPageUrl") ? value2.bookingPageUrl : Object.hasOwn(config, "bookingPageUrl") ? config.bookingPageUrl : googleConfig.bookingPageUrl;
2373
+ const connected = typeof (value2.connected ?? connection.connected) === "boolean" ? Boolean(value2.connected ?? connection.connected) : ["healthy", "degraded"].includes(stateValue);
2374
+ const bookingCalendarId = textField(value2.bookingCalendarId ?? config.bookingCalendarId, 1024);
2360
2375
  return {
2361
2376
  env,
2362
- enabled: typeof value.enabled === "boolean" ? value.enabled : true,
2377
+ enabled: typeof value2.enabled === "boolean" ? value2.enabled : true,
2363
2378
  connected,
2364
- writable: typeof value.writable === "boolean" ? value.writable : stateValue === "healthy",
2379
+ writable: typeof value2.writable === "boolean" ? value2.writable : stateValue === "healthy",
2365
2380
  provider: providerValue === "google" ? "google" : null,
2366
2381
  status: stateValue,
2367
2382
  ...accessValue !== void 0 ? { access: "book" } : {},
2368
2383
  ...bookingCalendarId ? { bookingCalendarId } : {},
2369
2384
  calendars: calendarIds(
2370
- value.availabilityCalendars ?? config.availabilityCalendars ?? value.configuredCalendars ?? value.calendars ?? config.calendars ?? googleConfig.calendars
2385
+ value2.availabilityCalendars ?? config.availabilityCalendars ?? value2.configuredCalendars ?? value2.calendars ?? config.calendars ?? googleConfig.calendars
2371
2386
  ),
2372
2387
  ...optionalNullableUrl("bookingPageUrl", bookingPageValue),
2373
- grantedScopes: stringList(value.grantedScopes ?? connection.grantedScopes ?? connection.scopes),
2374
- ...optionalText("attemptId", value.attemptId ?? connection.attemptId, 180),
2388
+ grantedScopes: stringList(value2.grantedScopes ?? connection.grantedScopes ?? connection.scopes),
2389
+ ...optionalText("attemptId", value2.attemptId ?? connection.attemptId, 180),
2375
2390
  ...errorValue || errorCode ? { error: {
2376
2391
  ...textField(errorValue?.code, 128) ? { code: textField(errorValue?.code, 128) } : {},
2377
2392
  ...textField(errorValue?.message, 500) ? { message: textField(errorValue?.message, 500) } : {},
@@ -2379,9 +2394,9 @@ function parseCalendarStatus(raw, env) {
2379
2394
  } } : {}
2380
2395
  };
2381
2396
  }
2382
- function calendarState(value) {
2383
- if (typeof value !== "string") return null;
2384
- if (CALENDAR_STATES.includes(value)) return value;
2397
+ function calendarState(value2) {
2398
+ if (typeof value2 !== "string") return null;
2399
+ if (CALENDAR_STATES.includes(value2)) return value2;
2385
2400
  const legacy = {
2386
2401
  disabled: "not_connected",
2387
2402
  disconnected: "disconnected",
@@ -2392,7 +2407,7 @@ function calendarState(value) {
2392
2407
  ready: "healthy",
2393
2408
  error: "failed"
2394
2409
  };
2395
- return legacy[value] ?? null;
2410
+ return legacy[value2] ?? null;
2396
2411
  }
2397
2412
  async function calendarJson(ctx, suffix, init) {
2398
2413
  const platform = platformAudience(ctx.platform);
@@ -2426,50 +2441,50 @@ function wrapped(raw, key) {
2426
2441
  if (!outer) throw new Error("calendar returned an invalid response");
2427
2442
  return record(outer[key]) ?? outer;
2428
2443
  }
2429
- function record(value) {
2430
- return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
2444
+ function record(value2) {
2445
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
2431
2446
  }
2432
- function textField(value, max) {
2433
- return typeof value === "string" && value.length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value) ? value : void 0;
2447
+ function textField(value2, max) {
2448
+ return typeof value2 === "string" && value2.length > 0 && value2.length <= max && !/[\u0000-\u001f\u007f]/.test(value2) ? value2 : void 0;
2434
2449
  }
2435
- function stringList(value) {
2436
- return Array.isArray(value) ? [...new Set(value.filter((item) => !!textField(item, 4096)))] : [];
2450
+ function stringList(value2) {
2451
+ return Array.isArray(value2) ? [...new Set(value2.filter((item) => !!textField(item, 4096)))] : [];
2437
2452
  }
2438
- function calendarIds(value) {
2439
- if (!Array.isArray(value)) return [];
2440
- return [...new Set(value.flatMap((item) => {
2453
+ function calendarIds(value2) {
2454
+ if (!Array.isArray(value2)) return [];
2455
+ return [...new Set(value2.flatMap((item) => {
2441
2456
  if (typeof item === "string") return textField(item, 4096) ? [item] : [];
2442
2457
  const calendar = record(item);
2443
2458
  const id = textField(calendar?.id, 4096);
2444
2459
  return id && calendar?.selected !== false ? [id] : [];
2445
2460
  }))];
2446
2461
  }
2447
- function timestamp3(value) {
2448
- if (typeof value === "number" && Number.isFinite(value) && value >= 0) return value;
2449
- if (typeof value === "string") {
2450
- const parsed = Date.parse(value);
2462
+ function timestamp3(value2) {
2463
+ if (typeof value2 === "number" && Number.isFinite(value2) && value2 >= 0) return value2;
2464
+ if (typeof value2 === "string") {
2465
+ const parsed = Date.parse(value2);
2451
2466
  if (Number.isFinite(parsed)) return parsed;
2452
2467
  }
2453
2468
  return void 0;
2454
2469
  }
2455
- function optionalText(key, value, max) {
2456
- const parsed = textField(value, max);
2470
+ function optionalText(key, value2, max) {
2471
+ const parsed = textField(value2, max);
2457
2472
  return parsed ? { [key]: parsed } : {};
2458
2473
  }
2459
- function optionalNullableUrl(key, value) {
2460
- if (value === null) return { [key]: null };
2461
- const parsed = textField(value, 4096);
2474
+ function optionalNullableUrl(key, value2) {
2475
+ if (value2 === null) return { [key]: null };
2476
+ const parsed = textField(value2, 4096);
2462
2477
  return parsed ? { [key]: parsed } : {};
2463
2478
  }
2464
- function identifier(value, name) {
2465
- if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,179}$/.test(value)) throw new Error(`${name} is invalid`);
2466
- return value;
2479
+ function identifier(value2, name) {
2480
+ if (typeof value2 !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,179}$/.test(value2)) throw new Error(`${name} is invalid`);
2481
+ return value2;
2467
2482
  }
2468
- function credential(value) {
2469
- if (typeof value !== "string" || value.length < 8 || value.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value)) {
2483
+ function credential(value2) {
2484
+ if (typeof value2 !== "string" || value2.length < 8 || value2.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value2)) {
2470
2485
  throw new Error("calendar requires an odla developer token");
2471
2486
  }
2472
- return value;
2487
+ return value2;
2473
2488
  }
2474
2489
 
2475
2490
  // src/calendar-poll.ts
@@ -2630,11 +2645,11 @@ async function connectWithContext(ctx, options) {
2630
2645
  }
2631
2646
  throw new Error('Google Calendar consent timed out; run "odla-ai calendar status" and retry connect');
2632
2647
  }
2633
- function trustedCalendarConsentUrl(platform, value) {
2648
+ function trustedCalendarConsentUrl(platform, value2) {
2634
2649
  const origin = platformAudience(platform);
2635
2650
  let url;
2636
2651
  try {
2637
- url = value.startsWith("/") ? new URL(value, origin) : new URL(value);
2652
+ url = value2.startsWith("/") ? new URL(value2, origin) : new URL(value2);
2638
2653
  } catch {
2639
2654
  throw new Error("odla.ai returned an invalid calendar consent URL");
2640
2655
  }
@@ -2645,9 +2660,9 @@ function trustedCalendarConsentUrl(platform, value) {
2645
2660
  }
2646
2661
  return url.toString();
2647
2662
  }
2648
- function pollTimeout(value = 10 * 6e4) {
2649
- if (!Number.isSafeInteger(value) || value < 1e3 || value > 60 * 6e4) throw new Error("calendar poll timeout must be 1000-3600000ms");
2650
- return value;
2663
+ function pollTimeout(value2 = 10 * 6e4) {
2664
+ if (!Number.isSafeInteger(value2) || value2 < 1e3 || value2 > 60 * 6e4) throw new Error("calendar poll timeout must be 1000-3600000ms");
2665
+ return value2;
2651
2666
  }
2652
2667
  function productionConsent(env, yes, action) {
2653
2668
  if ((env === "prod" || env === "production") && !yes) throw new Error(`refusing to ${action} for "${env}" without --yes`);
@@ -2679,6 +2694,7 @@ var CAPABILITIES = {
2679
2694
  "validate integration contracts offline and smoke-test a provisioned db environment plus anonymous capability routes",
2680
2695
  "save and explicitly select non-secret named operator contexts with isolated credential caches; resolve and explain platform, app, environment, and credential provenance without authenticating; then run PM, Discussions, o11y, runbook, and identity operations outside a project checkout",
2681
2696
  "read one versioned o11y status envelope spanning application RED, exact Worker versions and Cloudflare colos observed in traffic, current live-sync freshness/load, the protected commit-to-visible canary, collector ingest/scheduler trust, provider-owned runtime metrics, account-scoped Durable Object, D1, and R2 evidence under odla-db, and a bounded machine verdict",
2697
+ "read one canonical platform fleet snapshot over private service bindings, including release identities, probe latency, Cloudflare load/runtime freshness, explicit unknowns, and stable next actions through a read-only capability",
2682
2698
  "inspect durable agent wakeups as a versioned JSON envelope and explicitly requeue one dead-lettered job with a scoped environment credential",
2683
2699
  "run app-attributed hosted security discovery and independent validation without provider keys",
2684
2700
  "connect/revoke source-read-only GitHub sources and drive commit-pinned hosted security jobs without PATs or provider keys",
@@ -2862,8 +2878,8 @@ function wranglerWarnings(rootDir) {
2862
2878
  }
2863
2879
  const vars = block.vars;
2864
2880
  if (vars && typeof vars === "object") {
2865
- for (const [name, value] of Object.entries(vars)) {
2866
- if (name === "ODLA_API_KEY" || name === "ODLA_O11Y_TOKEN" || typeof value === "string" && looksSecret(value)) {
2881
+ for (const [name, value2] of Object.entries(vars)) {
2882
+ if (name === "ODLA_API_KEY" || name === "ODLA_O11Y_TOKEN" || typeof value2 === "string" && looksSecret(value2)) {
2867
2883
  warnings.push(`wrangler ${label}vars.${name} looks like a secret \u2014 use "odla-ai secrets push" / wrangler secret put, never vars`);
2868
2884
  }
2869
2885
  }
@@ -3031,27 +3047,27 @@ function isUniqueAttr(schema, ns, attr) {
3031
3047
  const definition = entity.attrs[attr];
3032
3048
  return isRecord6(definition) && definition.unique === true;
3033
3049
  }
3034
- function normalizeSchema(value) {
3035
- if (value === void 0 || value === null) return { entities: {}, links: {} };
3036
- if (!isRecord6(value) || !isRecord6(value.entities)) {
3050
+ function normalizeSchema(value2) {
3051
+ if (value2 === void 0 || value2 === null) return { entities: {}, links: {} };
3052
+ if (!isRecord6(value2) || !isRecord6(value2.entities)) {
3037
3053
  throw new Error("db schema must be a serialized schema object with an entities map");
3038
3054
  }
3039
- if (value.links !== void 0 && !isRecord6(value.links)) throw new Error("db schema links must be an object");
3055
+ if (value2.links !== void 0 && !isRecord6(value2.links)) throw new Error("db schema links must be an object");
3040
3056
  return {
3041
- entities: { ...value.entities },
3042
- links: { ...value.links ?? {} }
3057
+ entities: { ...value2.entities },
3058
+ links: { ...value2.links ?? {} }
3043
3059
  };
3044
3060
  }
3045
3061
  function mergeMap(target, fragment, label) {
3046
- for (const [name, value] of Object.entries(fragment)) {
3047
- if (Object.hasOwn(target, name) && !(0, import_node_util.isDeepStrictEqual)(target[name], value)) {
3062
+ for (const [name, value2] of Object.entries(fragment)) {
3063
+ if (Object.hasOwn(target, name) && !(0, import_node_util.isDeepStrictEqual)(target[name], value2)) {
3048
3064
  throw new Error(`${label} "${name}" conflicts with an existing definition`);
3049
3065
  }
3050
- target[name] = value;
3066
+ target[name] = value2;
3051
3067
  }
3052
3068
  }
3053
- function isRecord6(value) {
3054
- return value !== null && typeof value === "object" && !Array.isArray(value);
3069
+ function isRecord6(value2) {
3070
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
3055
3071
  }
3056
3072
 
3057
3073
  // src/doctor.ts
@@ -3092,9 +3108,9 @@ async function doctor(options) {
3092
3108
  warnings.push(...integrationWarnings(database.integrations, schema, rules));
3093
3109
  if (cfg.services.includes("ai") && !cfg.ai?.provider) warnings.push("ai service is enabled but ai.provider is not set");
3094
3110
  if (cfg.auth?.clerk) {
3095
- for (const [env, value] of Object.entries(cfg.auth.clerk)) {
3096
- if (typeof value === "string" && value.startsWith("$") && !process.env[value.slice(1)]) {
3097
- warnings.push(`auth.clerk.${env} references unset env var ${value}`);
3111
+ for (const [env, value2] of Object.entries(cfg.auth.clerk)) {
3112
+ if (typeof value2 === "string" && value2.startsWith("$") && !process.env[value2.slice(1)]) {
3113
+ warnings.push(`auth.clerk.${env} references unset env var ${value2}`);
3098
3114
  }
3099
3115
  }
3100
3116
  }
@@ -3136,10 +3152,10 @@ function harnessList(parsed) {
3136
3152
  ];
3137
3153
  return selected.length ? selected : ["all"];
3138
3154
  }
3139
- function harnessOption(value, flag) {
3140
- if (value === void 0) return [];
3141
- if (typeof value === "boolean") throw new Error(`${flag} requires a harness name`);
3142
- const raw = Array.isArray(value) ? value : [value];
3155
+ function harnessOption(value2, flag) {
3156
+ if (value2 === void 0) return [];
3157
+ if (typeof value2 === "boolean") throw new Error(`${flag} requires a harness name`);
3158
+ const raw = Array.isArray(value2) ? value2 : [value2];
3143
3159
  const parts = raw.flatMap((item) => item.split(","));
3144
3160
  if (parts.some((item) => !item.trim())) {
3145
3161
  throw new Error(`${flag} requires a harness name`);
@@ -3150,6 +3166,7 @@ function harnessOption(value, flag) {
3150
3166
  // src/init.ts
3151
3167
  var import_node_fs11 = require("fs");
3152
3168
  var import_node_path9 = require("path");
3169
+ var import_apps3 = require("@odla-ai/apps");
3153
3170
  function initProject(options) {
3154
3171
  const out = options.stdout ?? console;
3155
3172
  const rootDir = (0, import_node_path9.resolve)(options.rootDir ?? process.cwd());
@@ -3162,7 +3179,13 @@ function initProject(options) {
3162
3179
  }
3163
3180
  const envs = options.envs?.length ? options.envs : ["dev"];
3164
3181
  const services = options.services?.length ? options.services : ["db", "ai"];
3165
- if (services.includes("calendar") && !services.includes("db")) throw new Error("--services calendar requires db");
3182
+ for (const service of services) {
3183
+ const definition = (0, import_apps3.appServiceDefinition)(service);
3184
+ if (!definition) throw new Error(`--services contains unknown service "${service}" (known: ${(0, import_apps3.appServiceIds)().join(", ")})`);
3185
+ for (const dependency of definition.requires) {
3186
+ if (!services.includes(dependency)) throw new Error(`--services ${service} requires ${dependency}`);
3187
+ }
3188
+ }
3166
3189
  const aiProvider = options.aiProvider ?? "anthropic";
3167
3190
  (0, import_node_fs11.mkdirSync)((0, import_node_path9.dirname)(configPath), { recursive: true });
3168
3191
  (0, import_node_fs11.mkdirSync)((0, import_node_path9.resolve)(rootDir, "src/odla"), { recursive: true });
@@ -3352,7 +3375,7 @@ function assertWranglerConfig(cfg) {
3352
3375
 
3353
3376
  // src/secrets-set.ts
3354
3377
  var import_ai = require("@odla-ai/ai");
3355
- var import_apps2 = require("@odla-ai/apps");
3378
+ var import_apps4 = require("@odla-ai/apps");
3356
3379
  var PROD_ENV_NAMES2 = /* @__PURE__ */ new Set(["prod", "production"]);
3357
3380
  async function secretsSet(options) {
3358
3381
  const name = (options.name ?? "").trim();
@@ -3360,38 +3383,38 @@ async function secretsSet(options) {
3360
3383
  if (name.startsWith("$")) {
3361
3384
  throw new Error('"$"-prefixed vault names are platform-reserved; for the Clerk secret key use "odla-ai secrets set-clerk-key"');
3362
3385
  }
3363
- const { cfg, tenantId, value, doFetch, out } = await resolveVaultWrite(options);
3386
+ const { cfg, tenantId, value: value2, doFetch, out } = await resolveVaultWrite(options);
3364
3387
  const token = await getDeveloperToken(cfg, options, doFetch, out);
3365
3388
  try {
3366
- await (0, import_ai.putSecret)({ endpoint: cfg.dbEndpoint, token, fetch: doFetch }, tenantId, name, value);
3389
+ await (0, import_ai.putSecret)({ endpoint: cfg.dbEndpoint, token, fetch: doFetch }, tenantId, name, value2);
3367
3390
  } catch (err) {
3368
- throw new Error(scrubValue(err instanceof Error ? err.message : String(err), value));
3391
+ throw new Error(scrubValue(err instanceof Error ? err.message : String(err), value2));
3369
3392
  }
3370
3393
  out.log(`${name} stored in the ${tenantId} vault (write-only; the value was never echoed and cannot be read back here)`);
3371
3394
  }
3372
3395
  async function secretsSetClerkKey(options) {
3373
- const { cfg, tenantId, value, doFetch, out } = await resolveVaultWrite(options);
3374
- if (!value.startsWith("sk_")) throw new Error("the Clerk secret key must start with sk_ (sk_test_\u2026 or sk_live_\u2026)");
3375
- if (value.startsWith("sk_test_") && PROD_ENV_NAMES2.has(options.env)) {
3396
+ const { cfg, tenantId, value: value2, doFetch, out } = await resolveVaultWrite(options);
3397
+ if (!value2.startsWith("sk_")) throw new Error("the Clerk secret key must start with sk_ (sk_test_\u2026 or sk_live_\u2026)");
3398
+ if (value2.startsWith("sk_test_") && PROD_ENV_NAMES2.has(options.env)) {
3376
3399
  throw new Error(`refusing to store an sk_test_ Clerk key for "${options.env}" \u2014 use the production instance's sk_live_ key`);
3377
3400
  }
3378
- if (value.startsWith("sk_live_") && !PROD_ENV_NAMES2.has(options.env) && !options.yes) {
3401
+ if (value2.startsWith("sk_live_") && !PROD_ENV_NAMES2.has(options.env) && !options.yes) {
3379
3402
  throw new Error(`refusing to store an sk_live_ Clerk key for "${options.env}" without --yes (live users would sync into a non-prod tenant)`);
3380
3403
  }
3381
3404
  const token = await getDeveloperToken(cfg, options, doFetch, out);
3382
3405
  const res = await doFetch(`${cfg.dbEndpoint}/admin/apps/${encodeURIComponent(tenantId)}/clerk-secret`, {
3383
3406
  method: "POST",
3384
3407
  headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
3385
- body: JSON.stringify({ value })
3408
+ body: JSON.stringify({ value: value2 })
3386
3409
  });
3387
3410
  if (!res.ok) {
3388
- const text = scrubValue((await res.text().catch(() => "")).slice(0, 300), value);
3411
+ const text = scrubValue((await res.text().catch(() => "")).slice(0, 300), value2);
3389
3412
  throw new Error(`store Clerk secret key failed (${res.status}): ${text || "request failed"}`);
3390
3413
  }
3391
3414
  out.log(`Clerk secret key stored for ${tenantId} ($clerk_secret, reserved + write-only; the value was never echoed)`);
3392
3415
  }
3393
- function scrubValue(text, value) {
3394
- return redactSecrets(text).split(value).join("[value redacted]");
3416
+ function scrubValue(text, value2) {
3417
+ return redactSecrets(text).split(value2).join("[value redacted]");
3395
3418
  }
3396
3419
  async function resolveVaultWrite(options) {
3397
3420
  const out = options.stdout ?? console;
@@ -3403,8 +3426,8 @@ async function resolveVaultWrite(options) {
3403
3426
  if (PROD_ENV_NAMES2.has(options.env) && !options.yes) {
3404
3427
  throw new Error(`refusing to store a secret for "${options.env}" without --yes`);
3405
3428
  }
3406
- const value = await secretInputValue(options, "secret");
3407
- return { cfg, tenantId: (0, import_apps2.tenantIdFor)(cfg.app.id, options.env), value, doFetch, out };
3429
+ const value2 = await secretInputValue(options, "secret");
3430
+ return { cfg, tenantId: (0, import_apps4.tenantIdFor)(cfg.app.id, options.env), value: value2, doFetch, out };
3408
3431
  }
3409
3432
 
3410
3433
  // src/skill.ts
@@ -3934,24 +3957,24 @@ var CONTROL = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/;
3934
3957
  var HarnessProtocolError = class extends Error {
3935
3958
  name = "HarnessProtocolError";
3936
3959
  };
3937
- function record2(value) {
3938
- return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
3960
+ function record2(value2) {
3961
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
3939
3962
  }
3940
- function boundedText(value, label, max) {
3941
- if (typeof value !== "string" || !value || value.length > max || CONTROL.test(value)) {
3963
+ function boundedText(value2, label, max) {
3964
+ if (typeof value2 !== "string" || !value2 || value2.length > max || CONTROL.test(value2)) {
3942
3965
  throw new HarnessProtocolError(`${label} must be a non-empty string of at most ${max} characters`);
3943
3966
  }
3944
- return value;
3967
+ return value2;
3945
3968
  }
3946
3969
  function parseAgentOutput(line) {
3947
3970
  if (Buffer.byteLength(line, "utf8") > 1e6) throw new HarnessProtocolError("agent message exceeds 1 MB");
3948
- let value;
3971
+ let value2;
3949
3972
  try {
3950
- value = JSON.parse(line);
3973
+ value2 = JSON.parse(line);
3951
3974
  } catch {
3952
3975
  throw new HarnessProtocolError("agent emitted invalid JSON");
3953
3976
  }
3954
- const message2 = record2(value);
3977
+ const message2 = record2(value2);
3955
3978
  if (!message2 || message2.protocolVersion !== HARNESS_PROTOCOL_VERSION) {
3956
3979
  throw new HarnessProtocolError(`agent protocolVersion must be ${HARNESS_PROTOCOL_VERSION}`);
3957
3980
  }
@@ -4260,7 +4283,7 @@ async function gitOutput(cwd, args, maxBytes) {
4260
4283
  else stdout.push(chunk);
4261
4284
  });
4262
4285
  child.stderr.on("data", (chunk) => {
4263
- if (stderr.reduce((sum, value) => sum + value.byteLength, 0) < 16384) stderr.push(chunk);
4286
+ if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
4264
4287
  });
4265
4288
  const code = await new Promise((accept, reject) => {
4266
4289
  child.once("error", reject);
@@ -4281,7 +4304,7 @@ async function gitBlobs(cwd, entries, maxBytes) {
4281
4304
  else stdout.push(chunk);
4282
4305
  });
4283
4306
  child.stderr.on("data", (chunk) => {
4284
- if (stderr.reduce((sum, value) => sum + value.byteLength, 0) < 16384) stderr.push(chunk);
4307
+ if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
4285
4308
  });
4286
4309
  child.stdin.end(`${entries.map((entry) => entry.hash).join("\n")}
4287
4310
  `);
@@ -4319,8 +4342,8 @@ async function materializeGitTree(source, commitSha, options = {}) {
4319
4342
  const maxFiles = options.maxFiles ?? 2e4;
4320
4343
  const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
4321
4344
  const inventory = (await gitOutput(sourceDir, ["ls-tree", "-rz", commitSha], 16 * 1024 * 1024)).toString("utf8").split("\0").filter(Boolean);
4322
- const entries = inventory.flatMap((record7) => {
4323
- const match = /^(100644|100755) blob ([0-9a-f]{40,64})\t([\s\S]+)$/.exec(record7);
4345
+ const entries = inventory.flatMap((record8) => {
4346
+ const match = /^(100644|100755) blob ([0-9a-f]{40,64})\t([\s\S]+)$/.exec(record8);
4324
4347
  return match && allowedWorkspacePath(match[3]) ? [{ mode: match[1], hash: match[2], path: match[3] }] : [];
4325
4348
  });
4326
4349
  if (entries.length > maxFiles) throw new Error(`workspace exceeds ${maxFiles} files`);
@@ -4395,7 +4418,7 @@ async function gitSourceFiles(sourceDir, maxFiles, maxBytes) {
4395
4418
  else stdout.push(chunk);
4396
4419
  });
4397
4420
  child.stderr.on("data", (chunk) => {
4398
- if (stderr.reduce((sum, value) => sum + value.byteLength, 0) < 16384) stderr.push(chunk);
4421
+ if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
4399
4422
  });
4400
4423
  const code = await new Promise((accept, reject) => {
4401
4424
  child.once("error", reject);
@@ -4455,7 +4478,7 @@ async function captureGitDiff(root, maxBytes) {
4455
4478
  else stdout.push(chunk);
4456
4479
  });
4457
4480
  child.stderr.on("data", (chunk) => {
4458
- if (stderr.reduce((sum, value) => sum + value.byteLength, 0) < 16384) stderr.push(chunk);
4481
+ if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
4459
4482
  });
4460
4483
  const code = await new Promise((accept, reject) => {
4461
4484
  child.once("error", reject);
@@ -4542,34 +4565,34 @@ var CamelError = class extends Error {
4542
4565
  };
4543
4566
 
4544
4567
  // ../camel/dist/chunk-L5DYU2E2.js
4545
- function canonicalJson(value) {
4546
- return JSON.stringify(normalize(value));
4568
+ function canonicalJson(value2) {
4569
+ return JSON.stringify(normalize(value2));
4547
4570
  }
4548
- async function sha256Hex(value) {
4549
- const bytes = typeof value === "string" ? new TextEncoder().encode(value) : value;
4571
+ async function sha256Hex(value2) {
4572
+ const bytes = typeof value2 === "string" ? new TextEncoder().encode(value2) : value2;
4550
4573
  const digest = await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes).buffer);
4551
4574
  return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
4552
4575
  }
4553
- function utf8Length(value) {
4554
- if (typeof value === "string") return new TextEncoder().encode(value).byteLength;
4555
- if (value instanceof Uint8Array) return value.byteLength;
4576
+ function utf8Length(value2) {
4577
+ if (typeof value2 === "string") return new TextEncoder().encode(value2).byteLength;
4578
+ if (value2 instanceof Uint8Array) return value2.byteLength;
4556
4579
  try {
4557
- return new TextEncoder().encode(canonicalJson(value)).byteLength;
4580
+ return new TextEncoder().encode(canonicalJson(value2)).byteLength;
4558
4581
  } catch {
4559
4582
  throw new CamelError("conversion_rejected", "Unsafe input could not be canonically measured.");
4560
4583
  }
4561
4584
  }
4562
- function normalize(value) {
4563
- if (value === null || typeof value === "string" || typeof value === "boolean") return value;
4564
- if (typeof value === "number") {
4565
- if (!Number.isFinite(value)) throw new CamelError("state_conflict", "Canonical JSON rejects non-finite numbers.");
4566
- return value;
4585
+ function normalize(value2) {
4586
+ if (value2 === null || typeof value2 === "string" || typeof value2 === "boolean") return value2;
4587
+ if (typeof value2 === "number") {
4588
+ if (!Number.isFinite(value2)) throw new CamelError("state_conflict", "Canonical JSON rejects non-finite numbers.");
4589
+ return value2;
4567
4590
  }
4568
- if (Array.isArray(value)) return value.map(normalize);
4569
- if (value instanceof Uint8Array) return { $bytes: [...value] };
4570
- if (typeof value === "object") {
4571
- const record7 = value;
4572
- return Object.fromEntries(Object.keys(record7).filter((key) => record7[key] !== void 0).sort().map((key) => [key, normalize(record7[key])]));
4591
+ if (Array.isArray(value2)) return value2.map(normalize);
4592
+ if (value2 instanceof Uint8Array) return { $bytes: [...value2] };
4593
+ if (typeof value2 === "object") {
4594
+ const record8 = value2;
4595
+ return Object.fromEntries(Object.keys(record8).filter((key) => record8[key] !== void 0).sort().map((key) => [key, normalize(record8[key])]));
4573
4596
  }
4574
4597
  throw new CamelError("state_conflict", "Canonical JSON rejects unsupported values.");
4575
4598
  }
@@ -4578,10 +4601,10 @@ function canRead(readers, readerId) {
4578
4601
  }
4579
4602
  function dependenciesOf(values, influence = "data") {
4580
4603
  const result = [];
4581
- for (const value of values) {
4582
- result.push(...value.label.dependencies);
4583
- for (const ref of value.label.provenance) {
4584
- result.push({ ref, influence, promptSafetyAtUse: value.label.promptSafety });
4604
+ for (const value2 of values) {
4605
+ result.push(...value2.label.dependencies);
4606
+ for (const ref of value2.label.provenance) {
4607
+ result.push({ ref, influence, promptSafetyAtUse: value2.label.promptSafety });
4585
4608
  }
4586
4609
  }
4587
4610
  const unique3 = /* @__PURE__ */ new Map();
@@ -4592,32 +4615,32 @@ function dependenciesOf(values, influence = "data") {
4592
4615
  // ../camel/dist/chunk-S7EVNA2U.js
4593
4616
  var camelValueBrand = /* @__PURE__ */ Symbol("@odla-ai/camel/value");
4594
4617
  var authenticCamelValues = /* @__PURE__ */ new WeakSet();
4595
- function isCamelValue(value) {
4596
- return typeof value === "object" && value !== null && authenticCamelValues.has(value);
4618
+ function isCamelValue(value2) {
4619
+ return typeof value2 === "object" && value2 !== null && authenticCamelValues.has(value2);
4597
4620
  }
4598
- function isSafe(value) {
4599
- return isCamelValue(value) && value.label.promptSafety === "safe";
4621
+ function isSafe(value2) {
4622
+ return isCamelValue(value2) && value2.label.promptSafety === "safe";
4600
4623
  }
4601
- function isUnsafe(value) {
4602
- return isCamelValue(value) && value.label.promptSafety === "unsafe";
4624
+ function isUnsafe(value2) {
4625
+ return isCamelValue(value2) && value2.label.promptSafety === "unsafe";
4603
4626
  }
4604
- function createSafeInternal(value, safeBasis, metadata2) {
4605
- return createValue(value, {
4627
+ function createSafeInternal(value2, safeBasis, metadata2) {
4628
+ return createValue(value2, {
4606
4629
  schemaVersion: 1,
4607
4630
  promptSafety: "safe",
4608
4631
  safeBasis,
4609
4632
  ...copyMetadata(metadata2)
4610
4633
  });
4611
4634
  }
4612
- function createUnsafeInternal(value, metadata2) {
4613
- return createValue(value, {
4635
+ function createUnsafeInternal(value2, metadata2) {
4636
+ return createValue(value2, {
4614
4637
  schemaVersion: 1,
4615
4638
  promptSafety: "unsafe",
4616
4639
  ...copyMetadata(metadata2)
4617
4640
  });
4618
4641
  }
4619
- function createValue(value, label) {
4620
- const result = { value, label: Object.freeze(label) };
4642
+ function createValue(value2, label) {
4643
+ const result = { value: value2, label: Object.freeze(label) };
4621
4644
  Object.defineProperty(result, camelValueBrand, { value: label.promptSafety, enumerable: false });
4622
4645
  authenticCamelValues.add(result);
4623
4646
  return Object.freeze(result);
@@ -4723,8 +4746,8 @@ async function createCodePortableCheckpoint(input) {
4723
4746
  const checkpointDigest = `sha256:${await sha256Hex(canonicalJson(fields))}`;
4724
4747
  return freeze({ ...fields, patch: input.patch, checkpointDigest });
4725
4748
  }
4726
- async function verifyCodePortableCheckpoint(value) {
4727
- const input = object(value, "checkpoint");
4749
+ async function verifyCodePortableCheckpoint(value2) {
4750
+ const input = object(value2, "checkpoint");
4728
4751
  exact2(input, ["schemaVersion", "baseCommitSha", "patch", "patchDigest", "state", "stateDigest", "checkpointDigest"]);
4729
4752
  if (input.schemaVersion !== 1 || typeof input.baseCommitSha !== "string" || typeof input.patch !== "string" || typeof input.patchDigest !== "string" || typeof input.stateDigest !== "string" || typeof input.checkpointDigest !== "string") {
4730
4753
  throw invalid2("Portable checkpoint fields are malformed.");
@@ -4739,8 +4762,8 @@ async function verifyCodePortableCheckpoint(value) {
4739
4762
  }
4740
4763
  return created;
4741
4764
  }
4742
- function normalizeState(value) {
4743
- const state2 = object(value, "state");
4765
+ function normalizeState(value2) {
4766
+ const state2 = object(value2, "state");
4744
4767
  exact2(state2, [
4745
4768
  "planCursor",
4746
4769
  "conversationRefs",
@@ -4798,30 +4821,30 @@ function validateBaseAndPatch(baseCommitSha, patch2) {
4798
4821
  throw invalid2("Portable checkpoint base or patch is malformed or outside its bounds.");
4799
4822
  }
4800
4823
  }
4801
- function strings(value, name, pattern, maximum, sort) {
4802
- if (!Array.isArray(value) || value.length > maximum || value.some((item) => typeof item !== "string" || !pattern.test(item)) || new Set(value).size !== value.length) {
4824
+ function strings(value2, name, pattern, maximum, sort) {
4825
+ if (!Array.isArray(value2) || value2.length > maximum || value2.some((item) => typeof item !== "string" || !pattern.test(item)) || new Set(value2).size !== value2.length) {
4803
4826
  throw invalid2(`Portable checkpoint ${name} is malformed or outside its bounds.`);
4804
4827
  }
4805
- const result = [...value];
4828
+ const result = [...value2];
4806
4829
  return sort ? result.sort() : result;
4807
4830
  }
4808
- function object(value, name) {
4809
- if (!value || typeof value !== "object" || Array.isArray(value)) throw invalid2(`Portable ${name} must be an object.`);
4810
- return value;
4831
+ function object(value2, name) {
4832
+ if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) throw invalid2(`Portable ${name} must be an object.`);
4833
+ return value2;
4811
4834
  }
4812
- function exact2(value, keys) {
4813
- if (Object.keys(value).some((key) => !keys.includes(key)) || keys.some((key) => !(key in value))) {
4835
+ function exact2(value2, keys) {
4836
+ if (Object.keys(value2).some((key) => !keys.includes(key)) || keys.some((key) => !(key in value2))) {
4814
4837
  throw invalid2("Portable checkpoint contains missing or unsupported fields.");
4815
4838
  }
4816
4839
  }
4817
- function freeze(value) {
4840
+ function freeze(value2) {
4818
4841
  return Object.freeze({
4819
- ...value,
4842
+ ...value2,
4820
4843
  state: Object.freeze({
4821
- ...value.state,
4822
- conversationRefs: Object.freeze([...value.state.conversationRefs]),
4823
- completedEffects: Object.freeze(value.state.completedEffects.map((item) => Object.freeze({ ...item }))),
4824
- unresolvedApprovals: Object.freeze([...value.state.unresolvedApprovals])
4844
+ ...value2.state,
4845
+ conversationRefs: Object.freeze([...value2.state.conversationRefs]),
4846
+ completedEffects: Object.freeze(value2.state.completedEffects.map((item) => Object.freeze({ ...item }))),
4847
+ unresolvedApprovals: Object.freeze([...value2.state.unresolvedApprovals])
4825
4848
  })
4826
4849
  });
4827
4850
  }
@@ -4912,61 +4935,61 @@ async function createConversionRegistry(config) {
4912
4935
  if (utf8Length(source.value) > policy.maximumSourceBytes) throw new CamelError("limit_exceeded", "Unsafe conversion input exceeds its byte bound.");
4913
4936
  return policy;
4914
4937
  };
4915
- const emit3 = (source, policy, value) => convert(source, policy, value, outputCounts);
4938
+ const emit3 = (source, policy, value2) => convert(source, policy, value2, outputCounts);
4916
4939
  const operations = Object.freeze({
4917
- boolean: async (value, id) => {
4918
- const policy = checked(value, id, "boolean");
4919
- return emit3(value, policy, requireBoolean(value.value));
4940
+ boolean: async (value2, id) => {
4941
+ const policy = checked(value2, id, "boolean");
4942
+ return emit3(value2, policy, requireBoolean(value2.value));
4920
4943
  },
4921
- integer: async (value, id) => {
4922
- const policy = checked(value, id, "integer");
4923
- return emit3(value, policy, boundedInteger(value.value, policy.output));
4944
+ integer: async (value2, id) => {
4945
+ const policy = checked(value2, id, "integer");
4946
+ return emit3(value2, policy, boundedInteger(value2.value, policy.output));
4924
4947
  },
4925
- finiteNumber: async (value, id) => {
4926
- const policy = checked(value, id, "finite_number");
4927
- return emit3(value, policy, boundedNumber(value.value, policy.output));
4948
+ finiteNumber: async (value2, id) => {
4949
+ const policy = checked(value2, id, "finite_number");
4950
+ return emit3(value2, policy, boundedNumber(value2.value, policy.output));
4928
4951
  },
4929
- enum: async (value, id) => {
4930
- const policy = checked(value, id, "enum");
4931
- return emit3(value, policy, enumMember(value.value, policy.output));
4952
+ enum: async (value2, id) => {
4953
+ const policy = checked(value2, id, "enum");
4954
+ return emit3(value2, policy, enumMember(value2.value, policy.output));
4932
4955
  },
4933
- date: async (value, id) => {
4934
- const policy = checked(value, id, "date");
4935
- return emit3(value, policy, canonicalDate(value.value, policy.output));
4956
+ date: async (value2, id) => {
4957
+ const policy = checked(value2, id, "date");
4958
+ return emit3(value2, policy, canonicalDate(value2.value, policy.output));
4936
4959
  },
4937
- registeredId: async (value, id) => {
4938
- const policy = checked(value, id, "registered_id");
4960
+ registeredId: async (value2, id) => {
4961
+ const policy = checked(value2, id, "registered_id");
4939
4962
  const registry = config.registeredIds?.[policy.output.registryId];
4940
- const output = typeof value.value === "string" ? registry?.values[value.value] : void 0;
4963
+ const output = typeof value2.value === "string" ? registry?.values[value2.value] : void 0;
4941
4964
  if (!output) throw new CamelError("conversion_rejected", "Registered-ID conversion rejected the candidate.");
4942
- return emit3(value, policy, output);
4965
+ return emit3(value2, policy, output);
4943
4966
  },
4944
- digest: async (value, id) => {
4945
- const policy = checked(value, id, "digest");
4946
- if (!(value.value instanceof Uint8Array)) throw new CamelError("conversion_rejected", "Digest conversion requires bytes.");
4947
- return emit3(value, policy, await sha256Hex(value.value));
4967
+ digest: async (value2, id) => {
4968
+ const policy = checked(value2, id, "digest");
4969
+ if (!(value2.value instanceof Uint8Array)) throw new CamelError("conversion_rejected", "Digest conversion requires bytes.");
4970
+ return emit3(value2, policy, await sha256Hex(value2.value));
4948
4971
  },
4949
- measure: async (value, metric, id) => {
4950
- const policy = checked(value, id, "integer");
4951
- const measured = measure(value.value, metric);
4952
- return emit3(value, policy, boundedInteger(measured, policy.output));
4972
+ measure: async (value2, metric, id) => {
4973
+ const policy = checked(value2, id, "integer");
4974
+ const measured = measure(value2.value, metric);
4975
+ return emit3(value2, policy, boundedInteger(measured, policy.output));
4953
4976
  },
4954
- test: async (value, predicateId, id) => {
4955
- const policy = checked(value, id, "boolean");
4977
+ test: async (value2, predicateId, id) => {
4978
+ const policy = checked(value2, id, "boolean");
4956
4979
  const predicate = config.predicates?.[predicateId];
4957
4980
  if (!predicate) throw new CamelError("conversion_rejected", "Predicate is not registered.");
4958
- return emit3(value, policy, evaluatePredicate(value.value, predicate, config.registeredIds));
4981
+ return emit3(value2, policy, evaluatePredicate(value2.value, predicate, config.registeredIds));
4959
4982
  }
4960
4983
  });
4961
4984
  return Object.freeze({ operations, policy: (id) => policies.get(id) ?? missingPolicy() });
4962
4985
  }
4963
- async function convert(source, policy, value, counts) {
4986
+ async function convert(source, policy, value2, counts) {
4964
4987
  const sourceKey = sourceIdentity(source);
4965
4988
  const countKey = `${policy.conversionId}\0${sourceKey}`;
4966
4989
  const count = counts.get(countKey) ?? 0;
4967
4990
  if (count >= policy.maximumOutputsPerArtifact) throw new CamelError("limit_exceeded", "Conversion output count exceeds its per-source bound.");
4968
4991
  counts.set(countKey, count + 1);
4969
- return createSafeInternal(value, "atomic_conversion", {
4992
+ return createSafeInternal(value2, "atomic_conversion", {
4970
4993
  readers: source.label.readers,
4971
4994
  provenance: [...source.label.provenance, { kind: "converter", id: policy.conversionId, digest: policy.digest }],
4972
4995
  dependencies: dependenciesOf([source])
@@ -4978,49 +5001,49 @@ function validatePolicyShape(policy) {
4978
5001
  const output = policy.output;
4979
5002
  if ((output.kind === "integer" || output.kind === "finite_number") && (!Number.isFinite(output.minimum) || !Number.isFinite(output.maximum) || output.minimum > output.maximum)) throw new CamelError("state_conflict", "Numeric conversion bounds are invalid.");
4980
5003
  if (output.kind === "finite_number" && (!Number.isSafeInteger(output.maximumDecimalPlaces) || output.maximumDecimalPlaces < 0 || output.maximumDecimalPlaces > 15)) throw new CamelError("state_conflict", "Decimal-place bound is invalid.");
4981
- if (output.kind === "enum" && (output.values.length === 0 || output.values.some((value) => typeof value !== "string" || !value) || new Set(output.values).size !== output.values.length)) throw new CamelError("state_conflict", "Enum conversion members must be unique and non-empty.");
5004
+ if (output.kind === "enum" && (output.values.length === 0 || output.values.some((value2) => typeof value2 !== "string" || !value2) || new Set(output.values).size !== output.values.length)) throw new CamelError("state_conflict", "Enum conversion members must be unique and non-empty.");
4982
5005
  if (output.kind === "registered_id" && (!output.registryId || !output.registryDigest)) throw new CamelError("state_conflict", "Registered-ID conversion identity is invalid.");
4983
5006
  if (output.kind === "date" && output.format !== "date" && output.format !== "rfc3339") throw new CamelError("state_conflict", "Date conversion format is invalid.");
4984
5007
  if (output.kind === "digest" && output.algorithm !== "sha256") throw new CamelError("state_conflict", "Digest conversion algorithm is invalid.");
4985
5008
  }
4986
- function requireBoolean(value) {
4987
- if (typeof value !== "boolean") throw new CamelError("conversion_rejected", "Boolean conversion requires a structured boolean.");
4988
- return value;
5009
+ function requireBoolean(value2) {
5010
+ if (typeof value2 !== "boolean") throw new CamelError("conversion_rejected", "Boolean conversion requires a structured boolean.");
5011
+ return value2;
4989
5012
  }
4990
- function boundedInteger(value, spec) {
4991
- if (spec.kind !== "integer" || typeof value !== "number" || !Number.isSafeInteger(value) || value < spec.minimum || value > spec.maximum) throw new CamelError("conversion_rejected", "Integer conversion rejected the structured value.");
4992
- return value;
5013
+ function boundedInteger(value2, spec) {
5014
+ if (spec.kind !== "integer" || typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 < spec.minimum || value2 > spec.maximum) throw new CamelError("conversion_rejected", "Integer conversion rejected the structured value.");
5015
+ return value2;
4993
5016
  }
4994
- function boundedNumber(value, spec) {
4995
- if (spec.kind !== "finite_number" || typeof value !== "number" || !Number.isFinite(value) || value < spec.minimum || value > spec.maximum) throw new CamelError("conversion_rejected", "Finite-number conversion rejected the structured value.");
4996
- const text = String(value);
5017
+ function boundedNumber(value2, spec) {
5018
+ if (spec.kind !== "finite_number" || typeof value2 !== "number" || !Number.isFinite(value2) || value2 < spec.minimum || value2 > spec.maximum) throw new CamelError("conversion_rejected", "Finite-number conversion rejected the structured value.");
5019
+ const text = String(value2);
4997
5020
  if (/e/i.test(text) || (text.split(".")[1]?.length ?? 0) > spec.maximumDecimalPlaces) throw new CamelError("conversion_rejected", "Finite-number conversion rejected a non-canonical decimal.");
4998
- return value;
5021
+ return value2;
4999
5022
  }
5000
- function enumMember(value, spec) {
5001
- if (spec.kind !== "enum" || typeof value !== "string") throw new CamelError("conversion_rejected", "Enum conversion requires a structured string member.");
5002
- const member = spec.caseSensitive ? spec.values.find((item) => item === value) : spec.values.find((item) => item.toLocaleLowerCase("en-US") === value.toLocaleLowerCase("en-US"));
5023
+ function enumMember(value2, spec) {
5024
+ if (spec.kind !== "enum" || typeof value2 !== "string") throw new CamelError("conversion_rejected", "Enum conversion requires a structured string member.");
5025
+ const member = spec.caseSensitive ? spec.values.find((item) => item === value2) : spec.values.find((item) => item.toLocaleLowerCase("en-US") === value2.toLocaleLowerCase("en-US"));
5003
5026
  if (member === void 0) throw new CamelError("conversion_rejected", "Enum conversion rejected a non-member.");
5004
5027
  return member;
5005
5028
  }
5006
- function canonicalDate(value, spec) {
5007
- if (spec.kind !== "date" || typeof value !== "string") throw new CamelError("conversion_rejected", "Date conversion requires a canonical structured string.");
5029
+ function canonicalDate(value2, spec) {
5030
+ if (spec.kind !== "date" || typeof value2 !== "string") throw new CamelError("conversion_rejected", "Date conversion requires a canonical structured string.");
5008
5031
  const pattern = spec.format === "date" ? /^\d{4}-\d{2}-\d{2}$/ : /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
5009
- const instant = Date.parse(spec.format === "date" ? `${value}T00:00:00Z` : value);
5010
- if (!pattern.test(value) || !Number.isFinite(instant) || spec.format === "date" && new Date(instant).toISOString().slice(0, 10) !== value) throw new CamelError("conversion_rejected", "Date conversion rejected a non-canonical value.");
5011
- if (spec.earliest && value < spec.earliest || spec.latest && value > spec.latest) throw new CamelError("conversion_rejected", "Date conversion rejected an out-of-range value.");
5012
- return value;
5013
- }
5014
- function measure(value, metric) {
5015
- if (metric === "byte_length" && (typeof value === "string" || value instanceof Uint8Array)) return utf8Length(value);
5016
- if (metric === "codepoint_length" && typeof value === "string") return [...value].length;
5017
- if (metric === "item_count" && Array.isArray(value)) return value.length;
5032
+ const instant = Date.parse(spec.format === "date" ? `${value2}T00:00:00Z` : value2);
5033
+ if (!pattern.test(value2) || !Number.isFinite(instant) || spec.format === "date" && new Date(instant).toISOString().slice(0, 10) !== value2) throw new CamelError("conversion_rejected", "Date conversion rejected a non-canonical value.");
5034
+ if (spec.earliest && value2 < spec.earliest || spec.latest && value2 > spec.latest) throw new CamelError("conversion_rejected", "Date conversion rejected an out-of-range value.");
5035
+ return value2;
5036
+ }
5037
+ function measure(value2, metric) {
5038
+ if (metric === "byte_length" && (typeof value2 === "string" || value2 instanceof Uint8Array)) return utf8Length(value2);
5039
+ if (metric === "codepoint_length" && typeof value2 === "string") return [...value2].length;
5040
+ if (metric === "item_count" && Array.isArray(value2)) return value2.length;
5018
5041
  throw new CamelError("conversion_rejected", "Measurement input does not match the registered metric.");
5019
5042
  }
5020
- function evaluatePredicate(value, predicate, registries) {
5021
- if (predicate.kind === "has_fields") return typeof value === "object" && value !== null && !Array.isArray(value) && predicate.fields.every((field) => Object.hasOwn(value, field));
5022
- if (predicate.kind === "registered_id") return typeof value === "string" && registries?.[predicate.registryId]?.values[value] !== void 0;
5023
- const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
5043
+ function evaluatePredicate(value2, predicate, registries) {
5044
+ if (predicate.kind === "has_fields") return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && predicate.fields.every((field) => Object.hasOwn(value2, field));
5045
+ if (predicate.kind === "registered_id") return typeof value2 === "string" && registries?.[predicate.registryId]?.values[value2] !== void 0;
5046
+ const actual = value2 === null ? "null" : Array.isArray(value2) ? "array" : typeof value2;
5024
5047
  return actual === predicate.valueType;
5025
5048
  }
5026
5049
  function sourceIdentity(source) {
@@ -5043,17 +5066,17 @@ function createCamelIngress(constants2 = []) {
5043
5066
  byId.set(item.id, item);
5044
5067
  }
5045
5068
  const ingress = {
5046
- userInstruction: (value, input) => createSafeInternal(value, "user_instruction", metadata("user_instruction", input.id, input.readers)),
5047
- systemPolicy: (value, input) => createSafeInternal(value, "system_policy", metadata("system_policy", input.id, input.readers)),
5069
+ userInstruction: (value2, input) => createSafeInternal(value2, "user_instruction", metadata("user_instruction", input.id, input.readers)),
5070
+ systemPolicy: (value2, input) => createSafeInternal(value2, "system_policy", metadata("system_policy", input.id, input.readers)),
5048
5071
  control: (id) => {
5049
5072
  const item = byId.get(id);
5050
5073
  if (!item) throw new CamelError("permission_denied", "Unknown control constant.");
5051
5074
  return createSafeInternal(item.value, "harness_constant", metadata("harness", id, item.readers));
5052
5075
  },
5053
- external: (value, label) => createUnsafeInternal(value, label),
5054
- quarantinedOutput: (value, input) => {
5076
+ external: (value2, label) => createUnsafeInternal(value2, label),
5077
+ quarantinedOutput: (value2, input) => {
5055
5078
  if (!input.runId) throw new CamelError("state_conflict", "Quarantined run IDs must be non-empty.");
5056
- return createUnsafeInternal(value, {
5079
+ return createUnsafeInternal(value2, {
5057
5080
  readers: input.readers,
5058
5081
  dependencies: input.dependencies,
5059
5082
  provenance: [{ kind: "quarantined_llm", id: input.runId, digest: input.digest }]
@@ -5062,15 +5085,15 @@ function createCamelIngress(constants2 = []) {
5062
5085
  };
5063
5086
  return Object.freeze(ingress);
5064
5087
  }
5065
- function assertNoUnsafeConstant(value, seen = /* @__PURE__ */ new WeakSet()) {
5066
- if (typeof value !== "object" || value === null || seen.has(value)) return;
5067
- seen.add(value);
5068
- if (isCamelValue(value)) {
5069
- if (isUnsafe(value)) throw new CamelError("unsafe_privileged_flow", "Control constants cannot contain Prompt-Unsafe values.");
5070
- assertNoUnsafeConstant(value.value, seen);
5088
+ function assertNoUnsafeConstant(value2, seen = /* @__PURE__ */ new WeakSet()) {
5089
+ if (typeof value2 !== "object" || value2 === null || seen.has(value2)) return;
5090
+ seen.add(value2);
5091
+ if (isCamelValue(value2)) {
5092
+ if (isUnsafe(value2)) throw new CamelError("unsafe_privileged_flow", "Control constants cannot contain Prompt-Unsafe values.");
5093
+ assertNoUnsafeConstant(value2.value, seen);
5071
5094
  return;
5072
5095
  }
5073
- for (const child of Object.values(value)) assertNoUnsafeConstant(child, seen);
5096
+ for (const child of Object.values(value2)) assertNoUnsafeConstant(child, seen);
5074
5097
  }
5075
5098
  function metadata(kind, id, readers) {
5076
5099
  if (!id) throw new CamelError("state_conflict", "Provenance IDs must be non-empty.");
@@ -5101,7 +5124,7 @@ async function evaluate(input, registries, approvals) {
5101
5124
  if (invalid3) return deny(invalid3);
5102
5125
  if (arg.role === "selector" && !isSafe(arg.value)) confined.add(arg.value);
5103
5126
  }
5104
- if (input.controlDependencies.some((value) => !isSafe(value) && !confined.has(value))) return deny("unsafe_control_dependency");
5127
+ if (input.controlDependencies.some((value2) => !isSafe(value2) && !confined.has(value2))) return deny("unsafe_control_dependency");
5105
5128
  if (confined.size > 0) {
5106
5129
  const fixed = input.tool.unsafeSelectorPolicy?.fixedProviderIds ?? [];
5107
5130
  const destinations = Object.values(input.args).filter((arg) => arg.role === "destination");
@@ -5128,29 +5151,29 @@ async function validateArgument(path, arg, tool, registries) {
5128
5151
  if (!isSafe(arg.value)) return "unsafe_destination_argument";
5129
5152
  if (!isControlOwned(arg.value)) return "destination_not_control_owned";
5130
5153
  const registry = registries[arg.registryId];
5131
- const validValues = registry && registry.values.length > 0 && registry.values.every((value) => typeof value === "string" && value.length > 0) && new Set(registry.values).size === registry.values.length;
5154
+ const validValues = registry && registry.values.length > 0 && registry.values.every((value2) => typeof value2 === "string" && value2.length > 0) && new Set(registry.values).size === registry.values.length;
5132
5155
  if (!registry || !validValues || registry.digest !== arg.registryDigest || await destinationRegistryDigest(registry.values) !== registry.digest || !registry.values.includes(arg.value.value)) return "destination_not_registered";
5133
5156
  }
5134
5157
  if (arg.role === "selector" && !isSafe(arg.value)) return validateUnsafeSelector(path, arg.value, tool);
5135
5158
  return void 0;
5136
5159
  }
5137
- function isControlOwned(value) {
5138
- return value.label.safeBasis === "system_policy" || value.label.safeBasis === "harness_constant";
5160
+ function isControlOwned(value2) {
5161
+ return value2.label.safeBasis === "system_policy" || value2.label.safeBasis === "harness_constant";
5139
5162
  }
5140
5163
  function copyRegistries(registries) {
5141
5164
  return Object.freeze(Object.fromEntries(Object.entries(registries).map(([id, registry]) => [id, Object.freeze({ digest: registry.digest, values: Object.freeze([...registry.values]) })])));
5142
5165
  }
5143
- function validateUnsafeSelector(path, value, tool) {
5166
+ function validateUnsafeSelector(path, value2, tool) {
5144
5167
  const policy = tool.unsafeSelectorPolicy;
5145
5168
  if (!policy || policy.effect !== tool.effect || !policy.selectorPaths.includes(path)) return "unsafe_selector_not_confined";
5146
5169
  if (!policy.fixedDestination || !policy.unsafeOutput || policy.fixedProviderIds.length === 0) return "unsafe_selector_not_confined";
5147
5170
  if (![policy.maximumCalls, policy.maximumResultsPerCall, policy.maximumOutputBytes, policy.maximumSelectorBytes].every((bound) => Number.isSafeInteger(bound) && bound > 0)) return "unsafe_selector_not_confined";
5148
- if (utf8Length(value.value) > policy.maximumSelectorBytes) return "unsafe_selector_too_large";
5149
- if (typeof value.value === "string" && looksLikeDestination(value.value)) return "unsafe_selector_is_destination";
5171
+ if (utf8Length(value2.value) > policy.maximumSelectorBytes) return "unsafe_selector_too_large";
5172
+ if (typeof value2.value === "string" && looksLikeDestination(value2.value)) return "unsafe_selector_is_destination";
5150
5173
  return void 0;
5151
5174
  }
5152
- function looksLikeDestination(value) {
5153
- const text = value.trim();
5175
+ function looksLikeDestination(value2) {
5176
+ const text = value2.trim();
5154
5177
  return /^(?:[a-z][a-z0-9+.-]*:\/\/|\/|\\\\)/i.test(text) || /^[\w.-]+\.[a-z]{2,}(?:[/:]|$)/i.test(text);
5155
5178
  }
5156
5179
 
@@ -5236,9 +5259,9 @@ var CodeRuntimeReconciler = class {
5236
5259
  }
5237
5260
  }
5238
5261
  };
5239
- function retryableControlFailure(value) {
5240
- if (!value || typeof value !== "object") return false;
5241
- const failure = value;
5262
+ function retryableControlFailure(value2) {
5263
+ if (!value2 || typeof value2 !== "object") return false;
5264
+ const failure = value2;
5242
5265
  if (failure.code === "invalid_response" || typeof failure.status !== "number") return false;
5243
5266
  return failure.status === 408 || failure.status === 425 || failure.status === 429 || failure.status >= 500;
5244
5267
  }
@@ -5290,16 +5313,16 @@ function createCodeRuntimeControlClient(options) {
5290
5313
  if (options.signal?.aborted) throw cause;
5291
5314
  throw new CodeRuntimeControlError("Code runtime control plane is unavailable", 503, "transport_unavailable");
5292
5315
  }
5293
- const value = await response2.json().catch(() => null);
5316
+ const value2 = await response2.json().catch(() => null);
5294
5317
  if (!response2.ok) {
5295
- const problem = record3(record3(value)?.error);
5318
+ const problem = record3(record3(value2)?.error);
5296
5319
  throw new CodeRuntimeControlError(
5297
5320
  typeof problem?.message === "string" ? problem.message : `Code runtime request failed (${response2.status})`,
5298
5321
  response2.status,
5299
5322
  typeof problem?.code === "string" ? problem.code : void 0
5300
5323
  );
5301
5324
  }
5302
- return value;
5325
+ return value2;
5303
5326
  };
5304
5327
  return {
5305
5328
  heartbeat: async (version, capabilities) => {
@@ -5314,15 +5337,15 @@ function createCodeRuntimeControlClient(options) {
5314
5337
  await call2(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/source`, {})
5315
5338
  ),
5316
5339
  infer: async (sessionId, inference) => {
5317
- const value = record3(await call2(
5340
+ const value2 = record3(await call2(
5318
5341
  `/registry/code/runtime/sessions/${validSessionId(sessionId)}/inference`,
5319
5342
  inference,
5320
5343
  modelRequestTimeoutMs
5321
5344
  ));
5322
- if (!value || value.requestId !== inference.requestId || !record3(value.response) || !record3(value.receipt)) {
5345
+ if (!value2 || value2.requestId !== inference.requestId || !record3(value2.response) || !record3(value2.receipt)) {
5323
5346
  throw new CodeRuntimeControlError("invalid Code inference response", 502, "invalid_response");
5324
5347
  }
5325
- return value;
5348
+ return value2;
5326
5349
  },
5327
5350
  review: async (sessionId, review) => parseReview(
5328
5351
  await call2(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/review`, review, modelRequestTimeoutMs)
@@ -5347,8 +5370,8 @@ function createCodeRuntimeControlClient(options) {
5347
5370
  }
5348
5371
  };
5349
5372
  }
5350
- function validatedEndpoint(value) {
5351
- const endpoint = value.replace(/\/+$/, "");
5373
+ function validatedEndpoint(value2) {
5374
+ const endpoint = value2.replace(/\/+$/, "");
5352
5375
  let url;
5353
5376
  try {
5354
5377
  url = new URL(endpoint);
@@ -5361,9 +5384,9 @@ function validatedEndpoint(value) {
5361
5384
  }
5362
5385
  return endpoint;
5363
5386
  }
5364
- function validSessionId(value) {
5365
- if (!/^csess_[0-9a-f]{32}$/.test(value)) throw new TypeError("invalid Code session id");
5366
- return value;
5387
+ function validSessionId(value2) {
5388
+ if (!/^csess_[0-9a-f]{32}$/.test(value2)) throw new TypeError("invalid Code session id");
5389
+ return value2;
5367
5390
  }
5368
5391
  function validateHeartbeat(version, capabilities) {
5369
5392
  if (!version.trim() || version.length > 80) throw new TypeError("runtimeVersion is required and at most 80 characters");
@@ -5376,8 +5399,8 @@ function validateHeartbeat(version, capabilities) {
5376
5399
  throw new TypeError("runtime resources must be positive integers");
5377
5400
  }
5378
5401
  }
5379
- function parseSnapshot(value) {
5380
- const root = record3(value);
5402
+ function parseSnapshot(value2) {
5403
+ const root = record3(value2);
5381
5404
  const host = record3(root?.host);
5382
5405
  if (!host || typeof host.hostId !== "string" || typeof host.runtimeVersion !== "string" || !Number.isSafeInteger(host.lastSeenAt) || host.revokedAt !== null || !Array.isArray(root?.bindings) || root.bindings.length > 1024 || !Array.isArray(root?.commands) || root.commands.length > 64) throw invalid("heartbeat");
5383
5406
  const bindingIds = /* @__PURE__ */ new Set();
@@ -5402,11 +5425,11 @@ function parseSnapshot(value) {
5402
5425
  });
5403
5426
  return { host, bindings, commands };
5404
5427
  }
5405
- async function parseSource(value) {
5406
- const snapshot = record3(record3(value)?.snapshot);
5428
+ async function parseSource(value2) {
5429
+ const snapshot = record3(record3(value2)?.snapshot);
5407
5430
  if (!snapshot || typeof snapshot.repository !== "string" || typeof snapshot.commitSha !== "string" || typeof snapshot.treeDigest !== "string" || !Array.isArray(snapshot.files)) throw invalid("source");
5408
- const files = snapshot.files.map((value2) => {
5409
- const file = record3(value2);
5431
+ const files = snapshot.files.map((value22) => {
5432
+ const file = record3(value22);
5410
5433
  if (!file || typeof file.path !== "string" || typeof file.content !== "string") throw invalid("source file");
5411
5434
  return { path: file.path, content: file.content };
5412
5435
  });
@@ -5433,19 +5456,19 @@ async function parseSource(value) {
5433
5456
  if (digest !== snapshot.treeDigest) throw invalid("source digest");
5434
5457
  return { ...source, treeDigest: digest, ...references.length ? { references } : {} };
5435
5458
  }
5436
- function parseReview(value) {
5437
- const review = record3(record3(value)?.review);
5459
+ function parseReview(value2) {
5460
+ const review = record3(record3(value2)?.review);
5438
5461
  if (!review || !["approved", "rejected"].includes(String(review.verdict)) || typeof review.reviewDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(review.reviewDigest) || typeof review.provider !== "string" || !review.provider || typeof review.model !== "string" || !review.model || !Number.isSafeInteger(review.policyVersion) || Number(review.policyVersion) < 1) throw invalid("review");
5439
5462
  return review;
5440
5463
  }
5441
- function parseCandidate(value) {
5442
- const candidate = record3(record3(value)?.candidate);
5464
+ function parseCandidate(value2) {
5465
+ const candidate = record3(record3(value2)?.candidate);
5443
5466
  if (!candidate || typeof candidate.candidateId !== "string" || !/^ccand_[0-9a-f]{32}$/.test(candidate.candidateId) || !["submitted", "approved", "published", "failed"].includes(String(candidate.status))) {
5444
5467
  throw invalid("candidate");
5445
5468
  }
5446
5469
  return { candidateId: candidate.candidateId, status: candidate.status };
5447
5470
  }
5448
- var record3 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
5471
+ var record3 = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
5449
5472
  var invalid = (part) => new CodeRuntimeControlError(`invalid Code runtime ${part} response`, 502, "invalid_response");
5450
5473
  var RESERVED = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_modules", "dist", "coverage"]);
5451
5474
  var SECRET = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
@@ -5479,8 +5502,8 @@ function validateCodePatch(patch2, maxBytes) {
5479
5502
  if (!paths.length || new Set(paths).size !== paths.length) throw new TypeError("patch has no diffs or repeats a path");
5480
5503
  return paths;
5481
5504
  }
5482
- function validHeaderPath(value, path, prefix) {
5483
- return value === "/dev/null" || value === `${prefix}/${path}`;
5505
+ function validHeaderPath(value2, path, prefix) {
5506
+ return value2 === "/dev/null" || value2 === `${prefix}/${path}`;
5484
5507
  }
5485
5508
  function validateRelativePath(path) {
5486
5509
  const parts = path.split("/");
@@ -5626,8 +5649,8 @@ function assertCodeBuildRecipe(recipe2) {
5626
5649
  throw new TypeError("build recipe is malformed or exceeds its control bounds");
5627
5650
  }
5628
5651
  }
5629
- function parseMemory(value) {
5630
- const match = /^([1-9][0-9]{0,4})([kmg])$/.exec(value.toLowerCase());
5652
+ function parseMemory(value2) {
5653
+ const match = /^([1-9][0-9]{0,4})([kmg])$/.exec(value2.toLowerCase());
5631
5654
  if (!match?.[1] || !match[2]) return 0;
5632
5655
  const scale = match[2] === "k" ? 1024 : match[2] === "m" ? 1024 ** 2 : 1024 ** 3;
5633
5656
  return Number(match[1]) * scale;
@@ -5862,14 +5885,14 @@ function normalizedRecipe(recipe2) {
5862
5885
  expectedArtifacts: [...recipe2.expectedArtifacts ?? []].sort((left, right) => left.id.localeCompare(right.id)).map((artifact) => ({ id: artifact.id, path: artifact.path, maximumBytes: artifact.maximumBytes }))
5863
5886
  };
5864
5887
  }
5865
- function digestJson(value) {
5866
- return digestBytes(JSON.stringify(value));
5888
+ function digestJson(value2) {
5889
+ return digestBytes(JSON.stringify(value2));
5867
5890
  }
5868
- function digestBytes(value) {
5869
- return `sha256:${(0, import_crypto3.createHash)("sha256").update(value).digest("hex")}`;
5891
+ function digestBytes(value2) {
5892
+ return `sha256:${(0, import_crypto3.createHash)("sha256").update(value2).digest("hex")}`;
5870
5893
  }
5871
- function integer(value, minimum, maximum) {
5872
- return Number.isSafeInteger(value) && value >= minimum && value <= maximum;
5894
+ function integer(value2, minimum, maximum) {
5895
+ return Number.isSafeInteger(value2) && value2 >= minimum && value2 <= maximum;
5873
5896
  }
5874
5897
  async function prepareRuntimeCheckpoint(input) {
5875
5898
  const patch2 = await input.workspace.patch(256 * 1024);
@@ -5922,7 +5945,7 @@ async function prepareRuntimeCheckpoint(input) {
5922
5945
  });
5923
5946
  return { checkpoint, verification, review, note };
5924
5947
  }
5925
- var message = (value) => (value instanceof Error ? value.message : String(value)).slice(0, 500);
5948
+ var message = (value2) => (value2 instanceof Error ? value2.message : String(value2)).slice(0, 500);
5926
5949
  var CodeRuntimeCheckpointManager = class {
5927
5950
  constructor(options) {
5928
5951
  this.options = options;
@@ -6116,7 +6139,7 @@ async function conversionPolicy(id, output) {
6116
6139
  return { ...definition, digest: await conversionPolicyDigest(definition) };
6117
6140
  }
6118
6141
  async function registeredPolicy(id, registryId, values) {
6119
- const mapping = Object.fromEntries(values.map((value) => [value, value]));
6142
+ const mapping = Object.fromEntries(values.map((value2) => [value2, value2]));
6120
6143
  return conversionPolicy(id, {
6121
6144
  kind: "registered_id",
6122
6145
  registryId,
@@ -6125,7 +6148,7 @@ async function registeredPolicy(id, registryId, values) {
6125
6148
  }
6126
6149
  async function conversionRegistry(policies, values) {
6127
6150
  const registeredIds = Object.fromEntries(await Promise.all(Object.entries(values).map(async ([id, entries]) => {
6128
- const mapping = Object.fromEntries(entries.map((value) => [value, value]));
6151
+ const mapping = Object.fromEntries(entries.map((value2) => [value2, value2]));
6129
6152
  return [id, { values: mapping, digest: await registeredIdRegistryDigest(mapping) }];
6130
6153
  })));
6131
6154
  return createConversionRegistry({ policies, registeredIds });
@@ -6149,8 +6172,8 @@ async function environment(input, options, tool) {
6149
6172
  };
6150
6173
  return { ingress, policy, fixedArgs, reader: ingress.control("reader"), runId: `${input.request.requestId}:${tool}` };
6151
6174
  }
6152
- function unsafe(base, value, field) {
6153
- return base.ingress.quarantinedOutput(value, {
6175
+ function unsafe(base, value2, field) {
6176
+ return base.ingress.quarantinedOutput(value2, {
6154
6177
  readers: base.reader.label.readers,
6155
6178
  runId: `${base.runId}:${field}`
6156
6179
  });
@@ -6230,14 +6253,14 @@ async function read(context, request2, options, policy) {
6230
6253
  }
6231
6254
  async function patch(context, request2, options, policy) {
6232
6255
  exactKeys(request2.input, ["patch"]);
6233
- const value = stringField(request2.input, "patch");
6234
- const paths = validateCodePatch(value, options.maxPatchBytes ?? 256 * 1024);
6256
+ const value2 = stringField(request2.input, "patch");
6257
+ const paths = validateCodePatch(value2, options.maxPatchBytes ?? 256 * 1024);
6235
6258
  if (paths.some((path) => options.readOnlyPrefixes?.some((prefix) => path === prefix || path.startsWith(`${prefix}/`)))) {
6236
6259
  throw new TypeError("patch targets a read-only reference source");
6237
6260
  }
6238
- const allowed = await policy.patch(policyContext(context, request2, options, { patch: value }));
6261
+ const allowed = await policy.patch(policyContext(context, request2, options, { patch: value2 }));
6239
6262
  if (!allowed) return response(request2, false, "tool denied by CaMeL policy");
6240
- await applyCodePatch(context.workspaceDir, value, paths);
6263
+ await applyCodePatch(context.workspaceDir, value2, paths);
6241
6264
  return response(request2, true, `Applied patch to ${paths.length} file(s).`, { paths });
6242
6265
  }
6243
6266
  async function recipe(context, request2, options, recipes, policy) {
@@ -6328,14 +6351,14 @@ function exactKeys(input, allowed) {
6328
6351
  if (Object.keys(input).some((key) => !allowed.includes(key))) throw new TypeError("tool input contains an unsupported field");
6329
6352
  }
6330
6353
  function stringField(input, name) {
6331
- const value = input[name];
6332
- if (typeof value !== "string" || !value) throw new TypeError(`${name} must be a non-empty string`);
6333
- return value;
6354
+ const value2 = input[name];
6355
+ if (typeof value2 !== "string" || !value2) throw new TypeError(`${name} must be a non-empty string`);
6356
+ return value2;
6334
6357
  }
6335
- function optionalInteger(value) {
6336
- if (value === void 0) return void 0;
6337
- if (!Number.isSafeInteger(value) || value < 1) throw new TypeError("line bounds must be positive integers");
6338
- return value;
6358
+ function optionalInteger(value2) {
6359
+ if (value2 === void 0) return void 0;
6360
+ if (!Number.isSafeInteger(value2) || value2 < 1) throw new TypeError("line bounds must be positive integers");
6361
+ return value2;
6339
6362
  }
6340
6363
  function response(request2, ok, content2, details) {
6341
6364
  return { requestId: request2.requestId, ok, content: content2, ...details ? { details } : {} };
@@ -6381,9 +6404,9 @@ function codeLocalSource(payload) {
6381
6404
  return source;
6382
6405
  }
6383
6406
  function codeCheckpointPayload(payload) {
6384
- const value = payload.checkpoint;
6385
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("resume checkpoint is missing");
6386
- return value;
6407
+ const value2 = payload.checkpoint;
6408
+ if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) throw new TypeError("resume checkpoint is missing");
6409
+ return value2;
6387
6410
  }
6388
6411
  function fakeCodeLease(command, metadata2) {
6389
6412
  return {
@@ -6407,7 +6430,7 @@ function fakeCodeLease(command, metadata2) {
6407
6430
  }
6408
6431
  };
6409
6432
  }
6410
- var record22 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
6433
+ var record22 = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
6411
6434
  var SOURCE_LIMITS = { maxFiles: 2e4, maxBytes: 512 * 1024 * 1024 };
6412
6435
  async function prepareRuntimeLocalSource(input) {
6413
6436
  const { command, descriptor: descriptor2, available, repository, baseCommitSha, resume } = input;
@@ -6497,24 +6520,24 @@ async function appendCodeRuntimeEvent(control, command, event, refs) {
6497
6520
  const bounded = event.type === "message" ? { ...event, body: event.body.trim().slice(0, 2e4) || `${event.actor} event` } : event;
6498
6521
  await control.appendSessionEvent(command.sessionId, eventId, bounded);
6499
6522
  }
6500
- var digestRuntimeValue = (value) => `sha256:${(0, import_crypto4.createHash)("sha256").update(value).digest("hex")}`;
6501
- var runtimeErrorMessage = (value) => value instanceof Error ? value.message : String(value);
6502
- var runtimeRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
6503
- var safeRuntimeJson = (value) => {
6523
+ var digestRuntimeValue = (value2) => `sha256:${(0, import_crypto4.createHash)("sha256").update(value2).digest("hex")}`;
6524
+ var runtimeErrorMessage = (value2) => value2 instanceof Error ? value2.message : String(value2);
6525
+ var runtimeRecord = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
6526
+ var safeRuntimeJson = (value2) => {
6504
6527
  try {
6505
- return JSON.stringify(value).slice(0, 1e4);
6528
+ return JSON.stringify(value2).slice(0, 1e4);
6506
6529
  } catch {
6507
6530
  return "[event]";
6508
6531
  }
6509
6532
  };
6510
- function runtimeResultText(value) {
6511
- const record32 = runtimeRecord(value);
6533
+ function runtimeResultText(value2) {
6534
+ const record32 = runtimeRecord(value2);
6512
6535
  if (record32 && typeof record32.text === "string") return record32.text.slice(0, 2e4);
6513
6536
  if (record32 && typeof record32.error === "string") return `Pi failed: ${record32.error.slice(0, 19989)}`;
6514
6537
  return null;
6515
6538
  }
6516
- function runtimeResultError(value) {
6517
- const record32 = runtimeRecord(value);
6539
+ function runtimeResultError(value2) {
6540
+ const record32 = runtimeRecord(value2);
6518
6541
  return record32 && typeof record32.error === "string" && record32.error.trim() ? record32.error.trim().slice(0, 2e3) : null;
6519
6542
  }
6520
6543
  var CodePiRuntimeEngine = class {
@@ -6788,14 +6811,14 @@ var CodePiRuntimeEngine = class {
6788
6811
  this.#active.delete(command.sessionId);
6789
6812
  return result;
6790
6813
  }
6791
- async #failure(command, active, value) {
6792
- active.failure = value.slice(0, 2e3);
6814
+ async #failure(command, active, value2) {
6815
+ active.failure = value2.slice(0, 2e3);
6793
6816
  if (active.acknowledged) {
6794
6817
  await this.options.control.reportSessionFailure(command.sessionId, active.failure).catch(() => void 0);
6795
6818
  }
6796
6819
  }
6797
- async #diagnostic(command, active, value) {
6798
- const detail = value.trim().slice(0, 2e3) || "Pi runtime failed";
6820
+ async #diagnostic(command, active, value2) {
6821
+ const detail = value2.trim().slice(0, 2e3) || "Pi runtime failed";
6799
6822
  this.options.onDiagnostic?.(detail);
6800
6823
  await this.#event(
6801
6824
  command,
@@ -6880,6 +6903,7 @@ Usage:
6880
6903
  odla-ai context save <name> [--platform <url>] [--app <id>] [--env <name>] [--json]
6881
6904
  odla-ai context remove <name> --yes [--json]
6882
6905
  odla-ai o11y status [--app <id>] [--context <name>] [--platform https://odla.ai] [--env prod] [--minutes 60] [--json]
6906
+ odla-ai platform status [--context <name>] [--platform https://odla.ai] [--email <odla-account>] [--json]
6883
6907
  odla-ai whoami [--context <name>] [--platform https://odla.ai] [--json]
6884
6908
  odla-ai runbook ask "<question>" [--app <id>] [--all] [--json]
6885
6909
  odla-ai runbook search "<question>" [--app <id>] [--all] [--limit <n>] [--json]
@@ -7004,6 +7028,8 @@ Commands:
7004
7028
  canary, collector ingest/scheduler trust, Cloudflare-owned
7005
7029
  runtime metrics, and a machine verdict.
7006
7030
  --json keeps auth progress on stderr for unattended agents.
7031
+ platform Read canonical fleet health, releases, provider load/freshness,
7032
+ explicit unknowns, and next actions through a read-only grant.
7007
7033
  provision Register services, compose integrations, persist credentials, optionally push secrets.
7008
7034
  smoke Verify credentials, public-config, composed schema, db aggregate, and integration probes.
7009
7035
  skill Same installer; --agent accepts all, claude, codex, cursor,
@@ -7090,31 +7116,31 @@ async function requestHostedSecurityJson(options, path, init, action) {
7090
7116
  }
7091
7117
  return body;
7092
7118
  }
7093
- function hostedIdentifier(value, name) {
7094
- const result = optionalHostedText(value, name, 180);
7119
+ function hostedIdentifier(value2, name) {
7120
+ const result = optionalHostedText(value2, name, 180);
7095
7121
  if (!result || !/^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(result)) {
7096
7122
  throw new Error(`${name} is invalid`);
7097
7123
  }
7098
7124
  return result;
7099
7125
  }
7100
- function positivePolicyVersion(value, name) {
7101
- if (!Number.isSafeInteger(value) || value < 1) {
7126
+ function positivePolicyVersion(value2, name) {
7127
+ if (!Number.isSafeInteger(value2) || value2 < 1) {
7102
7128
  throw new Error(`${name} is invalid`);
7103
7129
  }
7104
- return value;
7130
+ return value2;
7105
7131
  }
7106
- function optionalHostedText(value, name, maxLength) {
7107
- if (value === void 0 || value === null || value === "") return void 0;
7108
- if (typeof value !== "string" || value.length > maxLength || /[\u0000-\u001f\u007f]/.test(value)) {
7132
+ function optionalHostedText(value2, name, maxLength) {
7133
+ if (value2 === void 0 || value2 === null || value2 === "") return void 0;
7134
+ if (typeof value2 !== "string" || value2.length > maxLength || /[\u0000-\u001f\u007f]/.test(value2)) {
7109
7135
  throw new Error(`${name} is invalid`);
7110
7136
  }
7111
- return value;
7137
+ return value2;
7112
7138
  }
7113
- function githubRepositoryName(value) {
7114
- if (typeof value !== "string" || value.length > 201) {
7139
+ function githubRepositoryName(value2) {
7140
+ if (typeof value2 !== "string" || value2.length > 201) {
7115
7141
  throw new Error("repository must be owner/name");
7116
7142
  }
7117
- const parts = value.split("/");
7143
+ const parts = value2.split("/");
7118
7144
  const owner = parts[0] ?? "";
7119
7145
  const name = (parts[1] ?? "").replace(/\.git$/i, "");
7120
7146
  if (parts.length !== 2 || !/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,98}[A-Za-z0-9])?$/.test(owner) || !/^[A-Za-z0-9_.-]{1,100}$/.test(name) || name === "." || name === "..") {
@@ -7122,10 +7148,10 @@ function githubRepositoryName(value) {
7122
7148
  }
7123
7149
  return `${owner}/${name}`;
7124
7150
  }
7125
- function trustedGitHubInstallUrl(value) {
7151
+ function trustedGitHubInstallUrl(value2) {
7126
7152
  let url;
7127
7153
  try {
7128
- url = new URL(value);
7154
+ url = new URL(value2);
7129
7155
  } catch {
7130
7156
  throw new Error("odla.ai returned an invalid GitHub installation URL");
7131
7157
  }
@@ -7134,17 +7160,17 @@ function trustedGitHubInstallUrl(value) {
7134
7160
  }
7135
7161
  return url.toString();
7136
7162
  }
7137
- function hostedPollInterval(value = 2e3) {
7138
- if (!Number.isSafeInteger(value) || value < 100 || value > 3e4) {
7163
+ function hostedPollInterval(value2 = 2e3) {
7164
+ if (!Number.isSafeInteger(value2) || value2 < 100 || value2 > 3e4) {
7139
7165
  throw new Error("poll interval must be 100-30000ms");
7140
7166
  }
7141
- return value;
7167
+ return value2;
7142
7168
  }
7143
- function hostedPollTimeout(value = 10 * 6e4) {
7144
- if (!Number.isSafeInteger(value) || value < 1e3 || value > 60 * 6e4) {
7169
+ function hostedPollTimeout(value2 = 10 * 6e4) {
7170
+ if (!Number.isSafeInteger(value2) || value2 < 1e3 || value2 > 60 * 6e4) {
7145
7171
  throw new Error("poll timeout must be 1000-3600000ms");
7146
7172
  }
7147
- return value;
7173
+ return value2;
7148
7174
  }
7149
7175
  async function waitForHostedPoll(milliseconds, signal) {
7150
7176
  if (signal?.aborted) throw signal.reason ?? new DOMException("aborted", "AbortError");
@@ -7156,16 +7182,16 @@ async function waitForHostedPoll(milliseconds, signal) {
7156
7182
  }, { once: true });
7157
7183
  });
7158
7184
  }
7159
- function isValidHostedSecurityPlan(value, env) {
7160
- if (!value || value.env !== env || !/^sha256:[a-f0-9]{64}$/.test(value.planDigest) || value.consentContract !== "odla.hosted-security-consent.v1" || value.reportProjection !== "odla.hosted-security-report.v1" || value.redactionContract !== "odla.best-effort-credential-pattern-redaction.v1" || typeof value.promptBundle !== "string" || value.promptBundle.length < 1 || value.promptBundle.length > 100 || typeof value.ready !== "boolean" || typeof value.independent !== "boolean" || value.sourceDisclosure !== "redacted" || value.targetExecution !== false || !Number.isSafeInteger(value.reportRetentionDays) || value.reportRetentionDays < 1) return false;
7185
+ function isValidHostedSecurityPlan(value2, env) {
7186
+ if (!value2 || value2.env !== env || !/^sha256:[a-f0-9]{64}$/.test(value2.planDigest) || value2.consentContract !== "odla.hosted-security-consent.v1" || value2.reportProjection !== "odla.hosted-security-report.v1" || value2.redactionContract !== "odla.best-effort-credential-pattern-redaction.v1" || typeof value2.promptBundle !== "string" || value2.promptBundle.length < 1 || value2.promptBundle.length > 100 || typeof value2.ready !== "boolean" || typeof value2.independent !== "boolean" || value2.sourceDisclosure !== "redacted" || value2.targetExecution !== false || !Number.isSafeInteger(value2.reportRetentionDays) || value2.reportRetentionDays < 1) return false;
7161
7187
  const validRoute = (route2, purpose) => !!route2 && route2.purpose === purpose && typeof route2.enabled === "boolean" && typeof route2.credentialReady === "boolean" && typeof route2.provider === "string" && route2.provider.length > 0 && route2.provider.length <= 100 && typeof route2.model === "string" && route2.model.length > 0 && route2.model.length <= 200 && Number.isSafeInteger(route2.policyVersion) && route2.policyVersion >= 1 && Number.isSafeInteger(route2.maxCallsPerRun) && route2.maxCallsPerRun >= 1 && Number.isSafeInteger(route2.maxInputBytes) && route2.maxInputBytes >= 1 && Number.isSafeInteger(route2.maxOutputTokens) && route2.maxOutputTokens >= 1;
7162
- return validRoute(value.routes?.discovery, "security.discovery") && validRoute(value.routes?.validation, "security.validation");
7188
+ return validRoute(value2.routes?.discovery, "security.discovery") && validRoute(value2.routes?.validation, "security.validation");
7163
7189
  }
7164
- function hostedSecurityCredential(value) {
7165
- if (typeof value !== "string" || value.length < 8 || value.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value)) {
7190
+ function hostedSecurityCredential(value2) {
7191
+ if (typeof value2 !== "string" || value2.length < 8 || value2.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value2)) {
7166
7192
  throw new Error("Hosted security requires an injected odla developer token");
7167
7193
  }
7168
- return value;
7194
+ return value2;
7169
7195
  }
7170
7196
 
7171
7197
  // src/security-hosted-github.ts
@@ -7318,17 +7344,17 @@ async function prepareCodeLocalSource(cwd, repository, readHead = readGitHead) {
7318
7344
  }
7319
7345
  }
7320
7346
  async function readGitHead(cwd) {
7321
- const value = await new Promise((accept, reject) => {
7347
+ const value2 = await new Promise((accept, reject) => {
7322
7348
  (0, import_node_child_process5.execFile)("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8", maxBuffer: 16384 }, (error, stdout) => {
7323
7349
  if (error) reject(new Error("code connect requires a Git checkout with an initial commit"));
7324
7350
  else accept(stdout.trim());
7325
7351
  });
7326
7352
  });
7327
- if (!/^[0-9a-f]{40}$/.test(value)) throw new Error("code connect could not resolve the checkout HEAD commit");
7328
- return value;
7353
+ if (!/^[0-9a-f]{40}$/.test(value2)) throw new Error("code connect could not resolve the checkout HEAD commit");
7354
+ return value2;
7329
7355
  }
7330
- function digestText(value) {
7331
- return `sha256:${(0, import_node_crypto.createHash)("sha256").update(value).digest("hex")}`;
7356
+ function digestText(value2) {
7357
+ return `sha256:${(0, import_node_crypto.createHash)("sha256").update(value2).digest("hex")}`;
7332
7358
  }
7333
7359
 
7334
7360
  // src/code-images.ts
@@ -7599,8 +7625,8 @@ async function runCodeRuntime(input) {
7599
7625
  for (const [name, handler] of handlers) process.removeListener(name, handler);
7600
7626
  }
7601
7627
  }
7602
- function parseConnection(value, appId, appEnv) {
7603
- const root = record4(value);
7628
+ function parseConnection(value2, appId, appEnv) {
7629
+ const root = record4(value2);
7604
7630
  const host = record4(root?.host);
7605
7631
  const offer = record4(root?.offer);
7606
7632
  const binding = record4(root?.binding);
@@ -7609,12 +7635,12 @@ function parseConnection(value, appId, appEnv) {
7609
7635
  }
7610
7636
  return root;
7611
7637
  }
7612
- function apiFailure(action, status, value) {
7613
- const message2 = record4(record4(value)?.error)?.message;
7638
+ function apiFailure(action, status, value2) {
7639
+ const message2 = record4(record4(value2)?.error)?.message;
7614
7640
  return `${action} failed (${status})${typeof message2 === "string" ? `: ${message2}` : ""}`;
7615
7641
  }
7616
- function record4(value) {
7617
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
7642
+ function record4(value2) {
7643
+ return value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
7618
7644
  }
7619
7645
 
7620
7646
  // src/code-command.ts
@@ -7673,8 +7699,8 @@ function developerTokenStatus(context, parsed, now = Date.now()) {
7673
7699
  cacheStatus
7674
7700
  };
7675
7701
  }
7676
- function clean3(value) {
7677
- const normalized = value?.trim();
7702
+ function clean3(value2) {
7703
+ const normalized = value2?.trim();
7678
7704
  return normalized || void 0;
7679
7705
  }
7680
7706
 
@@ -7823,8 +7849,8 @@ async function request(ctx, method, path, body) {
7823
7849
  throw new Error(`discuss ${method} ${path} failed: ${data.error ?? `registry returned ${res.status}`}`);
7824
7850
  return data;
7825
7851
  }
7826
- function emit(ctx, value, human) {
7827
- if (ctx.json) ctx.out.log(JSON.stringify(value, null, 2));
7852
+ function emit(ctx, value2, human) {
7853
+ if (ctx.json) ctx.out.log(JSON.stringify(value2, null, 2));
7828
7854
  else human();
7829
7855
  }
7830
7856
  var state = (topic) => topic.resolved ? "resolved" : "open";
@@ -7869,8 +7895,8 @@ async function discussList(ctx, parsed) {
7869
7895
  ["limit", "limit"],
7870
7896
  ["offset", "offset"]
7871
7897
  ]) {
7872
- const value = stringOpt(parsed.options[flag]);
7873
- if (value) query.set(param, value);
7898
+ const value2 = stringOpt(parsed.options[flag]);
7899
+ if (value2) query.set(param, value2);
7874
7900
  }
7875
7901
  const qs = query.toString();
7876
7902
  const page = await request(ctx, "GET", `/topics${qs ? `?${qs}` : ""}`);
@@ -8067,11 +8093,11 @@ var MAX_CONSECUTIVE_FAILURES = 5;
8067
8093
  var MAX_BACKOFF_MS = 3e4;
8068
8094
  function numberOpt2(parsed, flag, fallback) {
8069
8095
  const raw = stringOpt(parsed.options[flag]);
8070
- const value = raw == null ? NaN : Number(raw);
8071
- return Number.isFinite(value) && value > 0 ? value : fallback;
8096
+ const value2 = raw == null ? NaN : Number(raw);
8097
+ return Number.isFinite(value2) && value2 > 0 ? value2 : fallback;
8072
8098
  }
8073
- function jsonl(ctx, parsed, value) {
8074
- if (parsed.options.jsonl === true) ctx.out.log(JSON.stringify({ v: 1, ...value }));
8099
+ function jsonl(ctx, parsed, value2) {
8100
+ if (parsed.options.jsonl === true) ctx.out.log(JSON.stringify({ v: 1, ...value2 }));
8075
8101
  }
8076
8102
  async function discussWatch(ctx, topicId, parsed) {
8077
8103
  if (ctx.json && parsed.options.jsonl === true) throw new Error("--json and --jsonl cannot be combined");
@@ -8333,13 +8359,13 @@ async function pmRequest(ctx, method, path, body) {
8333
8359
  function collectFields(parsed, allowClear) {
8334
8360
  const out = {};
8335
8361
  for (const [flag, spec] of Object.entries(FIELD_MAP)) {
8336
- const value = parsed.options[flag];
8337
- if (value === void 0 || value === true) continue;
8338
- if (value === false) {
8362
+ const value2 = parsed.options[flag];
8363
+ if (value2 === void 0 || value2 === true) continue;
8364
+ if (value2 === false) {
8339
8365
  if (allowClear) out[spec.key] = null;
8340
8366
  continue;
8341
8367
  }
8342
- const text = stringOpt(value);
8368
+ const text = stringOpt(value2);
8343
8369
  out[spec.key] = spec.num ? Number(text) : text;
8344
8370
  }
8345
8371
  return out;
@@ -8360,8 +8386,8 @@ function statusCol(entity, r) {
8360
8386
  function printRecord(ctx, entity, r) {
8361
8387
  ctx.out.log(`${r.id} [${statusCol(entity, r)}] ${r.appId} ${r.title ?? ""}`);
8362
8388
  }
8363
- function emit2(ctx, value, human) {
8364
- if (ctx.json) ctx.out.log(JSON.stringify(value, null, 2));
8389
+ function emit2(ctx, value2, human) {
8390
+ if (ctx.json) ctx.out.log(JSON.stringify(value2, null, 2));
8365
8391
  else human();
8366
8392
  }
8367
8393
  async function pmList(ctx, entity, parsed) {
@@ -8407,8 +8433,8 @@ async function pmAdd(ctx, entity, parsed) {
8407
8433
  emit2(ctx, res, () => ctx.out.log(`created ${entity} ${res.id}`));
8408
8434
  }
8409
8435
  async function pmGet(ctx, entity, id) {
8410
- const { record: record7 } = await pmRequest(ctx, "GET", `/${entity}/${encodeURIComponent(id)}`);
8411
- emit2(ctx, record7, () => printRecord(ctx, entity, record7));
8436
+ const { record: record8 } = await pmRequest(ctx, "GET", `/${entity}/${encodeURIComponent(id)}`);
8437
+ emit2(ctx, record8, () => printRecord(ctx, entity, record8));
8412
8438
  }
8413
8439
  async function pmSet(ctx, entity, id, parsed) {
8414
8440
  const patch2 = collectEntityFields(entity, parsed, true);
@@ -8453,9 +8479,9 @@ async function pmHandoff(ctx, parsed) {
8453
8479
  ]);
8454
8480
  const handoff = {
8455
8481
  appId,
8456
- unmetGoals: goals.filter((record7) => record7.status !== "met"),
8457
- activeTasks: tasks.filter((record7) => record7.column !== "done"),
8458
- openBugs: bugs.filter((record7) => record7.status !== "fixed" && record7.status !== "wontfix")
8482
+ unmetGoals: goals.filter((record8) => record8.status !== "met"),
8483
+ activeTasks: tasks.filter((record8) => record8.column !== "done"),
8484
+ openBugs: bugs.filter((record8) => record8.status !== "fixed" && record8.status !== "wontfix")
8459
8485
  };
8460
8486
  const result = {
8461
8487
  ...handoff,
@@ -8474,10 +8500,10 @@ async function pmHandoff(ctx, parsed) {
8474
8500
  ]) {
8475
8501
  ctx.out.log(`${label}:`);
8476
8502
  if (!records.length) ctx.out.log("- (none)");
8477
- else for (const record7 of records) printRecord(
8503
+ else for (const record8 of records) printRecord(
8478
8504
  ctx,
8479
8505
  label === "unmet goals" ? "goal" : label === "active tasks" ? "task" : "bug",
8480
- record7
8506
+ record8
8481
8507
  );
8482
8508
  }
8483
8509
  });
@@ -8625,6 +8651,113 @@ async function pmCommand(parsed, deps = {}) {
8625
8651
  }
8626
8652
  }
8627
8653
 
8654
+ // src/platform-output.ts
8655
+ function printPlatformStatus(status, out) {
8656
+ out.log(`platform ${status.verdict.status} ${status.observedAt}`);
8657
+ out.log(
8658
+ `fleet ${status.summary.healthy}/${status.summary.services} healthy ${status.summary.required} required ${status.summary.unreachable} unreachable ${status.summary.notConfigured} not configured`
8659
+ );
8660
+ out.log(`catalog ${status.catalog.revision}`);
8661
+ out.log(
8662
+ "service required health probe ms version provider age requests errors cpu p99 us wall p99 us"
8663
+ );
8664
+ for (const service of status.services) {
8665
+ const metrics = service.provider.metrics;
8666
+ out.log([
8667
+ service.id,
8668
+ service.required ? "yes" : "no",
8669
+ service.health.status,
8670
+ value(service.health.latencyMs),
8671
+ service.release.observedVersionId ?? "unknown",
8672
+ service.provider.status,
8673
+ age(service.provider.ageMs),
8674
+ value(metrics?.requests),
8675
+ value(metrics?.errors),
8676
+ value(metrics?.cpuTimeP99),
8677
+ value(metrics?.wallTimeP99)
8678
+ ].join(" "));
8679
+ }
8680
+ if (status.verdict.reasons.length) {
8681
+ out.log(`reasons ${status.verdict.reasons.join(", ")}`);
8682
+ }
8683
+ for (const action of status.nextActions) {
8684
+ out.log(`next ${action.service} ${action.code} ${action.message}`);
8685
+ }
8686
+ }
8687
+ function value(input) {
8688
+ return input === null || input === void 0 ? "unknown" : String(input);
8689
+ }
8690
+ function age(input) {
8691
+ if (input === null) return "unknown";
8692
+ if (input < 1e3) return `${input}ms`;
8693
+ if (input < 6e4) return `${Math.round(input / 1e3)}s`;
8694
+ return `${Math.round(input / 6e4)}m`;
8695
+ }
8696
+
8697
+ // src/platform-command.ts
8698
+ async function platformCommand(parsed, deps = {}) {
8699
+ assertArgs(
8700
+ parsed,
8701
+ ["config", "context", "platform", "token", "email", "open", "json"],
8702
+ 2
8703
+ );
8704
+ const action = parsed.positionals[1];
8705
+ if (action !== "status") {
8706
+ throw new Error(
8707
+ `unknown platform action "${action ?? ""}". Try "odla-ai platform status --json".`
8708
+ );
8709
+ }
8710
+ const context = await resolveOperatorContext(parsed, {
8711
+ allowMissingConfig: true
8712
+ });
8713
+ const platform = context.platform.value;
8714
+ const doFetch = deps.fetch ?? fetch;
8715
+ const out = deps.stdout ?? console;
8716
+ const token = await resolveAdminPlatformToken({
8717
+ platform,
8718
+ scope: "platform:status:read",
8719
+ token: stringOpt(parsed.options.token),
8720
+ tokenFile: context.credentials.scopedTokenFile,
8721
+ email: stringOpt(parsed.options.email),
8722
+ open: parsed.options.open === false ? false : parsed.options.open === true ? true : void 0,
8723
+ fetch: doFetch,
8724
+ stdout: out,
8725
+ openApprovalUrl: deps.openUrl,
8726
+ label: "odla CLI (platform fleet status)"
8727
+ });
8728
+ const response2 = await doFetch(`${platform}/registry/platform/status`, {
8729
+ headers: { authorization: `Bearer ${token}` }
8730
+ });
8731
+ const body = await response2.json().catch(() => null);
8732
+ if (!response2.ok) {
8733
+ throw new Error(
8734
+ `read platform status failed (HTTP ${response2.status}): ${apiMessage(body)}`
8735
+ );
8736
+ }
8737
+ if (!isPlatformStatus(body)) {
8738
+ throw new Error("platform returned an invalid odla.platform-status/v1 envelope");
8739
+ }
8740
+ if (parsed.options.json === true) {
8741
+ out.log(JSON.stringify(body, null, 2));
8742
+ } else {
8743
+ printPlatformStatus(body, out);
8744
+ }
8745
+ }
8746
+ function isPlatformStatus(value2) {
8747
+ if (!record5(value2) || value2.schemaVersion !== "odla.platform-status/v1") return false;
8748
+ if (!record5(value2.verdict) || !Array.isArray(value2.verdict.reasons)) return false;
8749
+ if (!record5(value2.catalog) || !record5(value2.summary)) return false;
8750
+ return Array.isArray(value2.services) && Array.isArray(value2.nextActions);
8751
+ }
8752
+ function apiMessage(value2) {
8753
+ if (!record5(value2)) return "request failed";
8754
+ const error = record5(value2.error) ? value2.error : value2;
8755
+ return typeof error.message === "string" ? error.message : typeof error.code === "string" ? error.code : "request failed";
8756
+ }
8757
+ function record5(value2) {
8758
+ return !!value2 && typeof value2 === "object" && !Array.isArray(value2);
8759
+ }
8760
+
8628
8761
  // src/o11y-verdict.ts
8629
8762
  function statusVerdict(reads) {
8630
8763
  const reasons = [];
@@ -8662,7 +8795,7 @@ function statusVerdict(reads) {
8662
8795
  severity: "degraded"
8663
8796
  });
8664
8797
  }
8665
- const performance = record5(reads.liveSync.body.performance) ? reads.liveSync.body.performance : null;
8798
+ const performance = record6(reads.liveSync.body.performance) ? reads.liveSync.body.performance : null;
8666
8799
  if (performance?.status === "unavailable") {
8667
8800
  reasons.push({
8668
8801
  source: "liveSync",
@@ -8743,11 +8876,11 @@ function statusVerdict(reads) {
8743
8876
  reasons
8744
8877
  };
8745
8878
  }
8746
- function record5(value) {
8747
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
8879
+ function record6(value2) {
8880
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
8748
8881
  }
8749
- function numeric2(value) {
8750
- return typeof value === "number" && Number.isFinite(value) ? value : 0;
8882
+ function numeric2(value2) {
8883
+ return typeof value2 === "number" && Number.isFinite(value2) ? value2 : 0;
8751
8884
  }
8752
8885
  function collectorReason(read3, fallback) {
8753
8886
  const reasons = read3.body.reasons;
@@ -8771,7 +8904,7 @@ function printO11yStatus(status, out) {
8771
8904
  out.log(
8772
8905
  `o11y status ${status.scope.appId}/${status.scope.env} (${status.scope.minutes}m)`
8773
8906
  );
8774
- const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(record6) : [];
8907
+ const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(record7) : [];
8775
8908
  const requests = routes.reduce(
8776
8909
  (total, row) => total + numeric3(row.requests),
8777
8910
  0
@@ -8783,39 +8916,39 @@ function printO11yStatus(status, out) {
8783
8916
  out.log(
8784
8917
  `application ${status.application.httpStatus} ${requests} requests ${errors} errors`
8785
8918
  );
8786
- const versions = Array.isArray(status.applicationVersions.body.rows) ? status.applicationVersions.body.rows.filter(record6) : [];
8919
+ const versions = Array.isArray(status.applicationVersions.body.rows) ? status.applicationVersions.body.rows.filter(record7) : [];
8787
8920
  out.log(
8788
8921
  `application-versions ${status.applicationVersions.httpStatus} ${versions.length ? versions.slice(0, 5).map(
8789
8922
  (row) => `${String(row.value || "(unattributed)")}:${numeric3(row.requests)}`
8790
8923
  ).join(", ") : "none observed"}`
8791
8924
  );
8792
8925
  out.log(liveSyncLine(status.liveSync));
8793
- const canaryDurations = record6(status.canary.body.durationsMs) ? status.canary.body.durationsMs : {};
8926
+ const canaryDurations = record7(status.canary.body.durationsMs) ? status.canary.body.durationsMs : {};
8794
8927
  out.log(
8795
8928
  `canary ${status.canary.httpStatus} ${String(status.canary.body.status ?? status.canary.body.error ?? "unavailable")} ${optionalNumeric(canaryDurations.publishToVisibleMs)} publish-to-visible`
8796
8929
  );
8797
- const collectorIngest = record6(status.collector.body.ingest) ? status.collector.body.ingest : {};
8798
- const collectorStorage = record6(collectorIngest.storage) ? collectorIngest.storage : {};
8930
+ const collectorIngest = record7(status.collector.body.ingest) ? status.collector.body.ingest : {};
8931
+ const collectorStorage = record7(collectorIngest.storage) ? collectorIngest.storage : {};
8799
8932
  out.log(
8800
8933
  `collector ${status.collector.httpStatus} ${String(status.collector.body.status ?? status.collector.body.error ?? "unavailable")} ${numeric3(collectorStorage.affectedPoints)} affected points`
8801
8934
  );
8802
- const providerMetrics = record6(status.provider.body.metrics) ? status.provider.body.metrics : {};
8803
- const providerCapacity = record6(status.provider.body.capacity) ? status.provider.body.capacity : {};
8804
- const workerMemory = record6(providerCapacity.memory) ? providerCapacity.memory : {};
8935
+ const providerMetrics = record7(status.provider.body.metrics) ? status.provider.body.metrics : {};
8936
+ const providerCapacity = record7(status.provider.body.capacity) ? status.provider.body.capacity : {};
8937
+ const workerMemory = record7(providerCapacity.memory) ? providerCapacity.memory : {};
8805
8938
  out.log(
8806
8939
  `cloudflare ${status.provider.httpStatus} ${String(status.provider.body.status ?? status.provider.body.error ?? "unavailable")} ${numeric3(providerMetrics.requests)} invocations ${numeric3(providerMetrics.errors)} runtime errors ${optionalBytes(workerMemory.headroomBytes)} isolate memory headroom`
8807
8940
  );
8808
8941
  for (const line of providerCapacityLines(status.providerCapacity)) {
8809
8942
  out.log(line);
8810
8943
  }
8811
- const coverage = record6(status.providerReconciliation.body.comparison) ? status.providerReconciliation.body.comparison : {};
8812
- const coverageCounts = record6(status.providerReconciliation.body.counts) ? status.providerReconciliation.body.counts : {};
8813
- const coverageBudget = record6(status.providerReconciliation.body.budget) ? status.providerReconciliation.body.budget : {};
8944
+ const coverage = record7(status.providerReconciliation.body.comparison) ? status.providerReconciliation.body.comparison : {};
8945
+ const coverageCounts = record7(status.providerReconciliation.body.counts) ? status.providerReconciliation.body.counts : {};
8946
+ const coverageBudget = record7(status.providerReconciliation.body.budget) ? status.providerReconciliation.body.budget : {};
8814
8947
  out.log(
8815
8948
  `request-coverage ${status.providerReconciliation.httpStatus} ${String(status.providerReconciliation.body.status ?? status.providerReconciliation.body.error ?? "unavailable")} ${optionalPercent(coverage.applicationCoverage)} application/provider ${numeric3(coverageCounts.applicationRequests)}/${numeric3(coverageCounts.providerRequests)} requests \xB1${optionalPercent(coverageBudget.maxRelativeError)} budget`
8816
8949
  );
8817
8950
  const providerPoints = Array.isArray(status.providerHistory.body.points) ? status.providerHistory.body.points.length : 0;
8818
- const providerFreshness = record6(status.providerHistory.body.freshness) ? status.providerHistory.body.freshness : {};
8951
+ const providerFreshness = record7(status.providerHistory.body.freshness) ? status.providerHistory.body.freshness : {};
8819
8952
  out.log(
8820
8953
  `cloudflare-history ${status.providerHistory.httpStatus} ${String(status.providerHistory.body.status ?? status.providerHistory.body.error ?? "unavailable")} ${providerPoints} snapshots ${optionalAge(providerFreshness.ageMs)} old`
8821
8954
  );
@@ -8824,17 +8957,17 @@ function printO11yStatus(status, out) {
8824
8957
  );
8825
8958
  }
8826
8959
  function providerCapacityLines(read3) {
8827
- const resources = record6(read3.body.resources) ? read3.body.resources : {};
8828
- const durableObjects = record6(resources.durableObjects) ? resources.durableObjects : {};
8829
- const periodic = record6(durableObjects.periodic) ? durableObjects.periodic : {};
8830
- const storage = record6(durableObjects.sqliteStorage) ? durableObjects.sqliteStorage : {};
8831
- const d1 = record6(resources.d1) ? resources.d1 : {};
8832
- const d1Activity = record6(d1.activity) ? d1.activity : {};
8833
- const d1Storage = record6(d1.storage) ? d1.storage : {};
8834
- const d1Latency = record6(d1Activity.latency) ? d1Activity.latency : {};
8835
- const r2 = record6(resources.r2) ? resources.r2 : {};
8836
- const r2Operations = record6(r2.operations) ? r2.operations : {};
8837
- const r2Storage = record6(r2.storage) ? r2.storage : {};
8960
+ const resources = record7(read3.body.resources) ? read3.body.resources : {};
8961
+ const durableObjects = record7(resources.durableObjects) ? resources.durableObjects : {};
8962
+ const periodic = record7(durableObjects.periodic) ? durableObjects.periodic : {};
8963
+ const storage = record7(durableObjects.sqliteStorage) ? durableObjects.sqliteStorage : {};
8964
+ const d1 = record7(resources.d1) ? resources.d1 : {};
8965
+ const d1Activity = record7(d1.activity) ? d1.activity : {};
8966
+ const d1Storage = record7(d1.storage) ? d1.storage : {};
8967
+ const d1Latency = record7(d1Activity.latency) ? d1Activity.latency : {};
8968
+ const r2 = record7(resources.r2) ? resources.r2 : {};
8969
+ const r2Operations = record7(r2.operations) ? r2.operations : {};
8970
+ const r2Storage = record7(r2.storage) ? r2.storage : {};
8838
8971
  const status = String(
8839
8972
  read3.body.status ?? read3.body.error ?? "unavailable"
8840
8973
  );
@@ -8845,42 +8978,42 @@ function providerCapacityLines(read3) {
8845
8978
  ];
8846
8979
  }
8847
8980
  function liveSyncLine(read3) {
8848
- const performance = record6(read3.body.performance) ? read3.body.performance : {};
8849
- const commitToSend = record6(performance.commitToSend) ? performance.commitToSend : {};
8981
+ const performance = record7(read3.body.performance) ? read3.body.performance : {};
8982
+ const commitToSend = record7(performance.commitToSend) ? performance.commitToSend : {};
8850
8983
  return `live-sync ${read3.httpStatus} ${String(read3.body.status ?? read3.body.error ?? "unavailable")} ${numeric3(read3.body.activeConnections)} active ${optionalNumeric(commitToSend.p95)} commit-to-send p95 ${numeric3(performance.sendFailures)} send failures`;
8851
8984
  }
8852
- function record6(value) {
8853
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
8985
+ function record7(value2) {
8986
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
8854
8987
  }
8855
- function numeric3(value) {
8856
- return typeof value === "number" && Number.isFinite(value) ? value : 0;
8988
+ function numeric3(value2) {
8989
+ return typeof value2 === "number" && Number.isFinite(value2) ? value2 : 0;
8857
8990
  }
8858
- function optionalNumeric(value) {
8859
- return typeof value === "number" && Number.isFinite(value) ? `${value} ms` : "\u2014";
8991
+ function optionalNumeric(value2) {
8992
+ return typeof value2 === "number" && Number.isFinite(value2) ? `${value2} ms` : "\u2014";
8860
8993
  }
8861
- function optionalAge(value) {
8862
- if (typeof value !== "number" || !Number.isFinite(value)) return "unknown";
8863
- return `${Math.max(0, Math.round(value / 1e3))}s`;
8994
+ function optionalAge(value2) {
8995
+ if (typeof value2 !== "number" || !Number.isFinite(value2)) return "unknown";
8996
+ return `${Math.max(0, Math.round(value2 / 1e3))}s`;
8864
8997
  }
8865
- function optionalPercent(value) {
8866
- return typeof value === "number" && Number.isFinite(value) ? `${Math.round(value * 100)}%` : "\u2014";
8998
+ function optionalPercent(value2) {
8999
+ return typeof value2 === "number" && Number.isFinite(value2) ? `${Math.round(value2 * 100)}%` : "\u2014";
8867
9000
  }
8868
- function optionalBytes(value) {
8869
- if (typeof value !== "number" || !Number.isFinite(value)) return "\u2014";
8870
- if (value >= 1024 * 1024 * 1024) {
8871
- return `${(value / (1024 * 1024 * 1024)).toFixed(2)} GiB`;
9001
+ function optionalBytes(value2) {
9002
+ if (typeof value2 !== "number" || !Number.isFinite(value2)) return "\u2014";
9003
+ if (value2 >= 1024 * 1024 * 1024) {
9004
+ return `${(value2 / (1024 * 1024 * 1024)).toFixed(2)} GiB`;
8872
9005
  }
8873
- if (value >= 1024 * 1024) {
8874
- return `${(value / (1024 * 1024)).toFixed(1)} MiB`;
9006
+ if (value2 >= 1024 * 1024) {
9007
+ return `${(value2 / (1024 * 1024)).toFixed(1)} MiB`;
8875
9008
  }
8876
- if (value >= 1024) return `${(value / 1024).toFixed(1)} KiB`;
8877
- return `${Math.round(value)} B`;
9009
+ if (value2 >= 1024) return `${(value2 / 1024).toFixed(1)} KiB`;
9010
+ return `${Math.round(value2)} B`;
8878
9011
  }
8879
- function optionalCount(value, unit) {
8880
- return typeof value === "number" && Number.isFinite(value) ? `${value} ${unit}` : `\u2014 ${unit}`;
9012
+ function optionalCount(value2, unit) {
9013
+ return typeof value2 === "number" && Number.isFinite(value2) ? `${value2} ${unit}` : `\u2014 ${unit}`;
8881
9014
  }
8882
- function optionalAgeSeconds(value) {
8883
- return typeof value === "number" && Number.isFinite(value) ? `${Math.max(0, Math.round(value))}s` : "unknown";
9015
+ function optionalAgeSeconds(value2) {
9016
+ return typeof value2 === "number" && Number.isFinite(value2) ? `${Math.max(0, Math.round(value2))}s` : "unknown";
8884
9017
  }
8885
9018
 
8886
9019
  // src/o11y-command.ts
@@ -9010,11 +9143,11 @@ async function o11yCommand(parsed, deps = {}) {
9010
9143
  }
9011
9144
  printO11yStatus(status, out);
9012
9145
  }
9013
- function statusMinutes(value) {
9014
- if (!Number.isSafeInteger(value) || value < 1 || value > 7 * 24 * 60) {
9146
+ function statusMinutes(value2) {
9147
+ if (!Number.isSafeInteger(value2) || value2 < 1 || value2 > 7 * 24 * 60) {
9015
9148
  throw new Error("--minutes must be an integer from 1 to 10080");
9016
9149
  }
9017
- return value;
9150
+ return value2;
9018
9151
  }
9019
9152
  async function read2(url, headers, doFetch) {
9020
9153
  const response2 = await doFetch(url, { headers });
@@ -9022,8 +9155,8 @@ async function read2(url, headers, doFetch) {
9022
9155
  let body = {};
9023
9156
  if (text) {
9024
9157
  try {
9025
- const value = JSON.parse(text);
9026
- body = value && typeof value === "object" && !Array.isArray(value) ? value : { value };
9158
+ const value2 = JSON.parse(text);
9159
+ body = value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : { value: value2 };
9027
9160
  } catch {
9028
9161
  body = { message: text.slice(0, 300) };
9029
9162
  }
@@ -9032,7 +9165,7 @@ async function read2(url, headers, doFetch) {
9032
9165
  }
9033
9166
 
9034
9167
  // src/provision.ts
9035
- var import_apps5 = require("@odla-ai/apps");
9168
+ var import_apps7 = require("@odla-ai/apps");
9036
9169
  var import_ai3 = require("@odla-ai/ai");
9037
9170
  var import_node_process10 = __toESM(require("process"), 1);
9038
9171
 
@@ -9077,8 +9210,8 @@ async function postJson2(doFetch, url, bearer, body) {
9077
9210
  if (!res.ok) throw new Error(`${new URL(url).pathname} failed: ${res.status} ${await responseText(res)}`);
9078
9211
  return res.json().catch(() => ({}));
9079
9212
  }
9080
- function isRecord7(value) {
9081
- return value !== null && typeof value === "object" && !Array.isArray(value);
9213
+ function isRecord7(value2) {
9214
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
9082
9215
  }
9083
9216
  async function responseText(res) {
9084
9217
  try {
@@ -9089,9 +9222,9 @@ async function responseText(res) {
9089
9222
  }
9090
9223
 
9091
9224
  // src/provision-credentials.ts
9092
- var import_apps3 = require("@odla-ai/apps");
9225
+ var import_apps5 = require("@odla-ai/apps");
9093
9226
  async function provisionEnvCredentials(opts) {
9094
- const tenantId = (0, import_apps3.tenantIdFor)(opts.cfg.app.id, opts.env);
9227
+ const tenantId = (0, import_apps5.tenantIdFor)(opts.cfg.app.id, opts.env);
9095
9228
  const prior = opts.credentials?.envs[opts.env];
9096
9229
  let credentials = opts.credentials;
9097
9230
  let dbKey = opts.cfg.services.includes("db") && !opts.rotateDb ? prior?.dbKey : void 0;
@@ -9185,18 +9318,13 @@ async function safeText4(res) {
9185
9318
 
9186
9319
  // src/provision-helpers.ts
9187
9320
  var import_ai2 = require("@odla-ai/ai");
9188
- var import_apps4 = require("@odla-ai/apps");
9189
- function serviceRank(service) {
9190
- if (service === "db") return 0;
9191
- if (service === "calendar") return 2;
9192
- return 1;
9193
- }
9321
+ var import_apps6 = require("@odla-ai/apps");
9194
9322
  function defaultSecretName(provider) {
9195
9323
  const names = import_ai2.DEFAULT_SECRET_NAMES;
9196
9324
  return names[provider] ?? `${provider}_api_key`;
9197
9325
  }
9198
9326
  async function assertTenantAdminAccess(doFetch, cfg, env, token) {
9199
- const tenantId = (0, import_apps4.tenantIdFor)(cfg.app.id, env);
9327
+ const tenantId = (0, import_apps6.tenantIdFor)(cfg.app.id, env);
9200
9328
  const res = await doFetch(`${cfg.dbEndpoint}/admin/apps/${encodeURIComponent(tenantId)}/entitlements`, {
9201
9329
  headers: { authorization: `Bearer ${token}` }
9202
9330
  });
@@ -9216,14 +9344,14 @@ async function postJson3(doFetch, url, bearer, body) {
9216
9344
  });
9217
9345
  if (!res.ok) throw new Error(`${new URL(url).pathname} failed: ${res.status} ${await safeText5(res)}`);
9218
9346
  }
9219
- function normalizeClerkConfig(value) {
9220
- if (!value) return null;
9221
- if (typeof value === "string") {
9222
- const publishableKey2 = envValue(value);
9347
+ function normalizeClerkConfig(value2) {
9348
+ if (!value2) return null;
9349
+ if (typeof value2 === "string") {
9350
+ const publishableKey2 = envValue(value2);
9223
9351
  return publishableKey2 ? { publishableKey: publishableKey2 } : null;
9224
9352
  }
9225
- if (typeof value !== "object") return null;
9226
- const cfg = value;
9353
+ if (typeof value2 !== "object") return null;
9354
+ const cfg = value2;
9227
9355
  const publishableKey = envValue(cfg.publishableKey);
9228
9356
  return publishableKey ? { publishableKey, ...cfg.audience ? { audience: cfg.audience } : {}, ...cfg.mode ? { mode: cfg.mode } : {} } : null;
9229
9357
  }
@@ -9305,7 +9433,7 @@ async function provision(options) {
9305
9433
  }
9306
9434
  const doFetch = options.fetch ?? fetch;
9307
9435
  const token = await getDeveloperToken(cfg, options, doFetch, out);
9308
- const apps = (0, import_apps5.createAppsClient)({ endpoint: cfg.platformUrl, token, fetcher: { fetch: doFetch } });
9436
+ const apps = (0, import_apps7.createAppsClient)({ endpoint: cfg.platformUrl, token, fetcher: { fetch: doFetch } });
9309
9437
  const existing = await apps.resolveApp(cfg.app.id);
9310
9438
  if (existing) {
9311
9439
  out.log(`app: ${cfg.app.id} already exists`);
@@ -9316,7 +9444,7 @@ async function provision(options) {
9316
9444
  for (const env of cfg.envs) {
9317
9445
  await assertTenantAdminAccess(doFetch, cfg, env, token);
9318
9446
  }
9319
- const serviceOrder = [...cfg.services].sort((a, b) => serviceRank(a) - serviceRank(b));
9447
+ const serviceOrder = (0, import_apps7.orderAppServices)(cfg.services);
9320
9448
  for (const env of cfg.envs) {
9321
9449
  for (const service of serviceOrder) {
9322
9450
  if (service === "ai") {
@@ -9349,7 +9477,7 @@ async function provision(options) {
9349
9477
  }
9350
9478
  }
9351
9479
  for (const env of cfg.envs) {
9352
- const tenantId = (0, import_apps5.tenantIdFor)(cfg.app.id, env);
9480
+ const tenantId = (0, import_apps7.tenantIdFor)(cfg.app.id, env);
9353
9481
  credentials = await provisionEnvCredentials({
9354
9482
  cfg,
9355
9483
  env,
@@ -9500,6 +9628,7 @@ var COMMAND_SURFACE = {
9500
9628
  help: {},
9501
9629
  init: {},
9502
9630
  o11y: { status: {} },
9631
+ platform: { status: {} },
9503
9632
  pm: {
9504
9633
  ...PM_ENTITIES,
9505
9634
  handoff: {}
@@ -9592,7 +9721,7 @@ function recordInvocation(parsed) {
9592
9721
  try {
9593
9722
  const entry = {
9594
9723
  path: invocationPath(parsed.positionals),
9595
- options: Object.entries(parsed.options).map(([name, value]) => value === false ? `no-${name}` : name).sort()
9724
+ options: Object.entries(parsed.options).map(([name, value2]) => value2 === false ? `no-${name}` : name).sort()
9596
9725
  };
9597
9726
  if (!entry.path.length) return;
9598
9727
  (0, import_node_fs15.appendFileSync)(file, `${JSON.stringify(entry)}
@@ -9606,10 +9735,10 @@ var import_node_fs16 = require("fs");
9606
9735
 
9607
9736
  // src/runbook-requires.ts
9608
9737
  var SPEC = /^(@?[\w./-]+?)@(\d+\.\d+\.\d+(?:[\w.-]*)?)$/;
9609
- function parseRequires(value) {
9610
- if (!value) return [];
9738
+ function parseRequires(value2) {
9739
+ if (!value2) return [];
9611
9740
  const out = [];
9612
- for (const token of value.split(/[\s,]+/).filter(Boolean)) {
9741
+ for (const token of value2.split(/[\s,]+/).filter(Boolean)) {
9613
9742
  const match = SPEC.exec(token);
9614
9743
  if (match?.[1] && match[2]) out.push({ name: match[1], min: match[2] });
9615
9744
  }
@@ -9785,9 +9914,9 @@ function parseRunbook(text, slug) {
9785
9914
  for (const line of fm[1].split(/\r?\n/)) {
9786
9915
  const pair = /^(\w+)\s*:\s*(.+)$/.exec(line.trim());
9787
9916
  if (!pair) continue;
9788
- const value = pair[2].trim().replace(/^["']|["']$/g, "");
9789
- if (pair[1] === "summary") meta.summary = value;
9790
- if (pair[1] === "tags") meta.tags = value.replace(/^\[|\]$/g, "").trim();
9917
+ const value2 = pair[2].trim().replace(/^["']|["']$/g, "");
9918
+ if (pair[1] === "summary") meta.summary = value2;
9919
+ if (pair[1] === "tags") meta.tags = value2.replace(/^\[|\]$/g, "").trim();
9791
9920
  }
9792
9921
  }
9793
9922
  const lines = rest.split("\n");
@@ -9904,7 +10033,7 @@ var NOISE = /* @__PURE__ */ new Set([
9904
10033
  "and",
9905
10034
  "for"
9906
10035
  ]);
9907
- var words = (value) => value.replace(/^@[\w-]+\//, "").split(/[^A-Za-z0-9]+/).filter((w) => w.length > 1 && !NOISE.has(w.toLowerCase()));
10036
+ var words = (value2) => value2.replace(/^@[\w-]+\//, "").split(/[^A-Za-z0-9]+/).filter((w) => w.length > 1 && !NOISE.has(w.toLowerCase()));
9908
10037
  function namedExports(clause) {
9909
10038
  return clause.split(",").map((part) => part.trim().split(/\s+as\s+/)[0]?.trim() ?? "").filter((name) => /^[A-Za-z_$][\w$]*$/.test(name) && name !== "type");
9910
10039
  }
@@ -10257,8 +10386,8 @@ var import_node_process12 = __toESM(require("process"), 1);
10257
10386
  var EDITOR_ENV = ["ODLA_EDITOR", "VISUAL", "EDITOR"];
10258
10387
  function resolveEditor(env = import_node_process12.default.env) {
10259
10388
  for (const name of EDITOR_ENV) {
10260
- const value = env[name];
10261
- if (value && value.trim()) return value.trim();
10389
+ const value2 = env[name];
10390
+ if (value2 && value2.trim()) return value2.trim();
10262
10391
  }
10263
10392
  return null;
10264
10393
  }
@@ -10523,9 +10652,9 @@ async function runbookCommand(parsed, deps = {}) {
10523
10652
  });
10524
10653
  }
10525
10654
  case "visibility": {
10526
- const value = parsed.positionals[3] ?? stringOpt(parsed.options.visibility);
10527
- if (!value) throw new Error('"runbook visibility" needs operator|admin, e.g. "runbook visibility release operator"');
10528
- return runbookVisibility(ctx, requireSlug(slug, "visibility"), value);
10655
+ const value2 = parsed.positionals[3] ?? stringOpt(parsed.options.visibility);
10656
+ if (!value2) throw new Error('"runbook visibility" needs operator|admin, e.g. "runbook visibility release operator"');
10657
+ return runbookVisibility(ctx, requireSlug(slug, "visibility"), value2);
10529
10658
  }
10530
10659
  case "publish":
10531
10660
  return runbookStatus(ctx, requireSlug(slug, "publish"), "published");
@@ -10581,13 +10710,13 @@ async function interactiveConfirmation(message2, dependencies) {
10581
10710
  }
10582
10711
  }
10583
10712
  function requiredSecurityPositional(parsed, index, label) {
10584
- const value = parsed.positionals[index];
10585
- if (!value) throw new Error(`${label} is required`);
10586
- return value;
10713
+ const value2 = parsed.positionals[index];
10714
+ if (!value2) throw new Error(`${label} is required`);
10715
+ return value2;
10587
10716
  }
10588
- function securityProfile(value) {
10589
- if (value === void 0) return void 0;
10590
- if (value === "odla" || value === "cloudflare-app" || value === "generic") return value;
10717
+ function securityProfile(value2) {
10718
+ if (value2 === void 0) return void 0;
10719
+ if (value2 === "odla" || value2 === "cloudflare-app" || value2 === "generic") return value2;
10591
10720
  throw new Error("--profile must be odla, cloudflare-app, or generic");
10592
10721
  }
10593
10722
 
@@ -10688,9 +10817,9 @@ function routeLabel(route2) {
10688
10817
  return `${route2.provider}/${route2.model}${route2.policyVersion ? ` policy v${route2.policyVersion}` : ""}`;
10689
10818
  }
10690
10819
  var HOSTED_SEVERITIES = ["informational", "low", "medium", "high", "critical"];
10691
- function hostedSeverity(value, flag) {
10692
- if (HOSTED_SEVERITIES.includes(value)) {
10693
- return value;
10820
+ function hostedSeverity(value2, flag) {
10821
+ if (HOSTED_SEVERITIES.includes(value2)) {
10822
+ return value2;
10694
10823
  }
10695
10824
  throw new Error(`${flag} must be informational, low, medium, high, or critical`);
10696
10825
  }
@@ -10773,13 +10902,13 @@ function selectEnv(requested, declared, configPath, rootDir) {
10773
10902
  return env;
10774
10903
  }
10775
10904
  async function injectedToken(options, request2) {
10776
- const value = options.token ?? await options.getToken?.(Object.freeze({ ...request2 }));
10777
- if (typeof value !== "string" || value.length < 8 || value.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value)) {
10905
+ const value2 = options.token ?? await options.getToken?.(Object.freeze({ ...request2 }));
10906
+ if (typeof value2 !== "string" || value2.length < 8 || value2.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value2)) {
10778
10907
  throw new Error(
10779
10908
  request2.selfAudit ? "Self-audit requires an injected, scoped platform security token" : "Hosted security requires an injected app developer token or getToken callback"
10780
10909
  );
10781
10910
  }
10782
- return value;
10911
+ return value2;
10783
10912
  }
10784
10913
  function profileFor(name, maxHuntTasks) {
10785
10914
  const profile = name === "odla" ? (0, import_security.odlaProfile)() : name === "cloudflare-app" ? (0, import_security.cloudflareAppProfile)() : name === "generic" ? (0, import_security.genericProfile)() : void 0;
@@ -10825,8 +10954,8 @@ async function getHostedSecurityIntent(options) {
10825
10954
  }
10826
10955
  return response2;
10827
10956
  }
10828
- function isValidIntent(value, expected) {
10829
- return !!value && value.executionContract === "odla.hosted-security-execution-consent.v1" && /^sha256:[a-f0-9]{64}$/.test(value.executionDigest) && /^sha256:[a-f0-9]{64}$/.test(value.planDigest) && value.appId === expected.appId && value.env === expected.env && value.sourceId === expected.sourceId && typeof value.repository === "string" && value.repository.length > 2 && value.repository.length <= 201 && typeof value.defaultBranch === "string" && value.defaultBranch.length > 0 && value.defaultBranch.length <= 255 && typeof value.requestedRef === "string" && value.requestedRef.length > 0 && value.requestedRef.length <= 255 && !/[\u0000-\u001f\u007f]/.test(value.requestedRef) && ["odla", "cloudflare-app", "generic"].includes(value.profile) && value.sourceDisclosure === "redacted";
10957
+ function isValidIntent(value2, expected) {
10958
+ return !!value2 && value2.executionContract === "odla.hosted-security-execution-consent.v1" && /^sha256:[a-f0-9]{64}$/.test(value2.executionDigest) && /^sha256:[a-f0-9]{64}$/.test(value2.planDigest) && value2.appId === expected.appId && value2.env === expected.env && value2.sourceId === expected.sourceId && typeof value2.repository === "string" && value2.repository.length > 2 && value2.repository.length <= 201 && typeof value2.defaultBranch === "string" && value2.defaultBranch.length > 0 && value2.defaultBranch.length <= 255 && typeof value2.requestedRef === "string" && value2.requestedRef.length > 0 && value2.requestedRef.length <= 255 && !/[\u0000-\u001f\u007f]/.test(value2.requestedRef) && ["odla", "cloudflare-app", "generic"].includes(value2.profile) && value2.sourceDisclosure === "redacted";
10830
10959
  }
10831
10960
 
10832
10961
  // src/security-hosted-jobs.ts
@@ -10952,17 +11081,17 @@ function hostedJobPath(appIdInput, jobIdInput) {
10952
11081
  const jobId = hostedIdentifier(jobIdInput, "jobId");
10953
11082
  return `/registry/apps/${encodeURIComponent(appId)}/security/jobs/${encodeURIComponent(jobId)}`;
10954
11083
  }
10955
- function securityPlanDigest(value) {
10956
- if (!/^sha256:[a-f0-9]{64}$/.test(value)) {
11084
+ function securityPlanDigest(value2) {
11085
+ if (!/^sha256:[a-f0-9]{64}$/.test(value2)) {
10957
11086
  throw new Error("expected plan digest must be a sha256 digest from security plan");
10958
11087
  }
10959
- return value;
11088
+ return value2;
10960
11089
  }
10961
- function securityExecutionDigest(value) {
10962
- if (!/^sha256:[a-f0-9]{64}$/.test(value)) {
11090
+ function securityExecutionDigest(value2) {
11091
+ if (!/^sha256:[a-f0-9]{64}$/.test(value2)) {
10963
11092
  throw new Error("expected execution digest must be a sha256 digest from security intent");
10964
11093
  }
10965
- return value;
11094
+ return value2;
10966
11095
  }
10967
11096
 
10968
11097
  // src/security-run-command.ts
@@ -11026,7 +11155,7 @@ async function runSourceSecurityCommand(parsed, dependencies, sourceId) {
11026
11155
  ...context,
11027
11156
  jobId: job.jobId,
11028
11157
  wait: dependencies.pollWait,
11029
- onUpdate: parsed.options.json === true ? void 0 : (value) => printHostedJob(context.stdout, value, context.platform, context.appId)
11158
+ onUpdate: parsed.options.json === true ? void 0 : (value2) => printHostedJob(context.stdout, value2, context.platform, context.appId)
11030
11159
  }) : job;
11031
11160
  if (!follow) {
11032
11161
  if (parsed.options.json === true) {
@@ -11126,9 +11255,9 @@ function enforceLocalGate(report4, parsed) {
11126
11255
  throw new Error(`hosted security gate failed: ${confirmed.length} confirmed >= ${failOn}; ${leads.length} leads >= ${failOnCandidates ?? "disabled"}${incomplete ? "; coverage incomplete" : ""}`);
11127
11256
  }
11128
11257
  }
11129
- function severityOpt(value, flag) {
11130
- if (["informational", "low", "medium", "high", "critical"].includes(value)) {
11131
- return value;
11258
+ function severityOpt(value2, flag) {
11259
+ if (["informational", "low", "medium", "high", "critical"].includes(value2)) {
11260
+ return value2;
11132
11261
  }
11133
11262
  throw new Error(`${flag} must be informational, low, medium, high, or critical`);
11134
11263
  }
@@ -11236,7 +11365,7 @@ async function securityStatus(parsed, dependencies) {
11236
11365
  ...context,
11237
11366
  jobId,
11238
11367
  wait: dependencies.pollWait,
11239
- onUpdate: parsed.options.json === true ? void 0 : (value) => printHostedJob(context.stdout, value, context.platform, context.appId)
11368
+ onUpdate: parsed.options.json === true ? void 0 : (value2) => printHostedJob(context.stdout, value2, context.platform, context.appId)
11240
11369
  }) : await getHostedSecurityJob({ ...context, jobId });
11241
11370
  if (parsed.options.json === true) context.stdout.log(JSON.stringify(job, null, 2));
11242
11371
  else if (parsed.options.follow !== true) {
@@ -11320,6 +11449,10 @@ async function runCli(argv = process.argv.slice(2), dependencies = {}) {
11320
11449
  await o11yCommand(parsed, runtime);
11321
11450
  return;
11322
11451
  }
11452
+ if (command === "platform") {
11453
+ await platformCommand(parsed, runtime);
11454
+ return;
11455
+ }
11323
11456
  if (command === "provision") {
11324
11457
  await provisionCommand(parsed, runtime);
11325
11458
  return;