@lssm/lib.contracts 1.42.10 → 1.43.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/app-config/app-config.feature.d.ts +2 -1
- package/dist/app-config/contracts.d.ts +51 -51
- package/dist/app-config/docs/app-config.docblock.js +1 -1
- package/dist/app-config/events.d.ts +27 -27
- package/dist/app-config/lifecycle-contracts.d.ts +55 -55
- package/dist/app-config/runtime.d.ts +7 -4
- package/dist/app-config/spec.d.ts +3 -2
- package/dist/app-config/validation.d.ts +1 -1
- package/dist/client/react/feature-render.d.ts +3 -1
- package/dist/contract-registry/schemas.d.ts +2 -2
- package/dist/data-views/data-views.d.ts +5 -138
- package/dist/data-views/data-views.js +3 -57
- package/dist/data-views/index.d.ts +4 -4
- package/dist/data-views/index.js +3 -4
- package/dist/data-views/query-generator.d.ts +1 -1
- package/dist/data-views/registry.d.ts +51 -0
- package/dist/data-views/registry.js +82 -0
- package/dist/data-views/runtime.d.ts +2 -1
- package/dist/data-views/spec.d.ts +32 -0
- package/dist/data-views/spec.js +10 -0
- package/dist/data-views/types.d.ts +157 -0
- package/dist/data-views/types.js +0 -0
- package/dist/docs/index.js +3 -1
- package/dist/docs/tech/contracts/openapi-import.docblock.d.ts +6 -0
- package/dist/docs/tech/contracts/openapi-import.docblock.js +65 -0
- package/dist/docs/tech/presentation-runtime.docblock.js +1 -1
- package/dist/docs/tech/schema/README.docblock.js +1 -1
- package/dist/experiments/spec-resolver.d.ts +1 -1
- package/dist/features/index.d.ts +5 -0
- package/dist/features/index.js +5 -0
- package/dist/features/install.d.ts +22 -0
- package/dist/features/install.js +36 -0
- package/dist/features/registry.d.ts +26 -0
- package/dist/features/registry.js +49 -0
- package/dist/features/types.d.ts +88 -0
- package/dist/features/types.js +0 -0
- package/dist/features/validation.d.ts +8 -0
- package/dist/features/validation.js +14 -0
- package/dist/index.d.ts +16 -12
- package/dist/index.js +7 -6
- package/dist/install.d.ts +1 -1
- package/dist/integrations/integrations.feature.d.ts +2 -1
- package/dist/integrations/openbanking/contracts/accounts.d.ts +67 -67
- package/dist/integrations/openbanking/contracts/balances.d.ts +35 -35
- package/dist/integrations/openbanking/contracts/transactions.d.ts +49 -49
- package/dist/integrations/openbanking/models.d.ts +55 -55
- package/dist/integrations/openbanking/openbanking.feature.d.ts +2 -1
- package/dist/integrations/operations.d.ts +103 -103
- package/dist/jsonschema.d.ts +3 -4
- package/dist/knowledge/knowledge.feature.d.ts +2 -1
- package/dist/knowledge/operations.d.ts +67 -67
- package/dist/llm/exporters.d.ts +3 -2
- package/dist/llm/prompts.d.ts +1 -1
- package/dist/llm/types.d.ts +3 -2
- package/dist/markdown.d.ts +2 -2
- package/dist/model-registry.d.ts +1 -1
- package/dist/model-registry.js +14 -3
- package/dist/onboarding-base.d.ts +29 -29
- package/dist/operations/operation.d.ts +7 -1
- package/dist/schema-to-markdown.js +3 -0
- package/dist/server/contracts-adapter-input.js +36 -30
- package/dist/server/graphql-pothos.js +33 -26
- package/dist/tests/runner.js +1 -1
- package/dist/tests/spec.d.ts +2 -10
- package/dist/{docs/tech/workflows → workflow}/overview.docblock.d.ts +1 -1
- package/dist/{docs/tech/workflows → workflow}/overview.docblock.js +2 -2
- package/dist/workflow/runner.d.ts +2 -1
- package/dist/workflow/spec.d.ts +3 -2
- package/dist/workspace-config/contractsrc-schema.d.ts +81 -5
- package/dist/workspace-config/contractsrc-schema.js +38 -4
- package/dist/workspace-config/index.d.ts +2 -2
- package/dist/workspace-config/index.js +2 -2
- package/dist/workspace-config/workspace-config.docblock.d.ts +6 -0
- package/dist/workspace-config/workspace-config.docblock.js +45 -0
- package/package.json +18 -8
- package/dist/features.d.ts +0 -104
- package/dist/features.js +0 -91
package/README.md
CHANGED
|
@@ -30,6 +30,7 @@ bun add @lssm/lib.contracts @lssm/lib.schema
|
|
|
30
30
|
## Exports
|
|
31
31
|
|
|
32
32
|
- **Core**: `OperationSpecRegistry`, `defineCommand`, `defineQuery`, `defineEvent`.
|
|
33
|
+
- **Config**: `SchemaFormat` ('contractspec' | 'zod' | 'json-schema' | 'graphql').
|
|
33
34
|
- **Adapters**:
|
|
34
35
|
- `server/rest-next-app`: Next.js App Router adapter.
|
|
35
36
|
- `server/provider-mcp`: Model Context Protocol (MCP) adapter for AI agents.
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import "../operations/index.js";
|
|
2
1
|
import { OperationSpec } from "../operations/operation.js";
|
|
3
2
|
import { OperationSpecRegistry } from "../operations/registry.js";
|
|
4
|
-
import
|
|
3
|
+
import "../operations/index.js";
|
|
4
|
+
import * as _lssm_lib_schema128 from "@lssm/lib.schema";
|
|
5
5
|
import { SchemaModel } from "@lssm/lib.schema";
|
|
6
6
|
|
|
7
7
|
//#region src/app-config/contracts.d.ts
|
|
8
8
|
declare const UpdateTenantBrandingCommand: OperationSpec<SchemaModel<{
|
|
9
9
|
tenantId: {
|
|
10
|
-
type:
|
|
10
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
11
11
|
isOptional: false;
|
|
12
12
|
};
|
|
13
13
|
appId: {
|
|
14
|
-
type:
|
|
14
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
15
15
|
isOptional: false;
|
|
16
16
|
};
|
|
17
17
|
environment: {
|
|
18
|
-
type:
|
|
18
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
19
19
|
isOptional: true;
|
|
20
20
|
};
|
|
21
21
|
appName: {
|
|
22
|
-
type:
|
|
22
|
+
type: _lssm_lib_schema128.FieldType<Record<string, unknown>, Record<string, unknown>>;
|
|
23
23
|
isOptional: true;
|
|
24
24
|
};
|
|
25
25
|
assets: {
|
|
26
26
|
type: SchemaModel<{
|
|
27
27
|
type: {
|
|
28
|
-
type:
|
|
28
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
29
29
|
isOptional: false;
|
|
30
30
|
};
|
|
31
31
|
url: {
|
|
32
|
-
type:
|
|
32
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
33
33
|
isOptional: false;
|
|
34
34
|
};
|
|
35
35
|
mimeType: {
|
|
36
|
-
type:
|
|
36
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
37
37
|
isOptional: true;
|
|
38
38
|
};
|
|
39
39
|
}>;
|
|
@@ -41,92 +41,92 @@ declare const UpdateTenantBrandingCommand: OperationSpec<SchemaModel<{
|
|
|
41
41
|
isArray: true;
|
|
42
42
|
};
|
|
43
43
|
colors: {
|
|
44
|
-
type:
|
|
44
|
+
type: _lssm_lib_schema128.FieldType<Record<string, unknown>, Record<string, unknown>>;
|
|
45
45
|
isOptional: true;
|
|
46
46
|
};
|
|
47
47
|
customDomain: {
|
|
48
|
-
type:
|
|
48
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
49
49
|
isOptional: true;
|
|
50
50
|
};
|
|
51
51
|
subdomain: {
|
|
52
|
-
type:
|
|
52
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
53
53
|
isOptional: true;
|
|
54
54
|
};
|
|
55
55
|
}>, SchemaModel<{
|
|
56
56
|
success: {
|
|
57
|
-
type:
|
|
57
|
+
type: _lssm_lib_schema128.FieldType<boolean, boolean>;
|
|
58
58
|
isOptional: false;
|
|
59
59
|
};
|
|
60
60
|
updatedAt: {
|
|
61
|
-
type:
|
|
61
|
+
type: _lssm_lib_schema128.FieldType<Date, string>;
|
|
62
62
|
isOptional: false;
|
|
63
63
|
};
|
|
64
64
|
}>, undefined>;
|
|
65
65
|
declare const VerifyCustomDomainCommand: OperationSpec<SchemaModel<{
|
|
66
66
|
tenantId: {
|
|
67
|
-
type:
|
|
67
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
68
68
|
isOptional: false;
|
|
69
69
|
};
|
|
70
70
|
appId: {
|
|
71
|
-
type:
|
|
71
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
72
72
|
isOptional: false;
|
|
73
73
|
};
|
|
74
74
|
domain: {
|
|
75
|
-
type:
|
|
75
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
76
76
|
isOptional: false;
|
|
77
77
|
};
|
|
78
78
|
}>, SchemaModel<{
|
|
79
79
|
status: {
|
|
80
|
-
type:
|
|
80
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
81
81
|
isOptional: false;
|
|
82
82
|
};
|
|
83
83
|
message: {
|
|
84
|
-
type:
|
|
84
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
85
85
|
isOptional: true;
|
|
86
86
|
};
|
|
87
87
|
}>, undefined>;
|
|
88
88
|
declare const UpdateBlueprintTranslationCatalogCommand: OperationSpec<SchemaModel<{
|
|
89
89
|
blueprintName: {
|
|
90
|
-
type:
|
|
90
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
91
91
|
isOptional: false;
|
|
92
92
|
};
|
|
93
93
|
blueprintVersion: {
|
|
94
|
-
type:
|
|
94
|
+
type: _lssm_lib_schema128.FieldType<number, number>;
|
|
95
95
|
isOptional: false;
|
|
96
96
|
};
|
|
97
97
|
catalogName: {
|
|
98
|
-
type:
|
|
98
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
99
99
|
isOptional: false;
|
|
100
100
|
};
|
|
101
101
|
catalogVersion: {
|
|
102
|
-
type:
|
|
102
|
+
type: _lssm_lib_schema128.FieldType<number, number>;
|
|
103
103
|
isOptional: false;
|
|
104
104
|
};
|
|
105
105
|
defaultLocale: {
|
|
106
|
-
type:
|
|
106
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
107
107
|
isOptional: false;
|
|
108
108
|
};
|
|
109
109
|
supportedLocales: {
|
|
110
|
-
type:
|
|
110
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
111
111
|
isOptional: false;
|
|
112
112
|
isArray: true;
|
|
113
113
|
};
|
|
114
114
|
entries: {
|
|
115
115
|
type: SchemaModel<{
|
|
116
116
|
key: {
|
|
117
|
-
type:
|
|
117
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
118
118
|
isOptional: false;
|
|
119
119
|
};
|
|
120
120
|
locale: {
|
|
121
|
-
type:
|
|
121
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
122
122
|
isOptional: false;
|
|
123
123
|
};
|
|
124
124
|
value: {
|
|
125
|
-
type:
|
|
125
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
126
126
|
isOptional: false;
|
|
127
127
|
};
|
|
128
128
|
context: {
|
|
129
|
-
type:
|
|
129
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
130
130
|
isOptional: true;
|
|
131
131
|
};
|
|
132
132
|
}>;
|
|
@@ -135,39 +135,39 @@ declare const UpdateBlueprintTranslationCatalogCommand: OperationSpec<SchemaMode
|
|
|
135
135
|
};
|
|
136
136
|
}>, SchemaModel<{
|
|
137
137
|
success: {
|
|
138
|
-
type:
|
|
138
|
+
type: _lssm_lib_schema128.FieldType<boolean, boolean>;
|
|
139
139
|
isOptional: false;
|
|
140
140
|
};
|
|
141
141
|
updatedAt: {
|
|
142
|
-
type:
|
|
142
|
+
type: _lssm_lib_schema128.FieldType<Date, string>;
|
|
143
143
|
isOptional: false;
|
|
144
144
|
};
|
|
145
145
|
}>, undefined>;
|
|
146
146
|
declare const UpdateTenantTranslationOverridesCommand: OperationSpec<SchemaModel<{
|
|
147
147
|
tenantId: {
|
|
148
|
-
type:
|
|
148
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
149
149
|
isOptional: false;
|
|
150
150
|
};
|
|
151
151
|
appId: {
|
|
152
|
-
type:
|
|
152
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
153
153
|
isOptional: false;
|
|
154
154
|
};
|
|
155
155
|
entries: {
|
|
156
156
|
type: SchemaModel<{
|
|
157
157
|
key: {
|
|
158
|
-
type:
|
|
158
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
159
159
|
isOptional: false;
|
|
160
160
|
};
|
|
161
161
|
locale: {
|
|
162
|
-
type:
|
|
162
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
163
163
|
isOptional: false;
|
|
164
164
|
};
|
|
165
165
|
value: {
|
|
166
|
-
type:
|
|
166
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
167
167
|
isOptional: false;
|
|
168
168
|
};
|
|
169
169
|
context: {
|
|
170
|
-
type:
|
|
170
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
171
171
|
isOptional: true;
|
|
172
172
|
};
|
|
173
173
|
}>;
|
|
@@ -175,67 +175,67 @@ declare const UpdateTenantTranslationOverridesCommand: OperationSpec<SchemaModel
|
|
|
175
175
|
isArray: true;
|
|
176
176
|
};
|
|
177
177
|
defaultLocale: {
|
|
178
|
-
type:
|
|
178
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
179
179
|
isOptional: true;
|
|
180
180
|
};
|
|
181
181
|
enabledLocales: {
|
|
182
|
-
type:
|
|
182
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
183
183
|
isOptional: true;
|
|
184
184
|
isArray: true;
|
|
185
185
|
};
|
|
186
186
|
}>, SchemaModel<{
|
|
187
187
|
success: {
|
|
188
|
-
type:
|
|
188
|
+
type: _lssm_lib_schema128.FieldType<boolean, boolean>;
|
|
189
189
|
isOptional: false;
|
|
190
190
|
};
|
|
191
191
|
updatedAt: {
|
|
192
|
-
type:
|
|
192
|
+
type: _lssm_lib_schema128.FieldType<Date, string>;
|
|
193
193
|
isOptional: false;
|
|
194
194
|
};
|
|
195
195
|
}>, undefined>;
|
|
196
196
|
declare const GetResolvedBrandingQuery: OperationSpec<SchemaModel<{
|
|
197
197
|
tenantId: {
|
|
198
|
-
type:
|
|
198
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
199
199
|
isOptional: false;
|
|
200
200
|
};
|
|
201
201
|
appId: {
|
|
202
|
-
type:
|
|
202
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
203
203
|
isOptional: false;
|
|
204
204
|
};
|
|
205
205
|
environment: {
|
|
206
|
-
type:
|
|
206
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
207
207
|
isOptional: true;
|
|
208
208
|
};
|
|
209
209
|
}>, SchemaModel<{
|
|
210
210
|
branding: {
|
|
211
|
-
type:
|
|
211
|
+
type: _lssm_lib_schema128.FieldType<Record<string, unknown>, Record<string, unknown>>;
|
|
212
212
|
isOptional: false;
|
|
213
213
|
};
|
|
214
214
|
}>, undefined>;
|
|
215
215
|
declare const ResolveMessageQuery: OperationSpec<SchemaModel<{
|
|
216
216
|
tenantId: {
|
|
217
|
-
type:
|
|
217
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
218
218
|
isOptional: false;
|
|
219
219
|
};
|
|
220
220
|
appId: {
|
|
221
|
-
type:
|
|
221
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
222
222
|
isOptional: false;
|
|
223
223
|
};
|
|
224
224
|
locale: {
|
|
225
|
-
type:
|
|
225
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
226
226
|
isOptional: false;
|
|
227
227
|
};
|
|
228
228
|
key: {
|
|
229
|
-
type:
|
|
229
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
230
230
|
isOptional: false;
|
|
231
231
|
};
|
|
232
232
|
}>, SchemaModel<{
|
|
233
233
|
value: {
|
|
234
|
-
type:
|
|
234
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
235
235
|
isOptional: true;
|
|
236
236
|
};
|
|
237
237
|
source: {
|
|
238
|
-
type:
|
|
238
|
+
type: _lssm_lib_schema128.FieldType<string, string>;
|
|
239
239
|
isOptional: true;
|
|
240
240
|
};
|
|
241
241
|
}>, undefined>;
|
|
@@ -13,7 +13,7 @@ const tech_contracts_app_config_DocBlocks = [{
|
|
|
13
13
|
"contracts",
|
|
14
14
|
"app-config"
|
|
15
15
|
],
|
|
16
|
-
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```\
|
|
16
|
+
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```\nbuncontractspec 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"
|
|
17
17
|
}];
|
|
18
18
|
registerDocBlocks(tech_contracts_app_config_DocBlocks);
|
|
19
19
|
|
|
@@ -1,120 +1,120 @@
|
|
|
1
1
|
import { EventSpec } from "../events.js";
|
|
2
2
|
import "../index.js";
|
|
3
|
-
import * as
|
|
3
|
+
import * as _lssm_lib_schema177 from "@lssm/lib.schema";
|
|
4
4
|
import { SchemaModel } from "@lssm/lib.schema";
|
|
5
5
|
|
|
6
6
|
//#region src/app-config/events.d.ts
|
|
7
7
|
declare const ConfigDraftCreatedEvent: EventSpec<SchemaModel<{
|
|
8
8
|
tenantId: {
|
|
9
|
-
type:
|
|
9
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
10
10
|
isOptional: false;
|
|
11
11
|
};
|
|
12
12
|
appId: {
|
|
13
|
-
type:
|
|
13
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
14
14
|
isOptional: false;
|
|
15
15
|
};
|
|
16
16
|
version: {
|
|
17
|
-
type:
|
|
17
|
+
type: _lssm_lib_schema177.FieldType<number, number>;
|
|
18
18
|
isOptional: false;
|
|
19
19
|
};
|
|
20
20
|
blueprintName: {
|
|
21
|
-
type:
|
|
21
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
22
22
|
isOptional: false;
|
|
23
23
|
};
|
|
24
24
|
blueprintVersion: {
|
|
25
|
-
type:
|
|
25
|
+
type: _lssm_lib_schema177.FieldType<number, number>;
|
|
26
26
|
isOptional: false;
|
|
27
27
|
};
|
|
28
28
|
createdBy: {
|
|
29
|
-
type:
|
|
29
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
30
30
|
isOptional: false;
|
|
31
31
|
};
|
|
32
32
|
clonedFrom: {
|
|
33
|
-
type:
|
|
33
|
+
type: _lssm_lib_schema177.FieldType<number, number>;
|
|
34
34
|
isOptional: true;
|
|
35
35
|
};
|
|
36
36
|
}>>;
|
|
37
37
|
declare const ConfigPromotedToPreviewEvent: EventSpec<SchemaModel<{
|
|
38
38
|
tenantId: {
|
|
39
|
-
type:
|
|
39
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
40
40
|
isOptional: false;
|
|
41
41
|
};
|
|
42
42
|
appId: {
|
|
43
|
-
type:
|
|
43
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
44
44
|
isOptional: false;
|
|
45
45
|
};
|
|
46
46
|
version: {
|
|
47
|
-
type:
|
|
47
|
+
type: _lssm_lib_schema177.FieldType<number, number>;
|
|
48
48
|
isOptional: false;
|
|
49
49
|
};
|
|
50
50
|
promotedBy: {
|
|
51
|
-
type:
|
|
51
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
52
52
|
isOptional: false;
|
|
53
53
|
};
|
|
54
54
|
warnings: {
|
|
55
|
-
type:
|
|
55
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
56
56
|
isOptional: true;
|
|
57
57
|
isArray: true;
|
|
58
58
|
};
|
|
59
59
|
}>>;
|
|
60
60
|
declare const ConfigPublishedEvent: EventSpec<SchemaModel<{
|
|
61
61
|
tenantId: {
|
|
62
|
-
type:
|
|
62
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
63
63
|
isOptional: false;
|
|
64
64
|
};
|
|
65
65
|
appId: {
|
|
66
|
-
type:
|
|
66
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
67
67
|
isOptional: false;
|
|
68
68
|
};
|
|
69
69
|
version: {
|
|
70
|
-
type:
|
|
70
|
+
type: _lssm_lib_schema177.FieldType<number, number>;
|
|
71
71
|
isOptional: false;
|
|
72
72
|
};
|
|
73
73
|
previousVersion: {
|
|
74
|
-
type:
|
|
74
|
+
type: _lssm_lib_schema177.FieldType<number, number>;
|
|
75
75
|
isOptional: true;
|
|
76
76
|
};
|
|
77
77
|
publishedBy: {
|
|
78
|
-
type:
|
|
78
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
79
79
|
isOptional: false;
|
|
80
80
|
};
|
|
81
81
|
changeSummary: {
|
|
82
|
-
type:
|
|
82
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
83
83
|
isOptional: true;
|
|
84
84
|
};
|
|
85
85
|
changedSections: {
|
|
86
|
-
type:
|
|
86
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
87
87
|
isOptional: true;
|
|
88
88
|
isArray: true;
|
|
89
89
|
};
|
|
90
90
|
}>>;
|
|
91
91
|
declare const ConfigRolledBackEvent: EventSpec<SchemaModel<{
|
|
92
92
|
tenantId: {
|
|
93
|
-
type:
|
|
93
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
94
94
|
isOptional: false;
|
|
95
95
|
};
|
|
96
96
|
appId: {
|
|
97
|
-
type:
|
|
97
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
98
98
|
isOptional: false;
|
|
99
99
|
};
|
|
100
100
|
newVersion: {
|
|
101
|
-
type:
|
|
101
|
+
type: _lssm_lib_schema177.FieldType<number, number>;
|
|
102
102
|
isOptional: false;
|
|
103
103
|
};
|
|
104
104
|
rolledBackFrom: {
|
|
105
|
-
type:
|
|
105
|
+
type: _lssm_lib_schema177.FieldType<number, number>;
|
|
106
106
|
isOptional: false;
|
|
107
107
|
};
|
|
108
108
|
rolledBackTo: {
|
|
109
|
-
type:
|
|
109
|
+
type: _lssm_lib_schema177.FieldType<number, number>;
|
|
110
110
|
isOptional: false;
|
|
111
111
|
};
|
|
112
112
|
rolledBackBy: {
|
|
113
|
-
type:
|
|
113
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
114
114
|
isOptional: false;
|
|
115
115
|
};
|
|
116
116
|
reason: {
|
|
117
|
-
type:
|
|
117
|
+
type: _lssm_lib_schema177.FieldType<string, string>;
|
|
118
118
|
isOptional: false;
|
|
119
119
|
};
|
|
120
120
|
}>>;
|