@friggframework/schemas 2.0.0--canary.702.0a3e1ef.0 → 2.0.0--canary.701.00d6b2c.0
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 +0 -26
- package/index.js +2 -14
- package/package.json +2 -3
- package/schemas/app-definition.schema.json +130 -533
- package/app-definition.js +0 -113
package/README.md
CHANGED
|
@@ -41,32 +41,6 @@ if (result.valid) {
|
|
|
41
41
|
}
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
### Integration classes and defaults (ADR-051)
|
|
45
|
-
|
|
46
|
-
Apps list integration classes, which JSON Schema cannot describe.
|
|
47
|
-
`validateAppDefinition` validates a view of the definition in which each
|
|
48
|
-
class in `integrations`, `adminScripts` and `reports` is replaced by
|
|
49
|
-
`{ Definition }`; `frigg validate` checks the classes themselves.
|
|
50
|
-
|
|
51
|
-
```javascript
|
|
52
|
-
const { applyAppDefinitionDefaults } = require('@friggframework/schemas');
|
|
53
|
-
// or, without loading Ajv:
|
|
54
|
-
// require('@friggframework/schemas/app-definition').applyAppDefinitionDefaults
|
|
55
|
-
|
|
56
|
-
const definition = applyAppDefinitionDefaults(require('./index').Definition);
|
|
57
|
-
definition.user.individualUserRequired; // true (schema default)
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
`applyAppDefinitionDefaults` returns a copy with every `default` declared in
|
|
61
|
-
the app-definition schema applied (only inside blocks the app sets, plus
|
|
62
|
-
blocks that have a default themselves, such as `user`). core's
|
|
63
|
-
`loadAppDefinition` and devtools' `createFriggInfrastructure` call it, so a
|
|
64
|
-
schema default is the runtime default. A schema default must equal what the
|
|
65
|
-
code does when the key is absent; the contract test in
|
|
66
|
-
`packages/devtools/infrastructure/app-definition-schema-contract.test.js`
|
|
67
|
-
checks this for the infrastructure builders. Keys nothing reads are marked
|
|
68
|
-
`"deprecated": true`.
|
|
69
|
-
|
|
70
44
|
### Advanced Validation
|
|
71
45
|
|
|
72
46
|
```javascript
|
package/index.js
CHANGED
|
@@ -12,10 +12,6 @@ const path = require('path');
|
|
|
12
12
|
|
|
13
13
|
// Import middleware
|
|
14
14
|
const schemaValidationMiddleware = require('./middleware/schema-validation');
|
|
15
|
-
const {
|
|
16
|
-
applyAppDefinitionDefaults,
|
|
17
|
-
toAppDefinitionSchemaView,
|
|
18
|
-
} = require('./app-definition');
|
|
19
15
|
const {
|
|
20
16
|
toApiModuleDefinitionSchemaView,
|
|
21
17
|
} = require('./api-module-definition');
|
|
@@ -83,13 +79,7 @@ function validate(schemaName, data) {
|
|
|
83
79
|
* @returns {object} - Validation result
|
|
84
80
|
*/
|
|
85
81
|
function validateAppDefinition(appDefinition) {
|
|
86
|
-
|
|
87
|
-
// validate the serialisable view and return the original definition.
|
|
88
|
-
const result = validate(
|
|
89
|
-
'app-definition',
|
|
90
|
-
toAppDefinitionSchemaView(appDefinition)
|
|
91
|
-
);
|
|
92
|
-
return { ...result, data: appDefinition };
|
|
82
|
+
return validate('app-definition', appDefinition);
|
|
93
83
|
}
|
|
94
84
|
|
|
95
85
|
/**
|
|
@@ -104,7 +94,7 @@ function validateIntegrationDefinition(integrationDefinition) {
|
|
|
104
94
|
/**
|
|
105
95
|
* Validate API Module Definition.
|
|
106
96
|
* Real Definitions carry classes and functions; validate the serialisable
|
|
107
|
-
* view and return the original definition
|
|
97
|
+
* view and return the original definition.
|
|
108
98
|
* @param {object} apiModuleDefinition - API module definition object to validate
|
|
109
99
|
* @returns {object} - Validation result
|
|
110
100
|
*/
|
|
@@ -376,8 +366,6 @@ module.exports = {
|
|
|
376
366
|
// Validation functions
|
|
377
367
|
validate,
|
|
378
368
|
validateAppDefinition,
|
|
379
|
-
applyAppDefinitionDefaults,
|
|
380
|
-
toAppDefinitionSchemaView,
|
|
381
369
|
toApiModuleDefinitionSchemaView,
|
|
382
370
|
validateIntegrationDefinition,
|
|
383
371
|
validateApiModuleDefinition,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/schemas",
|
|
3
|
-
"version": "2.0.0--canary.
|
|
3
|
+
"version": "2.0.0--canary.701.00d6b2c.0",
|
|
4
4
|
"description": "Canonical JSON Schema definitions for Frigg Framework",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "",
|
|
@@ -39,9 +39,8 @@
|
|
|
39
39
|
"validators/",
|
|
40
40
|
"mocks/",
|
|
41
41
|
"middleware/",
|
|
42
|
-
"app-definition.js",
|
|
43
42
|
"api-module-definition.js",
|
|
44
43
|
"index.js"
|
|
45
44
|
],
|
|
46
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "00d6b2c41f32118d4dbde57f8dfe3c6416840992"
|
|
47
46
|
}
|
|
@@ -22,35 +22,22 @@
|
|
|
22
22
|
},
|
|
23
23
|
"label": {
|
|
24
24
|
"type": "string",
|
|
25
|
-
"description": "Human-readable display name for the application
|
|
25
|
+
"description": "Human-readable display name for the application",
|
|
26
26
|
"minLength": 1,
|
|
27
27
|
"maxLength": 200,
|
|
28
|
-
"examples": ["My Frigg Application", "Customer Portal Integrations"]
|
|
29
|
-
"deprecated": true
|
|
30
|
-
},
|
|
31
|
-
"region": {
|
|
32
|
-
"type": "string",
|
|
33
|
-
"description": "AWS region. The deploy region comes from AWS_REGION (default us-east-1), not from this key. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
34
|
-
"deprecated": true
|
|
35
|
-
},
|
|
36
|
-
"stage": {
|
|
37
|
-
"type": "string",
|
|
38
|
-
"description": "Stage name used only to infer the KMS key alias. The deployed stage comes from `--stage`."
|
|
28
|
+
"examples": ["My Frigg Application", "Customer Portal Integrations"]
|
|
39
29
|
},
|
|
40
30
|
"managementMode": {
|
|
41
31
|
"type": "string",
|
|
42
|
-
"description": "Infrastructure management mode
|
|
43
|
-
"enum": ["managed", "discover", "
|
|
32
|
+
"description": "Infrastructure management mode: 'managed' lets Frigg manage resources, 'discover' uses existing resources, 'custom' for manual configuration",
|
|
33
|
+
"enum": ["managed", "discover", "custom"],
|
|
34
|
+
"default": "managed"
|
|
44
35
|
},
|
|
45
36
|
"vpcIsolation": {
|
|
46
37
|
"type": "string",
|
|
47
|
-
"description": "
|
|
48
|
-
"enum": ["isolated", "shared"]
|
|
49
|
-
|
|
50
|
-
"usePrismaLambdaLayer": {
|
|
51
|
-
"type": "boolean",
|
|
52
|
-
"description": "Ship Prisma in a shared Lambda layer. false bundles Prisma into each function instead.",
|
|
53
|
-
"default": true
|
|
38
|
+
"description": "VPC isolation strategy: 'isolated' creates separate VPC per stage, 'shared' reuses VPC across stages",
|
|
39
|
+
"enum": ["isolated", "shared"],
|
|
40
|
+
"default": "isolated"
|
|
54
41
|
},
|
|
55
42
|
"environment": {
|
|
56
43
|
"type": "object",
|
|
@@ -81,17 +68,10 @@
|
|
|
81
68
|
},
|
|
82
69
|
"integrations": {
|
|
83
70
|
"type": "array",
|
|
84
|
-
"description": "
|
|
71
|
+
"description": "Array of integration classes to enable in the application",
|
|
85
72
|
"items": {
|
|
86
73
|
"type": "object",
|
|
87
|
-
"description": "
|
|
88
|
-
"required": ["Definition"],
|
|
89
|
-
"properties": {
|
|
90
|
-
"Definition": {
|
|
91
|
-
"type": "object",
|
|
92
|
-
"description": "The integration's static Definition (see integration-definition.schema.json)"
|
|
93
|
-
}
|
|
94
|
-
}
|
|
74
|
+
"description": "Integration class or configuration object"
|
|
95
75
|
},
|
|
96
76
|
"default": []
|
|
97
77
|
},
|
|
@@ -130,56 +110,51 @@
|
|
|
130
110
|
},
|
|
131
111
|
"user": {
|
|
132
112
|
"type": "object",
|
|
133
|
-
"description": "User management and authentication
|
|
113
|
+
"description": "User management and authentication configuration",
|
|
134
114
|
"properties": {
|
|
135
115
|
"usePassword": {
|
|
136
116
|
"type": "boolean",
|
|
137
|
-
"description": "
|
|
138
|
-
"default":
|
|
117
|
+
"description": "Enable password-based authentication for user login",
|
|
118
|
+
"default": true
|
|
139
119
|
},
|
|
140
120
|
"password": {
|
|
141
121
|
"type": "boolean",
|
|
142
|
-
"description": "DEPRECATED
|
|
143
|
-
"
|
|
122
|
+
"description": "DEPRECATED: Use 'usePassword' instead. Enable password-based authentication",
|
|
123
|
+
"default": true
|
|
144
124
|
},
|
|
145
125
|
"primary": {
|
|
146
126
|
"type": "string",
|
|
147
|
-
"description": "Primary user type
|
|
127
|
+
"description": "Primary user type for authentication",
|
|
148
128
|
"enum": ["individual", "organization"],
|
|
149
129
|
"default": "individual"
|
|
150
130
|
},
|
|
151
131
|
"individualUserRequired": {
|
|
152
132
|
"type": "boolean",
|
|
153
|
-
"description": "Require
|
|
133
|
+
"description": "Require individual user for authentication",
|
|
154
134
|
"default": true
|
|
155
135
|
},
|
|
156
136
|
"organizationUserRequired": {
|
|
157
137
|
"type": "boolean",
|
|
158
|
-
"description": "Require
|
|
159
|
-
"default": false
|
|
160
|
-
},
|
|
161
|
-
"strictUserValidation": {
|
|
162
|
-
"type": "boolean",
|
|
163
|
-
"description": "With x-frigg headers, reject a user id that does not exist instead of creating and linking it.",
|
|
138
|
+
"description": "Require organization user for authentication",
|
|
164
139
|
"default": false
|
|
165
140
|
},
|
|
166
141
|
"authModes": {
|
|
167
142
|
"type": "object",
|
|
168
|
-
"description": "Authentication
|
|
143
|
+
"description": "Authentication mode configuration - enables multiple authentication strategies. x-frigg-appUserId and x-frigg-appOrgId headers are automatically supported for user identification with any auth mode.",
|
|
169
144
|
"properties": {
|
|
170
145
|
"friggToken": {
|
|
171
146
|
"type": "boolean",
|
|
172
|
-
"description": "
|
|
147
|
+
"description": "Enable Frigg native bearer token authentication (from /user/login)",
|
|
173
148
|
"default": true
|
|
174
149
|
},
|
|
175
150
|
"sharedSecret": {
|
|
176
151
|
"type": "boolean",
|
|
177
|
-
"description": "
|
|
178
|
-
"default":
|
|
152
|
+
"description": "Enable shared secret authentication for backend-to-backend communication (requires FRIGG_API_KEY env var and x-frigg-api-key header)",
|
|
153
|
+
"default": false
|
|
179
154
|
},
|
|
180
155
|
"adopterJwt": {
|
|
181
156
|
"type": "boolean",
|
|
182
|
-
"description": "
|
|
157
|
+
"description": "Enable custom JWT authentication from adopter's auth system (requires jwtConfig)",
|
|
183
158
|
"default": false
|
|
184
159
|
}
|
|
185
160
|
},
|
|
@@ -215,25 +190,22 @@
|
|
|
215
190
|
},
|
|
216
191
|
"fields": {
|
|
217
192
|
"type": "array",
|
|
218
|
-
"description": "Additional user fields
|
|
219
|
-
"items": {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
]
|
|
223
|
-
"deprecated": true
|
|
193
|
+
"description": "Additional user fields",
|
|
194
|
+
"items": {
|
|
195
|
+
"type": "string"
|
|
196
|
+
},
|
|
197
|
+
"examples": [["email", "firstName", "lastName"]]
|
|
224
198
|
},
|
|
225
199
|
"model": {
|
|
226
200
|
"type": "object",
|
|
227
|
-
"description": "Custom user model class
|
|
228
|
-
"deprecated": true
|
|
201
|
+
"description": "Custom user model class"
|
|
229
202
|
}
|
|
230
203
|
},
|
|
231
|
-
"additionalProperties": false
|
|
232
|
-
"default": {}
|
|
204
|
+
"additionalProperties": false
|
|
233
205
|
},
|
|
234
206
|
"auth": {
|
|
235
207
|
"type": "object",
|
|
236
|
-
"description": "Authentication configuration
|
|
208
|
+
"description": "Authentication configuration for integrations",
|
|
237
209
|
"properties": {
|
|
238
210
|
"jwtSecret": {
|
|
239
211
|
"type": "string",
|
|
@@ -242,16 +214,17 @@
|
|
|
242
214
|
"tokenExpiry": {
|
|
243
215
|
"type": "string",
|
|
244
216
|
"description": "Token expiration time",
|
|
245
|
-
"pattern": "^\\d+[smhd]$"
|
|
217
|
+
"pattern": "^\\d+[smhd]$",
|
|
218
|
+
"default": "24h"
|
|
246
219
|
},
|
|
247
220
|
"refreshTokenExpiry": {
|
|
248
221
|
"type": "string",
|
|
249
|
-
"description": "Refresh token expiration time",
|
|
250
|
-
"pattern": "^\\d+[smhd]$"
|
|
222
|
+
"description": "Refresh token expiration time",
|
|
223
|
+
"pattern": "^\\d+[smhd]$",
|
|
224
|
+
"default": "7d"
|
|
251
225
|
}
|
|
252
226
|
},
|
|
253
|
-
"additionalProperties": false
|
|
254
|
-
"deprecated": true
|
|
227
|
+
"additionalProperties": false
|
|
255
228
|
},
|
|
256
229
|
"database": {
|
|
257
230
|
"type": "object",
|
|
@@ -259,8 +232,8 @@
|
|
|
259
232
|
"properties": {
|
|
260
233
|
"uri": {
|
|
261
234
|
"type": "string",
|
|
262
|
-
"description": "Database connection URI (should be set via environment variable)
|
|
263
|
-
"
|
|
235
|
+
"description": "Database connection URI (should be set via environment variable)",
|
|
236
|
+
"format": "uri"
|
|
264
237
|
},
|
|
265
238
|
"mongoDB": {
|
|
266
239
|
"type": "object",
|
|
@@ -273,8 +246,7 @@
|
|
|
273
246
|
},
|
|
274
247
|
"uri": {
|
|
275
248
|
"type": "string",
|
|
276
|
-
"description": "MongoDB connection URI
|
|
277
|
-
"deprecated": true
|
|
249
|
+
"description": "MongoDB connection URI"
|
|
278
250
|
}
|
|
279
251
|
},
|
|
280
252
|
"additionalProperties": true
|
|
@@ -302,16 +274,18 @@
|
|
|
302
274
|
"properties": {
|
|
303
275
|
"enable": {
|
|
304
276
|
"type": "boolean",
|
|
305
|
-
"description": "
|
|
277
|
+
"description": "Enable PostgreSQL database",
|
|
278
|
+
"default": false
|
|
306
279
|
},
|
|
307
280
|
"management": {
|
|
308
281
|
"type": "string",
|
|
309
|
-
"description": "How
|
|
310
|
-
"enum": ["discover", "
|
|
282
|
+
"description": "How to manage the PostgreSQL database",
|
|
283
|
+
"enum": ["discover", "create-new", "existing"],
|
|
284
|
+
"default": "discover"
|
|
311
285
|
},
|
|
312
286
|
"endpoint": {
|
|
313
287
|
"type": "string",
|
|
314
|
-
"description": "Existing database endpoint (
|
|
288
|
+
"description": "Existing database endpoint (when management='existing')",
|
|
315
289
|
"examples": ["mydb.cluster-abc123.us-east-1.rds.amazonaws.com"]
|
|
316
290
|
},
|
|
317
291
|
"port": {
|
|
@@ -329,15 +303,10 @@
|
|
|
329
303
|
"description": "Database username",
|
|
330
304
|
"default": "postgres"
|
|
331
305
|
},
|
|
332
|
-
"engineVersion": {
|
|
333
|
-
"type": "string",
|
|
334
|
-
"description": "Aurora PostgreSQL engine version for a cluster Frigg creates",
|
|
335
|
-
"default": "15.13"
|
|
336
|
-
},
|
|
337
306
|
"selfHeal": {
|
|
338
307
|
"type": "boolean",
|
|
339
|
-
"description": "Automatically fix database configuration issues
|
|
340
|
-
"
|
|
308
|
+
"description": "Automatically fix database configuration issues",
|
|
309
|
+
"default": true
|
|
341
310
|
},
|
|
342
311
|
"publiclyAccessible": {
|
|
343
312
|
"type": "boolean",
|
|
@@ -346,7 +315,7 @@
|
|
|
346
315
|
},
|
|
347
316
|
"autoCreateCredentials": {
|
|
348
317
|
"type": "boolean",
|
|
349
|
-
"description": "
|
|
318
|
+
"description": "Automatically create Secrets Manager secret and rotate Aurora password when discovering existing cluster (only applies when management='discover')",
|
|
350
319
|
"default": false
|
|
351
320
|
},
|
|
352
321
|
"minCapacity": {
|
|
@@ -361,65 +330,7 @@
|
|
|
361
330
|
"description": "Maximum Aurora Serverless capacity units (0.5-128)",
|
|
362
331
|
"minimum": 0.5,
|
|
363
332
|
"maximum": 128,
|
|
364
|
-
"default":
|
|
365
|
-
},
|
|
366
|
-
"clusterId": {
|
|
367
|
-
"type": "string",
|
|
368
|
-
"description": "Only discover the Aurora cluster with this identifier"
|
|
369
|
-
},
|
|
370
|
-
"instanceId": {
|
|
371
|
-
"type": "string",
|
|
372
|
-
"description": "Only discover the Aurora instance with this identifier"
|
|
373
|
-
},
|
|
374
|
-
"ownership": {
|
|
375
|
-
"type": "object",
|
|
376
|
-
"description": "Per-resource ownership. When set, `management` is not translated.",
|
|
377
|
-
"properties": {
|
|
378
|
-
"cluster": {
|
|
379
|
-
"type": "string",
|
|
380
|
-
"enum": ["stack", "external", "auto"],
|
|
381
|
-
"description": "Aurora cluster. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
382
|
-
},
|
|
383
|
-
"instance": {
|
|
384
|
-
"type": "string",
|
|
385
|
-
"enum": ["stack", "external", "auto"],
|
|
386
|
-
"description": "Aurora instance. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
387
|
-
},
|
|
388
|
-
"subnetGroup": {
|
|
389
|
-
"type": "string",
|
|
390
|
-
"enum": ["stack", "external", "auto"],
|
|
391
|
-
"description": "DB subnet group. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
392
|
-
},
|
|
393
|
-
"secret": {
|
|
394
|
-
"type": "string",
|
|
395
|
-
"enum": ["stack", "external", "auto"],
|
|
396
|
-
"description": "Secrets Manager credentials secret. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
397
|
-
}
|
|
398
|
-
},
|
|
399
|
-
"additionalProperties": false
|
|
400
|
-
},
|
|
401
|
-
"external": {
|
|
402
|
-
"type": "object",
|
|
403
|
-
"description": "Ids of externally owned resources (ownership 'external')",
|
|
404
|
-
"properties": {
|
|
405
|
-
"clusterIdentifier": {"type": "string"},
|
|
406
|
-
"instanceIdentifier": {"type": "string"},
|
|
407
|
-
"subnetGroupName": {"type": "string"},
|
|
408
|
-
"secretArn": {"type": "string"}
|
|
409
|
-
},
|
|
410
|
-
"additionalProperties": false
|
|
411
|
-
}
|
|
412
|
-
},
|
|
413
|
-
"additionalProperties": false
|
|
414
|
-
},
|
|
415
|
-
"dynamodb": {
|
|
416
|
-
"type": "object",
|
|
417
|
-
"description": "DynamoDB access from inside the VPC",
|
|
418
|
-
"properties": {
|
|
419
|
-
"enable": {
|
|
420
|
-
"type": "boolean",
|
|
421
|
-
"description": "Add a DynamoDB VPC endpoint",
|
|
422
|
-
"default": false
|
|
333
|
+
"default": 1
|
|
423
334
|
}
|
|
424
335
|
},
|
|
425
336
|
"additionalProperties": false
|
|
@@ -433,12 +344,14 @@
|
|
|
433
344
|
"properties": {
|
|
434
345
|
"fieldLevelEncryptionMethod": {
|
|
435
346
|
"type": "string",
|
|
436
|
-
"description": "
|
|
437
|
-
"enum": ["kms", "aes"]
|
|
347
|
+
"description": "Method for field-level encryption",
|
|
348
|
+
"enum": ["kms", "aes"],
|
|
349
|
+
"default": "aes"
|
|
438
350
|
},
|
|
439
351
|
"createResourceIfNoneFound": {
|
|
440
352
|
"type": "boolean",
|
|
441
|
-
"description": "
|
|
353
|
+
"description": "Create KMS key if none found during discovery",
|
|
354
|
+
"default": false
|
|
442
355
|
},
|
|
443
356
|
"schema": {
|
|
444
357
|
"type": "object",
|
|
@@ -475,48 +388,6 @@
|
|
|
475
388
|
}
|
|
476
389
|
}
|
|
477
390
|
]
|
|
478
|
-
},
|
|
479
|
-
"ownership": {
|
|
480
|
-
"type": "object",
|
|
481
|
-
"description": "Per-resource ownership. When set, createResourceIfNoneFound is not translated.",
|
|
482
|
-
"properties": {
|
|
483
|
-
"key": {
|
|
484
|
-
"type": "string",
|
|
485
|
-
"enum": ["stack", "external", "auto"],
|
|
486
|
-
"description": "KMS key. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
487
|
-
}
|
|
488
|
-
},
|
|
489
|
-
"additionalProperties": false
|
|
490
|
-
},
|
|
491
|
-
"kmsKeyAlias": {
|
|
492
|
-
"type": "boolean",
|
|
493
|
-
"description": "Create an alias for a KMS key Frigg creates",
|
|
494
|
-
"default": false
|
|
495
|
-
},
|
|
496
|
-
"keyAlias": {
|
|
497
|
-
"type": "string",
|
|
498
|
-
"description": "Only discover the KMS key with this alias",
|
|
499
|
-
"pattern": "^alias/",
|
|
500
|
-
"examples": ["alias/my-app-key"]
|
|
501
|
-
},
|
|
502
|
-
"disable": {
|
|
503
|
-
"type": "object",
|
|
504
|
-
"description": "Opt specific core-encrypted fields out of encryption: { Model: ['field.path'] }. Existing encrypted values still decrypt.",
|
|
505
|
-
"patternProperties": {
|
|
506
|
-
"^[A-Z][a-zA-Z0-9]*$": {
|
|
507
|
-
"type": "array",
|
|
508
|
-
"items": {
|
|
509
|
-
"type": "string",
|
|
510
|
-
"minLength": 1
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
},
|
|
514
|
-
"additionalProperties": false
|
|
515
|
-
},
|
|
516
|
-
"enable": {
|
|
517
|
-
"type": "boolean",
|
|
518
|
-
"description": "Encryption is controlled by fieldLevelEncryptionMethod. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
519
|
-
"deprecated": true
|
|
520
391
|
}
|
|
521
392
|
},
|
|
522
393
|
"additionalProperties": false
|
|
@@ -527,23 +398,24 @@
|
|
|
527
398
|
"properties": {
|
|
528
399
|
"enable": {
|
|
529
400
|
"type": "boolean",
|
|
530
|
-
"description": "
|
|
401
|
+
"description": "Enable VPC for Lambda functions",
|
|
531
402
|
"default": false
|
|
532
403
|
},
|
|
533
404
|
"management": {
|
|
534
405
|
"type": "string",
|
|
535
|
-
"description": "How
|
|
536
|
-
"enum": ["discover", "create-new", "
|
|
406
|
+
"description": "How to manage VPC infrastructure",
|
|
407
|
+
"enum": ["discover", "create-new", "existing"],
|
|
408
|
+
"default": "discover"
|
|
537
409
|
},
|
|
538
410
|
"vpcId": {
|
|
539
411
|
"type": "string",
|
|
540
|
-
"description": "Existing VPC ID (
|
|
412
|
+
"description": "Existing VPC ID (when management='existing')",
|
|
541
413
|
"pattern": "^vpc-[a-z0-9]+$",
|
|
542
414
|
"examples": ["vpc-abc123"]
|
|
543
415
|
},
|
|
544
416
|
"cidrBlock": {
|
|
545
417
|
"type": "string",
|
|
546
|
-
"description": "CIDR block for
|
|
418
|
+
"description": "CIDR block for VPC (when management='create-new')",
|
|
547
419
|
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",
|
|
548
420
|
"default": "10.0.0.0/16"
|
|
549
421
|
},
|
|
@@ -554,9 +426,7 @@
|
|
|
554
426
|
"type": "string",
|
|
555
427
|
"pattern": "^sg-[a-z0-9]+$"
|
|
556
428
|
},
|
|
557
|
-
"examples": [
|
|
558
|
-
["sg-abc123", "sg-def456"]
|
|
559
|
-
]
|
|
429
|
+
"examples": [["sg-abc123", "sg-def456"]]
|
|
560
430
|
},
|
|
561
431
|
"subnets": {
|
|
562
432
|
"type": "object",
|
|
@@ -564,20 +434,19 @@
|
|
|
564
434
|
"properties": {
|
|
565
435
|
"management": {
|
|
566
436
|
"type": "string",
|
|
567
|
-
"description": "
|
|
568
|
-
"enum": ["
|
|
437
|
+
"description": "How to manage subnets",
|
|
438
|
+
"enum": ["discover", "create-new", "existing"],
|
|
439
|
+
"default": "discover"
|
|
569
440
|
},
|
|
570
441
|
"ids": {
|
|
571
442
|
"type": "array",
|
|
572
|
-
"description": "Existing subnet IDs
|
|
443
|
+
"description": "Existing subnet IDs",
|
|
573
444
|
"items": {
|
|
574
445
|
"type": "string",
|
|
575
446
|
"pattern": "^subnet-[a-z0-9]+$"
|
|
576
447
|
},
|
|
577
448
|
"minItems": 2,
|
|
578
|
-
"examples": [
|
|
579
|
-
["subnet-abc123", "subnet-def456"]
|
|
580
|
-
]
|
|
449
|
+
"examples": [["subnet-abc123", "subnet-def456"]]
|
|
581
450
|
}
|
|
582
451
|
},
|
|
583
452
|
"additionalProperties": false
|
|
@@ -588,12 +457,13 @@
|
|
|
588
457
|
"properties": {
|
|
589
458
|
"management": {
|
|
590
459
|
"type": "string",
|
|
591
|
-
"description": "
|
|
592
|
-
"enum": ["
|
|
460
|
+
"description": "How to manage NAT Gateway",
|
|
461
|
+
"enum": ["discover", "create-new", "existing"],
|
|
462
|
+
"default": "discover"
|
|
593
463
|
},
|
|
594
464
|
"id": {
|
|
595
465
|
"type": "string",
|
|
596
|
-
"description": "Existing NAT Gateway ID
|
|
466
|
+
"description": "Existing NAT Gateway ID",
|
|
597
467
|
"pattern": "^nat-[a-z0-9]+$",
|
|
598
468
|
"examples": ["nat-abc123"]
|
|
599
469
|
}
|
|
@@ -602,112 +472,13 @@
|
|
|
602
472
|
},
|
|
603
473
|
"enableVPCEndpoints": {
|
|
604
474
|
"type": "boolean",
|
|
605
|
-
"description": "Create VPC endpoints for AWS services (S3, DynamoDB, KMS, Secrets Manager)
|
|
475
|
+
"description": "Create VPC endpoints for AWS services (S3, DynamoDB, KMS, Secrets Manager)",
|
|
606
476
|
"default": true
|
|
607
477
|
},
|
|
608
478
|
"selfHeal": {
|
|
609
479
|
"type": "boolean",
|
|
610
|
-
"description": "
|
|
611
|
-
|
|
612
|
-
"shareAcrossStages": {
|
|
613
|
-
"type": "boolean",
|
|
614
|
-
"description": "Legacy: true reuses (auto) the VPC and subnets across stages; false creates a VPC, subnets and NAT gateway per stage. Ignored when `ownership` is set."
|
|
615
|
-
},
|
|
616
|
-
"ownership": {
|
|
617
|
-
"type": "object",
|
|
618
|
-
"description": "Per-resource ownership. When set, management, subnets, natGateway, shareAcrossStages, enableVPCEndpoints and selfHeal are not translated; use `config` instead.",
|
|
619
|
-
"properties": {
|
|
620
|
-
"vpc": {
|
|
621
|
-
"type": "string",
|
|
622
|
-
"enum": ["stack", "external", "auto"],
|
|
623
|
-
"description": "VPC. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
624
|
-
},
|
|
625
|
-
"securityGroup": {
|
|
626
|
-
"type": "string",
|
|
627
|
-
"enum": ["stack", "external", "auto"],
|
|
628
|
-
"description": "Lambda security group. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
629
|
-
},
|
|
630
|
-
"subnets": {
|
|
631
|
-
"type": "string",
|
|
632
|
-
"enum": ["stack", "external", "auto"],
|
|
633
|
-
"description": "Private subnets. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
634
|
-
},
|
|
635
|
-
"natGateway": {
|
|
636
|
-
"type": "string",
|
|
637
|
-
"enum": ["stack", "external", "auto"],
|
|
638
|
-
"description": "NAT gateway. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
639
|
-
},
|
|
640
|
-
"vpcEndpoints": {
|
|
641
|
-
"type": "string",
|
|
642
|
-
"enum": ["stack", "external", "auto"],
|
|
643
|
-
"description": "VPC endpoints. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
644
|
-
}
|
|
645
|
-
},
|
|
646
|
-
"additionalProperties": false
|
|
647
|
-
},
|
|
648
|
-
"external": {
|
|
649
|
-
"type": "object",
|
|
650
|
-
"description": "Ids of externally owned resources (ownership 'external'); discovered ids are used when omitted",
|
|
651
|
-
"properties": {
|
|
652
|
-
"vpcId": {
|
|
653
|
-
"type": "string",
|
|
654
|
-
"pattern": "^vpc-[a-z0-9]+$"
|
|
655
|
-
},
|
|
656
|
-
"securityGroupIds": {
|
|
657
|
-
"type": "array",
|
|
658
|
-
"items": {
|
|
659
|
-
"type": "string",
|
|
660
|
-
"pattern": "^sg-[a-z0-9]+$"
|
|
661
|
-
}
|
|
662
|
-
},
|
|
663
|
-
"subnetIds": {
|
|
664
|
-
"type": "array",
|
|
665
|
-
"items": {
|
|
666
|
-
"type": "string",
|
|
667
|
-
"pattern": "^subnet-[a-z0-9]+$"
|
|
668
|
-
}
|
|
669
|
-
},
|
|
670
|
-
"natGatewayId": {
|
|
671
|
-
"type": "string",
|
|
672
|
-
"pattern": "^nat-[a-z0-9]+$"
|
|
673
|
-
},
|
|
674
|
-
"vpcEndpointIds": {
|
|
675
|
-
"type": "object",
|
|
676
|
-
"description": "Endpoint ids by type (s3, dynamodb, kms, secretsManager, sqs)",
|
|
677
|
-
"additionalProperties": {"type": "string"}
|
|
678
|
-
}
|
|
679
|
-
},
|
|
680
|
-
"additionalProperties": false
|
|
681
|
-
},
|
|
682
|
-
"config": {
|
|
683
|
-
"type": "object",
|
|
684
|
-
"description": "Settings for the ownership-based VPC configuration",
|
|
685
|
-
"properties": {
|
|
686
|
-
"cidrBlock": {
|
|
687
|
-
"type": "string",
|
|
688
|
-
"description": "CIDR block for a VPC Frigg creates (wins over vpc.cidrBlock)",
|
|
689
|
-
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$"
|
|
690
|
-
},
|
|
691
|
-
"selfHeal": {
|
|
692
|
-
"type": "boolean",
|
|
693
|
-
"description": "Recreate missing stack-owned subnets. Enabled unless false."
|
|
694
|
-
},
|
|
695
|
-
"natGateway": {
|
|
696
|
-
"type": "object",
|
|
697
|
-
"properties": {
|
|
698
|
-
"enable": {
|
|
699
|
-
"type": "boolean",
|
|
700
|
-
"description": "Resolve a NAT gateway. Enabled unless false."
|
|
701
|
-
}
|
|
702
|
-
},
|
|
703
|
-
"additionalProperties": false
|
|
704
|
-
},
|
|
705
|
-
"enableVpcEndpoints": {
|
|
706
|
-
"type": "boolean",
|
|
707
|
-
"description": "Create VPC endpoints. Enabled unless false."
|
|
708
|
-
}
|
|
709
|
-
},
|
|
710
|
-
"additionalProperties": false
|
|
480
|
+
"description": "Automatically fix VPC configuration issues",
|
|
481
|
+
"default": false
|
|
711
482
|
}
|
|
712
483
|
},
|
|
713
484
|
"additionalProperties": false
|
|
@@ -752,7 +523,9 @@
|
|
|
752
523
|
"enum": ["standard", "advanced"],
|
|
753
524
|
"default": "standard"
|
|
754
525
|
},
|
|
755
|
-
"description": {
|
|
526
|
+
"description": {
|
|
527
|
+
"type": "string"
|
|
528
|
+
}
|
|
756
529
|
}
|
|
757
530
|
}
|
|
758
531
|
},
|
|
@@ -763,15 +536,15 @@
|
|
|
763
536
|
},
|
|
764
537
|
"secretsManager": {
|
|
765
538
|
"type": "object",
|
|
766
|
-
"description": "AWS Secrets Manager configuration
|
|
539
|
+
"description": "AWS Secrets Manager configuration",
|
|
767
540
|
"properties": {
|
|
768
541
|
"enable": {
|
|
769
542
|
"type": "boolean",
|
|
770
|
-
"description": "Enable AWS Secrets Manager for secure credential storage"
|
|
543
|
+
"description": "Enable AWS Secrets Manager for secure credential storage",
|
|
544
|
+
"default": false
|
|
771
545
|
}
|
|
772
546
|
},
|
|
773
|
-
"additionalProperties": false
|
|
774
|
-
"deprecated": true
|
|
547
|
+
"additionalProperties": false
|
|
775
548
|
},
|
|
776
549
|
"lambda": {
|
|
777
550
|
"type": "object",
|
|
@@ -781,11 +554,6 @@
|
|
|
781
554
|
"type": "boolean",
|
|
782
555
|
"description": "Scope framework-generated environment variables (queue URLs, migration/scheduler vars) to the functions that consume them instead of broadcasting to every function. Reduces per-function env size against the Lambda 4KB limit",
|
|
783
556
|
"default": false
|
|
784
|
-
},
|
|
785
|
-
"keepNestedNodeModules": {
|
|
786
|
-
"type": "boolean",
|
|
787
|
-
"description": "Keep nested node_modules in function packages (nested Frigg, AWS SDK and Prisma packages are still excluded)",
|
|
788
|
-
"default": false
|
|
789
557
|
}
|
|
790
558
|
},
|
|
791
559
|
"additionalProperties": false
|
|
@@ -801,15 +569,15 @@
|
|
|
801
569
|
},
|
|
802
570
|
"routeSelectionExpression": {
|
|
803
571
|
"type": "string",
|
|
804
|
-
"description": "Route selection expression for WebSocket
|
|
805
|
-
"
|
|
572
|
+
"description": "Route selection expression for WebSocket",
|
|
573
|
+
"default": "$request.body.action"
|
|
806
574
|
}
|
|
807
575
|
},
|
|
808
576
|
"additionalProperties": false
|
|
809
577
|
},
|
|
810
578
|
"security": {
|
|
811
579
|
"type": "object",
|
|
812
|
-
"description": "Security settings for the application
|
|
580
|
+
"description": "Security settings for the application",
|
|
813
581
|
"properties": {
|
|
814
582
|
"cors": {
|
|
815
583
|
"type": "object",
|
|
@@ -818,17 +586,16 @@
|
|
|
818
586
|
"origin": {
|
|
819
587
|
"oneOf": [
|
|
820
588
|
{"type": "string"},
|
|
821
|
-
{
|
|
822
|
-
"type": "array",
|
|
823
|
-
"items": {"type": "string"}
|
|
824
|
-
},
|
|
589
|
+
{"type": "array", "items": {"type": "string"}},
|
|
825
590
|
{"type": "boolean"}
|
|
826
591
|
],
|
|
827
|
-
"description": "Allowed origins for CORS requests"
|
|
592
|
+
"description": "Allowed origins for CORS requests",
|
|
593
|
+
"default": "http://localhost:3000"
|
|
828
594
|
},
|
|
829
595
|
"credentials": {
|
|
830
596
|
"type": "boolean",
|
|
831
|
-
"description": "Allow credentials in CORS requests"
|
|
597
|
+
"description": "Allow credentials in CORS requests",
|
|
598
|
+
"default": true
|
|
832
599
|
},
|
|
833
600
|
"methods": {
|
|
834
601
|
"type": "array",
|
|
@@ -853,23 +620,24 @@
|
|
|
853
620
|
"windowMs": {
|
|
854
621
|
"type": "integer",
|
|
855
622
|
"description": "Time window in milliseconds",
|
|
856
|
-
"minimum": 1000
|
|
623
|
+
"minimum": 1000,
|
|
624
|
+
"default": 900000
|
|
857
625
|
},
|
|
858
626
|
"max": {
|
|
859
|
-
"type": "integer",
|
|
627
|
+
"type": "integer",
|
|
860
628
|
"description": "Maximum requests per window",
|
|
861
|
-
"minimum": 1
|
|
629
|
+
"minimum": 1,
|
|
630
|
+
"default": 100
|
|
862
631
|
}
|
|
863
632
|
},
|
|
864
633
|
"additionalProperties": false
|
|
865
634
|
}
|
|
866
635
|
},
|
|
867
|
-
"additionalProperties": false
|
|
868
|
-
"deprecated": true
|
|
636
|
+
"additionalProperties": false
|
|
869
637
|
},
|
|
870
638
|
"webhooks": {
|
|
871
639
|
"type": "object",
|
|
872
|
-
"description": "Webhook handling configuration
|
|
640
|
+
"description": "Webhook handling configuration",
|
|
873
641
|
"properties": {
|
|
874
642
|
"secret": {
|
|
875
643
|
"type": "string",
|
|
@@ -878,11 +646,11 @@
|
|
|
878
646
|
"prefix": {
|
|
879
647
|
"type": "string",
|
|
880
648
|
"description": "Webhook endpoint prefix",
|
|
881
|
-
"pattern": "^/[a-zA-Z0-9/_-]*$"
|
|
649
|
+
"pattern": "^/[a-zA-Z0-9/_-]*$",
|
|
650
|
+
"default": "/webhooks"
|
|
882
651
|
}
|
|
883
652
|
},
|
|
884
|
-
"additionalProperties": false
|
|
885
|
-
"deprecated": true
|
|
653
|
+
"additionalProperties": false
|
|
886
654
|
},
|
|
887
655
|
"logging": {
|
|
888
656
|
"type": "object",
|
|
@@ -890,8 +658,9 @@
|
|
|
890
658
|
"properties": {
|
|
891
659
|
"level": {
|
|
892
660
|
"type": "string",
|
|
893
|
-
"description": "Minimum log level, in lower or upper case. Sets FRIGG_LOG_LEVEL (when not info) and the Lambda application log level.
|
|
894
|
-
"enum": ["trace", "debug", "info", "warn", "error", "fatal", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"]
|
|
661
|
+
"description": "Minimum log level, in lower or upper case. Sets FRIGG_LOG_LEVEL (when not info) and the Lambda application log level.",
|
|
662
|
+
"enum": ["trace", "debug", "info", "warn", "error", "fatal", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"],
|
|
663
|
+
"default": "info"
|
|
895
664
|
},
|
|
896
665
|
"retentionInDays": {
|
|
897
666
|
"type": "integer",
|
|
@@ -900,225 +669,46 @@
|
|
|
900
669
|
},
|
|
901
670
|
"format": {
|
|
902
671
|
"type": "string",
|
|
903
|
-
"description": "Log format. Records are always JSON lines
|
|
904
|
-
"enum": ["json"]
|
|
905
|
-
|
|
906
|
-
},
|
|
907
|
-
"additionalProperties": false
|
|
908
|
-
},
|
|
909
|
-
"scheduler": {
|
|
910
|
-
"type": "object",
|
|
911
|
-
"description": "EventBridge Scheduler resources for one-time jobs. Also enabled automatically when an integration declares webhooks.",
|
|
912
|
-
"properties": {
|
|
913
|
-
"enable": {
|
|
914
|
-
"type": "boolean",
|
|
915
|
-
"description": "Provision the scheduler role and dead-letter queue",
|
|
916
|
-
"default": false
|
|
917
|
-
}
|
|
918
|
-
},
|
|
919
|
-
"additionalProperties": false
|
|
920
|
-
},
|
|
921
|
-
"aws": {
|
|
922
|
-
"type": "object",
|
|
923
|
-
"description": "AWS options for the build",
|
|
924
|
-
"properties": {
|
|
925
|
-
"discovery": {
|
|
926
|
-
"type": "object",
|
|
927
|
-
"description": "AWS resource discovery during build/deploy",
|
|
928
|
-
"properties": {
|
|
929
|
-
"enabled": {
|
|
930
|
-
"type": "boolean",
|
|
931
|
-
"description": "Force discovery on or off. When omitted, discovery runs when a feature needs it (VPC, KMS, SSM, PostgreSQL) and FRIGG_SKIP_AWS_DISCOVERY is not set."
|
|
932
|
-
},
|
|
933
|
-
"failOnError": {
|
|
934
|
-
"type": "boolean",
|
|
935
|
-
"description": "Fail the build when discovery fails",
|
|
936
|
-
"default": false
|
|
937
|
-
}
|
|
938
|
-
},
|
|
939
|
-
"additionalProperties": false
|
|
940
|
-
}
|
|
941
|
-
},
|
|
942
|
-
"additionalProperties": false
|
|
943
|
-
},
|
|
944
|
-
"migration": {
|
|
945
|
-
"type": "object",
|
|
946
|
-
"description": "Database migration resources",
|
|
947
|
-
"properties": {
|
|
948
|
-
"ownership": {
|
|
949
|
-
"type": "object",
|
|
950
|
-
"properties": {
|
|
951
|
-
"bucket": {
|
|
952
|
-
"type": "string",
|
|
953
|
-
"enum": ["stack", "external", "auto"],
|
|
954
|
-
"description": "Migration S3 bucket. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
955
|
-
},
|
|
956
|
-
"queue": {
|
|
957
|
-
"type": "string",
|
|
958
|
-
"enum": ["stack", "external", "auto"],
|
|
959
|
-
"description": "Migration SQS queue. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
960
|
-
}
|
|
961
|
-
},
|
|
962
|
-
"additionalProperties": false
|
|
963
|
-
}
|
|
964
|
-
},
|
|
965
|
-
"additionalProperties": false
|
|
966
|
-
},
|
|
967
|
-
"telemetry": {
|
|
968
|
-
"type": "object",
|
|
969
|
-
"description": "Telemetry and usage tracking (ADR-011). An invalid block disables telemetry at runtime instead of failing.",
|
|
970
|
-
"properties": {
|
|
971
|
-
"exporter": {
|
|
972
|
-
"type": "object",
|
|
973
|
-
"description": "Where traces and metrics go. When omitted: 'console' for STAGE=local, else 'none'.",
|
|
974
|
-
"properties": {
|
|
975
|
-
"type": {
|
|
976
|
-
"type": "string",
|
|
977
|
-
"enum": ["none", "noop", "console", "otlp", "honeycomb", "datadog"]
|
|
978
|
-
},
|
|
979
|
-
"endpoint": {
|
|
980
|
-
"type": "string",
|
|
981
|
-
"description": "OTLP endpoint (honeycomb defaults to https://api.honeycomb.io)"
|
|
982
|
-
},
|
|
983
|
-
"headers": {
|
|
984
|
-
"type": "object",
|
|
985
|
-
"additionalProperties": {"type": "string"}
|
|
986
|
-
},
|
|
987
|
-
"apiKey": {
|
|
988
|
-
"type": "string",
|
|
989
|
-
"description": "Honeycomb API key (sent as x-honeycomb-team)"
|
|
990
|
-
},
|
|
991
|
-
"traceExporter": {
|
|
992
|
-
"description": "A pre-built OTel trace exporter instance (advanced)"
|
|
993
|
-
},
|
|
994
|
-
"metricExporter": {
|
|
995
|
-
"description": "A pre-built OTel metric exporter instance (advanced)"
|
|
996
|
-
}
|
|
997
|
-
},
|
|
998
|
-
"additionalProperties": false
|
|
999
|
-
},
|
|
1000
|
-
"sampleRatio": {
|
|
1001
|
-
"type": "number",
|
|
1002
|
-
"description": "Fraction of traces exported",
|
|
1003
|
-
"minimum": 0,
|
|
1004
|
-
"maximum": 1,
|
|
1005
|
-
"default": 1
|
|
1006
|
-
},
|
|
1007
|
-
"northStar": {
|
|
1008
|
-
"type": "object",
|
|
1009
|
-
"description": "The usage counter that measures each integration type's value: { default: { name }, byType: { <type>: { name } } }",
|
|
1010
|
-
"properties": {
|
|
1011
|
-
"default": {
|
|
1012
|
-
"type": "object",
|
|
1013
|
-
"required": ["name"],
|
|
1014
|
-
"properties": {
|
|
1015
|
-
"name": {"type": "string"}
|
|
1016
|
-
}
|
|
1017
|
-
},
|
|
1018
|
-
"byType": {
|
|
1019
|
-
"type": "object",
|
|
1020
|
-
"additionalProperties": {
|
|
1021
|
-
"type": "object",
|
|
1022
|
-
"required": ["name"],
|
|
1023
|
-
"properties": {
|
|
1024
|
-
"name": {"type": "string"}
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
},
|
|
1029
|
-
"additionalProperties": false
|
|
1030
|
-
},
|
|
1031
|
-
"subscribers": {
|
|
1032
|
-
"type": "array",
|
|
1033
|
-
"description": "Telemetry event subscribers: functions or { handler } objects",
|
|
1034
|
-
"items": {
|
|
1035
|
-
"description": "A function or { handler }"
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
},
|
|
1039
|
-
"additionalProperties": false
|
|
1040
|
-
},
|
|
1041
|
-
"admin": {
|
|
1042
|
-
"type": "object",
|
|
1043
|
-
"description": "Admin Script Runner options (ADR-005, ADR-010)",
|
|
1044
|
-
"properties": {
|
|
1045
|
-
"includeBuiltinReports": {
|
|
1046
|
-
"type": "boolean",
|
|
1047
|
-
"description": "Register Frigg's built-in reports",
|
|
1048
|
-
"default": false
|
|
1049
|
-
},
|
|
1050
|
-
"enableScheduling": {
|
|
1051
|
-
"type": "boolean",
|
|
1052
|
-
"description": "Provision scheduling for admin scripts"
|
|
1053
|
-
}
|
|
1054
|
-
},
|
|
1055
|
-
"additionalProperties": false
|
|
1056
|
-
},
|
|
1057
|
-
"adminScripts": {
|
|
1058
|
-
"type": "array",
|
|
1059
|
-
"description": "Admin script classes (each with a static Definition). Validators see each class as { Definition }.",
|
|
1060
|
-
"items": {
|
|
1061
|
-
"type": "object",
|
|
1062
|
-
"required": ["Definition"],
|
|
1063
|
-
"properties": {
|
|
1064
|
-
"Definition": {"type": "object"}
|
|
1065
|
-
}
|
|
1066
|
-
},
|
|
1067
|
-
"default": []
|
|
1068
|
-
},
|
|
1069
|
-
"reports": {
|
|
1070
|
-
"type": "array",
|
|
1071
|
-
"description": "Report classes (each with a static Definition). Validators see each class as { Definition }.",
|
|
1072
|
-
"items": {
|
|
1073
|
-
"type": "object",
|
|
1074
|
-
"required": ["Definition"],
|
|
1075
|
-
"properties": {
|
|
1076
|
-
"Definition": {"type": "object"}
|
|
1077
|
-
}
|
|
1078
|
-
},
|
|
1079
|
-
"default": []
|
|
1080
|
-
},
|
|
1081
|
-
"deployment": {
|
|
1082
|
-
"type": "object",
|
|
1083
|
-
"description": "`frigg deploy` options",
|
|
1084
|
-
"properties": {
|
|
1085
|
-
"skipPostDeploymentHealthCheck": {
|
|
1086
|
-
"type": "boolean",
|
|
1087
|
-
"description": "Skip `frigg doctor` after a deploy",
|
|
1088
|
-
"default": false
|
|
672
|
+
"description": "Log format. Records are always JSON lines.",
|
|
673
|
+
"enum": ["json"],
|
|
674
|
+
"default": "json"
|
|
1089
675
|
}
|
|
1090
676
|
},
|
|
1091
677
|
"additionalProperties": false
|
|
1092
678
|
},
|
|
1093
679
|
"custom": {
|
|
1094
680
|
"type": "object",
|
|
1095
|
-
"description": "Custom application-specific configuration
|
|
681
|
+
"description": "Custom application-specific configuration",
|
|
1096
682
|
"properties": {
|
|
1097
683
|
"appName": {
|
|
1098
684
|
"type": "string",
|
|
1099
|
-
"description": "Application display name"
|
|
685
|
+
"description": "Application display name",
|
|
686
|
+
"default": "My Frigg Application"
|
|
1100
687
|
},
|
|
1101
688
|
"version": {
|
|
1102
689
|
"type": "string",
|
|
1103
690
|
"description": "Application version",
|
|
1104
|
-
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$"
|
|
691
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$",
|
|
692
|
+
"default": "1.0.0"
|
|
1105
693
|
},
|
|
1106
694
|
"environment": {
|
|
1107
695
|
"type": "string",
|
|
1108
696
|
"description": "Deployment environment/stage",
|
|
1109
|
-
"enum": ["development", "staging", "production", "test"]
|
|
697
|
+
"enum": ["development", "staging", "production", "test"],
|
|
698
|
+
"default": "development"
|
|
1110
699
|
},
|
|
1111
700
|
"features": {
|
|
1112
701
|
"type": "object",
|
|
1113
702
|
"description": "Feature flags and toggles",
|
|
1114
703
|
"patternProperties": {
|
|
1115
|
-
"^[a-zA-Z][a-zA-Z0-9_]*$": {
|
|
704
|
+
"^[a-zA-Z][a-zA-Z0-9_]*$": {
|
|
705
|
+
"type": "boolean"
|
|
706
|
+
}
|
|
1116
707
|
},
|
|
1117
708
|
"additionalProperties": false
|
|
1118
709
|
}
|
|
1119
710
|
},
|
|
1120
|
-
"additionalProperties": true
|
|
1121
|
-
"deprecated": true
|
|
711
|
+
"additionalProperties": true
|
|
1122
712
|
}
|
|
1123
713
|
},
|
|
1124
714
|
"additionalProperties": false,
|
|
@@ -1132,15 +722,12 @@
|
|
|
1132
722
|
},
|
|
1133
723
|
"integrations": [],
|
|
1134
724
|
"user": {
|
|
1135
|
-
"
|
|
1136
|
-
"primary": "individual",
|
|
1137
|
-
"individualUserRequired": true,
|
|
1138
|
-
"organizationUserRequired": false
|
|
725
|
+
"password": true
|
|
1139
726
|
},
|
|
1140
727
|
"database": {
|
|
1141
728
|
"postgres": {
|
|
1142
729
|
"enable": true,
|
|
1143
|
-
"management": "
|
|
730
|
+
"management": "create-new"
|
|
1144
731
|
}
|
|
1145
732
|
},
|
|
1146
733
|
"encryption": {
|
|
@@ -1153,8 +740,18 @@
|
|
|
1153
740
|
"cidrBlock": "10.0.0.0/16",
|
|
1154
741
|
"enableVPCEndpoints": true
|
|
1155
742
|
},
|
|
1156
|
-
"ssm": {
|
|
1157
|
-
|
|
743
|
+
"ssm": {
|
|
744
|
+
"enable": true
|
|
745
|
+
},
|
|
746
|
+
"websockets": {
|
|
747
|
+
"enable": true
|
|
748
|
+
},
|
|
749
|
+
"security": {
|
|
750
|
+
"cors": {
|
|
751
|
+
"origin": "http://localhost:3000",
|
|
752
|
+
"credentials": true
|
|
753
|
+
}
|
|
754
|
+
},
|
|
1158
755
|
"logging": {
|
|
1159
756
|
"level": "info",
|
|
1160
757
|
"retentionInDays": 30
|
package/app-definition.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* App definition helpers shared by the runtime (core) and the tooling
|
|
3
|
-
* (devtools, frigg CLI). See ADR-051.
|
|
4
|
-
*
|
|
5
|
-
* This file loads only the JSON schema, not Ajv, so the runtime can apply
|
|
6
|
-
* the schema defaults at cold start without compiling a validator.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const appDefinitionSchema = require('./schemas/app-definition.schema.json');
|
|
10
|
-
|
|
11
|
-
function isPlainObject(value) {
|
|
12
|
-
if (value === null || typeof value !== 'object') return false;
|
|
13
|
-
const proto = Object.getPrototypeOf(value);
|
|
14
|
-
return proto === Object.prototype || proto === null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function cloneDefault(value) {
|
|
18
|
-
// Schema defaults are JSON values: a JSON round trip copies them fully.
|
|
19
|
-
return value === undefined ? value : JSON.parse(JSON.stringify(value));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Copy plain objects and arrays, keep everything else (classes, functions,
|
|
24
|
-
* instances) by reference.
|
|
25
|
-
*/
|
|
26
|
-
function clonePlain(value) {
|
|
27
|
-
if (Array.isArray(value)) return value.map(clonePlain);
|
|
28
|
-
if (isPlainObject(value)) {
|
|
29
|
-
const copy = {};
|
|
30
|
-
for (const [key, inner] of Object.entries(value)) {
|
|
31
|
-
copy[key] = clonePlain(inner);
|
|
32
|
-
}
|
|
33
|
-
return copy;
|
|
34
|
-
}
|
|
35
|
-
return value;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function applyDefaultsInPlace(schema, data) {
|
|
39
|
-
if (!schema || !isPlainObject(data)) return;
|
|
40
|
-
const properties = schema.properties || {};
|
|
41
|
-
for (const [key, propertySchema] of Object.entries(properties)) {
|
|
42
|
-
if (data[key] === undefined && propertySchema.default !== undefined) {
|
|
43
|
-
data[key] = cloneDefault(propertySchema.default);
|
|
44
|
-
}
|
|
45
|
-
if (isPlainObject(data[key]) && propertySchema.properties) {
|
|
46
|
-
applyDefaultsInPlace(propertySchema, data[key]);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Return a copy of the app definition with every `default` that the
|
|
53
|
-
* app-definition schema declares applied, the way Ajv `useDefaults` does:
|
|
54
|
-
* only for properties of objects that exist (a block the app leaves out is
|
|
55
|
-
* not created unless the block itself has a default, as `user` does). It
|
|
56
|
-
* also copies the deprecated `user.password` into `user.usePassword` when
|
|
57
|
-
* only the old spelling is set. Classes and other non-plain values are kept by reference.
|
|
58
|
-
* The input is not mutated, and the function is idempotent.
|
|
59
|
-
*
|
|
60
|
-
* This is the only place schema defaults are applied. core's
|
|
61
|
-
* loadAppDefinition and devtools' createFriggInfrastructure both call it,
|
|
62
|
-
* so a default in the schema is a default at runtime.
|
|
63
|
-
*
|
|
64
|
-
* @param {object} definition the `Definition` exported by the backend
|
|
65
|
-
* @returns {object} the definition with defaults applied
|
|
66
|
-
*/
|
|
67
|
-
function applyAppDefinitionDefaults(definition) {
|
|
68
|
-
if (!isPlainObject(definition)) return definition;
|
|
69
|
-
const copy = clonePlain(definition);
|
|
70
|
-
// user.password is the deprecated spelling of user.usePassword.
|
|
71
|
-
if (
|
|
72
|
-
isPlainObject(copy.user) &&
|
|
73
|
-
copy.user.usePassword === undefined &&
|
|
74
|
-
typeof copy.user.password === 'boolean'
|
|
75
|
-
) {
|
|
76
|
-
copy.user.usePassword = copy.user.password;
|
|
77
|
-
}
|
|
78
|
-
applyDefaultsInPlace(appDefinitionSchema, copy);
|
|
79
|
-
return copy;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Keys whose entries are classes with a static Definition.
|
|
83
|
-
const CLASS_LIST_KEYS = ['integrations', 'adminScripts', 'reports'];
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* JSON Schema cannot describe a JavaScript class, and apps list integration
|
|
87
|
-
* (and admin script, and report) classes. Validators therefore check this serialisable view, in which each
|
|
88
|
-
* class is replaced by `{ Definition }` (its static Definition). The schema
|
|
89
|
-
* describes that view; `frigg validate` checks the Definition itself.
|
|
90
|
-
*
|
|
91
|
-
* @param {object} definition the `Definition` exported by the backend
|
|
92
|
-
* @returns {object} a shallow copy with the class lists mapped to views
|
|
93
|
-
*/
|
|
94
|
-
function toAppDefinitionSchemaView(definition) {
|
|
95
|
-
if (!isPlainObject(definition)) return definition;
|
|
96
|
-
const view = { ...definition };
|
|
97
|
-
for (const key of CLASS_LIST_KEYS) {
|
|
98
|
-
if (Array.isArray(definition[key])) {
|
|
99
|
-
view[key] = definition[key].map((entry) =>
|
|
100
|
-
typeof entry === 'function'
|
|
101
|
-
? { Definition: entry.Definition }
|
|
102
|
-
: entry
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return view;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
module.exports = {
|
|
110
|
-
applyAppDefinitionDefaults,
|
|
111
|
-
toAppDefinitionSchemaView,
|
|
112
|
-
appDefinitionSchema,
|
|
113
|
-
};
|