@wildo-ai/saas-technical-doc 1.1.1 → 1.1.3

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 (123) hide show
  1. package/dist/esm/companion/application-documentation/application-administration-documentation.d.ts +52 -0
  2. package/dist/esm/companion/application-documentation/application-administration-documentation.d.ts.map +1 -0
  3. package/dist/esm/companion/application-documentation/application-administration-documentation.js +58 -0
  4. package/dist/esm/companion/application-documentation/application-administration-documentation.js.map +1 -0
  5. package/dist/esm/companion/application-documentation/application-authentication-documentation.d.ts +76 -0
  6. package/dist/esm/companion/application-documentation/application-authentication-documentation.d.ts.map +1 -0
  7. package/dist/esm/companion/application-documentation/application-authentication-documentation.js +116 -0
  8. package/dist/esm/companion/application-documentation/application-authentication-documentation.js.map +1 -0
  9. package/dist/esm/companion/application-documentation/application-connection-documentation.d.ts +111 -0
  10. package/dist/esm/companion/application-documentation/application-connection-documentation.d.ts.map +1 -0
  11. package/dist/esm/companion/application-documentation/application-connection-documentation.js +165 -0
  12. package/dist/esm/companion/application-documentation/application-connection-documentation.js.map +1 -0
  13. package/dist/esm/companion/application-documentation/application-domain-documentation.d.ts +133 -0
  14. package/dist/esm/companion/application-documentation/application-domain-documentation.d.ts.map +1 -0
  15. package/dist/esm/companion/application-documentation/application-domain-documentation.js +243 -0
  16. package/dist/esm/companion/application-documentation/application-domain-documentation.js.map +1 -0
  17. package/dist/esm/companion/application-documentation/application-integration-documentation.d.ts +48 -0
  18. package/dist/esm/companion/application-documentation/application-integration-documentation.d.ts.map +1 -0
  19. package/dist/esm/companion/application-documentation/application-integration-documentation.js +86 -0
  20. package/dist/esm/companion/application-documentation/application-integration-documentation.js.map +1 -0
  21. package/dist/esm/companion/application-documentation/application-organization-role-documentation.d.ts +30 -0
  22. package/dist/esm/companion/application-documentation/application-organization-role-documentation.d.ts.map +1 -1
  23. package/dist/esm/companion/application-documentation/application-organization-role-documentation.js +38 -0
  24. package/dist/esm/companion/application-documentation/application-organization-role-documentation.js.map +1 -1
  25. package/dist/esm/companion/application-documentation/technical-documentation-engine-content-bundle.d.ts +82 -4
  26. package/dist/esm/companion/application-documentation/technical-documentation-engine-content-bundle.d.ts.map +1 -1
  27. package/dist/esm/companion/application-documentation/technical-documentation-engine-content-bundle.js +412 -219
  28. package/dist/esm/companion/application-documentation/technical-documentation-engine-content-bundle.js.map +1 -1
  29. package/dist/esm/companion/application-documentation/technical-documentation-private-derivation.d.ts +10 -0
  30. package/dist/esm/companion/application-documentation/technical-documentation-private-derivation.d.ts.map +1 -1
  31. package/dist/esm/companion/application-documentation/technical-documentation-private-derivation.js +9 -1
  32. package/dist/esm/companion/application-documentation/technical-documentation-private-derivation.js.map +1 -1
  33. package/dist/esm/companion/application-documentation/technical-documentation-publication-policy.js +1 -1
  34. package/dist/esm/companion/application-documentation/technical-documentation-publication-policy.js.map +1 -1
  35. package/dist/esm/companion/index.d.ts +6 -1
  36. package/dist/esm/companion/index.d.ts.map +1 -1
  37. package/dist/esm/companion/index.js +6 -1
  38. package/dist/esm/companion/index.js.map +1 -1
  39. package/dist/esm/companion/manual-controller-route-projection.d.ts +112 -0
  40. package/dist/esm/companion/manual-controller-route-projection.d.ts.map +1 -0
  41. package/dist/esm/companion/manual-controller-route-projection.js +249 -0
  42. package/dist/esm/companion/manual-controller-route-projection.js.map +1 -0
  43. package/dist/esm/companion/openapi-generator.d.ts +16 -0
  44. package/dist/esm/companion/openapi-generator.d.ts.map +1 -1
  45. package/dist/esm/companion/openapi-generator.js +497 -32
  46. package/dist/esm/companion/openapi-generator.js.map +1 -1
  47. package/dist/esm/companion/operation-projection.schemas.d.ts +44 -0
  48. package/dist/esm/companion/operation-projection.schemas.d.ts.map +1 -1
  49. package/dist/esm/companion/operation-projection.schemas.js +37 -0
  50. package/dist/esm/companion/operation-projection.schemas.js.map +1 -1
  51. package/dist/esm/companion/rendering/technical-documentation-docusaurus-renderer.d.ts +7 -1
  52. package/dist/esm/companion/rendering/technical-documentation-docusaurus-renderer.d.ts.map +1 -1
  53. package/dist/esm/companion/rendering/technical-documentation-docusaurus-renderer.js +44 -20
  54. package/dist/esm/companion/rendering/technical-documentation-docusaurus-renderer.js.map +1 -1
  55. package/dist/esm/companion/rendering/technical-documentation-managed-tree-validator.d.ts.map +1 -1
  56. package/dist/esm/companion/rendering/technical-documentation-managed-tree-validator.js +8 -1
  57. package/dist/esm/companion/rendering/technical-documentation-managed-tree-validator.js.map +1 -1
  58. package/dist/esm/companion/rendering/technical-documentation-markdown-links.d.ts +28 -0
  59. package/dist/esm/companion/rendering/technical-documentation-markdown-links.d.ts.map +1 -0
  60. package/dist/esm/companion/rendering/technical-documentation-markdown-links.js +52 -0
  61. package/dist/esm/companion/rendering/technical-documentation-markdown-links.js.map +1 -0
  62. package/dist/esm/companion/rendering/technical-documentation-markdown-renderer.d.ts +0 -9
  63. package/dist/esm/companion/rendering/technical-documentation-markdown-renderer.d.ts.map +0 -1
  64. package/dist/esm/companion/rendering/technical-documentation-markdown-renderer.js +0 -106
  65. package/dist/esm/companion/rendering/technical-documentation-markdown-renderer.js.map +0 -1
  66. package/dist/esm/companion/rendering/technical-documentation-render-model.d.ts +1 -0
  67. package/dist/esm/companion/rendering/technical-documentation-render-model.d.ts.map +1 -1
  68. package/dist/esm/companion/rendering/technical-documentation-render-model.js +112 -88
  69. package/dist/esm/companion/rendering/technical-documentation-render-model.js.map +1 -1
  70. package/dist/esm/companion/rendering/technical-documentation-search-index-renderer.d.ts +10 -0
  71. package/dist/esm/companion/rendering/technical-documentation-search-index-renderer.d.ts.map +1 -1
  72. package/dist/esm/companion/rendering/technical-documentation-search-index-renderer.js +10 -15
  73. package/dist/esm/companion/rendering/technical-documentation-search-index-renderer.js.map +1 -1
  74. package/dist/esm/companion/technical-documentation-capture-execution-port.d.ts +27 -1
  75. package/dist/esm/companion/technical-documentation-capture-execution-port.d.ts.map +1 -1
  76. package/dist/esm/companion/technical-documentation-capture-execution-port.js.map +1 -1
  77. package/dist/esm/companion/technical-documentation-diagram-definitions.d.ts +33 -0
  78. package/dist/esm/companion/technical-documentation-diagram-definitions.d.ts.map +1 -0
  79. package/dist/esm/companion/technical-documentation-diagram-definitions.js +54 -0
  80. package/dist/esm/companion/technical-documentation-diagram-definitions.js.map +1 -0
  81. package/dist/esm/companion/technical-documentation-diagram-materializer.d.ts +10 -18
  82. package/dist/esm/companion/technical-documentation-diagram-materializer.d.ts.map +1 -1
  83. package/dist/esm/companion/technical-documentation-diagram-materializer.js +9 -39
  84. package/dist/esm/companion/technical-documentation-diagram-materializer.js.map +1 -1
  85. package/dist/esm/config/wildo-tech-doc-config.schemas.d.ts +8 -4
  86. package/dist/esm/config/wildo-tech-doc-config.schemas.d.ts.map +1 -1
  87. package/dist/esm/config/wildo-tech-doc-config.schemas.js +8 -4
  88. package/dist/esm/config/wildo-tech-doc-config.schemas.js.map +1 -1
  89. package/dist/esm/content/application-consumer-documentation-content.techdoc.d.ts +105 -122
  90. package/dist/esm/content/application-consumer-documentation-content.techdoc.d.ts.map +1 -1
  91. package/dist/esm/content/application-consumer-documentation-content.techdoc.js +934 -2161
  92. package/dist/esm/content/application-consumer-documentation-content.techdoc.js.map +1 -1
  93. package/dist/esm/runtime/DocsAuthContext.d.ts +16 -1
  94. package/dist/esm/runtime/DocsAuthContext.d.ts.map +1 -1
  95. package/dist/esm/runtime/DocsAuthContext.js +18 -2
  96. package/dist/esm/runtime/DocsAuthContext.js.map +1 -1
  97. package/dist/esm/runtime/decode-jwt-claims.d.ts +7 -4
  98. package/dist/esm/runtime/decode-jwt-claims.d.ts.map +1 -1
  99. package/dist/esm/runtime/decode-jwt-claims.js +7 -4
  100. package/dist/esm/runtime/decode-jwt-claims.js.map +1 -1
  101. package/dist/esm/runtime/docs-auth-session.schemas.d.ts +16 -5
  102. package/dist/esm/runtime/docs-auth-session.schemas.d.ts.map +1 -1
  103. package/dist/esm/runtime/docs-auth-session.schemas.js +16 -5
  104. package/dist/esm/runtime/docs-auth-session.schemas.js.map +1 -1
  105. package/dist/esm/runtime/frontend-provider-registry.techdoc.d.ts +35 -13
  106. package/dist/esm/runtime/frontend-provider-registry.techdoc.d.ts.map +1 -1
  107. package/dist/esm/runtime/frontend-provider-registry.techdoc.js +28 -19
  108. package/dist/esm/runtime/frontend-provider-registry.techdoc.js.map +1 -1
  109. package/dist/esm/runtime/index.d.ts +1 -0
  110. package/dist/esm/runtime/index.d.ts.map +1 -1
  111. package/dist/esm/runtime/index.js +1 -0
  112. package/dist/esm/runtime/index.js.map +1 -1
  113. package/dist/esm/runtime/use-docs-auth-session.d.ts +9 -7
  114. package/dist/esm/runtime/use-docs-auth-session.d.ts.map +1 -1
  115. package/dist/esm/runtime/use-docs-auth-session.js +9 -7
  116. package/dist/esm/runtime/use-docs-auth-session.js.map +1 -1
  117. package/dist/esm/runtime/use-docs-provider-sdks.d.ts +21 -0
  118. package/dist/esm/runtime/use-docs-provider-sdks.d.ts.map +1 -0
  119. package/dist/esm/runtime/use-docs-provider-sdks.js +49 -0
  120. package/dist/esm/runtime/use-docs-provider-sdks.js.map +1 -0
  121. package/dist/tsconfig.build.tsbuildinfo +1 -1
  122. package/package.json +6 -5
  123. package/dist/esm/.builder.pid +0 -9
