@lssm/lib.contracts 0.0.0-canary-20251217063201 → 0.0.0-canary-20251217073102

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 (239) hide show
  1. package/dist/app-config/app-config.feature.js +53 -1
  2. package/dist/app-config/contracts.d.ts +50 -50
  3. package/dist/app-config/contracts.js +396 -1
  4. package/dist/app-config/docs/app-config.docblock.js +22 -220
  5. package/dist/app-config/events.d.ts +27 -27
  6. package/dist/app-config/events.js +168 -1
  7. package/dist/app-config/index.js +8 -1
  8. package/dist/app-config/lifecycle-contracts.d.ts +80 -80
  9. package/dist/app-config/lifecycle-contracts.js +441 -1
  10. package/dist/app-config/runtime.js +617 -1
  11. package/dist/app-config/spec.js +36 -1
  12. package/dist/app-config/validation.js +538 -1
  13. package/dist/capabilities/docs/capabilities.docblock.js +22 -1
  14. package/dist/capabilities/openbanking.js +92 -1
  15. package/dist/capabilities.js +50 -1
  16. package/dist/client/index.js +9 -1
  17. package/dist/client/react/drivers/rn-reusables.js +21 -1
  18. package/dist/client/react/drivers/shadcn.js +11 -1
  19. package/dist/client/react/feature-render.js +43 -1
  20. package/dist/client/react/form-render.js +298 -1
  21. package/dist/client/react/index.js +8 -1
  22. package/dist/contract-registry/index.js +3 -1
  23. package/dist/contract-registry/schemas.js +61 -1
  24. package/dist/contracts-adapter-hydration.js +41 -1
  25. package/dist/contracts-adapter-input.js +77 -1
  26. package/dist/data-views/docs/data-views.docblock.js +22 -1
  27. package/dist/data-views/query-generator.js +48 -1
  28. package/dist/data-views/runtime.js +39 -1
  29. package/dist/data-views.js +35 -1
  30. package/dist/docs/PUBLISHING.docblock.js +17 -76
  31. package/dist/docs/accessibility_wcag_compliance_specs.docblock.js +17 -350
  32. package/dist/docs/index.js +33 -1
  33. package/dist/docs/meta.docs.js +15 -2
  34. package/dist/docs/presentations.js +77 -1
  35. package/dist/docs/registry.js +51 -1
  36. package/dist/docs/tech/PHASE_1_QUICKSTART.docblock.js +17 -383
  37. package/dist/docs/tech/PHASE_2_AI_NATIVE_OPERATIONS.docblock.js +17 -68
  38. package/dist/docs/tech/PHASE_3_AUTO_EVOLUTION.docblock.js +17 -140
  39. package/dist/docs/tech/PHASE_4_PERSONALIZATION_ENGINE.docblock.js +17 -86
  40. package/dist/docs/tech/PHASE_5_ZERO_TOUCH_OPERATIONS.docblock.js +17 -1
  41. package/dist/docs/tech/auth/better-auth-nextjs.docblock.js +25 -2
  42. package/dist/docs/tech/contracts/README.docblock.js +21 -1
  43. package/dist/docs/tech/contracts/create-subscription.docblock.js +21 -1
  44. package/dist/docs/tech/contracts/graphql-typed-outputs.docblock.js +21 -180
  45. package/dist/docs/tech/contracts/migrations.docblock.js +21 -1
  46. package/dist/docs/tech/contracts/openapi-export.docblock.js +22 -2
  47. package/dist/docs/tech/contracts/ops-to-presentation-linking.docblock.js +19 -60
  48. package/dist/docs/tech/contracts/overlays.docblock.js +21 -68
  49. package/dist/docs/tech/contracts/tests.docblock.js +21 -132
  50. package/dist/docs/tech/contracts/themes.docblock.js +21 -1
  51. package/dist/docs/tech/contracts/vertical-pocket-family-office.docblock.js +21 -106
  52. package/dist/docs/tech/lifecycle-stage-system.docblock.js +17 -213
  53. package/dist/docs/tech/llm/llm-integration.docblock.js +74 -5
  54. package/dist/docs/tech/mcp-endpoints.docblock.js +38 -1
  55. package/dist/docs/tech/presentation-runtime.docblock.js +17 -1
  56. package/dist/docs/tech/schema/README.docblock.js +21 -262
  57. package/dist/docs/tech/studio/learning-events.docblock.js +49 -1
  58. package/dist/docs/tech/studio/learning-journeys.docblock.js +25 -2
  59. package/dist/docs/tech/studio/platform-admin-panel.docblock.js +24 -2
  60. package/dist/docs/tech/studio/project-access-teams.docblock.js +26 -16
  61. package/dist/docs/tech/studio/project-routing.docblock.js +68 -1
  62. package/dist/docs/tech/studio/sandbox-unlogged.docblock.js +23 -2
  63. package/dist/docs/tech/studio/team-invitations.docblock.js +41 -36
  64. package/dist/docs/tech/studio/workspace-ops.docblock.js +48 -1
  65. package/dist/docs/tech/studio/workspaces.docblock.js +24 -2
  66. package/dist/docs/tech/telemetry-ingest.docblock.js +37 -3
  67. package/dist/docs/tech/templates/runtime.docblock.js +21 -1
  68. package/dist/docs/tech/vscode-extension.docblock.js +37 -3
  69. package/dist/docs/tech/workflows/overview.docblock.js +21 -1
  70. package/dist/docs/tech-contracts.docs.js +19 -2
  71. package/dist/events.js +12 -1
  72. package/dist/experiments/docs/experiments.docblock.js +22 -128
  73. package/dist/experiments/evaluator.js +101 -1
  74. package/dist/experiments/spec.js +33 -1
  75. package/dist/features.js +68 -1
  76. package/dist/forms/docs/forms.docblock.js +22 -1
  77. package/dist/forms.js +119 -1
  78. package/dist/index.js +107 -1
  79. package/dist/install.js +40 -1
  80. package/dist/integrations/contracts.d.ts +102 -102
  81. package/dist/integrations/contracts.js +388 -1
  82. package/dist/integrations/docs/integrations.docblock.js +95 -1
  83. package/dist/integrations/health.js +69 -1
  84. package/dist/integrations/index.js +23 -1
  85. package/dist/integrations/openbanking/contracts/accounts.d.ts +66 -66
  86. package/dist/integrations/openbanking/contracts/accounts.js +237 -1
  87. package/dist/integrations/openbanking/contracts/balances.d.ts +34 -34
  88. package/dist/integrations/openbanking/contracts/balances.js +167 -1
  89. package/dist/integrations/openbanking/contracts/index.js +12 -1
  90. package/dist/integrations/openbanking/contracts/transactions.d.ts +48 -48
  91. package/dist/integrations/openbanking/contracts/transactions.js +218 -1
  92. package/dist/integrations/openbanking/guards.js +32 -1
  93. package/dist/integrations/openbanking/models.d.ts +55 -55
  94. package/dist/integrations/openbanking/models.js +242 -1
  95. package/dist/integrations/openbanking/openbanking.feature.js +68 -1
  96. package/dist/integrations/openbanking/telemetry.js +39 -1
  97. package/dist/integrations/providers/elevenlabs.js +56 -1
  98. package/dist/integrations/providers/gcs-storage.js +79 -1
  99. package/dist/integrations/providers/gmail.js +91 -1
  100. package/dist/integrations/providers/google-calendar.js +70 -1
  101. package/dist/integrations/providers/impls/elevenlabs-voice.js +95 -1
  102. package/dist/integrations/providers/impls/gcs-storage.js +88 -1
  103. package/dist/integrations/providers/impls/gmail-inbound.js +200 -1
  104. package/dist/integrations/providers/impls/gmail-outbound.js +104 -5
  105. package/dist/integrations/providers/impls/google-calendar.js +154 -1
  106. package/dist/integrations/providers/impls/index.js +16 -1
  107. package/dist/integrations/providers/impls/mistral-embedding.js +41 -1
  108. package/dist/integrations/providers/impls/mistral-llm.js +247 -1
  109. package/dist/integrations/providers/impls/postmark-email.js +55 -1
  110. package/dist/integrations/providers/impls/powens-client.js +171 -1
  111. package/dist/integrations/providers/impls/powens-openbanking.js +218 -1
  112. package/dist/integrations/providers/impls/provider-factory.js +142 -1
  113. package/dist/integrations/providers/impls/qdrant-vector.js +69 -1
  114. package/dist/integrations/providers/impls/stripe-payments.js +202 -1
  115. package/dist/integrations/providers/impls/twilio-sms.js +58 -1
  116. package/dist/integrations/providers/index.js +13 -1
  117. package/dist/integrations/providers/mistral.js +72 -1
  118. package/dist/integrations/providers/postmark.js +72 -1
  119. package/dist/integrations/providers/powens.js +120 -1
  120. package/dist/integrations/providers/qdrant.js +77 -1
  121. package/dist/integrations/providers/registry.js +34 -1
  122. package/dist/integrations/providers/stripe.js +87 -1
  123. package/dist/integrations/providers/twilio-sms.js +65 -1
  124. package/dist/integrations/runtime.js +186 -1
  125. package/dist/integrations/secrets/aws-secret-manager.js +231 -1
  126. package/dist/integrations/secrets/env-secret-provider.js +81 -1
  127. package/dist/integrations/secrets/gcp-secret-manager.js +229 -1
  128. package/dist/integrations/secrets/index.js +8 -1
  129. package/dist/integrations/secrets/manager.js +103 -1
  130. package/dist/integrations/secrets/provider.js +58 -1
  131. package/dist/integrations/secrets/scaleway-secret-manager.js +247 -1
  132. package/dist/integrations/spec.js +39 -1
  133. package/dist/jobs/define-job.js +16 -1
  134. package/dist/jobs/gcp-cloud-tasks.js +53 -1
  135. package/dist/jobs/gcp-pubsub.js +39 -1
  136. package/dist/jobs/handlers/gmail-sync-handler.js +9 -1
  137. package/dist/jobs/handlers/index.js +12 -1
  138. package/dist/jobs/handlers/ping-handler.js +15 -1
  139. package/dist/jobs/handlers/storage-document-handler.js +14 -1
  140. package/dist/jobs/index.js +4 -1
  141. package/dist/jobs/memory-queue.js +71 -1
  142. package/dist/jobs/queue.js +33 -1
  143. package/dist/jobs/scaleway-sqs-queue.js +153 -1
  144. package/dist/jsonschema.d.ts +3 -3
  145. package/dist/jsonschema.js +32 -1
  146. package/dist/knowledge/contracts.d.ts +66 -66
  147. package/dist/knowledge/contracts.js +317 -1
  148. package/dist/knowledge/docs/knowledge.docblock.js +22 -138
  149. package/dist/knowledge/index.js +10 -1
  150. package/dist/knowledge/ingestion/document-processor.js +54 -1
  151. package/dist/knowledge/ingestion/embedding-service.js +25 -1
  152. package/dist/knowledge/ingestion/gmail-adapter.js +50 -5
  153. package/dist/knowledge/ingestion/index.js +7 -1
  154. package/dist/knowledge/ingestion/storage-adapter.js +26 -1
  155. package/dist/knowledge/ingestion/vector-indexer.js +32 -1
  156. package/dist/knowledge/query/index.js +3 -1
  157. package/dist/knowledge/query/service.js +64 -2
  158. package/dist/knowledge/runtime.js +49 -1
  159. package/dist/knowledge/spaces/email-threads.js +38 -1
  160. package/dist/knowledge/spaces/financial-docs.js +38 -1
  161. package/dist/knowledge/spaces/financial-overview.js +42 -1
  162. package/dist/knowledge/spaces/index.js +8 -1
  163. package/dist/knowledge/spaces/product-canon.js +38 -1
  164. package/dist/knowledge/spaces/support-faq.js +41 -1
  165. package/dist/knowledge/spaces/uploaded-docs.js +38 -1
  166. package/dist/knowledge/spec.js +39 -1
  167. package/dist/llm/exporters.js +541 -8
  168. package/dist/llm/index.js +4 -1
  169. package/dist/llm/prompts.js +246 -56
  170. package/dist/markdown.js +116 -3
  171. package/dist/migrations.js +33 -1
  172. package/dist/onboarding-base.d.ts +29 -29
  173. package/dist/onboarding-base.js +196 -1
  174. package/dist/openapi.js +75 -1
  175. package/dist/openbanking/docs/openbanking.docblock.js +22 -109
  176. package/dist/ownership.js +40 -1
  177. package/dist/policy/docs/policy.docblock.js +22 -1
  178. package/dist/policy/engine.js +223 -1
  179. package/dist/policy/opa-adapter.js +71 -1
  180. package/dist/policy/spec.js +33 -1
  181. package/dist/presentations/docs/presentations-conventions.docblock.js +21 -7
  182. package/dist/presentations.backcompat.js +47 -1
  183. package/dist/presentations.d.ts +3 -3
  184. package/dist/presentations.js +66 -1
  185. package/dist/presentations.v2.js +278 -6
  186. package/dist/prompt.js +10 -1
  187. package/dist/promptRegistry.js +34 -1
  188. package/dist/regenerator/docs/regenerator.docblock.js +22 -184
  189. package/dist/regenerator/executor.js +86 -1
  190. package/dist/regenerator/index.js +6 -1
  191. package/dist/regenerator/service.js +92 -1
  192. package/dist/regenerator/sinks.js +32 -1
  193. package/dist/regenerator/utils.js +51 -1
  194. package/dist/registry.js +208 -1
  195. package/dist/resources.js +47 -1
  196. package/dist/schema/dist/EnumType.js +2 -1
  197. package/dist/schema/dist/FieldType.js +49 -1
  198. package/dist/schema/dist/ScalarTypeEnum.js +236 -1
  199. package/dist/schema/dist/SchemaModel.js +39 -1
  200. package/dist/schema/dist/entity/defineEntity.js +1 -1
  201. package/dist/schema/dist/entity/index.js +2 -1
  202. package/dist/schema/dist/entity/types.js +1 -1
  203. package/dist/schema/dist/index.js +6 -1
  204. package/dist/schema-to-markdown.js +214 -10
  205. package/dist/server/graphql-pothos.js +128 -1
  206. package/dist/server/index.js +10 -1
  207. package/dist/server/mcp/createMcpServer.js +28 -1
  208. package/dist/server/mcp/registerPresentations.js +151 -1
  209. package/dist/server/mcp/registerPrompts.js +36 -2
  210. package/dist/server/mcp/registerResources.js +35 -1
  211. package/dist/server/mcp/registerTools.js +22 -1
  212. package/dist/server/provider-mcp.js +3 -1
  213. package/dist/server/rest-elysia.js +20 -1
  214. package/dist/server/rest-express.js +39 -1
  215. package/dist/server/rest-generic.js +125 -1
  216. package/dist/server/rest-next-app.js +38 -1
  217. package/dist/server/rest-next-mcp.js +45 -1
  218. package/dist/server/rest-next-pages.js +25 -1
  219. package/dist/spec.js +35 -1
  220. package/dist/telemetry/anomaly.js +48 -1
  221. package/dist/telemetry/docs/telemetry.docblock.js +22 -139
  222. package/dist/telemetry/index.js +5 -1
  223. package/dist/telemetry/spec.js +69 -1
  224. package/dist/telemetry/tracker.js +76 -1
  225. package/dist/tests/index.js +4 -1
  226. package/dist/tests/runner.js +150 -1
  227. package/dist/tests/spec.js +33 -1
  228. package/dist/themes.js +39 -1
  229. package/dist/workflow/adapters/db-adapter.js +83 -1
  230. package/dist/workflow/adapters/file-adapter.js +11 -1
  231. package/dist/workflow/adapters/index.js +5 -1
  232. package/dist/workflow/adapters/memory-store.js +58 -1
  233. package/dist/workflow/expression.js +98 -1
  234. package/dist/workflow/index.js +9 -1
  235. package/dist/workflow/runner.js +337 -1
  236. package/dist/workflow/sla-monitor.js +47 -1
  237. package/dist/workflow/spec.js +32 -1
  238. package/dist/workflow/validation.js +175 -1
  239. package/package.json +11 -4
