@wairon/cli 5.0.2-dev.6 → 5.0.2-dev.8

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.js CHANGED
@@ -393,7 +393,7 @@ var init_template = __esm({
393
393
  });
394
394
 
395
395
  // src/models/specs.ts
396
- var import_zod6, SpecIdSchema, SpecStatusSchema, BoundaryItemSchema, RequirementItemSchema, DatabaseSpecSchema, DiagramConfigSchema, SURFACE_AUDIENCES, SurfaceAudienceSchema, SystemPublicInterfaceSchema, SystemSpecSchema, PublicInterfaceTypeSchema, PublicInterfaceSchema, TrustedLinkSchema, LintAllowSchema, LintConfigSchema, ExtDataSchema, LifecycleEntrypointSchema, SubsystemSpecSchema, ComponentTypeSchema, PATTERN_TYPES, PortalTypeSchema, DispatchBindingSchema, DurabilitySchema, PatternRefSchema, EventBindingSchema, ComponentSpecSchema, HttpMethodSchema, TransportSchema, EndpointSchema, SEMANTIC_GUARANTEES, GuaranteeSchema, MethodParamSchema, MethodSignatureSchema, InterfaceSpecSchema, NarrativeStepTypeSchema, LoopKindSchema, SwitchCaseSchema, CatchClauseSchema, ParallelBranchSchema, NarrativeStepSchema, NarrativeDetailSchema, ConformanceTierSchema, MethodImplementationSchema, ImplementationSpecSchema, TypeKindSchema, TypeFieldSchema, TypeMethodSchema, InvariantSchema, TypeSpecSchema, SurfaceOriginSchema, SurfaceTypeDefSchema, SurfaceContractEntrySchema, SurfaceSnapshotSchema, GroupSpecSchema;
396
+ var import_zod6, SpecIdSchema, SpecStatusSchema, BoundaryItemSchema, RequirementItemSchema, DatabaseSpecSchema, DiagramConfigSchema, SURFACE_AUDIENCES, SurfaceAudienceSchema, SystemPublicInterfaceSchema, SystemSpecSchema, PublicInterfaceTypeSchema, PublicInterfaceSchema, TrustedLinkSchema, LintAllowSchema, LintConfigSchema, ExtDataSchema, LifecycleEntrypointSchema, SubsystemSpecSchema, ComponentTypeSchema, PATTERN_TYPES, PortalTypeSchema, DispatchBindingSchema, DurabilitySchema, PatternRefSchema, EventBindingSchema, ExternalLinkTypeSchema, ExternalLinkSchema, PortalAuthSchemeSchema, PortalAuthSchema, ComponentSpecSchema, HttpMethodSchema, TransportSchema, EndpointSchema, SEMANTIC_GUARANTEES, GuaranteeSchema, MethodParamSchema, MethodSignatureSchema, InterfaceSpecSchema, NarrativeStepTypeSchema, LoopKindSchema, SwitchCaseSchema, CatchClauseSchema, ParallelBranchSchema, NarrativeStepSchema, NarrativeDetailSchema, ConformanceTierSchema, MethodImplementationSchema, ImplementationSpecSchema, TypeKindSchema, TypeFieldSchema, TypeMethodSchema, InvariantSchema, TypeSpecSchema, SurfaceOriginSchema, SurfaceTypeDefSchema, SurfaceContractEntrySchema, SurfaceSnapshotSchema, NamedOpenApiSpecSchema, GroupSpecSchema;
397
397
  var init_specs = __esm({
398
398
  "src/models/specs.ts"() {
399
399
  "use strict";
@@ -597,6 +597,28 @@ var init_specs = __esm({
597
597
  event: import_zod6.z.string().optional(),
598
598
  description: import_zod6.z.string().optional()
599
599
  });
600
+ ExternalLinkTypeSchema = import_zod6.z.enum(["implementation", "informative"]);
601
+ ExternalLinkSchema = import_zod6.z.object({
602
+ url: import_zod6.z.string(),
603
+ /** Defaults to 'informative' so an untyped link never silently satisfies the source requirement. */
604
+ type: ExternalLinkTypeSchema.default("informative"),
605
+ label: import_zod6.z.string().optional()
606
+ });
607
+ PortalAuthSchemeSchema = import_zod6.z.enum(["none", "apiKey", "bearer", "basic", "oauth2", "openIdConnect", "custom"]);
608
+ PortalAuthSchema = import_zod6.z.object({
609
+ scheme: PortalAuthSchemeSchema,
610
+ in: import_zod6.z.enum(["header", "query", "cookie"]).optional(),
611
+ name: import_zod6.z.string().optional(),
612
+ bearerFormat: import_zod6.z.string().optional(),
613
+ authorizationUrl: import_zod6.z.string().optional(),
614
+ tokenUrl: import_zod6.z.string().optional(),
615
+ refreshUrl: import_zod6.z.string().optional(),
616
+ scopes: import_zod6.z.array(import_zod6.z.object({ name: import_zod6.z.string(), description: import_zod6.z.string() })).optional(),
617
+ flow: import_zod6.z.enum(["authorizationCode", "clientCredentials", "implicit", "password"]).optional(),
618
+ openIdConnectUrl: import_zod6.z.string().optional(),
619
+ description: import_zod6.z.string().optional(),
620
+ example: import_zod6.z.string().optional()
621
+ });
600
622
  ComponentSpecSchema = import_zod6.z.object({
601
623
  id: SpecIdSchema,
602
624
  name: import_zod6.z.string(),
@@ -610,6 +632,10 @@ var init_specs = __esm({
610
632
  dependsOn: import_zod6.z.array(import_zod6.z.string()).default([]),
611
633
  portalType: PortalTypeSchema.optional(),
612
634
  basePath: import_zod6.z.string().optional(),
635
+ /** Portal-only: the API's authentication scheme (see PortalAuthSchema) — projected
636
+ * into the generated OpenAPI's securitySchemes/security. Portals with different auth
637
+ * must be separate components (one auth per portal ⇒ one OpenAPI spec per portal). */
638
+ auth: PortalAuthSchema.optional(),
613
639
  /** Portal-only: capability → component.method dispatch table (see DispatchBindingSchema). */
614
640
  dispatch: import_zod6.z.array(DispatchBindingSchema).optional(),
615
641
  /** Store-only: whether held state survives restart (see DurabilitySchema). */
@@ -622,6 +648,11 @@ var init_specs = __esm({
622
648
  patterns: import_zod6.z.array(PatternRefSchema).optional(),
623
649
  /** Optional component variant — a declared, base-anchored specialization of this component's stereotype (resolved against the variant registry; UNKNOWN_VARIANT / VARIANT_BASE_MISMATCH). */
624
650
  variant: import_zod6.z.string().optional(),
651
+ /** Opaque external references (see ExternalLinkSchema) — documented URLs wairon does
652
+ * not fetch or validate. An `implementation` link is the external source-of-record and
653
+ * satisfies the source requirement for a source-less implementation (suppresses
654
+ * MISSING_SOURCE_PATH); `informative` links are context only. */
655
+ externalLinks: import_zod6.z.array(ExternalLinkSchema).optional(),
625
656
  /** Per-spec lint suppressions (see LintConfigSchema). */
626
657
  lint: LintConfigSchema.optional(),
627
658
  /** Opaque pack/tool extension data (see ExtDataSchema) — preserved verbatim. */
@@ -970,7 +1001,12 @@ var init_specs = __esm({
970
1001
  dispatch: import_zod6.z.array(DispatchBindingSchema).optional(),
971
1002
  details: import_zod6.z.string().default(""),
972
1003
  version: import_zod6.z.string().optional(),
973
- stability: import_zod6.z.string().optional()
1004
+ stability: import_zod6.z.string().optional(),
1005
+ /** Projected copy of the backing Portal's auth (see PortalAuthSchema) — the codec
1006
+ * emits it as OpenAPI securitySchemes/security. */
1007
+ auth: PortalAuthSchema.optional(),
1008
+ /** The backing Portal's basePath — becomes the per-portal OpenAPI `servers` url. */
1009
+ basePath: import_zod6.z.string().optional()
974
1010
  });
975
1011
  SurfaceSnapshotSchema = import_zod6.z.object({
976
1012
  /** Producing project/system name — the snapshot's resolution identity. */
@@ -985,6 +1021,11 @@ var init_specs = __esm({
985
1021
  /** Transitive type closure of every exported signature — self-contained. */
986
1022
  types: import_zod6.z.array(SurfaceTypeDefSchema).default([])
987
1023
  });
1024
+ NamedOpenApiSpecSchema = import_zod6.z.object({
1025
+ portalId: import_zod6.z.string(),
1026
+ name: import_zod6.z.string(),
1027
+ document: import_zod6.z.string()
1028
+ });
988
1029
  GroupSpecSchema = import_zod6.z.object({
989
1030
  kind: import_zod6.z.literal("group"),
990
1031
  id: SpecIdSchema,
@@ -1998,6 +2039,7 @@ function buildCanvasModel(issues = []) {
1998
2039
  ...ownerOf.has(comp.id) ? { owner: ownerOf.get(comp.id) } : {},
1999
2040
  owns: comp.owns.filter((o) => componentIds.has(o)),
2000
2041
  dependsOn: comp.dependsOn,
2042
+ ...comp.externalLinks && comp.externalLinks.length ? { externalLinks: comp.externalLinks } : {},
2001
2043
  interfaces: compInterfaces.map((i) => ({
2002
2044
  id: i.id,
2003
2045
  name: i.name,
@@ -5448,7 +5490,7 @@ var MODEL = __MODEL_JSON__;
5448
5490
  + (scopeFocus ? staticChip('current view') : '')
5449
5491
  + chip(c.subsystem, 'subsystem', c.subsystem)
5450
5492
  + (scopeFocus ? '' : openViewButton('component', c.id, c.owns.length > 0))
5451
- + openApiButton(componentExposesApi(c), c.apiTag)
5493
+ + openApiButton(componentExposesApi(c), c.id)
5452
5494
  + openSpecButton('component', c.id);
5453
5495
 
5454
5496
  var linkedTypes = MODEL.types.filter(function (t) { return t.componentClass === c.id; });
@@ -5459,6 +5501,14 @@ var MODEL = __MODEL_JSON__;
5459
5501
  }
5460
5502
  body += '<p class="desc">' + esc(c.description) + '</p>';
5461
5503
 
5504
+ if (c.externalLinks && c.externalLinks.length) {
5505
+ body += section('External links', c.externalLinks.length, c.externalLinks.map(function (l) {
5506
+ var label = l.label || l.url;
5507
+ var tag = l.type === 'implementation' ? staticChip('source') : '';
5508
+ return '<div class="method">' + tag + '<a href="' + esc(l.url) + '" target="_blank" rel="noopener" style="color:var(--accent);word-break:break-all">' + esc(label) + ' \\u2197</a></div>';
5509
+ }).join(''), true);
5510
+ }
5511
+
5462
5512
  var depInner = (c.dependsOn.length ? c.dependsOn.map(function (d) { return chip(d, 'component', d); }).join('') : '<span class="desc">none</span>')
5463
5513
  + (c.owns.length ? '<div style="margin-top:8px"><b style="font-size:11px">Owns:</b><br>' + c.owns.map(function (d) { return chip(d, 'component', d); }).join('') + '</div>' : '');
5464
5514
  body += section('Dependencies', c.dependsOn.length + c.owns.length, depInner, true);
@@ -6248,11 +6298,63 @@ function operationFor(method, closureIds) {
6248
6298
  }
6249
6299
  return op;
6250
6300
  }
6251
- function toOpenApi(snapshot) {
6252
- const closureIds = new Set(snapshot.types.map((t) => t.id));
6253
- const httpEntries = snapshot.interfaces.filter((e) => e.type === "REST" || e.methods.some((m) => m.endpoint?.transport === "HTTP"));
6301
+ function securitySchemeObject(auth) {
6302
+ if (auth.scheme === "none") return null;
6303
+ const desc = auth.description ? { description: auth.description } : {};
6304
+ switch (auth.scheme) {
6305
+ case "apiKey":
6306
+ return { type: "apiKey", in: auth.in ?? "header", name: auth.name ?? "X-API-Key", ...desc };
6307
+ case "bearer":
6308
+ return { type: "http", scheme: "bearer", ...auth.bearerFormat ? { bearerFormat: auth.bearerFormat } : {}, ...desc };
6309
+ case "basic":
6310
+ return { type: "http", scheme: "basic", ...desc };
6311
+ case "oauth2": {
6312
+ const flow = { scopes: Object.fromEntries((auth.scopes ?? []).map((s) => [s.name, s.description])) };
6313
+ if (auth.authorizationUrl) flow.authorizationUrl = auth.authorizationUrl;
6314
+ if (auth.tokenUrl) flow.tokenUrl = auth.tokenUrl;
6315
+ if (auth.refreshUrl) flow.refreshUrl = auth.refreshUrl;
6316
+ return { type: "oauth2", flows: { [auth.flow ?? "authorizationCode"]: flow }, ...desc };
6317
+ }
6318
+ case "openIdConnect":
6319
+ return { type: "openIdConnect", openIdConnectUrl: auth.openIdConnectUrl ?? "", ...desc };
6320
+ case "custom":
6321
+ return { type: "apiKey", in: auth.in ?? "header", name: auth.name ?? "Authorization", description: auth.description ?? auth.example ?? "Custom authentication scheme." };
6322
+ default:
6323
+ return null;
6324
+ }
6325
+ }
6326
+ function schemeBaseName(scheme) {
6327
+ return { apiKey: "ApiKeyAuth", bearer: "BearerAuth", basic: "BasicAuth", oauth2: "OAuth2", openIdConnect: "OpenIdConnect", custom: "CustomAuth" }[scheme] ?? "Auth";
6328
+ }
6329
+ function buildSecurity(entries) {
6330
+ const schemes = {};
6331
+ const nameByContent = /* @__PURE__ */ new Map();
6332
+ const securityByEntry = /* @__PURE__ */ new Map();
6333
+ for (const entry of entries) {
6334
+ if (!entry.auth) continue;
6335
+ const obj = securitySchemeObject(entry.auth);
6336
+ if (!obj) continue;
6337
+ const content = JSON.stringify(obj);
6338
+ let name = nameByContent.get(content);
6339
+ if (!name) {
6340
+ name = schemeBaseName(entry.auth.scheme);
6341
+ for (let n = 2; schemes[name]; n++) name = schemeBaseName(entry.auth.scheme) + n;
6342
+ schemes[name] = obj;
6343
+ nameByContent.set(content, name);
6344
+ }
6345
+ const scopeNames = entry.auth.scheme === "oauth2" ? (entry.auth.scopes ?? []).map((s) => s.name) : [];
6346
+ securityByEntry.set(entry.id, { [name]: scopeNames });
6347
+ }
6348
+ return { schemes, securityByEntry };
6349
+ }
6350
+ function httpEntriesOf(snapshot) {
6351
+ return snapshot.interfaces.filter((e) => e.type === "REST" || e.methods.some((m) => m.endpoint?.transport === "HTTP"));
6352
+ }
6353
+ function renderDoc(snapshot, entries, closureIds, opts = {}) {
6354
+ const { schemes, securityByEntry } = buildSecurity(entries);
6254
6355
  const paths = {};
6255
- for (const entry of httpEntries) {
6356
+ for (const entry of entries) {
6357
+ const security = securityByEntry.get(entry.id);
6256
6358
  for (const method of entry.methods) {
6257
6359
  const endpoint = method.endpoint;
6258
6360
  if (!endpoint || endpoint.transport !== "HTTP") continue;
@@ -6260,7 +6362,8 @@ function toOpenApi(snapshot) {
6260
6362
  paths[p] = paths[p] ?? {};
6261
6363
  paths[p][endpoint.method.toLowerCase()] = {
6262
6364
  tags: [entry.id],
6263
- ...operationFor(method, closureIds)
6365
+ ...operationFor(method, closureIds),
6366
+ ...security ? { security: [security] } : {}
6264
6367
  };
6265
6368
  }
6266
6369
  }
@@ -6273,19 +6376,45 @@ function toOpenApi(snapshot) {
6273
6376
  required: t.fields.filter((f) => !f.optional).map((f) => f.name)
6274
6377
  };
6275
6378
  }
6276
- const doc = {
6379
+ const components = {};
6380
+ if (Object.keys(schemas).length) components.schemas = schemas;
6381
+ if (Object.keys(schemes).length) components.securitySchemes = schemes;
6382
+ const basePaths = [...new Set(entries.map((e) => e.basePath).filter((b) => !!b))];
6383
+ const servers = opts.servers && basePaths.length === 1 ? [{ url: basePaths[0] }] : void 0;
6384
+ return {
6277
6385
  openapi: "3.1.0",
6278
6386
  info: {
6279
- title: snapshot.projectName,
6387
+ title: opts.title ?? snapshot.projectName,
6280
6388
  version: snapshot.version ?? "0.0.0",
6281
6389
  ...snapshot.stateId ? { "x-wairon-state-id": snapshot.stateId } : {},
6282
6390
  "x-wairon-origin": snapshot.origin,
6283
6391
  "x-wairon-generated-at": snapshot.generatedAt
6284
6392
  },
6393
+ ...servers ? { servers } : {},
6285
6394
  paths,
6286
- ...Object.keys(schemas).length ? { components: { schemas } } : {}
6395
+ ...Object.keys(components).length ? { components } : {}
6287
6396
  };
6288
- return JSON.stringify(doc, null, 2);
6397
+ }
6398
+ function toOpenApi(snapshot) {
6399
+ const closureIds = new Set(snapshot.types.map((t) => t.id));
6400
+ return JSON.stringify(renderDoc(snapshot, httpEntriesOf(snapshot), closureIds), null, 2);
6401
+ }
6402
+ function toOpenApiSet(snapshot) {
6403
+ const closureIds = new Set(snapshot.types.map((t) => t.id));
6404
+ const byPortal = /* @__PURE__ */ new Map();
6405
+ const order = [];
6406
+ for (const entry of httpEntriesOf(snapshot)) {
6407
+ if (!byPortal.has(entry.component)) {
6408
+ byPortal.set(entry.component, []);
6409
+ order.push(entry.component);
6410
+ }
6411
+ byPortal.get(entry.component).push(entry);
6412
+ }
6413
+ return order.map((portalId) => {
6414
+ const entries = byPortal.get(portalId);
6415
+ const name = entries[0]?.name ?? portalId;
6416
+ return { portalId, name, document: JSON.stringify(renderDoc(snapshot, entries, closureIds, { title: name, servers: true }), null, 2) };
6417
+ });
6289
6418
  }
6290
6419
  function isOpenApiDocument(body) {
6291
6420
  try {
@@ -6307,6 +6436,39 @@ function typeRefFromSchema(schema) {
6307
6436
  if (typeof t === "string" && t !== "object") return t;
6308
6437
  return "json";
6309
6438
  }
6439
+ function authFromSecurityScheme(scheme) {
6440
+ const desc = typeof scheme.description === "string" ? { description: scheme.description } : {};
6441
+ if (scheme.type === "apiKey") {
6442
+ return {
6443
+ scheme: "apiKey",
6444
+ ...scheme.in === "header" || scheme.in === "query" || scheme.in === "cookie" ? { in: scheme.in } : {},
6445
+ ...typeof scheme.name === "string" ? { name: scheme.name } : {},
6446
+ ...desc
6447
+ };
6448
+ }
6449
+ if (scheme.type === "http") {
6450
+ if (scheme.scheme === "bearer") return { scheme: "bearer", ...typeof scheme.bearerFormat === "string" ? { bearerFormat: scheme.bearerFormat } : {}, ...desc };
6451
+ if (scheme.scheme === "basic") return { scheme: "basic", ...desc };
6452
+ }
6453
+ if (scheme.type === "oauth2") {
6454
+ const flows = scheme.flows ?? {};
6455
+ const flowKey = Object.keys(flows)[0];
6456
+ const f = flows[flowKey] ?? {};
6457
+ return {
6458
+ scheme: "oauth2",
6459
+ ...flowKey === "authorizationCode" || flowKey === "clientCredentials" || flowKey === "implicit" || flowKey === "password" ? { flow: flowKey } : {},
6460
+ ...typeof f.authorizationUrl === "string" ? { authorizationUrl: f.authorizationUrl } : {},
6461
+ ...typeof f.tokenUrl === "string" ? { tokenUrl: f.tokenUrl } : {},
6462
+ ...typeof f.refreshUrl === "string" ? { refreshUrl: f.refreshUrl } : {},
6463
+ scopes: Object.entries(f.scopes ?? {}).map(([name, description]) => ({ name, description })),
6464
+ ...desc
6465
+ };
6466
+ }
6467
+ if (scheme.type === "openIdConnect") {
6468
+ return { scheme: "openIdConnect", openIdConnectUrl: typeof scheme.openIdConnectUrl === "string" ? scheme.openIdConnectUrl : "", ...desc };
6469
+ }
6470
+ return void 0;
6471
+ }
6310
6472
  function fromOpenApi(document, projectName) {
6311
6473
  let parsed;
6312
6474
  try {
@@ -6384,6 +6546,9 @@ function fromOpenApi(document, projectName) {
6384
6546
  }))
6385
6547
  });
6386
6548
  }
6549
+ const securitySchemes = parsed.components?.securitySchemes ?? {};
6550
+ const firstScheme = Object.values(securitySchemes)[0];
6551
+ const importedAuth = firstScheme ? authFromSecurityScheme(firstScheme) : void 0;
6387
6552
  const entry = {
6388
6553
  id: `${projectName}-api`,
6389
6554
  name: typeof info.title === "string" ? info.title : projectName,
@@ -6392,7 +6557,8 @@ function fromOpenApi(document, projectName) {
6392
6557
  component: `${projectName}-api`,
6393
6558
  methods,
6394
6559
  details: typeof info.description === "string" ? info.description : `Imported OpenAPI surface of ${projectName}.`,
6395
- ...typeof info.version === "string" ? { version: info.version } : {}
6560
+ ...typeof info.version === "string" ? { version: info.version } : {},
6561
+ ...importedAuth ? { auth: importedAuth } : {}
6396
6562
  };
6397
6563
  return SurfaceSnapshotSchema.parse({
6398
6564
  projectName,
@@ -6507,6 +6673,10 @@ function projectOwnSurface(maxAudience) {
6507
6673
  component: comp.id,
6508
6674
  methods,
6509
6675
  ...comp.dispatch && comp.dispatch.length ? { dispatch: comp.dispatch } : {},
6676
+ // Project the backing Portal's auth + basePath so the codec can emit
6677
+ // OpenAPI security + per-portal servers self-contained from the snapshot.
6678
+ ...comp.auth && comp.auth.scheme !== "none" ? { auth: comp.auth } : {},
6679
+ ...comp.basePath ? { basePath: comp.basePath } : {},
6510
6680
  details: raw.details ?? "",
6511
6681
  ...raw.version ? { version: raw.version } : {},
6512
6682
  ...raw.stability ? { stability: raw.stability } : {}
@@ -6556,20 +6726,28 @@ function removeSnapshot(projectName, rootDir = getProjectRoot()) {
6556
6726
  function loadSurfaceSnapshots() {
6557
6727
  return listSnapshots();
6558
6728
  }
6729
+ function renderOpenApiForms(snapshot) {
6730
+ const renderedSet = toOpenApiSet(snapshot);
6731
+ return { renderedSet, ...renderedSet.length === 1 ? { rendered: renderedSet[0].document } : {} };
6732
+ }
6733
+ function writeSurfaceFile(outPath, body, snapshot) {
6734
+ const resolved = path5.resolve(outPath);
6735
+ fs4.mkdirSync(path5.dirname(resolved), { recursive: true });
6736
+ if (body !== void 0) fs4.writeFileSync(resolved, body);
6737
+ else writeYamlFile(resolved, snapshot);
6738
+ return resolved;
6739
+ }
6559
6740
  function exportSurface(maxAudience, format, outPath) {
6560
6741
  const snapshot = projectOwnSurface(maxAudience);
6561
- const rendered = format === "openapi" ? toOpenApi(snapshot) : void 0;
6562
- let writtenTo;
6563
- if (outPath) {
6564
- fs4.mkdirSync(path5.dirname(path5.resolve(outPath)), { recursive: true });
6565
- if (rendered !== void 0) {
6566
- fs4.writeFileSync(path5.resolve(outPath), rendered);
6567
- } else {
6568
- writeYamlFile(path5.resolve(outPath), snapshot);
6569
- }
6570
- writtenTo = path5.resolve(outPath);
6571
- }
6572
- return { snapshot, ...rendered !== void 0 ? { rendered } : {}, ...writtenTo ? { writtenTo } : {} };
6742
+ const openapi = format === "openapi" ? renderOpenApiForms(snapshot) : void 0;
6743
+ const body = openapi?.rendered ?? openapi?.renderedSet[0]?.document;
6744
+ const writtenTo = outPath ? writeSurfaceFile(outPath, body, snapshot) : void 0;
6745
+ return {
6746
+ snapshot,
6747
+ ...openapi?.rendered !== void 0 ? { rendered: openapi.rendered } : {},
6748
+ ...openapi ? { renderedSet: openapi.renderedSet } : {},
6749
+ ...writtenTo ? { writtenTo } : {}
6750
+ };
6573
6751
  }
6574
6752
  function importSurface(sourcePath, origin) {
6575
6753
  const resolved = path5.resolve(sourcePath);
@@ -7829,13 +8007,16 @@ var init_conformance = __esm({
7829
8007
  if (isInChainedSubproject(component.subsystem, ctx)) continue;
7830
8008
  const draft = ctx.isImplementationDraft(impl);
7831
8009
  if (!impl.sourcePath) {
7832
- ctx.addIssue(
7833
- "warning",
7834
- "MISSING_SOURCE_PATH",
7835
- `Implementation "${impl.id}" declares no sourcePath \u2014 its contract "${impl.contract}" cannot be structurally checked against code.`,
7836
- impl.id,
7837
- draft
7838
- );
8010
+ const hasExternalSource = (component.externalLinks ?? []).some((l) => l.type === "implementation");
8011
+ if (!hasExternalSource) {
8012
+ ctx.addIssue(
8013
+ "warning",
8014
+ "MISSING_SOURCE_PATH",
8015
+ `Implementation "${impl.id}" declares no sourcePath \u2014 its contract "${impl.contract}" cannot be structurally checked against code.`,
8016
+ impl.id,
8017
+ draft
8018
+ );
8019
+ }
7839
8020
  continue;
7840
8021
  }
7841
8022
  const lookup = lookups.get(normalizeSourcePath(impl.sourcePath));
@@ -15103,6 +15284,8 @@ __export(src_exports, {
15103
15284
  EndpointSchema: () => EndpointSchema,
15104
15285
  EventBindingSchema: () => EventBindingSchema,
15105
15286
  ExtDataSchema: () => ExtDataSchema,
15287
+ ExternalLinkSchema: () => ExternalLinkSchema,
15288
+ ExternalLinkTypeSchema: () => ExternalLinkTypeSchema,
15106
15289
  GITHUB_REPO: () => GITHUB_REPO,
15107
15290
  GeminiExporter: () => GeminiExporter,
15108
15291
  GroupSpecSchema: () => GroupSpecSchema,
@@ -15120,6 +15303,7 @@ __export(src_exports, {
15120
15303
  MethodImplementationSchema: () => MethodImplementationSchema,
15121
15304
  MethodParamSchema: () => MethodParamSchema,
15122
15305
  MethodSignatureSchema: () => MethodSignatureSchema,
15306
+ NamedOpenApiSpecSchema: () => NamedOpenApiSpecSchema,
15123
15307
  NamingRuleConfigSchema: () => NamingRuleConfigSchema,
15124
15308
  NarrativeDetailSchema: () => NarrativeDetailSchema,
15125
15309
  NarrativeStepSchema: () => NarrativeStepSchema,
@@ -15133,6 +15317,8 @@ __export(src_exports, {
15133
15317
  PathsConfigSchema: () => PathsConfigSchema,
15134
15318
  PatternDefSchema: () => PatternDefSchema,
15135
15319
  PatternRefSchema: () => PatternRefSchema,
15320
+ PortalAuthSchema: () => PortalAuthSchema,
15321
+ PortalAuthSchemeSchema: () => PortalAuthSchemeSchema,
15136
15322
  PortalTypeSchema: () => PortalTypeSchema,
15137
15323
  ProfileDefSchema: () => ProfileDefSchema,
15138
15324
  ProjectConfigSchema: () => ProjectConfigSchema,
@@ -15352,6 +15538,7 @@ __export(src_exports, {
15352
15538
  syncContextFiles: () => syncContextFiles,
15353
15539
  toMarkdown: () => toMarkdown,
15354
15540
  toOpenApi: () => toOpenApi,
15541
+ toOpenApiSet: () => toOpenApiSet,
15355
15542
  updateSpec: () => updateSpec,
15356
15543
  validateAsComplete: () => validateAsComplete,
15357
15544
  validateProjectConfig: () => validateProjectConfig,
@@ -15387,7 +15574,7 @@ function defaultTargetConfig(type) {
15387
15574
  enabled: true
15388
15575
  };
15389
15576
  }
15390
- var WAIRON_VERSION = "5.0.2-dev.6";
15577
+ var WAIRON_VERSION = "5.0.2-dev.8";
15391
15578
  var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
15392
15579
  var ARCHITECT_AGENT_ID = "agent-architect";
15393
15580
  var ARCHITECT_TEMPLATE_ID = "architect";
@@ -16684,6 +16871,8 @@ init_yaml();
16684
16871
  EndpointSchema,
16685
16872
  EventBindingSchema,
16686
16873
  ExtDataSchema,
16874
+ ExternalLinkSchema,
16875
+ ExternalLinkTypeSchema,
16687
16876
  GITHUB_REPO,
16688
16877
  GeminiExporter,
16689
16878
  GroupSpecSchema,
@@ -16701,6 +16890,7 @@ init_yaml();
16701
16890
  MethodImplementationSchema,
16702
16891
  MethodParamSchema,
16703
16892
  MethodSignatureSchema,
16893
+ NamedOpenApiSpecSchema,
16704
16894
  NamingRuleConfigSchema,
16705
16895
  NarrativeDetailSchema,
16706
16896
  NarrativeStepSchema,
@@ -16714,6 +16904,8 @@ init_yaml();
16714
16904
  PathsConfigSchema,
16715
16905
  PatternDefSchema,
16716
16906
  PatternRefSchema,
16907
+ PortalAuthSchema,
16908
+ PortalAuthSchemeSchema,
16717
16909
  PortalTypeSchema,
16718
16910
  ProfileDefSchema,
16719
16911
  ProjectConfigSchema,
@@ -16933,6 +17125,7 @@ init_yaml();
16933
17125
  syncContextFiles,
16934
17126
  toMarkdown,
16935
17127
  toOpenApi,
17128
+ toOpenApiSet,
16936
17129
  updateSpec,
16937
17130
  validateAsComplete,
16938
17131
  validateProjectConfig,