@wildo-ai/saas-technical-doc 1.1.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 (216) hide show
  1. package/LICENSE +34 -0
  2. package/dist/esm/.builder.pid +9 -0
  3. package/dist/esm/build/csp-emit.d.ts +9 -0
  4. package/dist/esm/build/csp-emit.d.ts.map +1 -0
  5. package/dist/esm/build/csp-emit.js +8 -0
  6. package/dist/esm/build/csp-emit.js.map +1 -0
  7. package/dist/esm/build/load-materialized-frontend-providers.d.ts +9 -0
  8. package/dist/esm/build/load-materialized-frontend-providers.d.ts.map +1 -0
  9. package/dist/esm/build/load-materialized-frontend-providers.js +9 -0
  10. package/dist/esm/build/load-materialized-frontend-providers.js.map +1 -0
  11. package/dist/esm/companion/application-documentation/application-organization-role-documentation.d.ts +66 -0
  12. package/dist/esm/companion/application-documentation/application-organization-role-documentation.d.ts.map +1 -0
  13. package/dist/esm/companion/application-documentation/application-organization-role-documentation.js +195 -0
  14. package/dist/esm/companion/application-documentation/application-organization-role-documentation.js.map +1 -0
  15. package/dist/esm/companion/application-documentation/application-organization-unit-resource-documentation.d.ts +36 -0
  16. package/dist/esm/companion/application-documentation/application-organization-unit-resource-documentation.d.ts.map +1 -0
  17. package/dist/esm/companion/application-documentation/application-organization-unit-resource-documentation.js +71 -0
  18. package/dist/esm/companion/application-documentation/application-organization-unit-resource-documentation.js.map +1 -0
  19. package/dist/esm/companion/application-documentation/technical-documentation-engine-content-bundle.d.ts +37 -0
  20. package/dist/esm/companion/application-documentation/technical-documentation-engine-content-bundle.d.ts.map +1 -0
  21. package/dist/esm/companion/application-documentation/technical-documentation-engine-content-bundle.js +1865 -0
  22. package/dist/esm/companion/application-documentation/technical-documentation-engine-content-bundle.js.map +1 -0
  23. package/dist/esm/companion/application-documentation/technical-documentation-operational-evidence.d.ts +22 -0
  24. package/dist/esm/companion/application-documentation/technical-documentation-operational-evidence.d.ts.map +1 -0
  25. package/dist/esm/companion/application-documentation/technical-documentation-operational-evidence.js +31 -0
  26. package/dist/esm/companion/application-documentation/technical-documentation-operational-evidence.js.map +1 -0
  27. package/dist/esm/companion/application-documentation/technical-documentation-private-derivation.d.ts +31 -0
  28. package/dist/esm/companion/application-documentation/technical-documentation-private-derivation.d.ts.map +1 -0
  29. package/dist/esm/companion/application-documentation/technical-documentation-private-derivation.js +33 -0
  30. package/dist/esm/companion/application-documentation/technical-documentation-private-derivation.js.map +1 -0
  31. package/dist/esm/companion/application-documentation/technical-documentation-publication-policy.d.ts +13 -0
  32. package/dist/esm/companion/application-documentation/technical-documentation-publication-policy.d.ts.map +1 -0
  33. package/dist/esm/companion/application-documentation/technical-documentation-publication-policy.js +93 -0
  34. package/dist/esm/companion/application-documentation/technical-documentation-publication-policy.js.map +1 -0
  35. package/dist/esm/companion/content/application-consumer-documentation-content-loader.d.ts +52 -0
  36. package/dist/esm/companion/content/application-consumer-documentation-content-loader.d.ts.map +1 -0
  37. package/dist/esm/companion/content/application-consumer-documentation-content-loader.js +191 -0
  38. package/dist/esm/companion/content/application-consumer-documentation-content-loader.js.map +1 -0
  39. package/dist/esm/companion/index.d.ts +39 -0
  40. package/dist/esm/companion/index.d.ts.map +1 -0
  41. package/dist/esm/companion/index.js +39 -0
  42. package/dist/esm/companion/index.js.map +1 -0
  43. package/dist/esm/companion/openapi-generator.d.ts +94 -0
  44. package/dist/esm/companion/openapi-generator.d.ts.map +1 -0
  45. package/dist/esm/companion/openapi-generator.js +1562 -0
  46. package/dist/esm/companion/openapi-generator.js.map +1 -0
  47. package/dist/esm/companion/operation-projection.schemas.d.ts +797 -0
  48. package/dist/esm/companion/operation-projection.schemas.d.ts.map +1 -0
  49. package/dist/esm/companion/operation-projection.schemas.js +610 -0
  50. package/dist/esm/companion/operation-projection.schemas.js.map +1 -0
  51. package/dist/esm/companion/publish-result.types.d.ts +124 -0
  52. package/dist/esm/companion/publish-result.types.d.ts.map +1 -0
  53. package/dist/esm/companion/publish-result.types.js +28 -0
  54. package/dist/esm/companion/publish-result.types.js.map +1 -0
  55. package/dist/esm/companion/rendering/technical-documentation-authorized-bundle-reader.d.ts +26 -0
  56. package/dist/esm/companion/rendering/technical-documentation-authorized-bundle-reader.d.ts.map +1 -0
  57. package/dist/esm/companion/rendering/technical-documentation-authorized-bundle-reader.js +63 -0
  58. package/dist/esm/companion/rendering/technical-documentation-authorized-bundle-reader.js.map +1 -0
  59. package/dist/esm/companion/rendering/technical-documentation-build-measurement.d.ts +23 -0
  60. package/dist/esm/companion/rendering/technical-documentation-build-measurement.d.ts.map +1 -0
  61. package/dist/esm/companion/rendering/technical-documentation-build-measurement.js +104 -0
  62. package/dist/esm/companion/rendering/technical-documentation-build-measurement.js.map +1 -0
  63. package/dist/esm/companion/rendering/technical-documentation-docusaurus-renderer.d.ts +9 -0
  64. package/dist/esm/companion/rendering/technical-documentation-docusaurus-renderer.d.ts.map +1 -0
  65. package/dist/esm/companion/rendering/technical-documentation-docusaurus-renderer.js +421 -0
  66. package/dist/esm/companion/rendering/technical-documentation-docusaurus-renderer.js.map +1 -0
  67. package/dist/esm/companion/rendering/technical-documentation-managed-tree-validator.d.ts +72 -0
  68. package/dist/esm/companion/rendering/technical-documentation-managed-tree-validator.d.ts.map +1 -0
  69. package/dist/esm/companion/rendering/technical-documentation-managed-tree-validator.js +204 -0
  70. package/dist/esm/companion/rendering/technical-documentation-managed-tree-validator.js.map +1 -0
  71. package/dist/esm/companion/rendering/technical-documentation-markdown-renderer.d.ts +9 -0
  72. package/dist/esm/companion/rendering/technical-documentation-markdown-renderer.d.ts.map +1 -0
  73. package/dist/esm/companion/rendering/technical-documentation-markdown-renderer.js +106 -0
  74. package/dist/esm/companion/rendering/technical-documentation-markdown-renderer.js.map +1 -0
  75. package/dist/esm/companion/rendering/technical-documentation-mdx-escaping.d.ts +43 -0
  76. package/dist/esm/companion/rendering/technical-documentation-mdx-escaping.d.ts.map +1 -0
  77. package/dist/esm/companion/rendering/technical-documentation-mdx-escaping.js +88 -0
  78. package/dist/esm/companion/rendering/technical-documentation-mdx-escaping.js.map +1 -0
  79. package/dist/esm/companion/rendering/technical-documentation-openapi-renderer.d.ts +7 -0
  80. package/dist/esm/companion/rendering/technical-documentation-openapi-renderer.d.ts.map +1 -0
  81. package/dist/esm/companion/rendering/technical-documentation-openapi-renderer.js +51 -0
  82. package/dist/esm/companion/rendering/technical-documentation-openapi-renderer.js.map +1 -0
  83. package/dist/esm/companion/rendering/technical-documentation-render-model.d.ts +45 -0
  84. package/dist/esm/companion/rendering/technical-documentation-render-model.d.ts.map +1 -0
  85. package/dist/esm/companion/rendering/technical-documentation-render-model.js +178 -0
  86. package/dist/esm/companion/rendering/technical-documentation-render-model.js.map +1 -0
  87. package/dist/esm/companion/rendering/technical-documentation-search-index-renderer.d.ts +3 -0
  88. package/dist/esm/companion/rendering/technical-documentation-search-index-renderer.d.ts.map +1 -0
  89. package/dist/esm/companion/rendering/technical-documentation-search-index-renderer.js +49 -0
  90. package/dist/esm/companion/rendering/technical-documentation-search-index-renderer.js.map +1 -0
  91. package/dist/esm/companion/spec-to-operation-doc.d.ts +176 -0
  92. package/dist/esm/companion/spec-to-operation-doc.d.ts.map +1 -0
  93. package/dist/esm/companion/spec-to-operation-doc.js +326 -0
  94. package/dist/esm/companion/spec-to-operation-doc.js.map +1 -0
  95. package/dist/esm/companion/technical-documentation-asset-path.d.ts +16 -0
  96. package/dist/esm/companion/technical-documentation-asset-path.d.ts.map +1 -0
  97. package/dist/esm/companion/technical-documentation-asset-path.js +19 -0
  98. package/dist/esm/companion/technical-documentation-asset-path.js.map +1 -0
  99. package/dist/esm/companion/technical-documentation-capture-execution-port.d.ts +14 -0
  100. package/dist/esm/companion/technical-documentation-capture-execution-port.d.ts.map +1 -0
  101. package/dist/esm/companion/technical-documentation-capture-execution-port.js +1 -0
  102. package/dist/esm/companion/technical-documentation-capture-execution-port.js.map +1 -0
  103. package/dist/esm/companion/technical-documentation-diagram-materializer.d.ts +25 -0
  104. package/dist/esm/companion/technical-documentation-diagram-materializer.d.ts.map +1 -0
  105. package/dist/esm/companion/technical-documentation-diagram-materializer.js +86 -0
  106. package/dist/esm/companion/technical-documentation-diagram-materializer.js.map +1 -0
  107. package/dist/esm/companion/technical-documentation-placeholder-materializer.d.ts +17 -0
  108. package/dist/esm/companion/technical-documentation-placeholder-materializer.d.ts.map +1 -0
  109. package/dist/esm/companion/technical-documentation-placeholder-materializer.js +63 -0
  110. package/dist/esm/companion/technical-documentation-placeholder-materializer.js.map +1 -0
  111. package/dist/esm/companion/zod-to-openapi.d.ts +67 -0
  112. package/dist/esm/companion/zod-to-openapi.d.ts.map +1 -0
  113. package/dist/esm/companion/zod-to-openapi.js +211 -0
  114. package/dist/esm/companion/zod-to-openapi.js.map +1 -0
  115. package/dist/esm/companion-exports.d.ts +32 -0
  116. package/dist/esm/companion-exports.d.ts.map +1 -0
  117. package/dist/esm/companion-exports.js +32 -0
  118. package/dist/esm/companion-exports.js.map +1 -0
  119. package/dist/esm/config/define-tech-doc-config.d.ts +38 -0
  120. package/dist/esm/config/define-tech-doc-config.d.ts.map +1 -0
  121. package/dist/esm/config/define-tech-doc-config.js +40 -0
  122. package/dist/esm/config/define-tech-doc-config.js.map +1 -0
  123. package/dist/esm/config/index.d.ts +22 -0
  124. package/dist/esm/config/index.d.ts.map +1 -0
  125. package/dist/esm/config/index.js +22 -0
  126. package/dist/esm/config/index.js.map +1 -0
  127. package/dist/esm/config/wildo-tech-doc-config.schemas.d.ts +204 -0
  128. package/dist/esm/config/wildo-tech-doc-config.schemas.d.ts.map +1 -0
  129. package/dist/esm/config/wildo-tech-doc-config.schemas.js +192 -0
  130. package/dist/esm/config/wildo-tech-doc-config.schemas.js.map +1 -0
  131. package/dist/esm/content/application-consumer-documentation-content-manifest.schemas.d.ts +82 -0
  132. package/dist/esm/content/application-consumer-documentation-content-manifest.schemas.d.ts.map +1 -0
  133. package/dist/esm/content/application-consumer-documentation-content-manifest.schemas.js +114 -0
  134. package/dist/esm/content/application-consumer-documentation-content-manifest.schemas.js.map +1 -0
  135. package/dist/esm/content/application-consumer-documentation-content.techdoc.d.ts +420 -0
  136. package/dist/esm/content/application-consumer-documentation-content.techdoc.d.ts.map +1 -0
  137. package/dist/esm/content/application-consumer-documentation-content.techdoc.js +9619 -0
  138. package/dist/esm/content/application-consumer-documentation-content.techdoc.js.map +1 -0
  139. package/dist/esm/content.exports.d.ts +9 -0
  140. package/dist/esm/content.exports.d.ts.map +1 -0
  141. package/dist/esm/content.exports.js +9 -0
  142. package/dist/esm/content.exports.js.map +1 -0
  143. package/dist/esm/index.d.ts +26 -0
  144. package/dist/esm/index.d.ts.map +1 -0
  145. package/dist/esm/index.js +26 -0
  146. package/dist/esm/index.js.map +1 -0
  147. package/dist/esm/openapi/api-reference-link-index.d.ts +98 -0
  148. package/dist/esm/openapi/api-reference-link-index.d.ts.map +1 -0
  149. package/dist/esm/openapi/api-reference-link-index.js +301 -0
  150. package/dist/esm/openapi/api-reference-link-index.js.map +1 -0
  151. package/dist/esm/openapi/api-reference-targets.d.ts +71 -0
  152. package/dist/esm/openapi/api-reference-targets.d.ts.map +1 -0
  153. package/dist/esm/openapi/api-reference-targets.js +114 -0
  154. package/dist/esm/openapi/api-reference-targets.js.map +1 -0
  155. package/dist/esm/openapi/index.d.ts +20 -0
  156. package/dist/esm/openapi/index.d.ts.map +1 -0
  157. package/dist/esm/openapi/index.js +20 -0
  158. package/dist/esm/openapi/index.js.map +1 -0
  159. package/dist/esm/openapi/openapi-generation-output.schemas.d.ts +80 -0
  160. package/dist/esm/openapi/openapi-generation-output.schemas.d.ts.map +1 -0
  161. package/dist/esm/openapi/openapi-generation-output.schemas.js +76 -0
  162. package/dist/esm/openapi/openapi-generation-output.schemas.js.map +1 -0
  163. package/dist/esm/openapi-reference-model.exports.d.ts +10 -0
  164. package/dist/esm/openapi-reference-model.exports.d.ts.map +1 -0
  165. package/dist/esm/openapi-reference-model.exports.js +10 -0
  166. package/dist/esm/openapi-reference-model.exports.js.map +1 -0
  167. package/dist/esm/runtime/AuthExchangePage.d.ts +84 -0
  168. package/dist/esm/runtime/AuthExchangePage.d.ts.map +1 -0
  169. package/dist/esm/runtime/AuthExchangePage.js +188 -0
  170. package/dist/esm/runtime/AuthExchangePage.js.map +1 -0
  171. package/dist/esm/runtime/DocsAuthContext.d.ts +119 -0
  172. package/dist/esm/runtime/DocsAuthContext.d.ts.map +1 -0
  173. package/dist/esm/runtime/DocsAuthContext.js +171 -0
  174. package/dist/esm/runtime/DocsAuthContext.js.map +1 -0
  175. package/dist/esm/runtime/decode-jwt-claims.d.ts +39 -0
  176. package/dist/esm/runtime/decode-jwt-claims.d.ts.map +1 -0
  177. package/dist/esm/runtime/decode-jwt-claims.js +86 -0
  178. package/dist/esm/runtime/decode-jwt-claims.js.map +1 -0
  179. package/dist/esm/runtime/docs-auth-client.d.ts +193 -0
  180. package/dist/esm/runtime/docs-auth-client.d.ts.map +1 -0
  181. package/dist/esm/runtime/docs-auth-client.js +211 -0
  182. package/dist/esm/runtime/docs-auth-client.js.map +1 -0
  183. package/dist/esm/runtime/docs-auth-session.schemas.d.ts +77 -0
  184. package/dist/esm/runtime/docs-auth-session.schemas.d.ts.map +1 -0
  185. package/dist/esm/runtime/docs-auth-session.schemas.js +50 -0
  186. package/dist/esm/runtime/docs-auth-session.schemas.js.map +1 -0
  187. package/dist/esm/runtime/frontend-provider-registry.techdoc.d.ts +17 -0
  188. package/dist/esm/runtime/frontend-provider-registry.techdoc.d.ts.map +1 -0
  189. package/dist/esm/runtime/frontend-provider-registry.techdoc.js +23 -0
  190. package/dist/esm/runtime/frontend-provider-registry.techdoc.js.map +1 -0
  191. package/dist/esm/runtime/index.d.ts +57 -0
  192. package/dist/esm/runtime/index.d.ts.map +1 -0
  193. package/dist/esm/runtime/index.js +76 -0
  194. package/dist/esm/runtime/index.js.map +1 -0
  195. package/dist/esm/runtime/openapi-reference-conservation.d.ts +20 -0
  196. package/dist/esm/runtime/openapi-reference-conservation.d.ts.map +1 -0
  197. package/dist/esm/runtime/openapi-reference-conservation.js +102 -0
  198. package/dist/esm/runtime/openapi-reference-conservation.js.map +1 -0
  199. package/dist/esm/runtime/openapi-reference-model.d.ts +224 -0
  200. package/dist/esm/runtime/openapi-reference-model.d.ts.map +1 -0
  201. package/dist/esm/runtime/openapi-reference-model.js +579 -0
  202. package/dist/esm/runtime/openapi-reference-model.js.map +1 -0
  203. package/dist/esm/runtime/openapi-reference-view.d.ts +13 -0
  204. package/dist/esm/runtime/openapi-reference-view.d.ts.map +1 -0
  205. package/dist/esm/runtime/openapi-reference-view.js +284 -0
  206. package/dist/esm/runtime/openapi-reference-view.js.map +1 -0
  207. package/dist/esm/runtime/use-docs-auth-session.d.ts +26 -0
  208. package/dist/esm/runtime/use-docs-auth-session.d.ts.map +1 -0
  209. package/dist/esm/runtime/use-docs-auth-session.js +34 -0
  210. package/dist/esm/runtime/use-docs-auth-session.js.map +1 -0
  211. package/dist/esm/runtime/use-docs-frontend-provider-registry.d.ts +3 -0
  212. package/dist/esm/runtime/use-docs-frontend-provider-registry.d.ts.map +1 -0
  213. package/dist/esm/runtime/use-docs-frontend-provider-registry.js +5 -0
  214. package/dist/esm/runtime/use-docs-frontend-provider-registry.js.map +1 -0
  215. package/dist/tsconfig.build.tsbuildinfo +1 -0
  216. package/package.json +117 -0
