@elevasis/sdk 1.49.0 → 1.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -23570,6 +23570,10 @@ var init_profile_registry = __esm({
23570
23570
  });
23571
23571
 
23572
23572
  // ../core/src/organization-model/domains/systems.ts
23573
+ function isSystemLifecycleVisible(lifecycle, enabled) {
23574
+ if (enabled === false) return false;
23575
+ return lifecycle !== "draft" && lifecycle !== "deprecated" && lifecycle !== "archived";
23576
+ }
23573
23577
  function isReservedPlatformProfileId(profileId) {
23574
23578
  return BUILT_IN_VALIDATED_PROFILE_IDS.includes(profileId);
23575
23579
  }
@@ -23586,7 +23590,10 @@ var init_systems = __esm({
23586
23590
  init_ontology();
23587
23591
  init_profile_registry();
23588
23592
  SystemKindSchema = external_exports.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
23589
- SystemLifecycleSchema = external_exports.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
23593
+ SystemLifecycleSchema = external_exports.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({
23594
+ label: "Lifecycle",
23595
+ color: "teal"
23596
+ });
23590
23597
  SystemIdSchema = ModelIdSchema;
23591
23598
  SystemPathSchema = external_exports.string().trim().min(1).regex(
23592
23599
  /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
@@ -23706,8 +23713,13 @@ var init_systems = __esm({
23706
23713
  parentSystemId: SystemIdSchema.optional(),
23707
23714
  /** Optional UI presence. Systems without UI omit this. */
23708
23715
  ui: SystemUiSchema.optional(),
23709
- /** Canonical lifecycle state. `beta` is what gates a System to dev-mode viewers. */
23710
- lifecycle: SystemLifecycleSchema.optional(),
23716
+ /**
23717
+ * Canonical lifecycle state. `beta` is what gates a System to dev-mode
23718
+ * viewers. Defaults to `active` (not `.optional()`) so an omitted field
23719
+ * never reaches a consumer as `undefined` -- see `isSystemLifecycleVisible`
23720
+ * and `systemLifecycleAllowsAccess` above.
23721
+ */
23722
+ lifecycle: SystemLifecycleSchema.default("active"),
23711
23723
  /** Optional role responsible for this system. */
23712
23724
  responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
23713
23725
  /** Optional knowledge nodes that govern this system. */
@@ -24229,10 +24241,6 @@ function addIssue(ctx, path3, message) {
24229
24241
  message
24230
24242
  });
24231
24243
  }
24232
- function isLifecycleEnabled(lifecycle, enabled) {
24233
- if (enabled === false) return false;
24234
- return lifecycle !== "deprecated" && lifecycle !== "archived";
24235
- }
24236
24244
  function defaultSystemPathFor(id) {
24237
24245
  return `/${id.replaceAll(".", "/")}`;
24238
24246
  }
@@ -24303,11 +24311,11 @@ function refineOrganizationModel(model, ctx) {
24303
24311
  systemIdsByEffectivePath.set(effectivePath, path3);
24304
24312
  }
24305
24313
  }
24306
- if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
24314
+ if (hasChildren && isSystemLifecycleVisible(system.lifecycle, system.enabled)) {
24307
24315
  const hasEnabledDescendant = Object.values(system.systems ?? system.subsystems ?? {}).some(
24308
- (candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
24316
+ (candidate) => isSystemLifecycleVisible(candidate.lifecycle, candidate.enabled)
24309
24317
  ) || allSystems.some(
24310
- (candidate) => candidate.path.startsWith(`${path3}.`) && !candidate.path.slice(path3.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
24318
+ (candidate) => candidate.path.startsWith(`${path3}.`) && !candidate.path.slice(path3.length + 1).includes(".") && isSystemLifecycleVisible(candidate.system.lifecycle, candidate.system.enabled)
24311
24319
  );
24312
24320
  if (!hasEnabledDescendant) {
24313
24321
  addIssue(ctx, [...schemaPath, "lifecycle"], `System "${path3}" is active but has no active descendants`);
@@ -24722,6 +24730,7 @@ var init_schema_refinements = __esm({
24722
24730
  "use strict";
24723
24731
  init_zod();
24724
24732
  init_resources();
24733
+ init_systems();
24725
24734
  init_cross_ref();
24726
24735
  init_ontology();
24727
24736
  }
@@ -25054,7 +25063,7 @@ var init_content = __esm({
25054
25063
  "../core/src/organization-model/catalogs/content.ts"() {
25055
25064
  "use strict";
25056
25065
  init_zod();
25057
- ContentPipelineStepActorSchema = external_exports.enum(["workflow", "agent", "vendor"]);
25066
+ ContentPipelineStepActorSchema = external_exports.enum(["workflow", "agent", "vendor", "human"]);
25058
25067
  ContentPipelineStepReviewModeSchema = external_exports.enum(["none", "required"]);
25059
25068
  ContentPayloadFieldTypeSchema = external_exports.enum(["string", "text", "number", "boolean", "url", "string-array"]);
25060
25069
  ContentPayloadFieldDeclarationSchema = external_exports.object({
@@ -26291,6 +26300,13 @@ var init_lead_gen = __esm({
26291
26300
  }
26292
26301
  });
26293
26302
 
26303
+ // ../core/src/organization-model/catalogs/content-producer-factory.ts
26304
+ var init_content_producer_factory = __esm({
26305
+ "../core/src/organization-model/catalogs/content-producer-factory.ts"() {
26306
+ "use strict";
26307
+ }
26308
+ });
26309
+
26294
26310
  // ../core/src/organization-model/catalogs/define-content-pipeline.ts
26295
26311
  var init_define_content_pipeline = __esm({
26296
26312
  "../core/src/organization-model/catalogs/define-content-pipeline.ts"() {
@@ -26298,6 +26314,49 @@ var init_define_content_pipeline = __esm({
26298
26314
  }
26299
26315
  });
26300
26316
 
26317
+ // ../core/src/organization-model/catalogs/define-system-api-interface.ts
26318
+ function formatAdoptableProfiles() {
26319
+ return SYSTEM_INTERFACE_PROFILES.map((profile) => `"${profile.readinessProfile}"`).join(", ");
26320
+ }
26321
+ function defineSystemApiInterface(input) {
26322
+ const interfaceKey = input.interfaceKey ?? "api";
26323
+ const identity = `${input.systemPath}/${interfaceKey}`;
26324
+ const catalogEntry = SYSTEM_INTERFACE_PROFILES.find((profile) => profile.readinessProfile === input.readinessProfile);
26325
+ if (catalogEntry === void 0) {
26326
+ throw new Error(
26327
+ `System Interface "${identity}" declares readinessProfile "${input.readinessProfile}", which is not a member of SYSTEM_INTERFACE_PROFILES. Adoptable profiles: ${formatAdoptableProfiles()}. An uncataloged id names no route platform code actually serves -- it computes as ready and answers every request with a 503. Add an entry to SYSTEM_INTERFACE_PROFILES (packages/core/src/organization-model/domains/systems.ts) before declaring it on System "${input.systemPath}", or use one of the ids above.`
26328
+ );
26329
+ }
26330
+ if (input.resourceIds.length === 0) {
26331
+ throw new Error(
26332
+ `System Interface "${identity}" declares an empty resourceIds list. An interface with no scoped active resource computes as ready and answers every route with a 503 -- scope at least one active resource for System "${input.systemPath}".`
26333
+ );
26334
+ }
26335
+ const isBuiltIn = catalogEntry.validation === "built-in";
26336
+ if (!isBuiltIn && input.readinessContract === void 0) {
26337
+ throw new Error(
26338
+ `System Interface "${identity}" adopts contract-validated profile "${input.readinessProfile}" but declares no readinessContract. Contract-validated profiles have no registered platform validator -- each adopter's structural requirements differ, so System "${input.systemPath}" must pass a readinessContract with at least one requiredCatalogs entry.`
26339
+ );
26340
+ }
26341
+ if (isBuiltIn && input.readinessContract !== void 0) {
26342
+ throw new Error(
26343
+ `System Interface "${identity}" declares a readinessContract against built-in profile "${input.readinessProfile}". Built-in profiles derive their requirements from platform code registered via registerBuiltInReadinessProfile, and the readiness engine never reads an authored contract against one -- it is silently ignored (the "else if (readinessContract)" branch in readiness/engine.ts is unreachable for a built-in profile). Delete the readinessContract on System "${input.systemPath}"; it asserts nothing today.`
26344
+ );
26345
+ }
26346
+ return {
26347
+ lifecycle: input.lifecycle ?? "active",
26348
+ readinessProfile: input.readinessProfile,
26349
+ resourceIds: input.resourceIds,
26350
+ ...input.readinessContract !== void 0 ? { readinessContract: input.readinessContract } : {}
26351
+ };
26352
+ }
26353
+ var init_define_system_api_interface = __esm({
26354
+ "../core/src/organization-model/catalogs/define-system-api-interface.ts"() {
26355
+ "use strict";
26356
+ init_systems();
26357
+ }
26358
+ });
26359
+
26301
26360
  // ../core/src/organization-model/readiness/engine.ts
26302
26361
  function addReadinessIssue(issues, family, code, message, details = {}) {
26303
26362
  issues.push({
@@ -26638,7 +26697,9 @@ var init_organization_model = __esm({
26638
26697
  init_graph();
26639
26698
  init_lead_gen();
26640
26699
  init_content();
26700
+ init_content_producer_factory();
26641
26701
  init_define_content_pipeline();
26702
+ init_define_system_api_interface();
26642
26703
  init_branding();
26643
26704
  init_systems();
26644
26705
  init_resources();
@@ -45276,7 +45337,7 @@ function detectMissingApiInterfaceDeclarations(orgName, organizationModel) {
45276
45337
  for (const resource of Object.values(organizationModel.resources ?? {})) {
45277
45338
  const ontology = resource.ontology;
45278
45339
  if (ontology === void 0) continue;
45279
- const hasOntologyBindings = ontology.actions !== void 0 && ontology.actions.length > 0 || ontology.writes !== void 0 && ontology.writes.length > 0;
45340
+ const hasOntologyBindings = ontology.actions !== void 0 && ontology.actions.length > 0 || ontology.writes !== void 0 && ontology.writes.length > 0 || ontology.reads !== void 0 && ontology.reads.length > 0 || ontology.usesCatalogs !== void 0 && ontology.usesCatalogs.length > 0;
45280
45341
  if (!hasOntologyBindings) continue;
45281
45342
  const existing = apiBoundResourcesBySystemPath.get(resource.systemPath);
45282
45343
  if (existing) {
@@ -45309,18 +45370,15 @@ function validateDeclaredSystemInterfaceReadiness(orgName, organizationModel, op
45309
45370
  for (const { path: path3, system } of listAllSystems(model)) {
45310
45371
  if (system.apiInterface === void 0) continue;
45311
45372
  const interfaceKey = "api";
45312
- const resourceIds = system.apiInterface.resourceIds ?? [];
45313
- if (resourceIds.length === 0) {
45314
- const readinessProfile = system.apiInterface.readinessProfile;
45315
- if (readinessProfile !== void 0 && !SYSTEM_INTERFACE_PROFILES.some((profile) => profile.readinessProfile === readinessProfile)) {
45316
- addSystemInterfaceIssue(issues, orgName, path3, interfaceKey, {
45317
- family: "SYSTEM_INTERFACE_INVALID",
45318
- code: "unknown-readiness-profile",
45319
- path: `systems.${path3}.apiInterface.readinessProfile`,
45320
- ref: readinessProfile,
45321
- message: `System Interface "${path3}/${interfaceKey}" references unknown readiness profile "${readinessProfile}".`
45322
- });
45323
- }
45373
+ const readinessProfile = system.apiInterface.readinessProfile;
45374
+ if (readinessProfile !== void 0 && !SYSTEM_INTERFACE_PROFILES.some((profile) => profile.readinessProfile === readinessProfile)) {
45375
+ addSystemInterfaceIssue(issues, orgName, path3, interfaceKey, {
45376
+ family: "SYSTEM_INTERFACE_INVALID",
45377
+ code: "unknown-readiness-profile",
45378
+ path: `systems.${path3}.apiInterface.readinessProfile`,
45379
+ ref: readinessProfile,
45380
+ message: `System Interface "${path3}/${interfaceKey}" references unknown readiness profile "${readinessProfile}".`
45381
+ });
45324
45382
  }
45325
45383
  const result = computeInterfaceReadiness(model, { systemPath: path3, interfaceKey });
45326
45384
  for (const issue2 of result.issues) {
@@ -47661,6 +47719,13 @@ var init_clickup = __esm({
47661
47719
  }
47662
47720
  });
47663
47721
 
47722
+ // ../core/src/execution/engine/tools/integration/types/instagram.ts
47723
+ var init_instagram = __esm({
47724
+ "../core/src/execution/engine/tools/integration/types/instagram.ts"() {
47725
+ "use strict";
47726
+ }
47727
+ });
47728
+
47664
47729
  // ../core/src/execution/engine/tools/integration/types/index.ts
47665
47730
  var init_types9 = __esm({
47666
47731
  "../core/src/execution/engine/tools/integration/types/index.ts"() {
@@ -47678,6 +47743,7 @@ var init_types9 = __esm({
47678
47743
  init_tomba();
47679
47744
  init_millionverifier();
47680
47745
  init_clickup();
47746
+ init_instagram();
47681
47747
  }
47682
47748
  });
47683
47749
 
@@ -48771,7 +48837,14 @@ var init_api_schemas5 = __esm({
48771
48837
  "use strict";
48772
48838
  init_zod();
48773
48839
  init_validation();
48774
- CredentialTypeSchema = external_exports.enum(["oauth", "api-key", "webhook-secret", "api-key-secret", "clickup"]);
48840
+ CredentialTypeSchema = external_exports.enum([
48841
+ "oauth",
48842
+ "api-key",
48843
+ "webhook-secret",
48844
+ "api-key-secret",
48845
+ "clickup",
48846
+ "instagram"
48847
+ ]);
48775
48848
  CredentialValueSchema = external_exports.record(external_exports.string(), external_exports.unknown()).refine((val) => Object.keys(val).length > 0, { message: "Credential value must not be empty" }).refine((val) => Object.keys(val).length <= 50, { message: "Credential value has too many keys (max 50)" }).refine(
48776
48849
  (val) => {
48777
48850
  for (const v of Object.values(val)) {
@@ -49225,7 +49298,7 @@ var init_package = __esm({
49225
49298
  "package.json"() {
49226
49299
  package_default = {
49227
49300
  name: "@elevasis/sdk",
49228
- version: "1.49.0",
49301
+ version: "1.51.0",
49229
49302
  description: "SDK for building Elevasis organization resources",
49230
49303
  type: "module",
49231
49304
  bin: {
@@ -49257,6 +49330,7 @@ var init_package = __esm({
49257
49330
  "dist/test-utils/index.js",
49258
49331
  "dist/test-utils/index.d.ts",
49259
49332
  "dist/node/",
49333
+ "dist/chunk-*.js",
49260
49334
  "dist/cli.cjs",
49261
49335
  "reference/"
49262
49336
  ],
@@ -49276,8 +49350,14 @@ var init_package = __esm({
49276
49350
  "remark-gfm": "^4.0.1"
49277
49351
  },
49278
49352
  peerDependencies: {
49353
+ vitest: ">=3",
49279
49354
  zod: "^4.1.0"
49280
49355
  },
49356
+ peerDependenciesMeta: {
49357
+ vitest: {
49358
+ optional: true
49359
+ }
49360
+ },
49281
49361
  devDependencies: {
49282
49362
  "@repo/core": "workspace:*",
49283
49363
  "@repo/eslint-config": "workspace:*",
@@ -49292,6 +49372,7 @@ var init_package = __esm({
49292
49372
  "rollup-plugin-dts": "^6.3.0",
49293
49373
  tsup: "^8.0.0",
49294
49374
  typescript: "5.9.2",
49375
+ vitest: "^3.2.4",
49295
49376
  zod: "^4.1.0"
49296
49377
  }
49297
49378
  };
@@ -49992,18 +50073,35 @@ function emitSystemEntry(opts) {
49992
50073
  const order = opts.order ?? 10;
49993
50074
  let apiInterfaceBlock = "";
49994
50075
  let apiInterfaceNote;
50076
+ let importLine;
49995
50077
  if (opts.apiBacked) {
49996
50078
  const cataloged = SYSTEM_INTERFACE_PROFILES.find(
49997
50079
  (profile) => profile.systemPath === opts.id && profile.interfaceKey === "api"
49998
50080
  );
49999
- if (cataloged !== void 0) {
50081
+ const resourceIds = (opts.resourceIds ?? []).filter((id) => id.trim().length > 0);
50082
+ if (cataloged !== void 0 && cataloged.validation === "built-in" && resourceIds.length > 0) {
50083
+ defineSystemApiInterface({
50084
+ systemPath: opts.id,
50085
+ readinessProfile: cataloged.readinessProfile,
50086
+ resourceIds
50087
+ });
50088
+ importLine = `import { defineSystemApiInterface } from '@elevasis/core/organization-model'`;
50089
+ const resourceIdsLines = resourceIds.map((id) => ` '${id}'`).join(",\n");
50000
50090
  apiInterfaceBlock = `
50001
- apiInterface: {
50002
- lifecycle: 'active',
50003
- readinessProfile: '${cataloged.readinessProfile}'
50004
- },`;
50091
+ apiInterface: defineSystemApiInterface({
50092
+ systemPath: '${opts.id}',
50093
+ readinessProfile: '${cataloged.readinessProfile}',
50094
+ resourceIds: [
50095
+ ${resourceIdsLines}
50096
+ ]
50097
+ }),`;
50098
+ } else if (cataloged !== void 0 && cataloged.validation === "built-in") {
50099
+ apiInterfaceNote = `System \`${opts.id}\` is cataloged for readiness profile "${cataloged.readinessProfile}", but a brand-new System has no scoped resources yet to back an \`apiInterface\`. \`apiInterface\` was NOT added. Once real resource ids exist for this system, declare it with \`defineSystemApiInterface\` from '@elevasis/core/organization-model' (or re-run \`om:scaffold:fill\`, which does this for you).`;
50100
+ } else if (cataloged !== void 0) {
50101
+ apiInterfaceNote = `System \`${opts.id}\` adopts contract-validated readiness profile "${cataloged.readinessProfile}". \`apiInterface\` was NOT added \u2014 declare it with \`defineContentSystem\` from '@elevasis/core/organization-model', which derives the readinessContract, content:object/item, and status catalog from your pipelines, item voice, and status vocabulary.`;
50005
50102
  } else {
50006
- apiInterfaceNote = `System \`${opts.id}\` is not on a cataloged readiness profile (only sales.lead-gen and sales.crm ship built-in profiles today). \`apiInterface\` was NOT added. Declare it manually once real resourceIds exist for this system, using either a cataloged profile or a custom \`readinessProfile\` paired with a \`readinessContract\`.`;
50103
+ const adoptable = SYSTEM_INTERFACE_PROFILES.filter((profile) => profile.interfaceKey === "api").map((profile) => `"${profile.systemPath}"`).join(", ");
50104
+ apiInterfaceNote = `System \`${opts.id}\` is not on a cataloged readiness profile (adoptable system paths today: ${adoptable}). \`apiInterface\` was NOT added. A custom System extends behavior through workflows/operations plus ontology, resources, and topology \u2014 omitting apiInterface entirely is the designed opt-out.`;
50007
50105
  }
50008
50106
  }
50009
50107
  const code = ` {
@@ -50019,7 +50117,8 @@ function emitSystemEntry(opts) {
50019
50117
  `;
50020
50118
  const startAnchor = /^(?!\s*(?:\/\/|\*|\/\*)).*\bexport const templateSystems\s*=/m;
50021
50119
  const anchor = /^\] as const\s*$/m;
50022
- return { code, startAnchor, anchor, apiInterfaceNote };
50120
+ const importAnchor = /^\/\/ -{75,}\n\/\/ Feature/m;
50121
+ return { code, startAnchor, anchor, apiInterfaceNote, importLine, importAnchor };
50023
50122
  }
50024
50123
  var init_emit_system = __esm({
50025
50124
  "src/cli/commands/om/emit-system.ts"() {
@@ -50186,10 +50285,20 @@ async function scaffoldSystem(opts) {
50186
50285
  });
50187
50286
  apiBacked = answer.trim().toLowerCase() === "y";
50188
50287
  }
50189
- const { code, anchor, startAnchor, apiInterfaceNote } = emitSystemEntry({ id, title, kind, apiBacked });
50288
+ const { code, anchor, startAnchor, apiInterfaceNote, importLine, importAnchor } = emitSystemEntry({
50289
+ id,
50290
+ title,
50291
+ kind,
50292
+ apiBacked,
50293
+ resourceIds: options.resourceIds
50294
+ });
50190
50295
  const shouldWrite = options.write === true || options.dryRun === false;
50191
50296
  if (!shouldWrite) {
50192
50297
  console.log(source_default.cyan("Dry-run mode (default) \u2014 no files written. Pass --write to apply.\n"));
50298
+ if (importLine !== void 0) {
50299
+ console.log(source_default.gray("Import line to add near the top of core/config/organization-model/systems.ts:"));
50300
+ console.log(importLine);
50301
+ }
50193
50302
  console.log(source_default.gray("Proposed addition to core/config/organization-model/systems.ts:"));
50194
50303
  console.log(code);
50195
50304
  if (apiInterfaceNote !== void 0) {
@@ -50200,6 +50309,9 @@ async function scaffoldSystem(opts) {
50200
50309
  const systemsFilePath = (0, import_node_path13.join)(getOrganizationModelDir(projectDir), "systems.ts");
50201
50310
  try {
50202
50311
  await withSnapshotRollback([systemsFilePath], async () => {
50312
+ if (importLine !== void 0) {
50313
+ await appendBeforeAnchor(systemsFilePath, importLine + "\n", importAnchor);
50314
+ }
50203
50315
  await appendBeforeAnchor(systemsFilePath, code, anchor, startAnchor);
50204
50316
  const validationError = runValidation(projectDir);
50205
50317
  if (validationError !== null) {
@@ -50646,6 +50758,14 @@ var init_scaffold_knowledge = __esm({
50646
50758
  function toConstName(systemPath) {
50647
50759
  return systemPath.split(/[.-]/).map((segment, index) => index === 0 ? segment : segment.charAt(0).toUpperCase() + segment.slice(1)).join("") + "ApiInterface";
50648
50760
  }
50761
+ function buildContentPlaceholderReadinessContract(systemPath) {
50762
+ return {
50763
+ requiredObjects: [`${systemPath}:object/item`],
50764
+ requiredCatalogs: [
50765
+ "TODO -- replace with this System real pipeline, step, and status catalog ids (see defineContentPipeline and defineContentSystem in the organization-model subpath)"
50766
+ ]
50767
+ };
50768
+ }
50649
50769
  function emitApiInterfaceBlock(gap) {
50650
50770
  const constName = toConstName(gap.systemPath);
50651
50771
  const cataloged = SYSTEM_INTERFACE_PROFILES.find(
@@ -50658,17 +50778,44 @@ function emitApiInterfaceBlock(gap) {
50658
50778
  );
50659
50779
  }
50660
50780
  const readinessProfile = cataloged.readinessProfile;
50661
- const resourceIdsField = gap.resourceIds.length === 0 ? "" : `,
50662
- resourceIds: [
50663
- ${gap.resourceIds.map((id) => `'${id}'`).join(",\n ")}
50664
- ]`;
50781
+ if (gap.resourceIds.length === 0) {
50782
+ throw new Error(
50783
+ `Cannot emit an apiInterface for system path "${gap.systemPath}": the gap carries no resourceIds. defineSystemApiInterface requires at least one scoped resource id \u2014 an interface with none computes as ready and answers every route with a 503. Re-run this scaffolder once the system has at least one API-backed resource declared.`
50784
+ );
50785
+ }
50786
+ const resourceIds = gap.resourceIds;
50787
+ const isContractValidated = cataloged.validation === "contract";
50788
+ const readinessContract = isContractValidated ? buildContentPlaceholderReadinessContract(gap.systemPath) : void 0;
50789
+ defineSystemApiInterface({
50790
+ systemPath: gap.systemPath,
50791
+ readinessProfile,
50792
+ resourceIds,
50793
+ ...readinessContract !== void 0 ? { readinessContract } : {}
50794
+ });
50795
+ const resourceIdsLines = resourceIds.map((id) => ` '${id}'`).join(",\n");
50796
+ const readinessContractField = readinessContract === void 0 ? "" : `,
50797
+ // TODO: requiredCatalogs below is a placeholder. Replace it with this System's actual pipeline,
50798
+ // step, and status catalog ids before deploying \u2014 see extend-content.md in the SDK scaffold docs.
50799
+ readinessContract: {
50800
+ requiredObjects: [
50801
+ ${readinessContract.requiredObjects.map((id) => `'${id}'`).join(",\n ")}
50802
+ ],
50803
+ requiredCatalogs: [
50804
+ ${readinessContract.requiredCatalogs.map((id) => `'${id}'`).join(",\n ")}
50805
+ ]
50806
+ }`;
50665
50807
  const constFileCode = `// Auto-generated by om:scaffold:fill \u2014 do not edit manually.
50666
50808
  // Regenerate by running: elevasis-sdk om:scaffold:fill --gaps <path>
50667
50809
 
50668
- export const ${constName} = {
50669
- lifecycle: 'active' as const,
50670
- readinessProfile: '${readinessProfile}'${resourceIdsField}
50671
- }
50810
+ import { defineSystemApiInterface } from '@elevasis/core/organization-model'
50811
+
50812
+ export const ${constName} = defineSystemApiInterface({
50813
+ systemPath: '${gap.systemPath}',
50814
+ readinessProfile: '${readinessProfile}',
50815
+ resourceIds: [
50816
+ ${resourceIdsLines}
50817
+ ]${readinessContractField}
50818
+ })
50672
50819
  `;
50673
50820
  const importLine = `import { ${constName} } from './api-interfaces/${gap.systemPath}'`;
50674
50821
  const fieldLine = ` apiInterface: ${constName},`;
@@ -50769,11 +50916,21 @@ async function scaffoldFill(opts) {
50769
50916
  gap.resourceIds
50770
50917
  ) : gap.resourceId ? [gap.resourceId] : []
50771
50918
  );
50772
- const emitResult = emitApiInterfaceBlock({
50773
- systemPath,
50774
- resourceIds,
50775
- message: gap.reason
50776
- });
50919
+ let emitResult;
50920
+ try {
50921
+ emitResult = emitApiInterfaceBlock({
50922
+ systemPath,
50923
+ resourceIds,
50924
+ message: gap.reason
50925
+ });
50926
+ } catch (err) {
50927
+ skippedGaps.push({
50928
+ field: gap.field,
50929
+ resourceId: gap.resourceId,
50930
+ reason: err instanceof Error ? err.message : String(err)
50931
+ });
50932
+ continue;
50933
+ }
50777
50934
  const constFilePath = (0, import_node_path17.join)(getOrganizationModelDir(projectDir), "api-interfaces", `${systemPath}.ts`);
50778
50935
  touchedFiles.push(constFilePath);
50779
50936
  emitResults.push(emitResult);
@@ -51865,9 +52022,10 @@ Credentials (${data.credentials.length}):
51865
52022
  // src/cli/commands/creds/creds-create.ts
51866
52023
  init_source();
51867
52024
  init_ora();
52025
+ init_src();
51868
52026
  init_api_client();
51869
52027
  var CREDENTIAL_NAME_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
51870
- var VALID_TYPES = ["api-key", "webhook-secret"];
52028
+ var VALID_TYPES = CredentialTypeSchema.options.filter((type) => type !== "oauth");
51871
52029
  async function createCreds(apiUrl, name, type, valueJson) {
51872
52030
  if (!name || name.length < 1 || name.length > 100) {
51873
52031
  throw new Error("Credential name must be 1-100 characters");
@@ -51887,6 +52045,8 @@ Note: OAuth credentials must be created through the Command Center UI`
51887
52045
  if (!valueJson) {
51888
52046
  throw new Error(
51889
52047
  `Credential value is required. Provide it with --value '{"apiKey":"sk-..."}'
52048
+ For a secret you do not want in shell history, write it to a file and pass
52049
+ --value @json:tmp/credential.json instead.
51890
52050
  Value must be a valid JSON object.`
51891
52051
  );
51892
52052
  }
@@ -51906,11 +52066,7 @@ Example: --value '{"apiKey":"sk-abc123"}'`
51906
52066
  throw new Error("Credential value must not be empty");
51907
52067
  }
51908
52068
  const spinner = ora("Creating credential...").start();
51909
- const result = await apiPost(
51910
- "/api/external/credentials",
51911
- { name, type, value },
51912
- apiUrl
51913
- );
52069
+ const result = await apiPost("/api/external/credentials", { name, type, value }, apiUrl);
51914
52070
  spinner.stop();
51915
52071
  console.log(source_default.green(`
51916
52072
  Credential created successfully!`));
@@ -51944,10 +52100,8 @@ Example: --value '{"apiKey":"sk-new-key"}'`
51944
52100
  const credential = data.credentials.find((c) => c.name === name);
51945
52101
  if (!credential) {
51946
52102
  spinner.stop();
51947
- throw new Error(
51948
- `Credential '${name}' not found.
51949
- Run "elevasis-sdk creds list" to see available credentials.`
51950
- );
52103
+ throw new Error(`Credential '${name}' not found.
52104
+ Run "elevasis-sdk creds list" to see available credentials.`);
51951
52105
  }
51952
52106
  await apiPatch(`/api/external/credentials/${credential.id}`, { value }, apiUrl);
51953
52107
  spinner.stop();
@@ -52042,21 +52196,31 @@ Credential '${name}' deleted successfully.`));
52042
52196
  // src/cli/commands/creds/creds.ts
52043
52197
  function registerCredsCommand(program3) {
52044
52198
  const creds = program3.command("creds").description("Manage organization credentials");
52045
- creds.command("list").description("List all credentials (metadata only, no secrets)").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").option("--json", "Output as JSON").action(wrapAction("creds list", async (options) => {
52046
- await listCreds(resolveApiUrl(options.apiUrl, options.prod), options.json);
52047
- }));
52048
- creds.command("create").description("Create a new credential").requiredOption("--name <name>", "Credential name (lowercase, digits, hyphens)").requiredOption("--type <type>", "Credential type (api-key, webhook-secret)").option("--value <json>", "Credential value as JSON string").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").action(wrapAction("creds create", async (options) => {
52049
- await createCreds(resolveApiUrl(options.apiUrl, options.prod), options.name, options.type, options.value);
52050
- }));
52051
- creds.command("update <name>").description("Update a credential value").requiredOption("--value <json>", "New credential value as JSON string").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").action(wrapAction("creds update", async (name, options) => {
52052
- await updateCreds(resolveApiUrl(options.apiUrl, options.prod), name, options.value);
52053
- }));
52054
- creds.command("rename <name>").description("Rename a credential").requiredOption("--to <newName>", "New credential name").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").action(wrapAction("creds rename", async (name, options) => {
52055
- await renameCreds(resolveApiUrl(options.apiUrl, options.prod), name, options.to);
52056
- }));
52057
- creds.command("delete <name>").description("Delete a credential").option("--force", "Skip confirmation prompt").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").action(wrapAction("creds delete", async (name, options) => {
52058
- await deleteCreds(resolveApiUrl(options.apiUrl, options.prod), name, options.force);
52059
- }));
52199
+ creds.command("list").description("List all credentials (metadata only, no secrets)").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").option("--json", "Output as JSON").action(
52200
+ wrapAction("creds list", async (options) => {
52201
+ await listCreds(resolveApiUrl(options.apiUrl, options.prod), options.json);
52202
+ })
52203
+ );
52204
+ creds.command("create").description("Create a new credential").requiredOption("--name <name>", "Credential name (lowercase, digits, hyphens)").requiredOption("--type <type>", "Credential type (api-key, webhook-secret, api-key-secret, clickup, instagram)").option("--value <json>", "Credential value as JSON string (or @json:<path> to read it from a file)").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").action(
52205
+ wrapAction("creds create", async (options) => {
52206
+ await createCreds(resolveApiUrl(options.apiUrl, options.prod), options.name, options.type, options.value);
52207
+ })
52208
+ );
52209
+ creds.command("update <name>").description("Update a credential value").requiredOption("--value <json>", "New credential value as JSON string (or @json:<path> to read it from a file)").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").action(
52210
+ wrapAction("creds update", async (name, options) => {
52211
+ await updateCreds(resolveApiUrl(options.apiUrl, options.prod), name, options.value);
52212
+ })
52213
+ );
52214
+ creds.command("rename <name>").description("Rename a credential").requiredOption("--to <newName>", "New credential name").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").action(
52215
+ wrapAction("creds rename", async (name, options) => {
52216
+ await renameCreds(resolveApiUrl(options.apiUrl, options.prod), name, options.to);
52217
+ })
52218
+ );
52219
+ creds.command("delete <name>").description("Delete a credential").option("--force", "Skip confirmation prompt").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").action(
52220
+ wrapAction("creds delete", async (name, options) => {
52221
+ await deleteCreds(resolveApiUrl(options.apiUrl, options.prod), name, options.force);
52222
+ })
52223
+ );
52060
52224
  }
52061
52225
 
52062
52226
  // src/cli/commands/error/error.ts
@@ -56433,7 +56597,7 @@ function appendQuery4(params, key, value) {
56433
56597
  }
56434
56598
  function registerContentList(program3) {
56435
56599
  program3.command("content:list").description(
56436
- "List content pipeline items\n Example: elevasis-sdk content:list --status queued --pipeline-id short-form-repurpose"
56600
+ 'List content pipeline items\n Example: elevasis-sdk content:list --status <status> --pipeline-id <pipelineId>\n Note: both values come from the org model this project declares, not a platform enum --\n read them from the content:catalog/status catalog and content:pipeline.\n Note: "awaiting review" is not a status -- that read is content:queue.'
56437
56601
  ).option("--status <status>", "Filter by content item status").option("--pillar <pillar>", "Filter by content pillar").option("--pipeline-id <id>", "Filter by pipeline template id").option("--client-id <id>", "Filter by client id").option("--reviewed-by <id>", "Filter by reviewer user id").option("--search <query>", "Search by title").option("--limit <n>", "Maximum number of results").option("--offset <n>", "Pagination offset").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
56438
56602
  wrapAction("content:list", async (options) => {
56439
56603
  const apiUrl = resolveApiUrl(options.apiUrl, options.prod);
@@ -56671,7 +56835,7 @@ function printCards(cards, stepsByKey) {
56671
56835
  }
56672
56836
  function registerContentBoard(program3) {
56673
56837
  program3.command("content:board <pipelineId>").description(
56674
- "Render one pipeline as a board -- columns, review gates, and waiting counts\n Example: elevasis-sdk content:board short-form-repurpose --pretty"
56838
+ "Render one pipeline as a board -- columns, review gates, and waiting counts\n Example: elevasis-sdk content:board <pipelineId> --pretty\n Note: pipeline ids come from the org model this project declares -- list them with content:pipeline."
56675
56839
  ).option("--limit <n>", `Items to pull before deriving (default and API maximum ${DEFAULT_ITEM_LIMIT})`).option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
56676
56840
  wrapAction("content:board", async (pipelineId, options) => {
56677
56841
  const apiUrl = resolveApiUrl(options.apiUrl, options.prod);
@@ -56772,7 +56936,7 @@ Pipeline: ${pipeline.id}`));
56772
56936
  }
56773
56937
  function registerContentPipeline(program3) {
56774
56938
  program3.command("content:pipeline [id]").description(
56775
- "List content pipeline templates, or show one pipeline's step contract\n Example: elevasis-sdk content:pipeline short-form-repurpose"
56939
+ "List content pipeline templates, or show one pipeline's step contract\n Example: elevasis-sdk content:pipeline <pipelineId>\n Note: run without an id to list the pipeline ids this project declares in its org model."
56776
56940
  ).option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
56777
56941
  wrapAction("content:pipeline", async (id, options) => {
56778
56942
  const apiUrl = resolveApiUrl(options.apiUrl, options.prod);
@@ -56817,7 +56981,7 @@ function appendQuery5(params, key, value) {
56817
56981
  }
56818
56982
  function registerContentDistributions(program3) {
56819
56983
  program3.command("content:distributions").description(
56820
- "List content distributions\n Example: elevasis-sdk content:distributions --pipeline-id short-form-repurpose"
56984
+ "List content distributions\n Example: elevasis-sdk content:distributions --pipeline-id <pipelineId>\n Note: pipeline ids come from the org model this project declares -- list them with content:pipeline."
56821
56985
  ).option("--content-item-id <id>", "Filter by content item id").option("--pipeline-id <id>", "Filter by pipeline template id").option("--platform <platform>", "Filter by distribution platform").option("--status <status>", "Filter by distribution status").option("--limit <n>", "Maximum number of results").option("--offset <n>", "Pagination offset").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
56822
56986
  wrapAction("content:distributions", async (options) => {
56823
56987
  const apiUrl = resolveApiUrl(options.apiUrl, options.prod);