@@ -1,6 +1,15 @@
1
+ import { IMPLICIT_LEAD_SECTION_HEADING } from '../rendering/technical-documentation-markdown-links.js';
2
+ import { APPLICATION_CONNECTION_DOCUMENTATION_SOURCE_REF, } from './application-connection-documentation.js';
3
+ import { APPLICATION_AUTHENTICATION_DOCUMENTATION_SOURCE_REF, } from './application-authentication-documentation.js';
4
+ import { APPLICATION_INTEGRATION_DOCUMENTATION_SOURCE_REF, } from './application-integration-documentation.js';
5
+ import { APPLICATION_DOMAIN_DOCUMENTATION_SOURCE_REF, } from './application-domain-documentation.js';
6
+ import { APPLICATION_ADMINISTRATION_DOCUMENTATION_SOURCE_REF, } from './application-administration-documentation.js';
1
7
  import { canonicalizeTechnicalDocumentationJson, TechnicalDocumentationAccessClass, TechnicalDocumentationApiReferenceSection, TechnicalDocumentationApiReferenceTargetKind, TechnicalDocumentationApplicabilityEvidenceAxis, TechnicalDocumentationApplicabilityEvidenceStatus, TechnicalDocumentationEditorialStatus, TechnicalDocumentationEvidenceSubjectRef, TechnicalDocumentationLinkKind, TechnicalDocumentationReaderAudience, TechnicalDocumentationSourceClassification, TechnicalDocumentationSourceOwnership, TechnicalDocumentationUnitKind, createTechnicalDocumentationUnitV1, } from '@wildo-ai/saas-specifications/technical-documentation';
2
8
  import { EngineDocumentationSpecificationFamilyRef, } from '@wildo-ai/saas-specifications/companion';
3
9
  import { APPLICATION_CONSUMER_DOCUMENTATION_CONSUMER_FACT_SOURCE_PREFIX, APPLICATION_CONSUMER_DOCUMENTATION_ENGINE_CONTENT_SOURCE_PREFIX, } from '../../content/application-consumer-documentation-content-manifest.schemas.js';
10
+ // From the DECLARATIONS module, never the materializer: the materializer imports the render model,
11
+ // which imports this file, and naming a diagram here at module load closes that cycle (#474).
12
+ import { createTechnicalDocumentationApplicationRequestDiagramAssetRequest } from '../technical-documentation-diagram-definitions.js';
4
13
  import { APPLICATION_ORGANIZATION_ROLES_DOCUMENTATION_SOURCE_REF } from './application-organization-role-documentation.js';
5
14
  import { APPLICATION_ORGANIZATION_UNIT_RESOURCES_DOCUMENTATION_SOURCE_REF, } from './application-organization-unit-resource-documentation.js';
6
15
  const PROVEN = [TechnicalDocumentationApplicabilityEvidenceStatus.PROVEN];
@@ -31,12 +40,6 @@ const ORGANIZATION_SIEM_RECOVERY_APPLICABILITY_REQUIREMENTS = [{
31
40
  subjectRef: TechnicalDocumentationEvidenceSubjectRef.ORGANIZATION_SIEM_DELIVERY_RECOVERY,
32
41
  acceptableStatuses: [...PROVEN],
33
42
  }];
