@runtypelabs/cli 2.11.0 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +87 -3
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -19803,7 +19803,11 @@ var require_fpo_schema = __commonJS({
19803
19803
  var setupInstructionsSchema = zod_1.z.object({
19804
19804
  summary: zod_1.z.string().min(1),
19805
19805
  steps: zod_1.z.array(zod_1.z.string()),
19806
- docsUrl: zod_1.z.string().optional()
19806
+ // Constrained to an absolute URL because this lands in the rendered
19807
+ // `<a href={…}>` in the secret intake and quick-start preview UIs —
19808
+ // `javascript:` / `data:` schemes in an unrestricted string would be a
19809
+ // live XSS vector when a malicious template is imported.
19810
+ docsUrl: zod_1.z.string().url().optional()
19807
19811
  });
19808
19812
  var toolAuthSchema = zod_1.z.object({
19809
19813
  type: zod_1.z.enum(["oauth", "api_key", "none", "user_provided"]),
@@ -20073,12 +20077,59 @@ var require_capability_validator = __commonJS({
20073
20077
  }
20074
20078
  });
20075
20079
 
20080
+ // ../shared/dist/product-generation/secret-ref.js
20081
+ var require_secret_ref = __commonJS({
20082
+ "../shared/dist/product-generation/secret-ref.js"(exports) {
20083
+ "use strict";
20084
+ Object.defineProperty(exports, "__esModule", { value: true });
20085
+ exports.extractSecretReferences = extractSecretReferences;
20086
+ exports.extractSecretReferencesFromAnyValue = extractSecretReferencesFromAnyValue;
20087
+ var SECRET_REF_PATTERN = /\{\{secret:([A-Z][A-Z0-9_]*[A-Z0-9])\}\}/g;
20088
+ function extractSecretReferences(template) {
20089
+ const keys = /* @__PURE__ */ new Set();
20090
+ let match;
20091
+ const regex = new RegExp(SECRET_REF_PATTERN.source, "g");
20092
+ while ((match = regex.exec(template)) !== null) {
20093
+ const key = match[1];
20094
+ if (key)
20095
+ keys.add(key);
20096
+ }
20097
+ return Array.from(keys);
20098
+ }
20099
+ function extractSecretReferencesFromAnyValue(value, maxDepth = 10) {
20100
+ const keys = /* @__PURE__ */ new Set();
20101
+ walk(value, 0);
20102
+ return Array.from(keys);
20103
+ function walk(v, depth) {
20104
+ if (depth > maxDepth)
20105
+ return;
20106
+ if (typeof v === "string") {
20107
+ for (const key of extractSecretReferences(v))
20108
+ keys.add(key);
20109
+ return;
20110
+ }
20111
+ if (Array.isArray(v)) {
20112
+ for (const item of v)
20113
+ walk(item, depth + 1);
20114
+ return;
20115
+ }
20116
+ if (v && typeof v === "object") {
20117
+ for (const inner of Object.values(v)) {
20118
+ walk(inner, depth + 1);
20119
+ }
20120
+ }
20121
+ }
20122
+ }
20123
+ }
20124
+ });
20125
+
20076
20126
  // ../shared/dist/product-generation/validators/tool-validator.js
20077
20127
  var require_tool_validator = __commonJS({
20078
20128
  "../shared/dist/product-generation/validators/tool-validator.js"(exports) {
20079
20129
  "use strict";
20080
20130
  Object.defineProperty(exports, "__esModule", { value: true });
20081
20131
  exports.validateToolDefinition = validateToolDefinition;
20132
+ var secret_ref_1 = require_secret_ref();
20082
20133
  var types_1 = require_types2();
20083
20134
  function validateToolDefinition(tool, index) {
20084
20135
  const result = (0, types_1.emptyResult)();
@@ -20090,13 +20141,30 @@ var require_tool_validator = __commonJS({
20090
20141
  result.errors.push((0, types_1.createIssue)("error", "INTEGRATION_NO_PROVIDER", "Integration tools must have a provider", `${base}.provider`));
20091
20142
  }
20092
20143
  if (tool.auth) {
20144
+ const declaredKeys = /* @__PURE__ */ new Set();
20093
20145
  if (tool.auth.secrets) {
20094
20146
  for (const [i, secret] of tool.auth.secrets.entries()) {
20095
20147
  if (!secret.key || secret.key.trim() === "") {
20096
20148
  result.errors.push((0, types_1.createIssue)("error", "SECRET_KEY_EMPTY", "Secret key is required", `${base}.auth.secrets[${i}].key`));
20149
+ continue;
20097
20150
  }
20151
+ declaredKeys.add(secret.key);
20152
+ }
20153
+ }
20154
+ const referencedKeys = new Set((0, secret_ref_1.extractSecretReferencesFromAnyValue)(tool.config));
20155
+ for (const key of referencedKeys) {
20156
+ if (!declaredKeys.has(key)) {
20157
+ result.errors.push((0, types_1.createIssue)("error", "SECRET_REFERENCE_UNDECLARED", `Tool config references \`{{secret:${key}}}\` but this tool does not declare it in \`auth.secrets\`.`, `${base}.auth.secrets`, `Add \`{ key: '${key}', required: true }\` to this tool's \`auth.secrets\`.`));
20098
20158
  }
20099
20159
  }
20160
+ for (const key of declaredKeys) {
20161
+ if (!referencedKeys.has(key)) {
20162
+ result.warnings.push((0, types_1.createIssue)("warning", "SECRET_DECLARED_BUT_UNREFERENCED", `Secret \`${key}\` is declared in \`auth.secrets\` but never referenced as \`{{secret:${key}}}\` in this tool's config.`, `${base}.auth.secrets`, `Either reference \`{{secret:${key}}}\` in the tool config or remove it from \`auth.secrets\`. Integrations that consume secrets outside the config (e.g. MCP servers) can ignore this warning.`));
20163
+ }
20164
+ }
20165
+ if (declaredKeys.size > 0 && tool.auth.setupRequired === false) {
20166
+ result.recommendations.push((0, types_1.createIssue)("recommendation", "SETUP_REQUIRED_IMPLIED", `Tool declares ${declaredKeys.size} secret(s) in \`auth.secrets\` but \`auth.setupRequired\` is false \u2014 pending secrets will not be surfaced in the intake flow.`, `${base}.auth.setupRequired`, "Set `auth.setupRequired: true` so these secrets are materialized as pending bindings and shown to the user after import."));
20167
+ }
20100
20168
  }
20101
20169
  result.valid = result.errors.length === 0;
20102
20170
  return result;
@@ -20321,8 +20389,21 @@ var require_fpo_template = __commonJS({
20321
20389
  version: zod_1.z.literal(exports.FULL_PRODUCT_OBJECT_TEMPLATE_VERSION),
20322
20390
  productObject: fpo_schema_1.fullProductObjectSchema,
20323
20391
  template: zod_1.z.object({
20324
- variables: zod_1.z.array(exports.fpoTemplateVariableSchema).min(1, "Template must declare at least one variable")
20392
+ variables: zod_1.z.array(exports.fpoTemplateVariableSchema).max(50)
20325
20393
  })
20394
+ }).superRefine((doc, ctx) => {
20395
+ const hasVariables = doc.template.variables.length > 0;
20396
+ const hasPendingSecretTool = doc.productObject.tools.some((tool) => {
20397
+ var _a, _b;
20398
+ return ((_a = tool.auth) === null || _a === void 0 ? void 0 : _a.setupRequired) === true && Array.isArray((_b = tool.auth) === null || _b === void 0 ? void 0 : _b.secrets) && tool.auth.secrets.length > 0;
20399
+ });
20400
+ if (!hasVariables && !hasPendingSecretTool) {
20401
+ ctx.addIssue({
20402
+ code: "custom",
20403
+ message: "Template must declare at least one template variable or at least one tool with `auth.setupRequired: true` and pending secrets.",
20404
+ path: ["template", "variables"]
20405
+ });
20406
+ }
20326
20407
  });
20327
20408
  function collectStringLeafPaths(value, path14 = []) {
20328
20409
  if (typeof value === "string") {
@@ -20352,7 +20433,7 @@ var require_fpo_template = __commonJS({
20352
20433
  const inner = value.slice(start + 2, end);
20353
20434
  const separatorIndex = inner.indexOf("|");
20354
20435
  const key = (separatorIndex === -1 ? inner : inner.slice(0, separatorIndex)).trim();
20355
- if (key.length > 0) {
20436
+ if (key.length > 0 && !key.startsWith("secret:")) {
20356
20437
  references.push({
20357
20438
  key,
20358
20439
  defaultValue: separatorIndex === -1 ? void 0 : inner.slice(separatorIndex + 1).trim(),
@@ -20534,6 +20615,9 @@ var require_fpo_template = __commonJS({
20534
20615
  if (!referencedKeys.has(variable.key)) {
20535
20616
  result.warnings.push((0, types_1.createIssue)("warning", "UNUSED_TEMPLATE_VARIABLE", `Template variable "${variable.key}" is declared but not used`, `template.variables.${variable.key}`));
20536
20617
  }
20618
+ if (variable.inputType === "secret") {
20619
+ result.warnings.push((0, types_1.createIssue)("warning", "TEMPLATE_VARIABLE_SECRET_IS_UNSAFE", `Template variable "${variable.key}" uses \`inputType: 'secret'\`, which substitutes the supplied value literally into the product record at resolve time \u2014 the value ends up persisted in the database.`, `template.variables.${variable.key}.inputType`, `Prefer declaring pending secrets via the target tool's \`auth.secrets\` array and referencing the value as \`{{secret:${variable.key.toUpperCase()}}}\` so the secret is stored in the secrets vault instead of in the product object.`));
20620
+ }
20537
20621
  }
20538
20622
  const defaultsResolution = (_a = options.defaultsResolution) !== null && _a !== void 0 ? _a : resolveFPOTemplate(template);
20539
20623
  const defaultsValidation = (0, types_1.mergeResults)((0, fpo_validator_1.validateFPO)(defaultsResolution.resolved), defaultsResolution.missingVariables.length > 0 ? {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/cli",
3
- "version": "2.11.0",
3
+ "version": "2.11.1",
4
4
  "description": "Command-line interface for Runtype AI platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "micromatch": "^4.0.8",
24
24
  "yaml": "^2.8.3",
25
25
  "@runtypelabs/ink-components": "0.3.1",
26
- "@runtypelabs/sdk": "1.17.0",
26
+ "@runtypelabs/sdk": "1.17.1",
27
27
  "@runtypelabs/terminal-animations": "0.2.0"
28
28
  },
29
29
  "devDependencies": {