@@ -1 +1,396 @@
1
- import{l as e}from"../schema/dist/ScalarTypeEnum.js";import{t}from"../schema/dist/SchemaModel.js";import"../schema/dist/index.js";import{defineCommand as n,defineQuery as r}from"../spec.js";import{OwnersEnum as i,StabilityEnum as a,TagsEnum as o}from"../ownership.js";const s=new t({name:`BrandingAssetInput`,fields:{type:{type:e.String_unsecure(),isOptional:!1},url:{type:e.URL(),isOptional:!1},mimeType:{type:e.String_unsecure(),isOptional:!0}}}),c=new t({name:`UpdateTenantBrandingInput`,fields:{tenantId:{type:e.ID(),isOptional:!1},appId:{type:e.ID(),isOptional:!1},environment:{type:e.String_unsecure(),isOptional:!0},appName:{type:e.JSONObject(),isOptional:!0},assets:{type:s,isOptional:!0,isArray:!0},colors:{type:e.JSONObject(),isOptional:!0},customDomain:{type:e.String_unsecure(),isOptional:!0},subdomain:{type:e.String_unsecure(),isOptional:!0}}}),l=new t({name:`UpdateTenantBrandingOutput`,fields:{success:{type:e.Boolean(),isOptional:!1},updatedAt:{type:e.DateTime(),isOptional:!1}}}),u=new t({name:`VerifyCustomDomainInput`,fields:{tenantId:{type:e.ID(),isOptional:!1},appId:{type:e.ID(),isOptional:!1},domain:{type:e.String_unsecure(),isOptional:!1}}}),d=new t({name:`VerifyCustomDomainOutput`,fields:{status:{type:e.String_unsecure(),isOptional:!1},message:{type:e.String_unsecure(),isOptional:!0}}}),f=new t({name:`TranslationEntryInput`,fields:{key:{type:e.String_unsecure(),isOptional:!1},locale:{type:e.String_unsecure(),isOptional:!1},value:{type:e.String_unsecure(),isOptional:!1},context:{type:e.String_unsecure(),isOptional:!0}}}),p=new t({name:`UpdateBlueprintTranslationInput`,fields:{blueprintName:{type:e.String_unsecure(),isOptional:!1},blueprintVersion:{type:e.Int_unsecure(),isOptional:!1},catalogName:{type:e.String_unsecure(),isOptional:!1},catalogVersion:{type:e.Int_unsecure(),isOptional:!1},defaultLocale:{type:e.String_unsecure(),isOptional:!1},supportedLocales:{type:e.String_unsecure(),isOptional:!1,isArray:!0},entries:{type:f,isOptional:!1,isArray:!0}}}),m=new t({name:`UpdateTenantTranslationInput`,fields:{tenantId:{type:e.ID(),isOptional:!1},appId:{type:e.ID(),isOptional:!1},entries:{type:f,isOptional:!1,isArray:!0},defaultLocale:{type:e.String_unsecure(),isOptional:!0},enabledLocales:{type:e.String_unsecure(),isOptional:!0,isArray:!0}}}),h=new t({name:`MessageResolutionInput`,fields:{tenantId:{type:e.ID(),isOptional:!1},appId:{type:e.ID(),isOptional:!1},locale:{type:e.String_unsecure(),isOptional:!1},key:{type:e.String_unsecure(),isOptional:!1}}}),g=new t({name:`MessageResolutionOutput`,fields:{value:{type:e.String_unsecure(),isOptional:!0},source:{type:e.String_unsecure(),isOptional:!0}}}),_=n({meta:{name:`appConfig.updateTenantBranding`,version:1,description:`Applies tenant branding overrides (names, assets, domains).`,owners:[i.PlatformSigil],tags:[`branding`],stability:a.Beta,goal:`Maintain tenant-specific branding assets and domains.`,context:`Invoked by the Studio or automation when a tenant updates branding settings.`},io:{input:c,output:l},policy:{auth:`admin`,policies:[{name:`platform.app-config.manage`,version:1}]}}),v=n({meta:{name:`appConfig.verifyCustomDomain`,version:1,description:`Validates DNS ownership for tenant custom domains.`,owners:[i.PlatformSigil],tags:[`branding`],stability:a.Experimental,goal:`Confirm tenant-provided domains before activation.`,context:`Triggered after the tenant adds DNS records to verify domain ownership.`},io:{input:u,output:d},policy:{auth:`admin`,policies:[{name:`platform.app-config.manage`,version:1}]}}),y=n({meta:{name:`appConfig.updateBlueprintTranslationCatalog`,version:1,description:`Registers or updates translation entries for a blueprint.`,owners:[i.PlatformSigil],tags:[o.I18n],stability:a.Beta,goal:`Keep blueprint translation catalogs in sync with shipped copy.`,context:`Executed by platform automation or CI when committing updated translation catalogs.`},io:{input:p,output:l},policy:{auth:`admin`,policies:[{name:`platform.app-config.manage`,version:1}]}}),b=n({meta:{name:`appConfig.updateTenantTranslations`,version:1,description:`Applies tenant-specific translation entries.`,owners:[i.PlatformSigil],tags:[o.I18n],stability:a.Beta,goal:`Allow tenants to override selected message keys.`,context:`Called by the Studio when a tenant customizes labels or copy for their locale.`},io:{input:m,output:l},policy:{auth:`admin`,policies:[{name:`platform.app-config.manage`,version:1}]}}),x=r({meta:{name:`appConfig.getResolvedBranding`,version:1,description:`Returns the resolved branding for a tenant/app/environment.`,owners:[i.PlatformSigil],tags:[`branding`],stability:a.Beta,goal:`Expose hydrated branding assets for rendering UI/email experiences.`,context:`Used by runtime surfaces to fetch brand assets prior to rendering tenant-specific experiences.`},io:{input:new t({name:`GetResolvedBrandingInput`,fields:{tenantId:{type:e.ID(),isOptional:!1},appId:{type:e.ID(),isOptional:!1},environment:{type:e.String_unsecure(),isOptional:!0}}}),output:new t({name:`GetResolvedBrandingOutput`,fields:{branding:{type:e.JSONObject(),isOptional:!1}}})},policy:{auth:`admin`,policies:[{name:`platform.app-config.read`,version:1}]}}),S=r({meta:{name:`appConfig.resolveMessage`,version:1,description:`Resolves a translation key for a tenant in the requested locale.`,owners:[i.PlatformSigil],tags:[o.I18n],stability:a.Experimental,goal:`Expose a server-side API for resolving message keys on demand.`,context:`Used by backend services or scripts that need translated copy outside the front-end runtime.`},io:{input:h,output:g},policy:{auth:`admin`,policies:[{name:`platform.app-config.read`,version:1}]}}),C={UpdateTenantBrandingCommand:_,VerifyCustomDomainCommand:v,UpdateBlueprintTranslationCatalogCommand:y,UpdateTenantTranslationOverridesCommand:b,GetResolvedBrandingQuery:x,ResolveMessageQuery:S};function w(e){return e.register(_).register(v).register(y).register(b).register(x).register(S)}export{x as GetResolvedBrandingQuery,S as ResolveMessageQuery,y as UpdateBlueprintTranslationCatalogCommand,_ as UpdateTenantBrandingCommand,b as UpdateTenantTranslationOverridesCommand,v as VerifyCustomDomainCommand,C as appConfigContracts,w as registerAppConfigContracts};
1
+ import { ScalarTypeEnum } from "../schema/dist/ScalarTypeEnum.js";
2
+ import { SchemaModel } from "../schema/dist/SchemaModel.js";
3
+ import "../schema/dist/index.js";
4
+ import { defineCommand, defineQuery } from "../spec.js";
5
+ import { OwnersEnum, StabilityEnum, TagsEnum } from "../ownership.js";
6
+
7
+ //#region src/app-config/contracts.ts
8
+ const BrandingAssetInput = new SchemaModel({
9
+ name: "BrandingAssetInput",
10
+ fields: {
11
+ type: {
12
+ type: ScalarTypeEnum.String_unsecure(),
13
+ isOptional: false
14
+ },
15
+ url: {
16
+ type: ScalarTypeEnum.URL(),
17
+ isOptional: false
18
+ },
19
+ mimeType: {
20
+ type: ScalarTypeEnum.String_unsecure(),
21
+ isOptional: true
22
+ }
23
+ }
24
+ });
25
+ const UpdateTenantBrandingInput = new SchemaModel({
26
+ name: "UpdateTenantBrandingInput",
27
+ fields: {
28
+ tenantId: {
29
+ type: ScalarTypeEnum.ID(),
30
+ isOptional: false
31
+ },
32
+ appId: {
33
+ type: ScalarTypeEnum.ID(),
34
+ isOptional: false
35
+ },
36
+ environment: {
37
+ type: ScalarTypeEnum.String_unsecure(),
38
+ isOptional: true
39
+ },
40
+ appName: {
41
+ type: ScalarTypeEnum.JSONObject(),
42
+ isOptional: true
43
+ },
44
+ assets: {
45
+ type: BrandingAssetInput,
46
+ isOptional: true,
47
+ isArray: true
48
+ },
49
+ colors: {
50
+ type: ScalarTypeEnum.JSONObject(),
51
+ isOptional: true
52
+ },
53
+ customDomain: {
54
+ type: ScalarTypeEnum.String_unsecure(),
55
+ isOptional: true
56
+ },
57
+ subdomain: {
58
+ type: ScalarTypeEnum.String_unsecure(),
59
+ isOptional: true
60
+ }
61
+ }
62
+ });
63
+ const UpdateTenantBrandingOutput = new SchemaModel({
64
+ name: "UpdateTenantBrandingOutput",
65
+ fields: {
66
+ success: {
67
+ type: ScalarTypeEnum.Boolean(),
68
+ isOptional: false
69
+ },
70
+ updatedAt: {
71
+ type: ScalarTypeEnum.DateTime(),
72
+ isOptional: false
73
+ }
74
+ }
75
+ });
76
+ const VerifyCustomDomainInput = new SchemaModel({
77
+ name: "VerifyCustomDomainInput",
78
+ fields: {
79
+ tenantId: {
80
+ type: ScalarTypeEnum.ID(),
81
+ isOptional: false
82
+ },
83
+ appId: {
84
+ type: ScalarTypeEnum.ID(),
85
+ isOptional: false
86
+ },
87
+ domain: {
88
+ type: ScalarTypeEnum.String_unsecure(),
89
+ isOptional: false
90
+ }
91
+ }
92
+ });
93
+ const VerifyCustomDomainOutput = new SchemaModel({
94
+ name: "VerifyCustomDomainOutput",
95
+ fields: {
96
+ status: {
97
+ type: ScalarTypeEnum.String_unsecure(),
98
+ isOptional: false
99
+ },
100
+ message: {
101
+ type: ScalarTypeEnum.String_unsecure(),
102
+ isOptional: true
103
+ }
104
+ }
105
+ });
106
+ const TranslationEntryInput = new SchemaModel({
107
+ name: "TranslationEntryInput",
108
+ fields: {
109
+ key: {
110
+ type: ScalarTypeEnum.String_unsecure(),
111
+ isOptional: false
112
+ },
113
+ locale: {
114
+ type: ScalarTypeEnum.String_unsecure(),
115
+ isOptional: false
116
+ },
117
+ value: {
118
+ type: ScalarTypeEnum.String_unsecure(),
119
+ isOptional: false
120
+ },
121
+ context: {
122
+ type: ScalarTypeEnum.String_unsecure(),
123
+ isOptional: true
124
+ }
125
+ }
126
+ });
127
+ const UpdateBlueprintTranslationInput = new SchemaModel({
128
+ name: "UpdateBlueprintTranslationInput",
129
+ fields: {
130
+ blueprintName: {
131
+ type: ScalarTypeEnum.String_unsecure(),
132
+ isOptional: false
133
+ },
134
+ blueprintVersion: {
135
+ type: ScalarTypeEnum.Int_unsecure(),
136
+ isOptional: false
137
+ },
138
+ catalogName: {
139
+ type: ScalarTypeEnum.String_unsecure(),
140
+ isOptional: false
141
+ },
142
+ catalogVersion: {
143
+ type: ScalarTypeEnum.Int_unsecure(),
144
+ isOptional: false
145
+ },
146
+ defaultLocale: {
147
+ type: ScalarTypeEnum.String_unsecure(),
148
+ isOptional: false
149
+ },
150
+ supportedLocales: {
151
+ type: ScalarTypeEnum.String_unsecure(),
152
+ isOptional: false,
153
+ isArray: true
154
+ },
155
+ entries: {
156
+ type: TranslationEntryInput,
157
+ isOptional: false,
158
+ isArray: true
159
+ }
160
+ }
161
+ });
162
+ const UpdateTenantTranslationInput = new SchemaModel({
163
+ name: "UpdateTenantTranslationInput",
164
+ fields: {
165
+ tenantId: {
166
+ type: ScalarTypeEnum.ID(),
167
+ isOptional: false
168
+ },
169
+ appId: {
170
+ type: ScalarTypeEnum.ID(),
171
+ isOptional: false
172
+ },
173
+ entries: {
174
+ type: TranslationEntryInput,
175
+ isOptional: false,
176
+ isArray: true
177
+ },
178
+ defaultLocale: {
179
+ type: ScalarTypeEnum.String_unsecure(),
180
+ isOptional: true
181
+ },
182
+ enabledLocales: {
183
+ type: ScalarTypeEnum.String_unsecure(),
184
+ isOptional: true,
185
+ isArray: true
186
+ }
187
+ }
188
+ });
189
+ const MessageResolutionInput = new SchemaModel({
190
+ name: "MessageResolutionInput",
191
+ fields: {
192
+ tenantId: {
193
+ type: ScalarTypeEnum.ID(),
194
+ isOptional: false
195
+ },
196
+ appId: {
197
+ type: ScalarTypeEnum.ID(),
198
+ isOptional: false
199
+ },
200
+ locale: {
201
+ type: ScalarTypeEnum.String_unsecure(),
202
+ isOptional: false
203
+ },
204
+ key: {
205
+ type: ScalarTypeEnum.String_unsecure(),
206
+ isOptional: false
207
+ }
208
+ }
209
+ });
210
+ const MessageResolutionOutput = new SchemaModel({
211
+ name: "MessageResolutionOutput",
212
+ fields: {
213
+ value: {
214
+ type: ScalarTypeEnum.String_unsecure(),
215
+ isOptional: true
216
+ },
217
+ source: {
218
+ type: ScalarTypeEnum.String_unsecure(),
219
+ isOptional: true
220
+ }
221
+ }
222
+ });
223
+ const UpdateTenantBrandingCommand = defineCommand({
224
+ meta: {
225
+ name: "appConfig.updateTenantBranding",
226
+ version: 1,
227
+ description: "Applies tenant branding overrides (names, assets, domains).",
228
+ owners: [OwnersEnum.PlatformSigil],
229
+ tags: ["branding"],
230
+ stability: StabilityEnum.Beta,
231
+ goal: "Maintain tenant-specific branding assets and domains.",
232
+ context: "Invoked by the Studio or automation when a tenant updates branding settings."
233
+ },
234
+ io: {
235
+ input: UpdateTenantBrandingInput,
236
+ output: UpdateTenantBrandingOutput
237
+ },
238
+ policy: {
239
+ auth: "admin",
240
+ policies: [{
241
+ name: "platform.app-config.manage",
242
+ version: 1
243
+ }]
244
+ }
245
+ });
246
+ const VerifyCustomDomainCommand = defineCommand({
247
+ meta: {
248
+ name: "appConfig.verifyCustomDomain",
249
+ version: 1,
250
+ description: "Validates DNS ownership for tenant custom domains.",
251
+ owners: [OwnersEnum.PlatformSigil],
252
+ tags: ["branding"],
253
+ stability: StabilityEnum.Experimental,
254
+ goal: "Confirm tenant-provided domains before activation.",
255
+ context: "Triggered after the tenant adds DNS records to verify domain ownership."
256
+ },
257
+ io: {
258
+ input: VerifyCustomDomainInput,
259
+ output: VerifyCustomDomainOutput
260
+ },
261
+ policy: {
262
+ auth: "admin",
263
+ policies: [{
264
+ name: "platform.app-config.manage",
265
+ version: 1
266
+ }]
267
+ }
268
+ });
269
+ const UpdateBlueprintTranslationCatalogCommand = defineCommand({
270
+ meta: {
271
+ name: "appConfig.updateBlueprintTranslationCatalog",
272
+ version: 1,
273
+ description: "Registers or updates translation entries for a blueprint.",
274
+ owners: [OwnersEnum.PlatformSigil],
275
+ tags: [TagsEnum.I18n],
276
+ stability: StabilityEnum.Beta,
277
+ goal: "Keep blueprint translation catalogs in sync with shipped copy.",
278
+ context: "Executed by platform automation or CI when committing updated translation catalogs."
279
+ },
280
+ io: {
281
+ input: UpdateBlueprintTranslationInput,
282
+ output: UpdateTenantBrandingOutput
283
+ },
284
+ policy: {
285
+ auth: "admin",
286
+ policies: [{
287
+ name: "platform.app-config.manage",
288
+ version: 1
289
+ }]
290
+ }
291
+ });
292
+ const UpdateTenantTranslationOverridesCommand = defineCommand({
293
+ meta: {
294
+ name: "appConfig.updateTenantTranslations",
295
+ version: 1,
296
+ description: "Applies tenant-specific translation entries.",
297
+ owners: [OwnersEnum.PlatformSigil],
298
+ tags: [TagsEnum.I18n],
299
+ stability: StabilityEnum.Beta,
300
+ goal: "Allow tenants to override selected message keys.",
301
+ context: "Called by the Studio when a tenant customizes labels or copy for their locale."
302
+ },
303
+ io: {
304
+ input: UpdateTenantTranslationInput,
305
+ output: UpdateTenantBrandingOutput
306
+ },
307
+ policy: {
308
+ auth: "admin",
309
+ policies: [{
310
+ name: "platform.app-config.manage",
311
+ version: 1
312
+ }]
313
+ }
314
+ });
315
+ const GetResolvedBrandingQuery = defineQuery({
316
+ meta: {
317
+ name: "appConfig.getResolvedBranding",
318
+ version: 1,
319
+ description: "Returns the resolved branding for a tenant/app/environment.",
320
+ owners: [OwnersEnum.PlatformSigil],
321
+ tags: ["branding"],
322
+ stability: StabilityEnum.Beta,
323
+ goal: "Expose hydrated branding assets for rendering UI/email experiences.",
324
+ context: "Used by runtime surfaces to fetch brand assets prior to rendering tenant-specific experiences."
325
+ },
326
+ io: {
327
+ input: new SchemaModel({
328
+ name: "GetResolvedBrandingInput",
329
+ fields: {
330
+ tenantId: {
331
+ type: ScalarTypeEnum.ID(),
332
+ isOptional: false
333
+ },
334
+ appId: {
335
+ type: ScalarTypeEnum.ID(),
336
+ isOptional: false
337
+ },
338
+ environment: {
339
+ type: ScalarTypeEnum.String_unsecure(),
340
+ isOptional: true
341
+ }
342
+ }
343
+ }),
344
+ output: new SchemaModel({
345
+ name: "GetResolvedBrandingOutput",
346
+ fields: { branding: {
347
+ type: ScalarTypeEnum.JSONObject(),
348
+ isOptional: false
349
+ } }
350
+ })
351
+ },
352
+ policy: {
353
+ auth: "admin",
354
+ policies: [{
355
+ name: "platform.app-config.read",
356
+ version: 1
357
+ }]
358
+ }
359
+ });
360
+ const ResolveMessageQuery = defineQuery({
361
+ meta: {
362
+ name: "appConfig.resolveMessage",
363
+ version: 1,
364
+ description: "Resolves a translation key for a tenant in the requested locale.",
365
+ owners: [OwnersEnum.PlatformSigil],
366
+ tags: [TagsEnum.I18n],
367
+ stability: StabilityEnum.Experimental,
368
+ goal: "Expose a server-side API for resolving message keys on demand.",
369
+ context: "Used by backend services or scripts that need translated copy outside the front-end runtime."
370
+ },
371
+ io: {
372
+ input: MessageResolutionInput,
373
+ output: MessageResolutionOutput
374
+ },
375
+ policy: {
376
+ auth: "admin",
377
+ policies: [{
378
+ name: "platform.app-config.read",
379
+ version: 1
380
+ }]
381
+ }
382
+ });
383
+ const appConfigContracts = {
384
+ UpdateTenantBrandingCommand,
385
+ VerifyCustomDomainCommand,
386
+ UpdateBlueprintTranslationCatalogCommand,
387
+ UpdateTenantTranslationOverridesCommand,
388
+ GetResolvedBrandingQuery,
389
+ ResolveMessageQuery
390
+ };
391
+ function registerAppConfigContracts(registry) {
392
+ return registry.register(UpdateTenantBrandingCommand).register(VerifyCustomDomainCommand).register(UpdateBlueprintTranslationCatalogCommand).register(UpdateTenantTranslationOverridesCommand).register(GetResolvedBrandingQuery).register(ResolveMessageQuery);
393
+ }
394
+
395
+ //#endregion
396
+ export { GetResolvedBrandingQuery, ResolveMessageQuery, UpdateBlueprintTranslationCatalogCommand, UpdateTenantBrandingCommand, UpdateTenantTranslationOverridesCommand, VerifyCustomDomainCommand, appConfigContracts, registerAppConfigContracts };
@@ -1,220 +1,22 @@
1
- import{registerDocBlocks as e}from"../../docs/registry.js";import"../../registry.js";const t=[{id:`docs.tech.contracts.app-config`,title:`App Configuration Layers`,summary:`App orchestration is split into three explicit layers:`,kind:`reference`,visibility:`public`,route:`/docs/tech/contracts/app-config`,tags:[`tech`,`contracts`,`app-config`],body:`## App Configuration Layers
2
-
3
- App orchestration is split into three explicit layers:
4
-
5
- 1. **AppBlueprintSpec** global, versioned description of what an app can look like. Stored in Git, no tenant/environment data.
6
- 2. **TenantAppConfig** – tenant/environment overrides that the future Studio edits. Stored per tenant (DB/contract), mutable at runtime.
7
- 3. **ResolvedAppConfig** pure, merged view consumed by the runtime. Derived in-memory from a blueprint + tenant config.
8
-
9
- - Types & registry: \`packages/libs/contracts/src/app-config/spec.ts\`
10
- - Resolution helpers: \`packages/libs/contracts/src/app-config/runtime.ts\`
11
- - CLI wizard (blueprint scaffolding): \`contractspec create app-config\`
12
-
13
- ### 1. AppBlueprintSpec
14
-
15
- \`\`\`ts
16
- export interface AppBlueprintSpec {
17
- meta: AppBlueprintMeta; // { name, version, appId, ownership }
18
- capabilities?: { enabled?: CapabilityRef[]; disabled?: CapabilityRef[] };
19
- features?: { include?: FeatureRef[]; exclude?: FeatureRef[] };
20
- integrationSlots?: AppIntegrationSlot[];
21
- branding?: BrandingDefaults;
22
- dataViews?: Record<string, SpecPointer>;
23
- workflows?: Record<string, SpecPointer>;
24
- policies?: PolicyRef[];
25
- theme?: AppThemeBinding;
26
- telemetry?: TelemetryBinding;
27
- experiments?: { active?: ExperimentRef[]; paused?: ExperimentRef[] };
28
- featureFlags?: FeatureFlagState[];
29
- routes?: AppRouteConfig[];
30
- notes?: string;
31
- }
32
- \`\`\`
33
-
34
- Register blueprints with \`AppBlueprintRegistry\`. Blueprints only capture the default/global experience.
35
-
36
- - **Integration slots** declare the categories and capability requirements an app expects (e.g. \`"primary-payments"\` must be a payments provider that supports managed or BYOK credentials). Slots never include secrets; tenants bind concrete connections later.
37
- - **Branding defaults** provide message-key based names, placeholder assets, and theme token references that downstream tenants can override.
38
-
39
- ### 2. TenantAppConfig
40
-
41
- \`\`\`ts
42
- export interface TenantAppConfig {
43
- meta: TenantAppConfigMeta; // { id, tenantId, appId, blueprintName/version, environment?, version, timestamps }
44
- capabilities?: { enable?: CapabilityRef[]; disable?: CapabilityRef[] };
45
- features?: { include?: FeatureRef[]; exclude?: FeatureRef[] };
46
- dataViewOverrides?: TenantSpecOverride[];
47
- workflowOverrides?: TenantSpecOverride[];
48
- additionalPolicies?: PolicyRef[];
49
- themeOverride?: { primary?: ThemeRef | null; fallbacks?: ThemeRef[] };
50
- telemetryOverride?: { spec?: SpecPointer | null; disabledEvents?: string[] };
51
- experiments?: { active?: ExperimentRef[]; paused?: ExperimentRef[] };
52
- featureFlags?: FeatureFlagState[];
53
- routeOverrides?: TenantRouteOverride[];
54
- integrations?: AppIntegrationBinding[];
55
- knowledge?: AppKnowledgeBinding[];
56
- branding?: TenantBrandingConfig;
57
- notes?: string;
58
- }
59
- \`\`\`
60
-
61
- This object represents what a tenant edits via the Studio (stored in DB/contracts later).
62
-
63
- - **AppIntegrationBinding** now maps \`slotId\` → \`connectionId\` (plus optional workflow scopes). It no longer carries capability lists; those are defined once in the slot.
64
- - **TenantBrandingConfig** allows per-tenant names, assets, and domain overrides while keeping secrets and large files out of blueprints.
65
-
66
- ### 3. ResolvedAppConfig
67
-
68
- \`\`\`ts
69
- export interface ResolvedAppConfig {
70
- appId: string;
71
- tenantId: string;
72
- environment?: string;
73
- blueprintName: string;
74
- blueprintVersion: number;
75
- configVersion: number;
76
- capabilities: { enabled: CapabilityRef[]; disabled: CapabilityRef[] };
77
- features: { include: FeatureRef[]; exclude: FeatureRef[] };
78
- dataViews: Record<string, SpecPointer>;
79
- workflows: Record<string, SpecPointer>;
80
- policies: PolicyRef[];
81
- theme?: AppThemeBinding;
82
- telemetry?: TelemetryBinding;
83
- experiments: { catalog: ExperimentRef[]; active: ExperimentRef[]; paused: ExperimentRef[] };
84
- featureFlags: FeatureFlagState[];
85
- routes: AppRouteConfig[];
86
- integrations: ResolvedIntegration[];
87
- knowledge: ResolvedKnowledge[];
88
- branding: ResolvedBranding;
89
- notes?: string;
90
- }
91
- \`\`\`
92
-
93
- Use \`resolveAppConfig(blueprint, tenant)\` to produce this merged view. No IO, no registry lookups—pure data merge.
94
-
95
- - \`resolveAppConfig\` validates slot/category/mode constraints when \`integrationConnections\` and \`integrationSpecs\` are provided.
96
- - \`branding\` merges blueprint defaults with tenant overrides, producing a runtime-friendly shape (resolved asset URLs, color values, and effective domain).
97
-
98
- ### Materializing specs
99
-
100
- \`composeAppConfig(blueprint, tenant, registries, { strict })\`:
101
-
102
- 1. Calls \`resolveAppConfig\` to build the merged pointers.
103
- 2. Looks up referenced specs in the provided registries.
104
- 3. Returns:
105
- - \`resolved\` – the merged pointer view
106
- - \`capabilities\`, \`features\`, \`dataViews\`, \`workflows\`, \`policies\`, \`theme\`, \`telemetry\`, \`experiments\`
107
- - \`missing\` – unresolved references (strict mode throws).
108
-
109
- \`\`\`ts
110
- const blueprint = blueprintRegistry.get('core.app', 1)!;
111
- const tenant = loadTenantConfigFromDB();
112
-
113
- const composition = composeAppConfig(blueprint, tenant, {
114
- capabilities,
115
- features,
116
- dataViews,
117
- workflows,
118
- policies,
119
- themes,
120
- telemetry,
121
- experiments,
122
- });
123
-
124
- if (composition.missing.length) {
125
- console.warn('Unresolved references', composition.missing);
126
- }
127
- \`\`\`
128
-
129
- ### CLI workflow
130
-
131
- \`\`\`
132
- contractspec create app-config
133
- \`\`\`
134
-
135
- Generates an \`AppBlueprintSpec\`. A separate flow will later scaffold tenant configs.
136
-
137
- ### Best practices
138
-
139
- 1. Keep blueprint and tenant versions monotonic; bump when referenced spec versions change.
140
- 2. Favor stable slot keys (e.g. \`dataViews.dashboard\`) to align with Studio UX.
141
- 3. Reference telemetry and experiments declared in their respective specs to maintain observability.
142
- 4. Run \`resolveAppConfig\` in pure unit tests and \`composeAppConfig(..., { strict: true })\` in CI to catch drift early.
143
- 5. Pair resolved configs with \`TestSpec\` scenarios to guard tenant experiences end-to-end.
144
-
145
- ### Static validation
146
-
147
- Use the validation helpers in \`@lssm/lib.contracts/app-config/validation\` to keep blueprints and tenant configs safe before publish time.
148
-
149
- \`\`\`ts
150
- import {
151
- validateConfig,
152
- validateBlueprint,
153
- validateTenantConfig,
154
- validateResolvedConfig,
155
- } from '@lssm/lib.contracts/app-config/validation';
156
-
157
- const context = {
158
- integrationSpecs,
159
- tenantConnections,
160
- knowledgeSpaces,
161
- knowledgeSources,
162
- translationCatalogs: {
163
- blueprint: blueprintCatalog,
164
- platform: platformCatalog,
165
- },
166
- existingConfigs,
167
- };
168
-
169
- const blueprintReport = validateBlueprint(blueprint, context);
170
- const tenantReport = validateTenantConfig(blueprint, tenant, context);
171
- const publishReport = validateConfig(blueprint, tenant, context);
172
- \`\`\`
173
-
174
- - \`ValidationResult\` exposes \`valid\`, plus structured \`errors\`, \`warnings\`, and \`info\`.
175
- - Core rules cover capability references, integration slot bindings (category/ownership/capabilities), knowledge bindings, branding constraints (domains + assets), and translation coverage.
176
- - Call \`validateBlueprint\` in CI when committing new specs, and \`validateConfig\` before promoting/publishing a tenant config.
177
- - \`validateResolvedConfig\` can be used as a runtime pre-flight check when composing full configs for workflows.
178
- - CLI usage example (blueprint + tenant):
179
-
180
- \`\`\`
181
- pnpm contractspec validate \\
182
- packages/examples/integration-stripe/blueprint.ts \\
183
- --blueprint packages/examples/integration-stripe/blueprint.ts \\
184
- --tenant-config packages/examples/integration-stripe/tenant.ts
185
- \`\`\`
186
- - Repository script:
187
-
188
- \`\`\`
189
- bun run validate:blueprints
190
- \`\`\`
191
-
192
- Runs the static validator for the sample blueprints/tenants and is wired into CI.
193
-
194
-
195
- ### Lifecycle types & events
196
-
197
- To model multi-step configuration changes, use the lifecycle helpers exported from \`@lssm/lib.contracts/app-config\`:
198
-
199
- \`\`\`ts
200
- import type {
201
- ConfigStatus,
202
- TenantAppConfigVersion,
203
- ConfigTransition,
204
- } from '@lssm/lib.contracts/app-config';
205
- import {
206
- ConfigDraftCreatedEvent,
207
- ConfigPromotedToPreviewEvent,
208
- ConfigPublishedEvent,
209
- ConfigRolledBackEvent,
210
- } from '@lssm/lib.contracts/app-config';
211
- \`\`\`
212
-
213
- - \`ConfigStatus\` enumerates the canonical states: \`draft\`, \`preview\`, \`published\`, \`archived\`, \`superseded\`.
214
- - \`TenantAppConfigMeta\` now includes lifecycle metadata (\`status\`, \`createdBy\`, \`publishedBy\`, \`publishedAt\`, \`rolledBackFrom\`, \`rolledBackTo\`, \`changeSummary\`).
215
- - \`TenantAppConfigVersion\` couples the lifecycle-aware metadata with the \`TenantAppConfig\` payload for history views.
216
- - \`ConfigTransition\` captures state changes with actor, timestamp, and optional reason.
217
- - Lifecycle events (\`app_config.draft_created\`, \`app_config.promoted_to_preview\`, \`app_config.published\`, \`app_config.rolled_back\`) standardize observability across services.
218
- - Lifecycle contract specs (\`appConfig.lifecycle.*\`) expose typed commands/queries for create → preview → publish → rollback flows.
219
-
220
- `}];e(t);export{t as tech_contracts_app_config_DocBlocks};
1
+ import { registerDocBlocks } from "../../docs/registry.js";
2
+ import "../../registry.js";
3
+
4
+ //#region src/app-config/docs/app-config.docblock.ts
5
+ const tech_contracts_app_config_DocBlocks = [{
6
+ id: "docs.tech.contracts.app-config",
7
+ title: "App Configuration Layers",
8
+ summary: "App orchestration is split into three explicit layers:",
9
+ kind: "reference",
10
+ visibility: "public",
11
+ route: "/docs/tech/contracts/app-config",
12
+ tags: [
13
+ "tech",
14
+ "contracts",
15
+ "app-config"
16
+ ],
17
+ body: "## App Configuration Layers\n\nApp orchestration is split into three explicit layers:\n\n1. **AppBlueprintSpec** – global, versioned description of what an app can look like. Stored in Git, no tenant/environment data.\n2. **TenantAppConfig** – tenant/environment overrides that the future Studio edits. Stored per tenant (DB/contract), mutable at runtime.\n3. **ResolvedAppConfig** – pure, merged view consumed by the runtime. Derived in-memory from a blueprint + tenant config.\n\n- Types & registry: `packages/libs/contracts/src/app-config/spec.ts`\n- Resolution helpers: `packages/libs/contracts/src/app-config/runtime.ts`\n- CLI wizard (blueprint scaffolding): `contractspec create app-config`\n\n### 1. AppBlueprintSpec\n\n```ts\nexport interface AppBlueprintSpec {\n meta: AppBlueprintMeta; // { name, version, appId, ownership }\n capabilities?: { enabled?: CapabilityRef[]; disabled?: CapabilityRef[] };\n features?: { include?: FeatureRef[]; exclude?: FeatureRef[] };\n integrationSlots?: AppIntegrationSlot[];\n branding?: BrandingDefaults;\n dataViews?: Record<string, SpecPointer>;\n workflows?: Record<string, SpecPointer>;\n policies?: PolicyRef[];\n theme?: AppThemeBinding;\n telemetry?: TelemetryBinding;\n experiments?: { active?: ExperimentRef[]; paused?: ExperimentRef[] };\n featureFlags?: FeatureFlagState[];\n routes?: AppRouteConfig[];\n notes?: string;\n}\n```\n\nRegister blueprints with `AppBlueprintRegistry`. Blueprints only capture the default/global experience.\n\n- **Integration slots** declare the categories and capability requirements an app expects (e.g. `\"primary-payments\"` must be a payments provider that supports managed or BYOK credentials). Slots never include secrets; tenants bind concrete connections later.\n- **Branding defaults** provide message-key based names, placeholder assets, and theme token references that downstream tenants can override.\n\n### 2. TenantAppConfig\n\n```ts\nexport interface TenantAppConfig {\n meta: TenantAppConfigMeta; // { id, tenantId, appId, blueprintName/version, environment?, version, timestamps }\n capabilities?: { enable?: CapabilityRef[]; disable?: CapabilityRef[] };\n features?: { include?: FeatureRef[]; exclude?: FeatureRef[] };\n dataViewOverrides?: TenantSpecOverride[];\n workflowOverrides?: TenantSpecOverride[];\n additionalPolicies?: PolicyRef[];\n themeOverride?: { primary?: ThemeRef | null; fallbacks?: ThemeRef[] };\n telemetryOverride?: { spec?: SpecPointer | null; disabledEvents?: string[] };\n experiments?: { active?: ExperimentRef[]; paused?: ExperimentRef[] };\n featureFlags?: FeatureFlagState[];\n routeOverrides?: TenantRouteOverride[];\n integrations?: AppIntegrationBinding[];\n knowledge?: AppKnowledgeBinding[];\n branding?: TenantBrandingConfig;\n notes?: string;\n}\n```\n\nThis object represents what a tenant edits via the Studio (stored in DB/contracts later).\n\n- **AppIntegrationBinding** now maps `slotId` → `connectionId` (plus optional workflow scopes). It no longer carries capability lists; those are defined once in the slot.\n- **TenantBrandingConfig** allows per-tenant names, assets, and domain overrides while keeping secrets and large files out of blueprints.\n\n### 3. ResolvedAppConfig\n\n```ts\nexport interface ResolvedAppConfig {\n appId: string;\n tenantId: string;\n environment?: string;\n blueprintName: string;\n blueprintVersion: number;\n configVersion: number;\n capabilities: { enabled: CapabilityRef[]; disabled: CapabilityRef[] };\n features: { include: FeatureRef[]; exclude: FeatureRef[] };\n dataViews: Record<string, SpecPointer>;\n workflows: Record<string, SpecPointer>;\n policies: PolicyRef[];\n theme?: AppThemeBinding;\n telemetry?: TelemetryBinding;\n experiments: { catalog: ExperimentRef[]; active: ExperimentRef[]; paused: ExperimentRef[] };\n featureFlags: FeatureFlagState[];\n routes: AppRouteConfig[];\n integrations: ResolvedIntegration[];\n knowledge: ResolvedKnowledge[];\n branding: ResolvedBranding;\n notes?: string;\n}\n```\n\nUse `resolveAppConfig(blueprint, tenant)` to produce this merged view. No IO, no registry lookups—pure data merge.\n\n- `resolveAppConfig` validates slot/category/mode constraints when `integrationConnections` and `integrationSpecs` are provided.\n- `branding` merges blueprint defaults with tenant overrides, producing a runtime-friendly shape (resolved asset URLs, color values, and effective domain).\n\n### Materializing specs\n\n`composeAppConfig(blueprint, tenant, registries, { strict })`:\n\n1. Calls `resolveAppConfig` to build the merged pointers.\n2. Looks up referenced specs in the provided registries.\n3. Returns:\n - `resolved` – the merged pointer view\n - `capabilities`, `features`, `dataViews`, `workflows`, `policies`, `theme`, `telemetry`, `experiments`\n - `missing` – unresolved references (strict mode throws).\n\n```ts\nconst blueprint = blueprintRegistry.get('core.app', 1)!;\nconst tenant = loadTenantConfigFromDB();\n\nconst composition = composeAppConfig(blueprint, tenant, {\n capabilities,\n features,\n dataViews,\n workflows,\n policies,\n themes,\n telemetry,\n experiments,\n});\n\nif (composition.missing.length) {\n console.warn('Unresolved references', composition.missing);\n}\n```\n\n### CLI workflow\n\n```\ncontractspec create app-config\n```\n\nGenerates an `AppBlueprintSpec`. A separate flow will later scaffold tenant configs.\n\n### Best practices\n\n1. Keep blueprint and tenant versions monotonic; bump when referenced spec versions change.\n2. Favor stable slot keys (e.g. `dataViews.dashboard`) to align with Studio UX.\n3. Reference telemetry and experiments declared in their respective specs to maintain observability.\n4. Run `resolveAppConfig` in pure unit tests and `composeAppConfig(..., { strict: true })` in CI to catch drift early.\n5. Pair resolved configs with `TestSpec` scenarios to guard tenant experiences end-to-end.\n\n### Static validation\n\nUse the validation helpers in `@lssm/lib.contracts/app-config/validation` to keep blueprints and tenant configs safe before publish time.\n\n```ts\nimport {\n validateConfig,\n validateBlueprint,\n validateTenantConfig,\n validateResolvedConfig,\n} from '@lssm/lib.contracts/app-config/validation';\n\nconst context = {\n integrationSpecs,\n tenantConnections,\n knowledgeSpaces,\n knowledgeSources,\n translationCatalogs: {\n blueprint: blueprintCatalog,\n platform: platformCatalog,\n },\n existingConfigs,\n};\n\nconst blueprintReport = validateBlueprint(blueprint, context);\nconst tenantReport = validateTenantConfig(blueprint, tenant, context);\nconst publishReport = validateConfig(blueprint, tenant, context);\n```\n\n- `ValidationResult` exposes `valid`, plus structured `errors`, `warnings`, and `info`.\n- Core rules cover capability references, integration slot bindings (category/ownership/capabilities), knowledge bindings, branding constraints (domains + assets), and translation coverage.\n- Call `validateBlueprint` in CI when committing new specs, and `validateConfig` before promoting/publishing a tenant config.\n- `validateResolvedConfig` can be used as a runtime pre-flight check when composing full configs for workflows.\n- CLI usage example (blueprint + tenant):\n\n```\npnpm contractspec validate \\\n packages/examples/integration-stripe/blueprint.ts \\\n --blueprint packages/examples/integration-stripe/blueprint.ts \\\n --tenant-config packages/examples/integration-stripe/tenant.ts\n```\n- Repository script:\n\n```\nbun run validate:blueprints\n```\n\nRuns the static validator for the sample blueprints/tenants and is wired into CI.\n\n\n### Lifecycle types & events\n\nTo model multi-step configuration changes, use the lifecycle helpers exported from `@lssm/lib.contracts/app-config`:\n\n```ts\nimport type {\n ConfigStatus,\n TenantAppConfigVersion,\n ConfigTransition,\n} from '@lssm/lib.contracts/app-config';\nimport {\n ConfigDraftCreatedEvent,\n ConfigPromotedToPreviewEvent,\n ConfigPublishedEvent,\n ConfigRolledBackEvent,\n} from '@lssm/lib.contracts/app-config';\n```\n\n- `ConfigStatus` enumerates the canonical states: `draft`, `preview`, `published`, `archived`, `superseded`.\n- `TenantAppConfigMeta` now includes lifecycle metadata (`status`, `createdBy`, `publishedBy`, `publishedAt`, `rolledBackFrom`, `rolledBackTo`, `changeSummary`).\n- `TenantAppConfigVersion` couples the lifecycle-aware metadata with the `TenantAppConfig` payload for history views.\n- `ConfigTransition` captures state changes with actor, timestamp, and optional reason.\n- Lifecycle events (`app_config.draft_created`, `app_config.promoted_to_preview`, `app_config.published`, `app_config.rolled_back`) standardize observability across services.\n- Lifecycle contract specs (`appConfig.lifecycle.*`) expose typed commands/queries for create → preview → publish → rollback flows.\n\n"
18
+ }];
19
+ registerDocBlocks(tech_contracts_app_config_DocBlocks);
20
+
21
+ //#endregion
22
+ export { tech_contracts_app_config_DocBlocks };