34
- /** Billing is one operational journey; every page requires the admitted account and subscription surfaces. */
35
- const ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS = [{
36
- axis: TechnicalDocumentationApplicabilityEvidenceAxis.EXPOSED_API_SURFACE,
37
- subjectRef: TechnicalDocumentationEvidenceSubjectRef.ORGANIZATION_BILLING_ADMINISTRATION,
38
- acceptableStatuses: [...PROVEN],
39
- }];
40
43
  const MCP_INTEGRATION_APPLICABILITY_REQUIREMENTS = [{
41
44
  axis: TechnicalDocumentationApplicabilityEvidenceAxis.CONFIGURED_ACTIVATION,
42
45
  subjectRef: TechnicalDocumentationEvidenceSubjectRef.APPLICATION_MCP_TOOL_SURFACE,
@@ -50,6 +53,21 @@ const A2A_INTEGRATION_APPLICABILITY_REQUIREMENTS = [{
50
53
  const CONSUMER_FACT_TOKEN_PATTERN = /\{\{CONSUMER_FACT:([^#}]+)#([^}]+)\}\}/g;
51
54
  const APPLICATION_ORGANIZATION_ROLES_TOKEN = '{{APPLICATION_ORGANIZATION_ROLES}}';
52
55
  const APPLICATION_ORGANIZATION_UNIT_RESOURCES_TOKEN = '{{APPLICATION_ORGANIZATION_UNIT_RESOURCES}}';
56
+ /** Inline, and deliberately repeatable: a page names the product as often as its prose needs it. */
57
+ const APPLICATION_NAME_TOKEN = '{{APPLICATION_NAME}}';
58
+ /** Block, one per requested presentation — `{{APPLICATION_CONNECTION:baseUrls}}` and siblings. */
59
+ // A selector may carry digits (`a2aAgentCard`), which an alphabetic-only class silently refuses:
60
+ // the token then matches nothing and its page reads as declaring a projection it never used.
61
+ const APPLICATION_CONNECTION_TOKEN_PATTERN = /\{\{APPLICATION_CONNECTION:([A-Za-z0-9]+)\}\}/g;
62
+ /** Inline connection values, for use inside a sample where a block cannot go. */
63
+ const APPLICATION_CONNECTION_VALUE_TOKEN_PATTERN = /\{\{APPLICATION_CONNECTION_VALUE:([A-Za-z0-9]+)\}\}/g;
64
+ /** Same shape for the application's authentication policy. */
65
+ const APPLICATION_AUTHENTICATION_TOKEN_PATTERN = /\{\{APPLICATION_AUTHENTICATION:([A-Za-z0-9]+)\}\}/g;
66
+ /** Same shape again for who may perform each administrative action. */
67
+ const APPLICATION_ADMINISTRATION_TOKEN_PATTERN = /\{\{APPLICATION_ADMINISTRATION:([A-Za-z0-9]+)\}\}/g;
68
+ /** Same shape again for the tools and events this application publishes. */
69
+ const APPLICATION_INTEGRATION_TOKEN_PATTERN = /\{\{APPLICATION_INTEGRATION:([A-Za-z0-9]+)\}\}/g;
70
+ const APPLICATION_DOMAIN_TOKEN_PATTERN = /\{\{APPLICATION_DOMAIN:([A-Za-z0-9]+)\}\}/g;
53
71
  /**
54
72
  * Build one semantic guide-to-reference link without embedding a Docusaurus
55
73
  * route. The verified OpenAPI link index resolves the resource only when the
@@ -93,7 +111,6 @@ const scimProvisioningConfigApiReferenceTarget = () => resourceApiReferenceTarge
93
111
  const auditLogsApiReferenceTarget = () => resourceApiReferenceTarget('Audit records API reference', 'auditLogs');
94
112
  const organizationSiemExportConfigApiReferenceTarget = () => resourceApiReferenceTarget('Organization SIEM export configuration API reference', 'organizationSiemExportConfig');
95
113
  const organizationSiemDeliveryDlqApiReferenceTarget = () => resourceApiReferenceTarget('Organization SIEM delivery recovery API reference', 'organizationSiemDeliveryDlq');
96
- const organizationBillingAccountApiReferenceTarget = () => resourceApiReferenceTarget('Organization billing account API reference', 'organizationBillingAccounts');
97
114
  const organizationSubscriptionsApiReferenceTarget = () => resourceApiReferenceTarget('Organization subscriptions API reference', 'organizationSubscriptions');
98
115
  const organizationInvoiceRefsApiReferenceTarget = () => resourceApiReferenceTarget('Organization invoice summaries API reference', 'organizationInvoiceRefs');
99
116
  const organizationUsageRecordsApiReferenceTarget = () => resourceApiReferenceTarget('Organization usage records API reference', 'organizationUsageRecords');
@@ -105,6 +122,74 @@ const organizationUsageRecordsApiReferenceTarget = () => resourceApiReferenceTar
105
122
  * and title; this map owns type, audience, publication posture and navigation
106
123
  * relationships, allowing the projector to reject a mismatched content set.
107
124
  */
125
+ /**
126
+ * The unit-ref namespace generated resource pages live in, and the only place its shape is written.
127
+ *
128
+ * `technical-documentation:unit/manages/<resource>` — an ENGINE ref with a reserved segment, not an
129
+ * application-owned one. The distinction is load-bearing: `pathForUnit` still refuses a unit an
130
+ * application named, and these are engine units whose subject happens to come from the application.
131
+ */
132
+ export function applicationDomainResourcePageUnitRef(resourceIdentifier) {
133
+ return `technical-documentation:unit/manages/${resourceIdentifier}`;
134
+ }
135
+ /** The unit-ref prefix a renderer matches to recognise a generated resource page. */
136
+ export const APPLICATION_DOMAIN_RESOURCE_PAGE_UNIT_REF_PREFIX = 'technical-documentation:unit/manages/';
137
+ /**
138
+ * One definition shared by every generated resource page.
139
+ *
140
+ * A per-resource entry in `ENGINE_CONTENT_UNIT_DEFINITIONS` is impossible by construction — the
141
+ * resources are not known when this module is written — and it would be the wrong shape anyway:
142
+ * these pages differ only in subject, so a per-resource definition would be N copies of one answer
143
+ * with N chances to drift.
144
+ */
145
+ const GENERATED_RESOURCE_UNIT_DEFINITION = Object.freeze({
146
+ kind: TechnicalDocumentationUnitKind.REFERENCE,
147
+ readerAudiences: [
148
+ TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
149
+ TechnicalDocumentationReaderAudience.CONSUMING_INTERNAL_SERVICE,
150
+ TechnicalDocumentationReaderAudience.EXTERNAL_INTEGRATION_DEVELOPER,
151
+ TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
152
+ TechnicalDocumentationReaderAudience.ORGANIZATION_INTEGRATION_DEVELOPER,
153
+ ],
154
+ accessClass: TechnicalDocumentationAccessClass.PUBLIC,
155
+ /*
156
+ * APPROVED, explicitly. A generated per-resource page is emitted only for a resource the
157
+ * application actually publishes, so there is no draft state for it to be in — but the value is
158
+ * declared rather than defaulted because the authored tier can now say otherwise, and a reader
159
+ * comparing the two tiers should see the answer rather than infer it from an absence.
160
+ */
161
+ editorialStatus: TechnicalDocumentationEditorialStatus.APPROVED,
162
+ /*
163
+ * No assets. A generated per-resource page describes ONE application resource, and there is no
164
+ * engine-authored picture of a resource the engine has never seen — a diagram here would depict
165
+ * the framework's idea of a resource rather than this one. Declared empty rather than omitted so
166
+ * the absence reads as a decision beside the authored tier, which does request one.
167
+ */
168
+ assetRequests: [],
169
+ });
170
+ /**
171
+ * Unit kinds this catalog deliberately produces NO unit for, each with the reason.
172
+ *
173
+ * The vocabulary has eight members and, until 2026-09-09, two of them had no producer at all — a
174
+ * silent gap, because a kind nobody authors looks exactly like a kind nobody needed (#474). RUNBOOK
175
+ * now has one. CHANGE does not, and the reason is structural rather than editorial:
176
+ *
177
+ * A CHANGE unit is a record of what changed in ONE application, so only that application could
178
+ * author it — and an application-authored unit cannot be routed. `pathForUnit` admits engine-
179
+ * namespaced slugs and the reserved `unit/manages/` namespace, and refuses everything else with
180
+ * "has no consumer navigation category". Application material reaches the site only as an ENGINE
181
+ * unit carrying application-projected facts, never as an application-authored page. So the engine
182
+ * cannot write a changelog it has no knowledge of, and the party that could has no door.
183
+ *
184
+ * The member is therefore kept rather than retired: what is missing is a route for
185
+ * application-authored units, not the concept. When that route exists, this entry is removed in the
186
+ * same change — and `technical-documentation-engine-content-bundle.test.ts` fails until it is,
187
+ * because the partition below is asserted total over the enum.
188
+ */
189
+ export const ENGINE_CONTENT_UNIT_KINDS_WITHOUT_PRODUCER = {
190
+ [TechnicalDocumentationUnitKind.CHANGE]: 'A change record belongs to one application, and an application-authored unit has no route — `pathForUnit` '
191
+ + 'admits only engine-namespaced slugs and the reserved `unit/manages/` namespace. Blocked on routing, not on authoring.',
192
+ };
108
193
  export const ENGINE_CONTENT_UNIT_DEFINITIONS = Object.freeze({
109
194
  'technical-documentation:unit/application-orientation': {
110
195
  kind: TechnicalDocumentationUnitKind.ORIENTATION,
@@ -123,6 +208,34 @@ export const ENGINE_CONTENT_UNIT_DEFINITIONS = Object.freeze({
123
208
  'technical-documentation:unit/first-request',
124
209
  ],
125
210
  },
211
+ 'technical-documentation:unit/what-this-application-manages': {
212
+ kind: TechnicalDocumentationUnitKind.ORIENTATION,
213
+ /*
214
+ * Every audience, because this is the one page that answers "what IS this?" — the question
215
+ * that comes before the reason any of them opened the documentation. An operator, an
216
+ * integrator and an organization administrator all need it, and none of them should have to
217
+ * infer the product from the pages about administering it.
218
+ */
219
+ readerAudiences: [
220
+ TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
221
+ TechnicalDocumentationReaderAudience.CONSUMING_INTERNAL_SERVICE,
222
+ TechnicalDocumentationReaderAudience.EXTERNAL_INTEGRATION_DEVELOPER,
223
+ TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
224
+ TechnicalDocumentationReaderAudience.ORGANIZATION_INTEGRATION_DEVELOPER,
225
+ ],
226
+ accessClass: TechnicalDocumentationAccessClass.PUBLIC,
227
+ /*
228
+ * No applicability requirement. An application with no resources of its own still publishes
229
+ * this page, and the projection says so in a sentence — suppressing it would leave a reader
230
+ * unable to tell "manages nothing through its API" from "nobody wrote this page".
231
+ */
232
+ applicabilityRequirements: [],
233
+ relatedUnitRefs: [
234
+ 'technical-documentation:unit/first-request',
235
+ 'technical-documentation:unit/webhooks',
236
+ 'technical-documentation:unit/organization-roles',
237
+ ],
238
+ },
126
239
  'technical-documentation:unit/authentication': {
127
240
  kind: TechnicalDocumentationUnitKind.ORIENTATION,
128
241
  readerAudiences: [
@@ -983,8 +1096,18 @@ export const ENGINE_CONTENT_UNIT_DEFINITIONS = Object.freeze({
983
1096
  ],
984
1097
  apiReferenceTargets: [organizationSiemDeliveryDlqApiReferenceTarget()],
985
1098
  },
986
- 'technical-documentation:unit/protect-and-retain-audit-evidence': {
987
- kind: TechnicalDocumentationUnitKind.CONCEPT,
1099
+ /*
1100
+ * The catalog's first RUNBOOK, and the kind had no producer until 2026-09-09 (#474).
1101
+ *
1102
+ * It is not a re-labelled HOW_TO. Every other page in this section explains ONE capability;
1103
+ * `operate-webhook-deliveries` was checked first and is genuinely explanatory — statuses, a retry
1104
+ * ladder, monitoring advice — which is why re-kinding it to fill the vocabulary was rejected. A
1105
+ * RUNBOOK is an ORDER under time pressure, and the ordering is the content: contain before you
1106
+ * assess, assess before you recover, and loop back to contain when the assessment finds a change.
1107
+ * No existing page says what to do FIRST.
1108
+ */
1109
+ 'technical-documentation:unit/respond-to-leaked-credential': {
1110
+ kind: TechnicalDocumentationUnitKind.RUNBOOK,
988
1111
  readerAudiences: [
989
1112
  TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
990
1113
  TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
@@ -992,176 +1115,29 @@ export const ENGINE_CONTENT_UNIT_DEFINITIONS = Object.freeze({
992
1115
  accessClass: TechnicalDocumentationAccessClass.PUBLIC,
993
1116
  applicabilityRequirements: [],
994
1117
  relatedUnitRefs: [
995
- 'technical-documentation:unit/audit-and-siem',
1118
+ 'technical-documentation:unit/api-keys-lifecycle',
1119
+ 'technical-documentation:unit/oauth-operate-and-revoke',
1120
+ 'technical-documentation:unit/suspend-or-remove-user',
1121
+ 'technical-documentation:unit/investigate-audit-event',
1122
+ 'technical-documentation:unit/review-privileged-and-access-changes',
996
1123
  'technical-documentation:unit/export-audit-records',
997
- 'technical-documentation:unit/operate-and-troubleshoot-siem-delivery',
998
- ],
999
- apiReferenceTargets: [auditLogsApiReferenceTarget()],
1000
- },
1001
- 'technical-documentation:unit/billing': {
1002
- kind: TechnicalDocumentationUnitKind.ORIENTATION,
1003
- readerAudiences: [
1004
- TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
1005
- TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
1006
- ],
1007
- accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1008
- applicabilityRequirements: ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS,
1009
- relatedUnitRefs: [
1010
- 'technical-documentation:unit/understand-billing-plans-and-access',
1011
- 'technical-documentation:unit/start-billing-subscription',
1012
- 'technical-documentation:unit/change-or-end-billing-subscription',
1013
- 'technical-documentation:unit/billing-records-and-usage',
1014
- 'technical-documentation:unit/reconcile-billing-and-access',
1015
- 'technical-documentation:unit/troubleshoot-billing-change',
1016
- 'technical-documentation:unit/audit-and-siem',
1017
- ],
1018
- apiReferenceTargets: [
1019
- organizationBillingAccountApiReferenceTarget(),
1020
- organizationSubscriptionsApiReferenceTarget(),
1021
- ],
1022
- },
1023
- 'technical-documentation:unit/understand-billing-plans-and-access': {
1024
- kind: TechnicalDocumentationUnitKind.CONCEPT,
1025
- readerAudiences: [
1026
- TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
1027
- TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
1028
- ],
1029
- accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1030
- applicabilityRequirements: ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS,
1031
- relatedUnitRefs: [
1032
- 'technical-documentation:unit/billing',
1033
- 'technical-documentation:unit/start-billing-subscription',
1034
- 'technical-documentation:unit/reconcile-billing-and-access',
1035
- ],
1036
- apiReferenceTargets: [organizationBillingAccountApiReferenceTarget()],
1037
- },
1038
- 'technical-documentation:unit/start-billing-subscription': {
1039
- kind: TechnicalDocumentationUnitKind.HOW_TO,
1040
- readerAudiences: [TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR],
1041
- accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1042
- applicabilityRequirements: ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS,
1043
- relatedUnitRefs: [
1044
- 'technical-documentation:unit/billing',
1045
- 'technical-documentation:unit/understand-billing-plans-and-access',
1046
- 'technical-documentation:unit/reconcile-billing-and-access',
1047
- 'technical-documentation:unit/troubleshoot-billing-change',
1048
- ],
1049
- apiReferenceTargets: [
1050
- operationFamilyApiReferenceTarget('Open an organization checkout', 'organizationBillingAccounts', 'open_checkout'),
1051
- ],
1052
- },
1053
- 'technical-documentation:unit/change-or-end-billing-subscription': {
1054
- kind: TechnicalDocumentationUnitKind.HOW_TO,
1055
- readerAudiences: [TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR],
1056
- accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1057
- applicabilityRequirements: ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS,
1058
- relatedUnitRefs: [
1059
- 'technical-documentation:unit/billing',
1060
- 'technical-documentation:unit/understand-billing-plans-and-access',
1061
- 'technical-documentation:unit/reconcile-billing-and-access',
1062
- 'technical-documentation:unit/troubleshoot-billing-change',
1063
- ],
1064
- apiReferenceTargets: [
1065
- operationFamilyApiReferenceTarget('Change an organization subscription plan', 'organizationSubscriptions', 'change_plan'),
1066
- operationFamilyApiReferenceTarget('Cancel an organization subscription', 'organizationSubscriptions', 'cancel'),
1067
- operationFamilyApiReferenceTarget('Resume an organization subscription', 'organizationSubscriptions', 'resume'),
1068
- ],
1069
- },
1070
- 'technical-documentation:unit/manage-invoices-and-payments': {
1071
- kind: TechnicalDocumentationUnitKind.CONCEPT,
1072
- readerAudiences: [
1073
- TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
1074
- TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
1075
- ],
1076
- accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1077
- applicabilityRequirements: ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS,
1078
- relatedUnitRefs: [
1079
- 'technical-documentation:unit/billing',
1080
- 'technical-documentation:unit/billing-records-and-usage',
1081
- 'technical-documentation:unit/reconcile-billing-and-access',
1082
- 'technical-documentation:unit/understand-metered-usage',
1083
1124
  'technical-documentation:unit/protect-and-retain-audit-evidence',
1084
1125
  ],
1085
- apiReferenceTargets: [
1086
- organizationInvoiceRefsApiReferenceTarget(),
1087
- operationFamilyApiReferenceTarget('Open the authenticated billing portal', 'organizationBillingAccounts', 'open_portal'),
1088
- ],
1089
- },
1090
- 'technical-documentation:unit/billing-records-and-usage': {
1091
- kind: TechnicalDocumentationUnitKind.ORIENTATION,
1092
- readerAudiences: [
1093
- TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
1094
- TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
1095
- ],
1096
- accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1097
- applicabilityRequirements: ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS,
1098
- relatedUnitRefs: [
1099
- 'technical-documentation:unit/billing',
1100
- 'technical-documentation:unit/manage-invoices-and-payments',
1101
- 'technical-documentation:unit/understand-metered-usage',
1102
- 'technical-documentation:unit/reconcile-billing-and-access',
1103
- 'technical-documentation:unit/troubleshoot-billing-change',
1104
- ],
1105
- apiReferenceTargets: [
1106
- organizationInvoiceRefsApiReferenceTarget(),
1107
- organizationUsageRecordsApiReferenceTarget(),
1108
- ],
1109
1126
  },
1110
- 'technical-documentation:unit/understand-metered-usage': {
1127
+ 'technical-documentation:unit/protect-and-retain-audit-evidence': {
1111
1128
  kind: TechnicalDocumentationUnitKind.CONCEPT,
1112
1129
  readerAudiences: [
1113
1130
  TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
1114
1131
  TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
1115
1132
  ],
1116
1133
  accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1117
- applicabilityRequirements: ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS,
1118
- relatedUnitRefs: [
1119
- 'technical-documentation:unit/billing',
1120
- 'technical-documentation:unit/billing-records-and-usage',
1121
- 'technical-documentation:unit/manage-invoices-and-payments',
1122
- 'technical-documentation:unit/reconcile-billing-and-access',
1123
- 'technical-documentation:unit/troubleshoot-billing-change',
1124
- ],
1125
- apiReferenceTargets: [organizationUsageRecordsApiReferenceTarget()],
1126
- },
1127
- 'technical-documentation:unit/reconcile-billing-and-access': {
1128
- kind: TechnicalDocumentationUnitKind.HOW_TO,
1129
- readerAudiences: [
1130
- TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
1131
- TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
1132
- ],
1133
- accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1134
- applicabilityRequirements: ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS,
1134
+ applicabilityRequirements: [],
1135
1135
  relatedUnitRefs: [
1136
- 'technical-documentation:unit/billing',
1137
- 'technical-documentation:unit/manage-invoices-and-payments',
1138
- 'technical-documentation:unit/understand-metered-usage',
1139
- 'technical-documentation:unit/troubleshoot-billing-change',
1140
1136
  'technical-documentation:unit/audit-and-siem',
1137
+ 'technical-documentation:unit/export-audit-records',
1138
+ 'technical-documentation:unit/operate-and-troubleshoot-siem-delivery',
1141
1139
  ],
1142
- apiReferenceTargets: [
1143
- operationFamilyApiReferenceTarget('Read aggregated organization billing state', 'organizationBillingAccounts', 'get_state'),
1144
- organizationSubscriptionsApiReferenceTarget(),
1145
- ],
1146
- },
1147
- 'technical-documentation:unit/troubleshoot-billing-change': {
1148
- kind: TechnicalDocumentationUnitKind.TROUBLESHOOTING,
1149
- readerAudiences: [
1150
- TechnicalDocumentationReaderAudience.APPLICATION_OPERATIONS_STAFF,
1151
- TechnicalDocumentationReaderAudience.ORGANIZATION_ADMINISTRATOR,
1152
- ],
1153
- accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1154
- applicabilityRequirements: ORGANIZATION_BILLING_APPLICABILITY_REQUIREMENTS,
1155
- relatedUnitRefs: [
1156
- 'technical-documentation:unit/billing',
1157
- 'technical-documentation:unit/reconcile-billing-and-access',
1158
- 'technical-documentation:unit/manage-invoices-and-payments',
1159
- 'technical-documentation:unit/understand-metered-usage',
1160
- ],
1161
- apiReferenceTargets: [
1162
- organizationBillingAccountApiReferenceTarget(),
1163
- organizationSubscriptionsApiReferenceTarget(),
1164
- ],
1140
+ apiReferenceTargets: [auditLogsApiReferenceTarget()],
1165
1141
  },
1166
1142
  'technical-documentation:unit/integrations': {
1167
1143
  kind: TechnicalDocumentationUnitKind.ORIENTATION,
@@ -1346,6 +1322,17 @@ export const ENGINE_CONTENT_UNIT_DEFINITIONS = Object.freeze({
1346
1322
  'technical-documentation:unit/api-keys',
1347
1323
  'technical-documentation:unit/common-rest-api',
1348
1324
  ],
1325
+ /*
1326
+ * The FIRST asset any engine page has ever requested (#474), and deliberately the deterministic
1327
+ * one rather than a screenshot: it materializes offline, from a frozen definition, with no
1328
+ * browser, no provisioned tenant and no live stack — so the asset path is exercised on every
1329
+ * publication rather than only where a capture happens to be available.
1330
+ *
1331
+ * It belongs on this page because the diagram IS this page: a client sending an authenticated
1332
+ * request through the application API to a documented resource is what "send your first
1333
+ * request" describes in prose.
1334
+ */
1335
+ assetRequests: [createTechnicalDocumentationApplicationRequestDiagramAssetRequest()],
1349
1336
  },
1350
1337
  'technical-documentation:unit/common-rest-api': {
1351
1338
  kind: TechnicalDocumentationUnitKind.CONCEPT,
@@ -1357,6 +1344,7 @@ export const ENGINE_CONTENT_UNIT_DEFINITIONS = Object.freeze({
1357
1344
  accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1358
1345
  applicabilityRequirements: [],
1359
1346
  relatedUnitRefs: [
1347
+ 'technical-documentation:unit/rest-api-conventions',
1360
1348
  'technical-documentation:unit/send-api-request',
1361
1349
  'technical-documentation:unit/work-with-api-collections',
1362
1350
  'technical-documentation:unit/write-and-reconcile-api-changes',
@@ -1370,6 +1358,29 @@ export const ENGINE_CONTENT_UNIT_DEFINITIONS = Object.freeze({
1370
1358
  },
1371
1359
  }],
1372
1360
  },
1361
+ 'technical-documentation:unit/rest-api-conventions': {
1362
+ kind: TechnicalDocumentationUnitKind.REFERENCE,
1363
+ readerAudiences: [
1364
+ TechnicalDocumentationReaderAudience.CONSUMING_INTERNAL_SERVICE,
1365
+ TechnicalDocumentationReaderAudience.EXTERNAL_INTEGRATION_DEVELOPER,
1366
+ TechnicalDocumentationReaderAudience.ORGANIZATION_INTEGRATION_DEVELOPER,
1367
+ ],
1368
+ accessClass: TechnicalDocumentationAccessClass.PUBLIC,
1369
+ applicabilityRequirements: [],
1370
+ relatedUnitRefs: [
1371
+ 'technical-documentation:unit/common-rest-api',
1372
+ 'technical-documentation:unit/send-api-request',
1373
+ 'technical-documentation:unit/write-and-reconcile-api-changes',
1374
+ 'technical-documentation:unit/troubleshoot-api-request',
1375
+ ],
1376
+ apiReferenceTargets: [{
1377
+ label: 'API reference',
1378
+ target: {
1379
+ section: TechnicalDocumentationApiReferenceSection.API_REFERENCE,
1380
+ kind: TechnicalDocumentationApiReferenceTargetKind.ROOT,
1381
+ },
1382
+ }],
1383
+ },
1373
1384
  'technical-documentation:unit/send-api-request': {
1374
1385
  kind: TechnicalDocumentationUnitKind.QUICKSTART,
1375
1386
  readerAudiences: [
@@ -1564,7 +1575,7 @@ function parseEngineMarkdown(markdown, unitRef) {
1564
1575
  throw new Error(`engine content ${unitRef} must begin with exactly one H1 title`);
1565
1576
  const title = titleLine.slice(2).trim();
1566
1577
  const sections = [];
1567
- let heading = 'Overview';
1578
+ let heading = IMPLICIT_LEAD_SECTION_HEADING;
1568
1579
  let body = [];
1569
1580
  const flush = () => {
1570
1581
  const bodyMarkdown = body.join('\n').trim();
@@ -1591,7 +1602,7 @@ function parseEngineMarkdown(markdown, unitRef) {
1591
1602
  // An explicit H2 is not rewritten: its author chose a real section and may
1592
1603
  // intentionally need the opening paragraph in its body.
1593
1604
  const [firstSection, ...remainingSections] = sections;
1594
- if (firstSection !== undefined && firstSection.heading === 'Overview') {
1605
+ if (firstSection !== undefined && firstSection.heading === IMPLICIT_LEAD_SECTION_HEADING) {
1595
1606
  const overviewRemainder = firstSection.bodyMarkdown.replace(/^.*?(?:\n\s*\n|$)/s, '').trim();
1596
1607
  return {
1597
1608
  title,
@@ -1733,6 +1744,117 @@ function resolveConsumerFactMarkdown(markdown, declaredSourceRefs, catalog) {
1733
1744
  entriesBySourceRef: new Map([...resolvedFactRefs].map((sourceRef) => [sourceRef, catalogEntriesBySourceRef.get(sourceRef)])),
1734
1745
  };
1735
1746
  }
1747
+ /**
1748
+ * Substitutes a companion projection that offers NAMED PRESENTATIONS, and optionally one inline
1749
+ * value repeated as often as the prose needs it.
1750
+ *
1751
+ * Shared by the connection and authentication projections because both have the same shape and the
1752
+ * same three failure modes: a page that uses a token without declaring the source, a page that
1753
+ * declares the source and uses no token, and a page that asks for a presentation the projection
1754
+ * does not offer. Each must fail the publication rather than render something plausible.
1755
+ */
1756
+ function resolveSelectorProjectionMarkdown(input) {
1757
+ const { markdown, declaredSourceRefs, sourceRef, label, fact, selectorPattern, presentationFor, inline, inlineSelector } = input;
1758
+ const declaredRefs = declaredSourceRefs.filter((candidate) => candidate === sourceRef);
1759
+ const inlineCount = inline === undefined ? 0 : markdown.split(inline.token).length - 1;
1760
+ const selectorCount = [...markdown.matchAll(selectorPattern)].length;
1761
+ const inlineSelectorCount = inlineSelector === undefined ? 0 : [...markdown.matchAll(inlineSelector.pattern)].length;
1762
+ if (inlineCount === 0 && selectorCount === 0 && inlineSelectorCount === 0) {
1763
+ if (declaredRefs.length > 0)
1764
+ throw new Error(`engine content declares an unused ${label} projection: ${declaredRefs.join(', ')}`);
1765
+ return { markdown, fact: undefined };
1766
+ }
1767
+ if (declaredRefs.length !== 1 || fact === undefined || declaredRefs[0] !== fact.sourceRef) {
1768
+ throw new Error(`engine content ${label} projection must declare and resolve exactly one matching companion source`);
1769
+ }
1770
+ const withInline = inline === undefined ? markdown : markdown.split(inline.token).join(inline.valueFor(fact));
1771
+ const withInlineSelectors = inlineSelector === undefined ? withInline : withInline.replace(inlineSelector.pattern, (_token, selector) => {
1772
+ const value = inlineSelector.valueFor(fact, selector);
1773
+ if (value === undefined || value.trim().length === 0) {
1774
+ throw new Error(`engine content requests an unknown or empty ${label} inline value: ${selector}`);
1775
+ }
1776
+ return value;
1777
+ });
1778
+ const rendered = withInlineSelectors.replace(selectorPattern, (_token, selector) => {
1779
+ const presentation = presentationFor(fact, selector);
1780
+ if (presentation === undefined) {
1781
+ throw new Error(`engine content requests an unknown ${label} presentation: ${selector}`);
1782
+ }
1783
+ if (presentation.trim().length === 0) {
1784
+ throw new Error(`${label} presentation ${selector} rendered empty; every presentation must say something true even when the subject is absent`);
1785
+ }
1786
+ return presentation;
1787
+ });
1788
+ return { markdown: rendered, fact };
1789
+ }
1790
+ /**
1791
+ * The application's own name and connection details. The name is inline and repeatable — a page
1792
+ * names the product as often as its prose needs it — while a connection table is a block.
1793
+ */
1794
+ function resolveApplicationConnectionMarkdown(markdown, declaredSourceRefs, fact) {
1795
+ return resolveSelectorProjectionMarkdown({
1796
+ markdown,
1797
+ declaredSourceRefs,
1798
+ sourceRef: APPLICATION_CONNECTION_DOCUMENTATION_SOURCE_REF,
1799
+ label: 'application-connection',
1800
+ fact,
1801
+ selectorPattern: APPLICATION_CONNECTION_TOKEN_PATTERN,
1802
+ presentationFor: (resolved, selector) => resolved.presentations[selector],
1803
+ inline: { token: APPLICATION_NAME_TOKEN, valueFor: (resolved) => resolved.applicationName },
1804
+ inlineSelector: {
1805
+ pattern: APPLICATION_CONNECTION_VALUE_TOKEN_PATTERN,
1806
+ valueFor: (resolved, selector) => resolved.inlineValues[selector],
1807
+ },
1808
+ });
1809
+ }
1810
+ /** What this application actually asks of a person signing in. Presentations only. */
1811
+ function resolveApplicationAuthenticationMarkdown(markdown, declaredSourceRefs, fact) {
1812
+ return resolveSelectorProjectionMarkdown({
1813
+ markdown,
1814
+ declaredSourceRefs,
1815
+ sourceRef: APPLICATION_AUTHENTICATION_DOCUMENTATION_SOURCE_REF,
1816
+ label: 'application-authentication',
1817
+ fact,
1818
+ selectorPattern: APPLICATION_AUTHENTICATION_TOKEN_PATTERN,
1819
+ presentationFor: (resolved, selector) => resolved.presentations[selector],
1820
+ });
1821
+ }
1822
+ /** The tools and events this application publishes. Presentations only. */
1823
+ function resolveApplicationIntegrationMarkdown(markdown, declaredSourceRefs, fact) {
1824
+ return resolveSelectorProjectionMarkdown({
1825
+ markdown,
1826
+ declaredSourceRefs,
1827
+ sourceRef: APPLICATION_INTEGRATION_DOCUMENTATION_SOURCE_REF,
1828
+ label: 'application-integration',
1829
+ fact,
1830
+ selectorPattern: APPLICATION_INTEGRATION_TOKEN_PATTERN,
1831
+ presentationFor: (resolved, selector) => resolved.presentations[selector],
1832
+ });
1833
+ }
1834
+ /** What this application is FOR: its own resources, grouped as it groups them. Presentations only. */
1835
+ function resolveApplicationDomainMarkdown(markdown, declaredSourceRefs, fact) {
1836
+ return resolveSelectorProjectionMarkdown({
1837
+ markdown,
1838
+ declaredSourceRefs,
1839
+ sourceRef: APPLICATION_DOMAIN_DOCUMENTATION_SOURCE_REF,
1840
+ label: 'application-domain',
1841
+ fact,
1842
+ selectorPattern: APPLICATION_DOMAIN_TOKEN_PATTERN,
1843
+ presentationFor: (resolved, selector) => resolved.presentations[selector],
1844
+ });
1845
+ }
1846
+ /** Who may perform each administrative action here. Presentations only. */
1847
+ function resolveApplicationAdministrationMarkdown(markdown, declaredSourceRefs, fact) {
1848
+ return resolveSelectorProjectionMarkdown({
1849
+ markdown,
1850
+ declaredSourceRefs,
1851
+ sourceRef: APPLICATION_ADMINISTRATION_DOCUMENTATION_SOURCE_REF,
1852
+ label: 'application-administration',
1853
+ fact,
1854
+ selectorPattern: APPLICATION_ADMINISTRATION_TOKEN_PATTERN,
1855
+ presentationFor: (resolved, selector) => resolved.presentations[selector],
1856
+ });
1857
+ }
1736
1858
  function resolveApplicationOrganizationRolesMarkdown(markdown, declaredSourceRefs, fact) {
1737
1859
  const declaredRefs = declaredSourceRefs.filter((sourceRef) => sourceRef === APPLICATION_ORGANIZATION_ROLES_DOCUMENTATION_SOURCE_REF);
1738
1860
  const tokenCount = markdown.split(APPLICATION_ORGANIZATION_ROLES_TOKEN).length - 1;
@@ -1764,10 +1886,10 @@ function resolveApplicationOrganizationUnitResourcesMarkdown(markdown, declaredS
1764
1886
  return { markdown: markdown.replace(APPLICATION_ORGANIZATION_UNIT_RESOURCES_TOKEN, fact.markdown), fact };
1765
1887
  }
1766
1888
  /**
1767
- * Compiles verified engine content and the two explicit application facts
1768
- * (organization roles and unit-aware resources) into private documentation.
1889
+ * Compiles verified engine content and the application's own facts (organization roles,
1890
+ * unit-aware resources, name and connection details) into private documentation.
1769
1891
  */
1770
- export function projectEngineApplicationConsumerContentBundle(bundle, engineSpecificationCatalog, unitDefinitions = ENGINE_CONTENT_UNIT_DEFINITIONS, applicationOrganizationRolesFact, applicationOrganizationUnitResourcesFact) {
1892
+ export function projectEngineApplicationConsumerContentBundle(bundle, engineSpecificationCatalog, unitDefinitions = ENGINE_CONTENT_UNIT_DEFINITIONS, applicationFacts = {}) {
1771
1893
  const manifestRefs = bundle.manifest.units.map((unit) => unit.unitRef).sort();
1772
1894
  const definitionRefs = Object.keys(unitDefinitions).sort();
1773
1895
  if (manifestRefs.join('\0') !== definitionRefs.join('\0')) {
@@ -1778,13 +1900,23 @@ export function projectEngineApplicationConsumerContentBundle(bundle, engineSpec
1778
1900
  throw new Error(`engine content unit ${identity.unitRef} must resolve to exactly one Markdown source`);
1779
1901
  const authoredMarkdown = new TextDecoder('utf-8', { fatal: true }).decode(bundle.readManagedBytes(identity.managedPaths[0]));
1780
1902
  const resolvedConsumerFacts = resolveConsumerFactMarkdown(authoredMarkdown, identity.sourceRefs, engineSpecificationCatalog);
1781
- const resolvedApplicationOrganizationRoles = resolveApplicationOrganizationRolesMarkdown(resolvedConsumerFacts.markdown, identity.sourceRefs, applicationOrganizationRolesFact);
1782
- const resolvedApplicationOrganizationUnitResources = resolveApplicationOrganizationUnitResourcesMarkdown(resolvedApplicationOrganizationRoles.markdown, identity.sourceRefs, applicationOrganizationUnitResourcesFact);
1903
+ const resolvedApplicationOrganizationRoles = resolveApplicationOrganizationRolesMarkdown(resolvedConsumerFacts.markdown, identity.sourceRefs, applicationFacts.organizationRoles);
1904
+ const resolvedApplicationOrganizationUnitResources = resolveApplicationOrganizationUnitResourcesMarkdown(resolvedApplicationOrganizationRoles.markdown, identity.sourceRefs, applicationFacts.organizationUnitResources);
1905
+ const resolvedApplicationConnection = resolveApplicationConnectionMarkdown(resolvedApplicationOrganizationUnitResources.markdown, identity.sourceRefs, applicationFacts.connection);
1906
+ const resolvedApplicationAuthentication = resolveApplicationAuthenticationMarkdown(resolvedApplicationConnection.markdown, identity.sourceRefs, applicationFacts.authentication);
1907
+ const resolvedApplicationAdministration = resolveApplicationAdministrationMarkdown(resolvedApplicationAuthentication.markdown, identity.sourceRefs, applicationFacts.administration);
1908
+ const resolvedApplicationIntegration = resolveApplicationIntegrationMarkdown(resolvedApplicationAdministration.markdown, identity.sourceRefs, applicationFacts.integration);
1909
+ const resolvedApplicationDomain = resolveApplicationDomainMarkdown(resolvedApplicationIntegration.markdown, identity.sourceRefs, applicationFacts.domain);
1783
1910
  return [identity.unitRef, {
1784
- parsed: parseEngineMarkdown(resolvedApplicationOrganizationUnitResources.markdown, identity.unitRef),
1911
+ parsed: parseEngineMarkdown(resolvedApplicationDomain.markdown, identity.unitRef),
1785
1912
  resolvedConsumerFacts,
1786
1913
  resolvedApplicationOrganizationRoles,
1787
1914
  resolvedApplicationOrganizationUnitResources,
1915
+ resolvedApplicationConnection,
1916
+ resolvedApplicationAuthentication,
1917
+ resolvedApplicationAdministration,
1918
+ resolvedApplicationIntegration,
1919
+ resolvedApplicationDomain,
1788
1920
  }];
1789
1921
  }));
1790
1922
  const relatedTargetByUnitRef = new Map(bundle.manifest.units.map((identity) => {
@@ -1806,60 +1938,121 @@ export function projectEngineApplicationConsumerContentBundle(bundle, engineSpec
1806
1938
  },
1807
1939
  }];
1808
1940
  }));
1809
- return bundle.manifest.units.map((identity) => {
1810
- const definition = unitDefinitions[identity.unitRef];
1811
- if (definition === undefined)
1812
- throw new Error(`unsupported engine application-consumer content unit ${identity.unitRef}`);
1813
- const content = parsedContentByUnitRef.get(identity.unitRef);
1814
- if (content === undefined)
1815
- throw new Error(`engine content ${identity.unitRef} has no parsed content`);
1816
- const { parsed, resolvedConsumerFacts, resolvedApplicationOrganizationRoles, resolvedApplicationOrganizationUnitResources } = content;
1817
- const unitSlug = identity.unitRef.slice(identity.unitRef.lastIndexOf('/') + 1);
1818
- const relatedTargets = resolveRelatedUnitLinkTargets(identity.unitRef, definition.relatedUnitRefs, relatedTargetByUnitRef);
1819
- const ownProvenance = identity.sourceRefs.map((sourceRef) => {
1820
- const fact = resolvedConsumerFacts.entriesBySourceRef.get(sourceRef);
1821
- const applicationProjection = resolvedApplicationOrganizationRoles.fact?.sourceRef === sourceRef
1822
- ? resolvedApplicationOrganizationRoles.fact
1823
- : resolvedApplicationOrganizationUnitResources.fact?.sourceRef === sourceRef
1824
- ? resolvedApplicationOrganizationUnitResources.fact
1825
- : undefined;
1826
- return {
1827
- sourceRef,
1828
- ownership: applicationProjection === undefined
1829
- ? TechnicalDocumentationSourceOwnership.ENGINE_GENERIC_CONTENT
1830
- : TechnicalDocumentationSourceOwnership.APPLICATION_COMPANION_PROJECTION,
1831
- classification: TechnicalDocumentationSourceClassification.PUBLIC,
1832
- /*
1833
- * A companion projection carries its own version; a curated engine fact takes the
1834
- * catalog projector's; authored engine content takes the content bundle's. All three
1835
- * were sha256 values until 2026-08-27 and none of them was ever compared to anything
1836
- * except another copy of itself.
1837
- */
1838
- sourceVersion: applicationProjection?.sourceVersion
1839
- ?? (fact === undefined ? bundle.identity.contentBundleVersion : engineSpecificationCatalog.identity.projectorVersion),
1840
- sourceAnchorRef: null,
1841
- };
1842
- });
1941
+ /*
1942
+ * The generated tier.
1943
+ *
1944
+ * Every unit above is AUTHORED: a Markdown file in the content module, a definition beside it,
1945
+ * and a fixed route. That is the right shape for a page whose text an engine owns, and the wrong
1946
+ * one for a page PER RESOURCE — the resources belong to the application, and an engine that
1947
+ * authored a page for each possible one would be authoring the application.
1948
+ *
1949
+ * So these units are projected whole, from the same domain fact the overview page uses. They are
1950
+ * still ENGINE units, and deliberately: the engine owns the page's shape, its sections and its
1951
+ * words, while the application supplies only the subject. That is what keeps `pathForUnit`'s
1952
+ * refusal of application-owned units intact — nothing here asks it to route a unit an
1953
+ * application named.
1954
+ */
1955
+ const generatedResourceUnits = (applicationFacts.domain?.resourcePages ?? []).map((page) => {
1956
+ const unitRef = applicationDomainResourcePageUnitRef(page.resourceIdentifier);
1957
+ const parsed = parseEngineMarkdown(page.markdown, unitRef);
1958
+ const unitSlug = page.resourceIdentifier;
1843
1959
  return createTechnicalDocumentationUnitV1({
1844
1960
  schemaVersion: 1,
1845
- unitRef: identity.unitRef,
1961
+ unitRef,
1846
1962
  unitVersion: 1,
1847
- kind: definition.kind,
1848
- readerAudiences: [...definition.readerAudiences],
1963
+ kind: GENERATED_RESOURCE_UNIT_DEFINITION.kind,
1964
+ readerAudiences: [...GENERATED_RESOURCE_UNIT_DEFINITION.readerAudiences],
1849
1965
  title: parsed.title,
1850
1966
  summary: parsed.summary,
1851
1967
  sections: parsed.sections.map((section, index) => ({
1852
- sectionRef: `technical-documentation:section/${unitSlug}-${index + 1}`,
1968
+ sectionRef: `technical-documentation:section/manages-${unitSlug}-${index + 1}`,
1853
1969
  heading: section.heading,
1854
1970
  bodyMarkdown: section.bodyMarkdown,
1855
1971
  })),
1856
- links: [...relatedLinks(identity.unitRef, relatedTargets), ...apiReferenceLinks(identity.unitRef, definition.apiReferenceTargets ?? [])],
1857
- provenance: mergeProvenance(ownProvenance, relatedTargets),
1858
- applicabilityRequirements: [...definition.applicabilityRequirements],
1859
- accessClass: definition.accessClass,
1860
- editorialStatus: TechnicalDocumentationEditorialStatus.APPROVED,
1861
- assetRequests: [],
1972
+ links: [],
1973
+ /*
1974
+ * Wholly application-projected: unlike an authored page carrying a token, there is no engine
1975
+ * Markdown behind this one. Recording it as engine content would misattribute the only thing
1976
+ * a reader might want to trace — where the words about their product came from.
1977
+ */
1978
+ provenance: [{
1979
+ sourceRef: APPLICATION_DOMAIN_DOCUMENTATION_SOURCE_REF,
1980
+ ownership: TechnicalDocumentationSourceOwnership.APPLICATION_COMPANION_PROJECTION,
1981
+ classification: TechnicalDocumentationSourceClassification.PUBLIC,
1982
+ sourceVersion: applicationFacts.domain?.sourceVersion ?? 1,
1983
+ sourceAnchorRef: null,
1984
+ }],
1985
+ /*
1986
+ * No applicability requirement, because the unit's EXISTENCE is the evidence: it is emitted
1987
+ * only for a resource the application actually publishes. A requirement here would be a
1988
+ * second, weaker statement of the same fact.
1989
+ */
1990
+ applicabilityRequirements: [],
1991
+ accessClass: GENERATED_RESOURCE_UNIT_DEFINITION.accessClass,
1992
+ editorialStatus: GENERATED_RESOURCE_UNIT_DEFINITION.editorialStatus ?? TechnicalDocumentationEditorialStatus.APPROVED,
1993
+ assetRequests: [...GENERATED_RESOURCE_UNIT_DEFINITION.assetRequests ?? []],
1862
1994
  });
1863
- }).sort((left, right) => left.unitRef.localeCompare(right.unitRef, 'en-US'));
1995
+ });
1996
+ return [...bundle.manifest.units.map((identity) => {
1997
+ const definition = unitDefinitions[identity.unitRef];
1998
+ if (definition === undefined)
1999
+ throw new Error(`unsupported engine application-consumer content unit ${identity.unitRef}`);
2000
+ const content = parsedContentByUnitRef.get(identity.unitRef);
2001
+ if (content === undefined)
2002
+ throw new Error(`engine content ${identity.unitRef} has no parsed content`);
2003
+ const { parsed, resolvedConsumerFacts, resolvedApplicationOrganizationRoles, resolvedApplicationOrganizationUnitResources, resolvedApplicationConnection, resolvedApplicationAuthentication, resolvedApplicationAdministration, resolvedApplicationIntegration, resolvedApplicationDomain } = content;
2004
+ const unitSlug = identity.unitRef.slice(identity.unitRef.lastIndexOf('/') + 1);
2005
+ const relatedTargets = resolveRelatedUnitLinkTargets(identity.unitRef, definition.relatedUnitRefs, relatedTargetByUnitRef);
2006
+ const ownProvenance = identity.sourceRefs.map((sourceRef) => {
2007
+ const fact = resolvedConsumerFacts.entriesBySourceRef.get(sourceRef);
2008
+ const applicationProjection = resolvedApplicationOrganizationRoles.fact?.sourceRef === sourceRef
2009
+ ? resolvedApplicationOrganizationRoles.fact
2010
+ : resolvedApplicationOrganizationUnitResources.fact?.sourceRef === sourceRef
2011
+ ? resolvedApplicationOrganizationUnitResources.fact
2012
+ : resolvedApplicationConnection.fact?.sourceRef === sourceRef
2013
+ ? resolvedApplicationConnection.fact
2014
+ : resolvedApplicationAuthentication.fact?.sourceRef === sourceRef
2015
+ ? resolvedApplicationAuthentication.fact
2016
+ : resolvedApplicationAdministration.fact?.sourceRef === sourceRef
2017
+ ? resolvedApplicationAdministration.fact
2018
+ : undefined;
2019
+ return {
2020
+ sourceRef,
2021
+ ownership: applicationProjection === undefined
2022
+ ? TechnicalDocumentationSourceOwnership.ENGINE_GENERIC_CONTENT
2023
+ : TechnicalDocumentationSourceOwnership.APPLICATION_COMPANION_PROJECTION,
2024
+ classification: TechnicalDocumentationSourceClassification.PUBLIC,
2025
+ /*
2026
+ * A companion projection carries its own version; a curated engine fact takes the
2027
+ * catalog projector's; authored engine content takes the content bundle's. All three
2028
+ * were sha256 values until 2026-08-27 and none of them was ever compared to anything
2029
+ * except another copy of itself.
2030
+ */
2031
+ sourceVersion: applicationProjection?.sourceVersion
2032
+ ?? (fact === undefined ? bundle.identity.contentBundleVersion : engineSpecificationCatalog.identity.projectorVersion),
2033
+ sourceAnchorRef: null,
2034
+ };
2035
+ });
2036
+ return createTechnicalDocumentationUnitV1({
2037
+ schemaVersion: 1,
2038
+ unitRef: identity.unitRef,
2039
+ unitVersion: 1,
2040
+ kind: definition.kind,
2041
+ readerAudiences: [...definition.readerAudiences],
2042
+ title: parsed.title,
2043
+ summary: parsed.summary,
2044
+ sections: parsed.sections.map((section, index) => ({
2045
+ sectionRef: `technical-documentation:section/${unitSlug}-${index + 1}`,
2046
+ heading: section.heading,
2047
+ bodyMarkdown: section.bodyMarkdown,
2048
+ })),
2049
+ links: [...relatedLinks(identity.unitRef, relatedTargets), ...apiReferenceLinks(identity.unitRef, definition.apiReferenceTargets ?? [])],
2050
+ provenance: mergeProvenance(ownProvenance, relatedTargets),
2051
+ applicabilityRequirements: [...definition.applicabilityRequirements],
2052
+ accessClass: definition.accessClass,
2053
+ editorialStatus: definition.editorialStatus ?? TechnicalDocumentationEditorialStatus.APPROVED,
2054
+ assetRequests: [...definition.assetRequests ?? []],
2055
+ });
2056
+ }), ...generatedResourceUnits].sort((left, right) => left.unitRef.localeCompare(right.unitRef, 'en-US'));
1864
2057
  }
1865
2058
  //# sourceMappingURL=technical-documentation-engine-content-bundle.js.map