@@ -0,0 +1,93 @@
1
+ import { TechnicalDocumentationAssetAccessClass, TechnicalDocumentationChannel, TechnicalDocumentationEditorialStatus, TechnicalDocumentationPublicationDecision, TechnicalDocumentationPublicationReason, TechnicalDocumentationSourceClassification, createTechnicalDocumentationAuthorizedBundleManifestV1, createTechnicalDocumentationUnitV1, } from '@wildo-ai/saas-specifications/technical-documentation';
2
+ import { evaluateTechnicalDocumentationApplicability } from './technical-documentation-operational-evidence.js';
3
+ function recreateUnit(unit, overrides) {
4
+ return createTechnicalDocumentationUnitV1({ ...unit, ...overrides });
5
+ }
6
+ /**
7
+ * Authorizes one framework unit for the public consumer portal.
8
+ *
9
+ * Application editorial overlays and authenticated/internal publication lanes
10
+ * are intentionally absent. Application-specific authoring will re-enter later
11
+ * through the app-creator acceptance flow, not through this framework policy.
12
+ */
13
+ function projectPublicUnit(sourceUnit, manifest) {
14
+ if (sourceUnit.editorialStatus !== TechnicalDocumentationEditorialStatus.APPROVED) {
15
+ return {
16
+ sourceUnit,
17
+ publishedUnit: null,
18
+ decision: TechnicalDocumentationPublicationDecision.SUPPRESS,
19
+ reason: TechnicalDocumentationPublicationReason.EDITORIAL_NOT_APPROVED,
20
+ };
21
+ }
22
+ if (!evaluateTechnicalDocumentationApplicability(sourceUnit.applicabilityRequirements, manifest.environmentEvidenceSnapshot).applicable) {
23
+ return {
24
+ sourceUnit,
25
+ publishedUnit: null,
26
+ decision: TechnicalDocumentationPublicationDecision.SUPPRESS,
27
+ reason: TechnicalDocumentationPublicationReason.APPLICABILITY_NOT_PROVEN,
28
+ };
29
+ }
30
+ if (sourceUnit.provenance.some((source) => source.classification !== TechnicalDocumentationSourceClassification.PUBLIC)) {
31
+ return {
32
+ sourceUnit,
33
+ publishedUnit: null,
34
+ decision: TechnicalDocumentationPublicationDecision.SUPPRESS,
35
+ reason: TechnicalDocumentationPublicationReason.RESTRICTED_SOURCE,
36
+ };
37
+ }
38
+ const assetRequests = sourceUnit.assetRequests.filter((asset) => asset.accessClass === TechnicalDocumentationAssetAccessClass.PUBLIC);
39
+ const redacted = assetRequests.length !== sourceUnit.assetRequests.length;
40
+ return {
41
+ sourceUnit,
42
+ publishedUnit: recreateUnit(sourceUnit, { assetRequests }),
43
+ decision: redacted ? TechnicalDocumentationPublicationDecision.REDACT : TechnicalDocumentationPublicationDecision.INCLUDE,
44
+ reason: redacted ? TechnicalDocumentationPublicationReason.RESTRICTED_SOURCE : TechnicalDocumentationPublicationReason.INCLUDED_BY_POLICY,
45
+ };
46
+ }
47
+ /** Projects and minimizes the public framework bundle before rendering. */
48
+ export function projectTechnicalDocumentationAuthorizedBundle(input) {
49
+ const initial = input.privateDerivation.units.map((unit) => projectPublicUnit(unit, input.privateDerivation));
50
+ const emittedUnitRefs = new Set(initial.flatMap((candidate) => candidate.publishedUnit === null ? [] : [candidate.publishedUnit.unitRef]));
51
+ const finalized = initial.map((candidate) => {
52
+ if (candidate.publishedUnit === null)
53
+ return candidate;
54
+ const links = candidate.publishedUnit.links.filter((link) => link.targetUnitRef === null || emittedUnitRefs.has(link.targetUnitRef));
55
+ if (links.length === candidate.publishedUnit.links.length)
56
+ return candidate;
57
+ return {
58
+ ...candidate,
59
+ publishedUnit: recreateUnit(candidate.publishedUnit, { links }),
60
+ decision: TechnicalDocumentationPublicationDecision.REDACT,
61
+ reason: TechnicalDocumentationPublicationReason.ACCESS_CLASS_MISMATCH,
62
+ };
63
+ });
64
+ const units = finalized.flatMap((candidate) => candidate.publishedUnit === null ? [] : [candidate.publishedUnit]);
65
+ const decisions = finalized.map((candidate) => ({
66
+ unitRef: candidate.sourceUnit.unitRef,
67
+ decision: candidate.decision,
68
+ reason: candidate.reason,
69
+ /*
70
+ * Both versions name the SAME unit version, and that is correct: a redaction narrows a unit's
71
+ * content without minting a new authored version. `decision` is what distinguishes INCLUDE
72
+ * from REDACT — it always was; the digest pair merely made the difference visible as two hex
73
+ * strings nobody could read.
74
+ */
75
+ sourceUnitVersion: candidate.sourceUnit.unitVersion,
76
+ publishedUnitVersion: candidate.publishedUnit?.unitVersion ?? null,
77
+ }));
78
+ return createTechnicalDocumentationAuthorizedBundleManifestV1({
79
+ schemaVersion: 1,
80
+ channel: TechnicalDocumentationChannel.PUBLIC_PORTAL,
81
+ policyRef: input.policyRef,
82
+ policyVersion: input.policyVersion,
83
+ bundleRef: input.bundleRef,
84
+ bundleVersion: input.bundleVersion,
85
+ derivationIdentity: {
86
+ ref: input.privateDerivation.derivationRef,
87
+ version: input.privateDerivation.derivationVersion,
88
+ },
89
+ units,
90
+ decisions,
91
+ });
92
+ }
93
+ //# sourceMappingURL=technical-documentation-publication-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"technical-documentation-publication-policy.js","sourceRoot":"","sources":["../../../../../src/companion/application-documentation/technical-documentation-publication-policy.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n TechnicalDocumentationAssetAccessClass,\n TechnicalDocumentationChannel,\n TechnicalDocumentationEditorialStatus,\n TechnicalDocumentationPublicationDecision,\n TechnicalDocumentationPublicationReason,\n TechnicalDocumentationSourceClassification,\n createTechnicalDocumentationAuthorizedBundleManifestV1,\n createTechnicalDocumentationUnitV1,\n type TechnicalDocumentationAuthorizedBundleManifestV1,\n type TechnicalDocumentationPrivateDerivationManifestV1,\n type TechnicalDocumentationUnitPublicationDecisionV1,\n type TechnicalDocumentationUnitV1,\n} from '@wildo-ai/saas-specifications/technical-documentation';\n\nimport { evaluateTechnicalDocumentationApplicability } from './technical-documentation-operational-evidence';\n\ninterface PolicyProjectionCandidate {\n readonly sourceUnit: TechnicalDocumentationUnitV1;\n readonly publishedUnit: TechnicalDocumentationUnitV1 | null;\n readonly decision: TechnicalDocumentationPublicationDecision;\n readonly reason: TechnicalDocumentationPublicationReason;\n}\n\nfunction recreateUnit(\n unit: TechnicalDocumentationUnitV1,\n overrides: Partial<TechnicalDocumentationUnitV1>,\n): TechnicalDocumentationUnitV1 {\n return createTechnicalDocumentationUnitV1({ ...unit, ...overrides });\n}\n\n/**\n * Authorizes one framework unit for the public consumer portal.\n *\n * Application editorial overlays and authenticated/internal publication lanes\n * are intentionally absent. Application-specific authoring will re-enter later\n * through the app-creator acceptance flow, not through this framework policy.\n */\nfunction projectPublicUnit(\n sourceUnit: TechnicalDocumentationUnitV1,\n manifest: TechnicalDocumentationPrivateDerivationManifestV1,\n): PolicyProjectionCandidate {\n if (sourceUnit.editorialStatus !== TechnicalDocumentationEditorialStatus.APPROVED) {\n return {\n sourceUnit,\n publishedUnit: null,\n decision: TechnicalDocumentationPublicationDecision.SUPPRESS,\n reason: TechnicalDocumentationPublicationReason.EDITORIAL_NOT_APPROVED,\n };\n }\n if (!evaluateTechnicalDocumentationApplicability(sourceUnit.applicabilityRequirements, manifest.environmentEvidenceSnapshot).applicable) {\n return {\n sourceUnit,\n publishedUnit: null,\n decision: TechnicalDocumentationPublicationDecision.SUPPRESS,\n reason: TechnicalDocumentationPublicationReason.APPLICABILITY_NOT_PROVEN,\n };\n }\n if (sourceUnit.provenance.some((source) => source.classification !== TechnicalDocumentationSourceClassification.PUBLIC)) {\n return {\n sourceUnit,\n publishedUnit: null,\n decision: TechnicalDocumentationPublicationDecision.SUPPRESS,\n reason: TechnicalDocumentationPublicationReason.RESTRICTED_SOURCE,\n };\n }\n\n const assetRequests = sourceUnit.assetRequests.filter((asset) => asset.accessClass === TechnicalDocumentationAssetAccessClass.PUBLIC);\n const redacted = assetRequests.length !== sourceUnit.assetRequests.length;\n return {\n sourceUnit,\n publishedUnit: recreateUnit(sourceUnit, { assetRequests }),\n decision: redacted ? TechnicalDocumentationPublicationDecision.REDACT : TechnicalDocumentationPublicationDecision.INCLUDE,\n reason: redacted ? TechnicalDocumentationPublicationReason.RESTRICTED_SOURCE : TechnicalDocumentationPublicationReason.INCLUDED_BY_POLICY,\n };\n}\n\nexport interface ProjectTechnicalDocumentationAuthorizedBundleInput {\n readonly privateDerivation: TechnicalDocumentationPrivateDerivationManifestV1;\n readonly channel: TechnicalDocumentationChannel.PUBLIC_PORTAL;\n readonly policyRef: string;\n readonly policyVersion: number;\n /** This bundle's own identity; the render manifest and the publication pointer name it. */\n readonly bundleRef: string;\n readonly bundleVersion: number;\n}\n\n/** Projects and minimizes the public framework bundle before rendering. */\nexport function projectTechnicalDocumentationAuthorizedBundle(\n input: ProjectTechnicalDocumentationAuthorizedBundleInput,\n): TechnicalDocumentationAuthorizedBundleManifestV1 {\n const initial = input.privateDerivation.units.map((unit) => projectPublicUnit(unit, input.privateDerivation));\n const emittedUnitRefs = new Set(initial.flatMap((candidate) => candidate.publishedUnit === null ? [] : [candidate.publishedUnit.unitRef]));\n const finalized = initial.map((candidate) => {\n if (candidate.publishedUnit === null) return candidate;\n const links = candidate.publishedUnit.links.filter((link) => link.targetUnitRef === null || emittedUnitRefs.has(link.targetUnitRef));\n if (links.length === candidate.publishedUnit.links.length) return candidate;\n return {\n ...candidate,\n publishedUnit: recreateUnit(candidate.publishedUnit, { links }),\n decision: TechnicalDocumentationPublicationDecision.REDACT,\n reason: TechnicalDocumentationPublicationReason.ACCESS_CLASS_MISMATCH,\n };\n });\n const units = finalized.flatMap((candidate) => candidate.publishedUnit === null ? [] : [candidate.publishedUnit]);\n const decisions: TechnicalDocumentationUnitPublicationDecisionV1[] = finalized.map((candidate) => ({\n unitRef: candidate.sourceUnit.unitRef,\n decision: candidate.decision,\n reason: candidate.reason,\n /*\n * Both versions name the SAME unit version, and that is correct: a redaction narrows a unit's\n * content without minting a new authored version. `decision` is what distinguishes INCLUDE\n * from REDACT — it always was; the digest pair merely made the difference visible as two hex\n * strings nobody could read.\n */\n sourceUnitVersion: candidate.sourceUnit.unitVersion,\n publishedUnitVersion: candidate.publishedUnit?.unitVersion ?? null,\n }));\n\n return createTechnicalDocumentationAuthorizedBundleManifestV1({\n schemaVersion: 1,\n channel: TechnicalDocumentationChannel.PUBLIC_PORTAL,\n policyRef: input.policyRef,\n policyVersion: input.policyVersion,\n bundleRef: input.bundleRef,\n bundleVersion: input.bundleVersion,\n derivationIdentity: {\n ref: input.privateDerivation.derivationRef,\n version: input.privateDerivation.derivationVersion,\n },\n units,\n decisions,\n });\n}\n"]}
@@ -0,0 +1,52 @@
1
+ import { type TechnicalDocumentationEngineContentBundleIdentityV1, type TechnicalDocumentationNormalizedRelativePath, type TechnicalDocumentationRef } from '@wildo-ai/saas-specifications/technical-documentation';
2
+ import { type ApplicationConsumerDocumentationAuthoredContentV1, type ApplicationConsumerDocumentationContentFileIdentityV1, ApplicationConsumerDocumentationContentMediaType, type ApplicationConsumerDocumentationContentManifestV1, type ApplicationConsumerDocumentationContentUnitIdentityV1 } from '../../content/application-consumer-documentation-content-manifest.schemas';
3
+ /** Builds the deterministic manifest candidate used by generation and by loader verification. */
4
+ export declare function createApplicationConsumerDocumentationContentManifestV1(authoredContent: readonly ApplicationConsumerDocumentationAuthoredContentV1[], generatedAt: string, contentBundleVersion?: number): ApplicationConsumerDocumentationContentManifestV1;
5
+ /**
6
+ * Canonical engine-content identity derived from the data-only authored source.
7
+ *
8
+ * The authored rows are the single semantic authority. Keeping this manifest mechanically derived avoids a second checked-in digest inventory that can
9
+ * drift independently while retaining fail-closed verification when a caller supplies or loads an external manifest.
10
+ */
11
+ export declare const APPLICATION_CONSUMER_DOCUMENTATION_CONTENT_MANIFEST_V1: {
12
+ schemaVersion: 1;
13
+ contentBundleVersion: number;
14
+ generatedAt: string;
15
+ fileCount: number;
16
+ unitCount: number;
17
+ files: {
18
+ managedPath: string & import("zod").$brand<"TechnicalDocumentationNormalizedRelativePath">;
19
+ mediaType: ApplicationConsumerDocumentationContentMediaType;
20
+ byteLength: number;
21
+ fileDigest: string;
22
+ unitRef: string;
23
+ }[];
24
+ units: {
25
+ unitRef: string;
26
+ sourceRefs: string[];
27
+ managedPaths: (string & import("zod").$brand<"TechnicalDocumentationNormalizedRelativePath">)[];
28
+ }[];
29
+ };
30
+ export interface LoadedApplicationConsumerDocumentationContentFileV1 {
31
+ readonly managedPath: string;
32
+ readonly mediaType: ApplicationConsumerDocumentationContentMediaType;
33
+ readonly byteLength: number;
34
+ readonly fileDigest: string;
35
+ readonly unitRef: string;
36
+ readonly sourceRefs: readonly string[];
37
+ }
38
+ export interface LoadedApplicationConsumerDocumentationContentBundleV1 {
39
+ readonly identity: TechnicalDocumentationEngineContentBundleIdentityV1;
40
+ readonly manifest: Readonly<Omit<ApplicationConsumerDocumentationContentManifestV1, 'files' | 'units'>> & {
41
+ readonly files: readonly Readonly<ApplicationConsumerDocumentationContentFileIdentityV1>[];
42
+ readonly units: readonly (Readonly<Omit<ApplicationConsumerDocumentationContentUnitIdentityV1, 'sourceRefs' | 'managedPaths'>> & {
43
+ readonly sourceRefs: readonly TechnicalDocumentationRef[];
44
+ readonly managedPaths: readonly TechnicalDocumentationNormalizedRelativePath[];
45
+ })[];
46
+ };
47
+ readonly files: readonly LoadedApplicationConsumerDocumentationContentFileV1[];
48
+ readManagedBytes(managedPath: string): Uint8Array;
49
+ }
50
+ /** Verifies the complete manifest and returns only copy-on-read managed bytes. */
51
+ export declare function loadApplicationConsumerDocumentationContentBundleV1(manifestInput?: unknown, authoredContentInput?: readonly ApplicationConsumerDocumentationAuthoredContentV1[]): LoadedApplicationConsumerDocumentationContentBundleV1;
52
+ //# sourceMappingURL=application-consumer-documentation-content-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-consumer-documentation-content-loader.d.ts","sourceRoot":"","sources":["../../../../../src/companion/content/application-consumer-documentation-content-loader.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,mDAAmD,EACxD,KAAK,4CAA4C,EACjD,KAAK,yBAAyB,EAC/B,MAAM,uDAAuD,CAAC;AAG/D,OAAO,EAKL,KAAK,iDAAiD,EACtD,KAAK,qDAAqD,EAE1D,gDAAgD,EAChD,KAAK,iDAAiD,EACtD,KAAK,qDAAqD,EAC3D,MAAM,2EAA2E,CAAC;AAoEnF,iGAAiG;AACjG,wBAAgB,uDAAuD,CACrE,eAAe,EAAE,SAAS,iDAAiD,EAAE,EAC7E,WAAW,EAAE,MAAM,EACnB,oBAAoB,SAAI,GACvB,iDAAiD,CA2CnD;AAED;;;;;GAKG;AACH,eAAO,MAAM,sDAAsD;;;;;;;;;;;;;;;;;;CAGlE,CAAC;AAEF,MAAM,WAAW,mDAAmD;IAClE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,gDAAgD,CAAC;IACrE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,qDAAqD;IACpE,QAAQ,CAAC,QAAQ,EAAE,mDAAmD,CAAC;IACvE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,iDAAiD,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,GAAG;QACxG,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,CAAC,qDAAqD,CAAC,EAAE,CAAC;QAC3F,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,qDAAqD,EAAE,YAAY,GAAG,cAAc,CAAC,CAAC,GAAG;YAC/H,QAAQ,CAAC,UAAU,EAAE,SAAS,yBAAyB,EAAE,CAAC;YAC1D,QAAQ,CAAC,YAAY,EAAE,SAAS,4CAA4C,EAAE,CAAC;SAChF,CAAC,EAAE,CAAC;KACN,CAAC;IACF,QAAQ,CAAC,KAAK,EAAE,SAAS,mDAAmD,EAAE,CAAC;IAC/E,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,CAAC;CACnD;AA4BD,kFAAkF;AAClF,wBAAgB,mDAAmD,CACjE,aAAa,GAAE,OAAgE,EAC/E,oBAAoB,GAAE,SAAS,iDAAiD,EAA2D,GAC1I,qDAAqD,CA0CvD"}
@@ -0,0 +1,191 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { TechnicalDocumentationEngineContentBundleIdentityV1Schema, TechnicalDocumentationNormalizedRelativePathSchema, TechnicalDocumentationRefSchema, } from '@wildo-ai/saas-specifications/technical-documentation';
3
+ import { APPLICATION_CONSUMER_DOCUMENTATION_AUTHORED_CONTENT_V1 } from '../../content/application-consumer-documentation-content.techdoc.js';
4
+ import { APPLICATION_CONSUMER_DOCUMENTATION_CONSUMER_FACT_SOURCE_PREFIX, APPLICATION_CONSUMER_DOCUMENTATION_COMPANION_PROJECTION_SOURCE_PREFIX, APPLICATION_CONSUMER_DOCUMENTATION_ENGINE_CONTENT_SOURCE_PREFIX, APPLICATION_CONSUMER_DOCUMENTATION_CONTENT_BUNDLE_REF, ApplicationConsumerDocumentationContentManifestV1Schema, ApplicationConsumerDocumentationContentMediaType, } from '../../content/application-consumer-documentation-content-manifest.schemas.js';
5
+ const UTF8_ENCODER = new TextEncoder();
6
+ const AUTHORED_CONTENT_KEYS = ['managedPath', 'markdown', 'sourceRefs', 'unitRef'];
7
+ const PRODUCTION_CONTENT_GENERATED_AT = '2026-08-02T00:00:00.000Z';
8
+ function sha256Digest(bytes) {
9
+ return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;
10
+ }
11
+ function expectedSourceRefForUnit(unitRef) {
12
+ const unitPrefix = 'technical-documentation:unit/';
13
+ if (!unitRef.startsWith(unitPrefix))
14
+ throw new Error(`engine content unitRef must start with ${unitPrefix}`);
15
+ return `${APPLICATION_CONSUMER_DOCUMENTATION_ENGINE_CONTENT_SOURCE_PREFIX}${unitRef.slice(unitPrefix.length)}`;
16
+ }
17
+ function validateAuthoredContentSources(authoredContent) {
18
+ if (authoredContent.length === 0)
19
+ throw new Error('application-consumer documentation content cannot be empty');
20
+ const managedPaths = new Set();
21
+ const caseFoldedPaths = new Set();
22
+ const unitRefs = new Set();
23
+ return authoredContent.map((source, index) => {
24
+ if (source === null || typeof source !== 'object' || Array.isArray(source))
25
+ throw new Error(`authored content row ${index} must be a plain object`);
26
+ const keys = Object.keys(source).sort();
27
+ if (keys.join('\0') !== [...AUTHORED_CONTENT_KEYS].sort().join('\0'))
28
+ throw new Error(`authored content row ${index} has an unknown or missing field`);
29
+ const managedPath = TechnicalDocumentationNormalizedRelativePathSchema.parse(source.managedPath);
30
+ const unitRef = TechnicalDocumentationRefSchema.parse(source.unitRef);
31
+ if (managedPaths.has(managedPath))
32
+ throw new Error(`duplicate managed content path: ${managedPath}`);
33
+ managedPaths.add(managedPath);
34
+ const caseFoldedPath = managedPath.toLocaleLowerCase('en-US');
35
+ if (caseFoldedPaths.has(caseFoldedPath))
36
+ throw new Error(`case-colliding managed content path: ${managedPath}`);
37
+ caseFoldedPaths.add(caseFoldedPath);
38
+ if (unitRefs.has(unitRef))
39
+ throw new Error(`duplicate application-consumer documentation unitRef: ${unitRef}`);
40
+ unitRefs.add(unitRef);
41
+ if (typeof source.markdown !== 'string' || source.markdown.trim().length === 0)
42
+ throw new Error(`content file ${managedPath} must contain Markdown`);
43
+ if (source.markdown.startsWith('\uFEFF') || source.markdown.includes('\r')) {
44
+ throw new Error(`content file ${managedPath} must use UTF-8 text with LF line endings and no BOM`);
45
+ }
46
+ const sourceRefs = source.sourceRefs.map((sourceRef) => TechnicalDocumentationRefSchema.parse(sourceRef));
47
+ if (sourceRefs.length === 0 || new Set(sourceRefs).size !== sourceRefs.length || sourceRefs.join('\0') !== [...sourceRefs].sort().join('\0')) {
48
+ throw new Error(`content source refs must be non-empty, unique and sorted for ${unitRef}`);
49
+ }
50
+ const expectedSourceRef = expectedSourceRefForUnit(unitRef);
51
+ const engineContentSourceRefs = sourceRefs.filter((sourceRef) => sourceRef.startsWith(APPLICATION_CONSUMER_DOCUMENTATION_ENGINE_CONTENT_SOURCE_PREFIX));
52
+ const consumerFactSourceRefs = sourceRefs.filter((sourceRef) => sourceRef.startsWith(APPLICATION_CONSUMER_DOCUMENTATION_CONSUMER_FACT_SOURCE_PREFIX));
53
+ const companionProjectionSourceRefs = sourceRefs.filter((sourceRef) => sourceRef.startsWith(APPLICATION_CONSUMER_DOCUMENTATION_COMPANION_PROJECTION_SOURCE_PREFIX));
54
+ if (engineContentSourceRefs.length !== 1 || engineContentSourceRefs[0] !== expectedSourceRef
55
+ || engineContentSourceRefs.length + consumerFactSourceRefs.length + companionProjectionSourceRefs.length !== sourceRefs.length) {
56
+ throw new Error(`unknown engine content source ref for ${unitRef}; expected ${expectedSourceRef}`);
57
+ }
58
+ return { managedPath, unitRef, sourceRefs, markdown: source.markdown };
59
+ });
60
+ }
61
+ /** Builds the deterministic manifest candidate used by generation and by loader verification. */
62
+ export function createApplicationConsumerDocumentationContentManifestV1(authoredContent, generatedAt, contentBundleVersion = 1) {
63
+ const sources = validateAuthoredContentSources(authoredContent);
64
+ const files = sources
65
+ .map((source) => {
66
+ const bytes = UTF8_ENCODER.encode(source.markdown);
67
+ return {
68
+ managedPath: source.managedPath,
69
+ mediaType: ApplicationConsumerDocumentationContentMediaType.MARKDOWN_UTF8,
70
+ byteLength: bytes.byteLength,
71
+ fileDigest: sha256Digest(bytes),
72
+ unitRef: source.unitRef,
73
+ };
74
+ })
75
+ .sort((left, right) => left.managedPath.localeCompare(right.managedPath, 'en-US'));
76
+ const sourcesByUnitRef = new Map(sources.map((source) => [source.unitRef, source]));
77
+ const filesByUnitRef = new Map();
78
+ for (const file of files) {
79
+ const unitFiles = filesByUnitRef.get(file.unitRef) ?? [];
80
+ unitFiles.push(file);
81
+ filesByUnitRef.set(file.unitRef, unitFiles);
82
+ }
83
+ const units = [...filesByUnitRef.entries()]
84
+ .sort(([left], [right]) => left.localeCompare(right, 'en-US'))
85
+ .map(([unitRef, unitFiles]) => {
86
+ const source = sourcesByUnitRef.get(unitRef);
87
+ if (source === undefined)
88
+ throw new Error(`missing authored metadata for ${unitRef}`);
89
+ return {
90
+ unitRef,
91
+ sourceRefs: [...source.sourceRefs],
92
+ managedPaths: unitFiles.map((file) => file.managedPath),
93
+ };
94
+ });
95
+ return ApplicationConsumerDocumentationContentManifestV1Schema.parse({
96
+ schemaVersion: 1,
97
+ contentBundleVersion,
98
+ generatedAt,
99
+ fileCount: files.length,
100
+ unitCount: units.length,
101
+ files,
102
+ units,
103
+ });
104
+ }
105
+ /**
106
+ * Canonical engine-content identity derived from the data-only authored source.
107
+ *
108
+ * The authored rows are the single semantic authority. Keeping this manifest mechanically derived avoids a second checked-in digest inventory that can
109
+ * drift independently while retaining fail-closed verification when a caller supplies or loads an external manifest.
110
+ */
111
+ export const APPLICATION_CONSUMER_DOCUMENTATION_CONTENT_MANIFEST_V1 = createApplicationConsumerDocumentationContentManifestV1(APPLICATION_CONSUMER_DOCUMENTATION_AUTHORED_CONTENT_V1, PRODUCTION_CONTENT_GENERATED_AT);
112
+ function exactManifestMismatch(expected, received) {
113
+ if (expected.contentBundleVersion !== received.contentBundleVersion)
114
+ return 'contentBundleVersion';
115
+ if (expected.fileCount !== received.fileCount)
116
+ return 'fileCount';
117
+ if (expected.unitCount !== received.unitCount)
118
+ return 'unitCount';
119
+ if (expected.files.length !== received.files.length)
120
+ return 'files.length';
121
+ for (const [index, expectedFile] of expected.files.entries()) {
122
+ const receivedFile = received.files[index];
123
+ if (receivedFile === undefined)
124
+ return `files[${index}]`;
125
+ for (const key of ['managedPath', 'mediaType', 'byteLength', 'fileDigest', 'unitRef']) {
126
+ if (expectedFile[key] !== receivedFile[key])
127
+ return `files[${index}].${key}`;
128
+ }
129
+ }
130
+ if (expected.units.length !== received.units.length)
131
+ return 'units.length';
132
+ for (const [index, expectedUnit] of expected.units.entries()) {
133
+ const receivedUnit = received.units[index];
134
+ if (receivedUnit === undefined)
135
+ return `units[${index}]`;
136
+ if (expectedUnit.unitRef !== receivedUnit.unitRef)
137
+ return `units[${index}].unitRef`;
138
+ if (expectedUnit.sourceRefs.join('\0') !== receivedUnit.sourceRefs.join('\0'))
139
+ return `units[${index}].sourceRefs`;
140
+ if (expectedUnit.managedPaths.join('\0') !== receivedUnit.managedPaths.join('\0'))
141
+ return `units[${index}].managedPaths`;
142
+ }
143
+ return null;
144
+ }
145
+ /** Verifies the complete manifest and returns only copy-on-read managed bytes. */
146
+ export function loadApplicationConsumerDocumentationContentBundleV1(manifestInput = APPLICATION_CONSUMER_DOCUMENTATION_CONTENT_MANIFEST_V1, authoredContentInput = APPLICATION_CONSUMER_DOCUMENTATION_AUTHORED_CONTENT_V1) {
147
+ const manifest = ApplicationConsumerDocumentationContentManifestV1Schema.parse(manifestInput);
148
+ const sources = validateAuthoredContentSources(authoredContentInput);
149
+ const sourcePaths = new Set(sources.map((source) => source.managedPath));
150
+ const manifestPaths = new Set(manifest.files.map((file) => file.managedPath));
151
+ const missingPaths = manifest.files.map((file) => file.managedPath).filter((path) => !sourcePaths.has(path));
152
+ if (missingPaths.length > 0)
153
+ throw new Error(`missing managed application-consumer content: ${missingPaths.join(', ')}`);
154
+ const extraPaths = sources.map((source) => source.managedPath).filter((path) => !manifestPaths.has(path));
155
+ if (extraPaths.length > 0)
156
+ throw new Error(`unlisted application-consumer content: ${extraPaths.join(', ')}`);
157
+ const expectedManifest = createApplicationConsumerDocumentationContentManifestV1(sources, manifest.generatedAt, manifest.contentBundleVersion);
158
+ const mismatch = exactManifestMismatch(expectedManifest, manifest);
159
+ if (mismatch !== null)
160
+ throw new Error(`application-consumer documentation content manifest mismatch at ${mismatch}`);
161
+ const bytesByPath = new Map(sources.map((source) => [source.managedPath, UTF8_ENCODER.encode(source.markdown)]));
162
+ const unitByRef = new Map(manifest.units.map((unit) => [unit.unitRef, unit]));
163
+ const files = manifest.files.map((file) => {
164
+ const unit = unitByRef.get(file.unitRef);
165
+ if (unit === undefined)
166
+ throw new Error(`managed content file ${file.managedPath} has no unit identity`);
167
+ return Object.freeze({ ...file, sourceRefs: Object.freeze([...unit.sourceRefs]) });
168
+ });
169
+ const identity = TechnicalDocumentationEngineContentBundleIdentityV1Schema.parse({
170
+ schemaVersion: 1,
171
+ contentBundleRef: APPLICATION_CONSUMER_DOCUMENTATION_CONTENT_BUNDLE_REF,
172
+ contentBundleVersion: manifest.contentBundleVersion,
173
+ });
174
+ return Object.freeze({
175
+ identity: Object.freeze(identity),
176
+ manifest: Object.freeze({
177
+ ...manifest,
178
+ files: Object.freeze(manifest.files.map((file) => Object.freeze({ ...file }))),
179
+ units: Object.freeze(manifest.units.map((unit) => Object.freeze({ ...unit, sourceRefs: Object.freeze([...unit.sourceRefs]), managedPaths: Object.freeze([...unit.managedPaths]) }))),
180
+ }),
181
+ files: Object.freeze(files),
182
+ readManagedBytes(managedPath) {
183
+ const normalizedPath = TechnicalDocumentationNormalizedRelativePathSchema.parse(managedPath);
184
+ const bytes = bytesByPath.get(normalizedPath);
185
+ if (bytes === undefined)
186
+ throw new Error(`unknown managed application-consumer content path: ${normalizedPath}`);
187
+ return new Uint8Array(bytes);
188
+ },
189
+ });
190
+ }
191
+ //# sourceMappingURL=application-consumer-documentation-content-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-consumer-documentation-content-loader.js","sourceRoot":"","sources":["../../../../../src/companion/content/application-consumer-documentation-content-loader.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto';\nimport {\n canonicalizeTechnicalDocumentationJson,\n TechnicalDocumentationEngineContentBundleIdentityV1Schema,\n TechnicalDocumentationNormalizedRelativePathSchema,\n TechnicalDocumentationRefSchema,\n type TechnicalDocumentationEngineContentBundleIdentityV1,\n type TechnicalDocumentationNormalizedRelativePath,\n type TechnicalDocumentationRef,\n} from '@wildo-ai/saas-specifications/technical-documentation';\n\nimport { APPLICATION_CONSUMER_DOCUMENTATION_AUTHORED_CONTENT_V1 } from '../../content/application-consumer-documentation-content.techdoc';\nimport {\n APPLICATION_CONSUMER_DOCUMENTATION_CONSUMER_FACT_SOURCE_PREFIX,\n APPLICATION_CONSUMER_DOCUMENTATION_COMPANION_PROJECTION_SOURCE_PREFIX,\n APPLICATION_CONSUMER_DOCUMENTATION_ENGINE_CONTENT_SOURCE_PREFIX,\n APPLICATION_CONSUMER_DOCUMENTATION_CONTENT_BUNDLE_REF,\n type ApplicationConsumerDocumentationAuthoredContentV1,\n type ApplicationConsumerDocumentationContentFileIdentityV1,\n ApplicationConsumerDocumentationContentManifestV1Schema,\n ApplicationConsumerDocumentationContentMediaType,\n type ApplicationConsumerDocumentationContentManifestV1,\n type ApplicationConsumerDocumentationContentUnitIdentityV1,\n} from '../../content/application-consumer-documentation-content-manifest.schemas';\n\nconst UTF8_ENCODER = new TextEncoder();\nconst AUTHORED_CONTENT_KEYS = ['managedPath', 'markdown', 'sourceRefs', 'unitRef'] as const;\nconst PRODUCTION_CONTENT_GENERATED_AT = '2026-08-02T00:00:00.000Z';\n\nfunction sha256Digest(bytes: Uint8Array): string {\n return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;\n}\n\n\nfunction expectedSourceRefForUnit(unitRef: string): string {\n const unitPrefix = 'technical-documentation:unit/';\n if (!unitRef.startsWith(unitPrefix)) throw new Error(`engine content unitRef must start with ${unitPrefix}`);\n return `${APPLICATION_CONSUMER_DOCUMENTATION_ENGINE_CONTENT_SOURCE_PREFIX}${unitRef.slice(unitPrefix.length)}`;\n}\n\ninterface ValidatedApplicationConsumerDocumentationAuthoredContentV1 {\n readonly managedPath: TechnicalDocumentationNormalizedRelativePath;\n readonly unitRef: TechnicalDocumentationRef;\n readonly sourceRefs: readonly TechnicalDocumentationRef[];\n readonly markdown: string;\n}\n\nfunction validateAuthoredContentSources(\n authoredContent: readonly ApplicationConsumerDocumentationAuthoredContentV1[],\n): readonly ValidatedApplicationConsumerDocumentationAuthoredContentV1[] {\n if (authoredContent.length === 0) throw new Error('application-consumer documentation content cannot be empty');\n\n const managedPaths = new Set<string>();\n const caseFoldedPaths = new Set<string>();\n const unitRefs = new Set<string>();\n return authoredContent.map((source, index) => {\n if (source === null || typeof source !== 'object' || Array.isArray(source)) throw new Error(`authored content row ${index} must be a plain object`);\n const keys = Object.keys(source).sort();\n if (keys.join('\\0') !== [...AUTHORED_CONTENT_KEYS].sort().join('\\0')) throw new Error(`authored content row ${index} has an unknown or missing field`);\n\n const managedPath = TechnicalDocumentationNormalizedRelativePathSchema.parse(source.managedPath);\n const unitRef = TechnicalDocumentationRefSchema.parse(source.unitRef);\n if (managedPaths.has(managedPath)) throw new Error(`duplicate managed content path: ${managedPath}`);\n managedPaths.add(managedPath);\n const caseFoldedPath = managedPath.toLocaleLowerCase('en-US');\n if (caseFoldedPaths.has(caseFoldedPath)) throw new Error(`case-colliding managed content path: ${managedPath}`);\n caseFoldedPaths.add(caseFoldedPath);\n if (unitRefs.has(unitRef)) throw new Error(`duplicate application-consumer documentation unitRef: ${unitRef}`);\n unitRefs.add(unitRef);\n\n if (typeof source.markdown !== 'string' || source.markdown.trim().length === 0) throw new Error(`content file ${managedPath} must contain Markdown`);\n if (source.markdown.startsWith('\\uFEFF') || source.markdown.includes('\\r')) {\n throw new Error(`content file ${managedPath} must use UTF-8 text with LF line endings and no BOM`);\n }\n const sourceRefs = source.sourceRefs.map((sourceRef) => TechnicalDocumentationRefSchema.parse(sourceRef));\n if (sourceRefs.length === 0 || new Set(sourceRefs).size !== sourceRefs.length || sourceRefs.join('\\0') !== [...sourceRefs].sort().join('\\0')) {\n throw new Error(`content source refs must be non-empty, unique and sorted for ${unitRef}`);\n }\n const expectedSourceRef = expectedSourceRefForUnit(unitRef);\n const engineContentSourceRefs = sourceRefs.filter((sourceRef) => sourceRef.startsWith(APPLICATION_CONSUMER_DOCUMENTATION_ENGINE_CONTENT_SOURCE_PREFIX));\n const consumerFactSourceRefs = sourceRefs.filter((sourceRef) => sourceRef.startsWith(APPLICATION_CONSUMER_DOCUMENTATION_CONSUMER_FACT_SOURCE_PREFIX));\n const companionProjectionSourceRefs = sourceRefs.filter((sourceRef) => sourceRef.startsWith(APPLICATION_CONSUMER_DOCUMENTATION_COMPANION_PROJECTION_SOURCE_PREFIX));\n if (engineContentSourceRefs.length !== 1 || engineContentSourceRefs[0] !== expectedSourceRef\n || engineContentSourceRefs.length + consumerFactSourceRefs.length + companionProjectionSourceRefs.length !== sourceRefs.length) {\n throw new Error(`unknown engine content source ref for ${unitRef}; expected ${expectedSourceRef}`);\n }\n\n return { managedPath, unitRef, sourceRefs, markdown: source.markdown };\n });\n}\n\n/** Builds the deterministic manifest candidate used by generation and by loader verification. */\nexport function createApplicationConsumerDocumentationContentManifestV1(\n authoredContent: readonly ApplicationConsumerDocumentationAuthoredContentV1[],\n generatedAt: string,\n contentBundleVersion = 1,\n): ApplicationConsumerDocumentationContentManifestV1 {\n const sources = validateAuthoredContentSources(authoredContent);\n const files = sources\n .map((source) => {\n const bytes = UTF8_ENCODER.encode(source.markdown);\n return {\n managedPath: source.managedPath,\n mediaType: ApplicationConsumerDocumentationContentMediaType.MARKDOWN_UTF8,\n byteLength: bytes.byteLength,\n fileDigest: sha256Digest(bytes),\n unitRef: source.unitRef,\n };\n })\n .sort((left, right) => left.managedPath.localeCompare(right.managedPath, 'en-US'));\n\n const sourcesByUnitRef = new Map(sources.map((source) => [source.unitRef, source]));\n const filesByUnitRef = new Map<string, typeof files>();\n for (const file of files) {\n const unitFiles = filesByUnitRef.get(file.unitRef) ?? [];\n unitFiles.push(file);\n filesByUnitRef.set(file.unitRef, unitFiles);\n }\n const units = [...filesByUnitRef.entries()]\n .sort(([left], [right]) => left.localeCompare(right, 'en-US'))\n .map(([unitRef, unitFiles]) => {\n const source = sourcesByUnitRef.get(unitRef);\n if (source === undefined) throw new Error(`missing authored metadata for ${unitRef}`);\n return {\n unitRef,\n sourceRefs: [...source.sourceRefs],\n managedPaths: unitFiles.map((file) => file.managedPath),\n };\n });\n\n return ApplicationConsumerDocumentationContentManifestV1Schema.parse({\n schemaVersion: 1 as const,\n contentBundleVersion,\n generatedAt,\n fileCount: files.length,\n unitCount: units.length,\n files,\n units,\n });\n}\n\n/**\n * Canonical engine-content identity derived from the data-only authored source.\n *\n * The authored rows are the single semantic authority. Keeping this manifest mechanically derived avoids a second checked-in digest inventory that can\n * drift independently while retaining fail-closed verification when a caller supplies or loads an external manifest.\n */\nexport const APPLICATION_CONSUMER_DOCUMENTATION_CONTENT_MANIFEST_V1 = createApplicationConsumerDocumentationContentManifestV1(\n APPLICATION_CONSUMER_DOCUMENTATION_AUTHORED_CONTENT_V1,\n PRODUCTION_CONTENT_GENERATED_AT,\n);\n\nexport interface LoadedApplicationConsumerDocumentationContentFileV1 {\n readonly managedPath: string;\n readonly mediaType: ApplicationConsumerDocumentationContentMediaType;\n readonly byteLength: number;\n readonly fileDigest: string;\n readonly unitRef: string;\n readonly sourceRefs: readonly string[];\n}\n\nexport interface LoadedApplicationConsumerDocumentationContentBundleV1 {\n readonly identity: TechnicalDocumentationEngineContentBundleIdentityV1;\n readonly manifest: Readonly<Omit<ApplicationConsumerDocumentationContentManifestV1, 'files' | 'units'>> & {\n readonly files: readonly Readonly<ApplicationConsumerDocumentationContentFileIdentityV1>[];\n readonly units: readonly (Readonly<Omit<ApplicationConsumerDocumentationContentUnitIdentityV1, 'sourceRefs' | 'managedPaths'>> & {\n readonly sourceRefs: readonly TechnicalDocumentationRef[];\n readonly managedPaths: readonly TechnicalDocumentationNormalizedRelativePath[];\n })[];\n };\n readonly files: readonly LoadedApplicationConsumerDocumentationContentFileV1[];\n readManagedBytes(managedPath: string): Uint8Array;\n}\n\nfunction exactManifestMismatch(\n expected: ApplicationConsumerDocumentationContentManifestV1,\n received: ApplicationConsumerDocumentationContentManifestV1,\n): string | null {\n if (expected.contentBundleVersion !== received.contentBundleVersion) return 'contentBundleVersion';\n if (expected.fileCount !== received.fileCount) return 'fileCount';\n if (expected.unitCount !== received.unitCount) return 'unitCount';\n if (expected.files.length !== received.files.length) return 'files.length';\n for (const [index, expectedFile] of expected.files.entries()) {\n const receivedFile = received.files[index];\n if (receivedFile === undefined) return `files[${index}]`;\n for (const key of ['managedPath', 'mediaType', 'byteLength', 'fileDigest', 'unitRef'] as const) {\n if (expectedFile[key] !== receivedFile[key]) return `files[${index}].${key}`;\n }\n }\n if (expected.units.length !== received.units.length) return 'units.length';\n for (const [index, expectedUnit] of expected.units.entries()) {\n const receivedUnit = received.units[index];\n if (receivedUnit === undefined) return `units[${index}]`;\n if (expectedUnit.unitRef !== receivedUnit.unitRef) return `units[${index}].unitRef`;\n if (expectedUnit.sourceRefs.join('\\0') !== receivedUnit.sourceRefs.join('\\0')) return `units[${index}].sourceRefs`;\n if (expectedUnit.managedPaths.join('\\0') !== receivedUnit.managedPaths.join('\\0')) return `units[${index}].managedPaths`;\n }\n return null;\n}\n\n/** Verifies the complete manifest and returns only copy-on-read managed bytes. */\nexport function loadApplicationConsumerDocumentationContentBundleV1(\n manifestInput: unknown = APPLICATION_CONSUMER_DOCUMENTATION_CONTENT_MANIFEST_V1,\n authoredContentInput: readonly ApplicationConsumerDocumentationAuthoredContentV1[] = APPLICATION_CONSUMER_DOCUMENTATION_AUTHORED_CONTENT_V1,\n): LoadedApplicationConsumerDocumentationContentBundleV1 {\n const manifest = ApplicationConsumerDocumentationContentManifestV1Schema.parse(manifestInput);\n const sources = validateAuthoredContentSources(authoredContentInput);\n const sourcePaths = new Set(sources.map((source) => source.managedPath));\n const manifestPaths = new Set(manifest.files.map((file) => file.managedPath));\n const missingPaths = manifest.files.map((file) => file.managedPath).filter((path) => !sourcePaths.has(path));\n if (missingPaths.length > 0) throw new Error(`missing managed application-consumer content: ${missingPaths.join(', ')}`);\n const extraPaths = sources.map((source) => source.managedPath).filter((path) => !manifestPaths.has(path));\n if (extraPaths.length > 0) throw new Error(`unlisted application-consumer content: ${extraPaths.join(', ')}`);\n\n const expectedManifest = createApplicationConsumerDocumentationContentManifestV1(sources, manifest.generatedAt, manifest.contentBundleVersion);\n const mismatch = exactManifestMismatch(expectedManifest, manifest);\n if (mismatch !== null) throw new Error(`application-consumer documentation content manifest mismatch at ${mismatch}`);\n\n const bytesByPath = new Map(sources.map((source) => [source.managedPath, UTF8_ENCODER.encode(source.markdown)]));\n const unitByRef = new Map(manifest.units.map((unit) => [unit.unitRef, unit]));\n const files = manifest.files.map((file) => {\n const unit = unitByRef.get(file.unitRef);\n if (unit === undefined) throw new Error(`managed content file ${file.managedPath} has no unit identity`);\n return Object.freeze({ ...file, sourceRefs: Object.freeze([...unit.sourceRefs]) });\n });\n const identity = TechnicalDocumentationEngineContentBundleIdentityV1Schema.parse({\n schemaVersion: 1,\n contentBundleRef: APPLICATION_CONSUMER_DOCUMENTATION_CONTENT_BUNDLE_REF,\n contentBundleVersion: manifest.contentBundleVersion,\n });\n\n return Object.freeze({\n identity: Object.freeze(identity),\n manifest: Object.freeze({\n ...manifest,\n files: Object.freeze(manifest.files.map((file) => Object.freeze({ ...file }))),\n units: Object.freeze(manifest.units.map((unit) => Object.freeze({ ...unit, sourceRefs: Object.freeze([...unit.sourceRefs]), managedPaths: Object.freeze([...unit.managedPaths]) }))),\n }),\n files: Object.freeze(files),\n readManagedBytes(managedPath: string): Uint8Array {\n const normalizedPath = TechnicalDocumentationNormalizedRelativePathSchema.parse(managedPath);\n const bytes = bytesByPath.get(normalizedPath);\n if (bytes === undefined) throw new Error(`unknown managed application-consumer content path: ${normalizedPath}`);\n return new Uint8Array(bytes);\n },\n });\n}\n"]}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * `@wildo-ai/saas-technical-doc/companion` — implementation surface.
3
+ *
4
+ * Pure-function OpenAPI projection, its input contract, and Node-side verification/materialization utilities for an exact engine-owned
5
+ * application-consumer documentation content bundle. Consumed by:
6
+ * - `examples/<app>/.wildo-saas/wildo-dev-companion/` controllers
7
+ * that call `generateOpenApiDocuments(input)` to produce
8
+ * the normal and application-administration YAML/JSON OpenAPI documents.
9
+ *
10
+ * @wildo-boundary
11
+ * Re-exports only companion-side OpenAPI and application-consumer content projection surfaces. All are React-free; the content loader is Node-only and
12
+ * never enters the browser runtime closure. Reusable authored content and portable identities are owned by the separate `./content`
13
+ * entry point.
14
+ */
15
+ export * from './operation-projection.schemas';
16
+ export * from './openapi-generator';
17
+ export * from './publish-result.types';
18
+ export * from './zod-to-openapi';
19
+ export * from './spec-to-operation-doc';
20
+ export * from './content/application-consumer-documentation-content-loader';
21
+ export * from './technical-documentation-capture-execution-port';
22
+ export * from './technical-documentation-asset-path';
23
+ export * from './technical-documentation-diagram-materializer';
24
+ export * from './technical-documentation-placeholder-materializer';
25
+ export * from './rendering/technical-documentation-authorized-bundle-reader';
26
+ export * from './rendering/technical-documentation-docusaurus-renderer';
27
+ export * from './rendering/technical-documentation-build-measurement';
28
+ export * from './rendering/technical-documentation-managed-tree-validator';
29
+ export * from './rendering/technical-documentation-markdown-renderer';
30
+ export * from './rendering/technical-documentation-openapi-renderer';
31
+ export * from './rendering/technical-documentation-render-model';
32
+ export * from './rendering/technical-documentation-search-index-renderer';
33
+ export * from './application-documentation/technical-documentation-engine-content-bundle';
34
+ export * from './application-documentation/application-organization-role-documentation';
35
+ export * from './application-documentation/application-organization-unit-resource-documentation';
36
+ export * from './application-documentation/technical-documentation-operational-evidence';
37
+ export * from './application-documentation/technical-documentation-private-derivation';
38
+ export * from './application-documentation/technical-documentation-publication-policy';
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/companion/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6DAA6D,CAAC;AAC5E,cAAc,kDAAkD,CAAC;AACjE,cAAc,sCAAsC,CAAC;AACrD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AACnE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,yDAAyD,CAAC;AACxE,cAAc,uDAAuD,CAAC;AACtE,cAAc,4DAA4D,CAAC;AAC3E,cAAc,uDAAuD,CAAC;AACtE,cAAc,sDAAsD,CAAC;AACrE,cAAc,kDAAkD,CAAC;AACjE,cAAc,2DAA2D,CAAC;AAC1E,cAAc,2EAA2E,CAAC;AAC1F,cAAc,yEAAyE,CAAC;AACxF,cAAc,kFAAkF,CAAC;AACjG,cAAc,0EAA0E,CAAC;AACzF,cAAc,wEAAwE,CAAC;AACvF,cAAc,wEAAwE,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * `@wildo-ai/saas-technical-doc/companion` — implementation surface.
3
+ *
4
+ * Pure-function OpenAPI projection, its input contract, and Node-side verification/materialization utilities for an exact engine-owned
5
+ * application-consumer documentation content bundle. Consumed by:
6
+ * - `examples/<app>/.wildo-saas/wildo-dev-companion/` controllers
7
+ * that call `generateOpenApiDocuments(input)` to produce
8
+ * the normal and application-administration YAML/JSON OpenAPI documents.
9
+ *
10
+ * @wildo-boundary
11
+ * Re-exports only companion-side OpenAPI and application-consumer content projection surfaces. All are React-free; the content loader is Node-only and
12
+ * never enters the browser runtime closure. Reusable authored content and portable identities are owned by the separate `./content`
13
+ * entry point.
14
+ */
15
+ export * from './operation-projection.schemas.js';
16
+ export * from './openapi-generator.js';
17
+ export * from './publish-result.types.js';
18
+ export * from './zod-to-openapi.js';
19
+ export * from './spec-to-operation-doc.js';
20
+ export * from './content/application-consumer-documentation-content-loader.js';
21
+ export * from './technical-documentation-capture-execution-port.js';
22
+ export * from './technical-documentation-asset-path.js';
23
+ export * from './technical-documentation-diagram-materializer.js';
24
+ export * from './technical-documentation-placeholder-materializer.js';
25
+ export * from './rendering/technical-documentation-authorized-bundle-reader.js';
26
+ export * from './rendering/technical-documentation-docusaurus-renderer.js';
27
+ export * from './rendering/technical-documentation-build-measurement.js';
28
+ export * from './rendering/technical-documentation-managed-tree-validator.js';
29
+ export * from './rendering/technical-documentation-markdown-renderer.js';
30
+ export * from './rendering/technical-documentation-openapi-renderer.js';
31
+ export * from './rendering/technical-documentation-render-model.js';
32
+ export * from './rendering/technical-documentation-search-index-renderer.js';
33
+ export * from './application-documentation/technical-documentation-engine-content-bundle.js';
34
+ export * from './application-documentation/application-organization-role-documentation.js';
35
+ export * from './application-documentation/application-organization-unit-resource-documentation.js';
36
+ export * from './application-documentation/technical-documentation-operational-evidence.js';
37
+ export * from './application-documentation/technical-documentation-private-derivation.js';
38
+ export * from './application-documentation/technical-documentation-publication-policy.js';
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/companion/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6DAA6D,CAAC;AAC5E,cAAc,kDAAkD,CAAC;AACjE,cAAc,sCAAsC,CAAC;AACrD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AACnE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,yDAAyD,CAAC;AACxE,cAAc,uDAAuD,CAAC;AACtE,cAAc,4DAA4D,CAAC;AAC3E,cAAc,uDAAuD,CAAC;AACtE,cAAc,sDAAsD,CAAC;AACrE,cAAc,kDAAkD,CAAC;AACjE,cAAc,2DAA2D,CAAC;AAC1E,cAAc,2EAA2E,CAAC;AAC1F,cAAc,yEAAyE,CAAC;AACxF,cAAc,kFAAkF,CAAC;AACjG,cAAc,0EAA0E,CAAC;AACzF,cAAc,wEAAwE,CAAC;AACvF,cAAc,wEAAwE,CAAC","sourcesContent":["/**\n * `@wildo-ai/saas-technical-doc/companion` — implementation surface.\n *\n * Pure-function OpenAPI projection, its input contract, and Node-side verification/materialization utilities for an exact engine-owned\n * application-consumer documentation content bundle. Consumed by:\n * - `examples/<app>/.wildo-saas/wildo-dev-companion/` controllers\n * that call `generateOpenApiDocuments(input)` to produce\n * the normal and application-administration YAML/JSON OpenAPI documents.\n *\n * @wildo-boundary\n * Re-exports only companion-side OpenAPI and application-consumer content projection surfaces. All are React-free; the content loader is Node-only and\n * never enters the browser runtime closure. Reusable authored content and portable identities are owned by the separate `./content`\n * entry point.\n */\n\nexport * from './operation-projection.schemas';\nexport * from './openapi-generator';\nexport * from './publish-result.types';\nexport * from './zod-to-openapi';\nexport * from './spec-to-operation-doc';\nexport * from './content/application-consumer-documentation-content-loader';\nexport * from './technical-documentation-capture-execution-port';\nexport * from './technical-documentation-asset-path';\nexport * from './technical-documentation-diagram-materializer';\nexport * from './technical-documentation-placeholder-materializer';\nexport * from './rendering/technical-documentation-authorized-bundle-reader';\nexport * from './rendering/technical-documentation-docusaurus-renderer';\nexport * from './rendering/technical-documentation-build-measurement';\nexport * from './rendering/technical-documentation-managed-tree-validator';\nexport * from './rendering/technical-documentation-markdown-renderer';\nexport * from './rendering/technical-documentation-openapi-renderer';\nexport * from './rendering/technical-documentation-render-model';\nexport * from './rendering/technical-documentation-search-index-renderer';\nexport * from './application-documentation/technical-documentation-engine-content-bundle';\nexport * from './application-documentation/application-organization-role-documentation';\nexport * from './application-documentation/application-organization-unit-resource-documentation';\nexport * from './application-documentation/technical-documentation-operational-evidence';\nexport * from './application-documentation/technical-documentation-private-derivation';\nexport * from './application-documentation/technical-documentation-publication-policy';\n"]}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @wildo-package @wildo-ai/saas-technical-doc/companion (generator)
3
+ *
4
+ * Pure-function OpenAPI 3.1 generator (saas-technical-doc.md Step 3).
5
+ *
6
+ * Pipeline:
7
+ *
8
+ * `OpenApiGenerationInput`
9
+ * ──filterApiCallOperations──► (assert URL-bearing variants)
10
+ * ──groupOperationsByConsumerApiSection──► (use source-resolved section)
11
+ * ──buildOpenApiDocument──► (per-section OpenAPI 3.1 doc as a JS object)
12
+ * ──assembleOpenApiGenerationOutput──►(top-level `OpenApiGenerationOutput`)
13
+ *
14
+ * Key design points:
15
+ *
16
+ * K-1: This module is `OpenApiGenerationInput` → `OpenApiGenerationOutput`
17
+ * and contains no I/O, no global state, and no DI. It is consumed by
18
+ * the companion controller (which owns the introspection hop +
19
+ * filesystem write — see Step 4) and by unit tests in isolation.
20
+ *
21
+ * K-2: Sections that contain ZERO operations after filtering are
22
+ * OMITTED from the output's `sections[]` array (per the
23
+ * `OpenApiGenerationOutputSchema` JSDoc). The companion UI
24
+ * surfaces this as an absent section — the empty section is
25
+ * intentional, not a generator bug.
26
+ *
27
+ * K-3: The generator uses Zod-parsed input (validated up-front via
28
+ * `OpenApiGenerationInputSchema`) so every downstream helper can
29
+ * assume well-formed projections. Callers MUST call
30
+ * `generateOpenApiDocuments(input)` (which parses) and NOT the
31
+ * sub-helpers directly with unparsed data.
32
+ *
33
+ * K-4: The semantic output carries one document object. YAML/JSON
34
+ * serialization is renderer-owned so divergent format payloads cannot
35
+ * cross this contract.
36
+ *
37
+ * @wildo-boundary
38
+ * Imports only the portable OpenAPI output contract, the local operation
39
+ * projection contract, the lightweight public runtime constants and
40
+ * specification-prose cleanup. No serializer, React or saas-models root
41
+ * barrel enters this semantic generator.
42
+ */
43
+ import { OpenApiSection, type OpenApiGenerationOutput } from '../openapi/openapi-generation-output.schemas';
44
+ import { type OperationProjection } from './operation-projection.schemas';
45
+ /**
46
+ * Retains every projected URL-bearing operation.
47
+ *
48
+ * - Variant outside `API_CALL` / `API_CALL_WITH_CALLBACK` (K-5):
49
+ * defense-in-depth re-check on top of the projector's filter.
50
+ * If a non-API variant ever leaks through, drop it silently here
51
+ * rather than throwing — the projector is the single source of
52
+ * truth for "should this op even be in the projection at all," but
53
+ * we don't want a future projector regression to corrupt the
54
+ * generated doc with non-HTTP operations.
55
+ *
56
+ * `isApiKeyAccessDisabled` controls the operation's accepted authentication
57
+ * schemes. It does not make an HTTP operation disappear from its API contract.
58
+ *
59
+ * Returns a NEW array — does not mutate the input.
60
+ */
61
+ export declare function filterApiCallOperations(operations: ReadonlyArray<OperationProjection>): ReadonlyArray<OperationProjection>;
62
+ /**
63
+ * Groups operations by the explicit consumer-facing section resolved by the
64
+ * source projector. This layer deliberately does not reinterpret role strings
65
+ * or internal resource scopes: doing so would create a second authority for
66
+ * which product reference owns an operation.
67
+ *
68
+ * Returns a frozen `Record` keyed by `OpenApiSection`. Sections with
69
+ * zero operations are returned as empty arrays (NOT omitted) so the
70
+ * caller's filtering logic in `assembleOpenApiGenerationOutput` is the
71
+ * single place that decides "drop empty sections from the output."
72
+ */
73
+ export declare function groupOperationsByConsumerApiSection(operations: ReadonlyArray<OperationProjection>): Readonly<Record<OpenApiSection, ReadonlyArray<OperationProjection>>>;
74
+ /**
75
+ * Public entry point — single function the companion controller
76
+ * calls.
77
+ *
78
+ * Steps:
79
+ * 1. Parse the input (defense-in-depth — the controller validates
80
+ * against `OpenApiGenerationInputSchema` already, but we re-parse
81
+ * here so direct callers can't bypass validation).
82
+ * 2. Assert URL-bearing variants without treating authentication-mode flags
83
+ * as eligibility filters.
84
+ * 3. Group by the explicit source-resolved consumer section.
85
+ * 4. Build one semantic OpenAPI document per non-empty section.
86
+ * 5. Drop empty sections (K-2).
87
+ *
88
+ * @param rawInput The unparsed input — typically the deserialised
89
+ * wire payload from the introspection subprocess hop.
90
+ * @returns The `OpenApiGenerationOutput` ready to be returned by the
91
+ * companion controller.
92
+ */
93
+ export declare function generateOpenApiDocuments(rawInput: unknown): OpenApiGenerationOutput;
94
+ //# sourceMappingURL=openapi-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi-generator.d.ts","sourceRoot":"","sources":["../../../../src/companion/openapi-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAIH,OAAO,EACL,cAAc,EACd,KAAK,uBAAuB,EAE7B,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EAOL,KAAK,mBAAmB,EACzB,MAAM,gCAAgC,CAAC;AAIxC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,aAAa,CAAC,mBAAmB,CAAC,GAC7C,aAAa,CAAC,mBAAmB,CAAC,CAUpC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mCAAmC,CACjD,UAAU,EAAE,aAAa,CAAC,mBAAmB,CAAC,GAC7C,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAqBtE;AAihDD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,GAAG,uBAAuB,CAyBnF"}