@friggframework/schemas 2.0.0--canary.731.ffe61d3.0 → 2.0.0--canary.658.130b4ec.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 +1 -13
- package/package.json +2 -3
- package/schemas/app-definition.schema.json +132 -539
- 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
|
|
|
20
16
|
// Initialize AJV with formats
|
|
21
17
|
const ajv = new Ajv({
|
|
@@ -80,13 +76,7 @@ function validate(schemaName, data) {
|
|
|
80
76
|
* @returns {object} - Validation result
|
|
81
77
|
*/
|
|
82
78
|
function validateAppDefinition(appDefinition) {
|
|
83
|
-
|
|
84
|
-
// validate the serialisable view and return the original definition.
|
|
85
|
-
const result = validate(
|
|
86
|
-
'app-definition',
|
|
87
|
-
toAppDefinitionSchemaView(appDefinition)
|
|
88
|
-
);
|
|
89
|
-
return { ...result, data: appDefinition };
|
|
79
|
+
return validate('app-definition', appDefinition);
|
|
90
80
|
}
|
|
91
81
|
|
|
92
82
|
/**
|
|
@@ -367,8 +357,6 @@ module.exports = {
|
|
|
367
357
|
// Validation functions
|
|
368
358
|
validate,
|
|
369
359
|
validateAppDefinition,
|
|
370
|
-
applyAppDefinitionDefaults,
|
|
371
|
-
toAppDefinitionSchemaView,
|
|
372
360
|
validateIntegrationDefinition,
|
|
373
361
|
validateApiModuleDefinition,
|
|
374
362
|
validateServerlessConfig,
|
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.658.130b4ec.0",
|
|
4
4
|
"description": "Canonical JSON Schema definitions for Frigg Framework",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "",
|
|
@@ -39,8 +39,7 @@
|
|
|
39
39
|
"validators/",
|
|
40
40
|
"mocks/",
|
|
41
41
|
"middleware/",
|
|
42
|
-
"app-definition.js",
|
|
43
42
|
"index.js"
|
|
44
43
|
],
|
|
45
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "130b4ec4ebf0f605416f3db316b5ddbe54a37d32"
|
|
46
45
|
}
|
|
@@ -22,40 +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
|
|
54
|
-
},
|
|
55
|
-
"architecture": {
|
|
56
|
-
"type": "string",
|
|
57
|
-
"description": "Lambda instruction set for every function, the Prisma layer and the migration worker. Unset deploys x86_64 with an unchanged template. 'arm64' (Graviton) needs a @friggframework/core release whose generated Prisma clients include the linux-arm64 engine.",
|
|
58
|
-
"enum": ["x86_64", "arm64"]
|
|
38
|
+
"description": "VPC isolation strategy: 'isolated' creates separate VPC per stage, 'shared' reuses VPC across stages",
|
|
39
|
+
"enum": ["isolated", "shared"],
|
|
40
|
+
"default": "isolated"
|
|
59
41
|
},
|
|
60
42
|
"environment": {
|
|
61
43
|
"type": "object",
|
|
@@ -86,72 +68,60 @@
|
|
|
86
68
|
},
|
|
87
69
|
"integrations": {
|
|
88
70
|
"type": "array",
|
|
89
|
-
"description": "
|
|
71
|
+
"description": "Array of integration classes to enable in the application",
|
|
90
72
|
"items": {
|
|
91
73
|
"type": "object",
|
|
92
|
-
"description": "
|
|
93
|
-
"required": ["Definition"],
|
|
94
|
-
"properties": {
|
|
95
|
-
"Definition": {
|
|
96
|
-
"type": "object",
|
|
97
|
-
"description": "The integration's static Definition (see integration-definition.schema.json)"
|
|
98
|
-
}
|
|
99
|
-
}
|
|
74
|
+
"description": "Integration class or configuration object"
|
|
100
75
|
},
|
|
101
76
|
"default": []
|
|
102
77
|
},
|
|
103
78
|
"user": {
|
|
104
79
|
"type": "object",
|
|
105
|
-
"description": "User management and authentication
|
|
80
|
+
"description": "User management and authentication configuration",
|
|
106
81
|
"properties": {
|
|
107
82
|
"usePassword": {
|
|
108
83
|
"type": "boolean",
|
|
109
|
-
"description": "
|
|
110
|
-
"default":
|
|
84
|
+
"description": "Enable password-based authentication for user login",
|
|
85
|
+
"default": true
|
|
111
86
|
},
|
|
112
87
|
"password": {
|
|
113
88
|
"type": "boolean",
|
|
114
|
-
"description": "DEPRECATED
|
|
115
|
-
"
|
|
89
|
+
"description": "DEPRECATED: Use 'usePassword' instead. Enable password-based authentication",
|
|
90
|
+
"default": true
|
|
116
91
|
},
|
|
117
92
|
"primary": {
|
|
118
93
|
"type": "string",
|
|
119
|
-
"description": "Primary user type
|
|
94
|
+
"description": "Primary user type for authentication",
|
|
120
95
|
"enum": ["individual", "organization"],
|
|
121
96
|
"default": "individual"
|
|
122
97
|
},
|
|
123
98
|
"individualUserRequired": {
|
|
124
99
|
"type": "boolean",
|
|
125
|
-
"description": "Require
|
|
100
|
+
"description": "Require individual user for authentication",
|
|
126
101
|
"default": true
|
|
127
102
|
},
|
|
128
103
|
"organizationUserRequired": {
|
|
129
104
|
"type": "boolean",
|
|
130
|
-
"description": "Require
|
|
131
|
-
"default": false
|
|
132
|
-
},
|
|
133
|
-
"strictUserValidation": {
|
|
134
|
-
"type": "boolean",
|
|
135
|
-
"description": "With x-frigg headers, reject a user id that does not exist instead of creating and linking it.",
|
|
105
|
+
"description": "Require organization user for authentication",
|
|
136
106
|
"default": false
|
|
137
107
|
},
|
|
138
108
|
"authModes": {
|
|
139
109
|
"type": "object",
|
|
140
|
-
"description": "Authentication
|
|
110
|
+
"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.",
|
|
141
111
|
"properties": {
|
|
142
112
|
"friggToken": {
|
|
143
113
|
"type": "boolean",
|
|
144
|
-
"description": "
|
|
114
|
+
"description": "Enable Frigg native bearer token authentication (from /user/login)",
|
|
145
115
|
"default": true
|
|
146
116
|
},
|
|
147
117
|
"sharedSecret": {
|
|
148
118
|
"type": "boolean",
|
|
149
|
-
"description": "
|
|
150
|
-
"default":
|
|
119
|
+
"description": "Enable shared secret authentication for backend-to-backend communication (requires FRIGG_API_KEY env var and x-frigg-api-key header)",
|
|
120
|
+
"default": false
|
|
151
121
|
},
|
|
152
122
|
"adopterJwt": {
|
|
153
123
|
"type": "boolean",
|
|
154
|
-
"description": "
|
|
124
|
+
"description": "Enable custom JWT authentication from adopter's auth system (requires jwtConfig)",
|
|
155
125
|
"default": false
|
|
156
126
|
}
|
|
157
127
|
},
|
|
@@ -163,7 +133,7 @@
|
|
|
163
133
|
"properties": {
|
|
164
134
|
"secret": {
|
|
165
135
|
"type": "string",
|
|
166
|
-
"description": "JWT secret key for signature validation
|
|
136
|
+
"description": "JWT secret key for signature validation (should be set via environment variable)"
|
|
167
137
|
},
|
|
168
138
|
"userIdClaim": {
|
|
169
139
|
"type": "string",
|
|
@@ -182,29 +152,27 @@
|
|
|
182
152
|
"default": "HS256"
|
|
183
153
|
}
|
|
184
154
|
},
|
|
155
|
+
"required": ["secret"],
|
|
185
156
|
"additionalProperties": false
|
|
186
157
|
},
|
|
187
158
|
"fields": {
|
|
188
159
|
"type": "array",
|
|
189
|
-
"description": "Additional user fields
|
|
190
|
-
"items": {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
]
|
|
194
|
-
"deprecated": true
|
|
160
|
+
"description": "Additional user fields",
|
|
161
|
+
"items": {
|
|
162
|
+
"type": "string"
|
|
163
|
+
},
|
|
164
|
+
"examples": [["email", "firstName", "lastName"]]
|
|
195
165
|
},
|
|
196
166
|
"model": {
|
|
197
167
|
"type": "object",
|
|
198
|
-
"description": "Custom user model class
|
|
199
|
-
"deprecated": true
|
|
168
|
+
"description": "Custom user model class"
|
|
200
169
|
}
|
|
201
170
|
},
|
|
202
|
-
"additionalProperties": false
|
|
203
|
-
"default": {}
|
|
171
|
+
"additionalProperties": false
|
|
204
172
|
},
|
|
205
173
|
"auth": {
|
|
206
174
|
"type": "object",
|
|
207
|
-
"description": "Authentication configuration
|
|
175
|
+
"description": "Authentication configuration for integrations",
|
|
208
176
|
"properties": {
|
|
209
177
|
"jwtSecret": {
|
|
210
178
|
"type": "string",
|
|
@@ -213,16 +181,17 @@
|
|
|
213
181
|
"tokenExpiry": {
|
|
214
182
|
"type": "string",
|
|
215
183
|
"description": "Token expiration time",
|
|
216
|
-
"pattern": "^\\d+[smhd]$"
|
|
184
|
+
"pattern": "^\\d+[smhd]$",
|
|
185
|
+
"default": "24h"
|
|
217
186
|
},
|
|
218
187
|
"refreshTokenExpiry": {
|
|
219
188
|
"type": "string",
|
|
220
|
-
"description": "Refresh token expiration time",
|
|
221
|
-
"pattern": "^\\d+[smhd]$"
|
|
189
|
+
"description": "Refresh token expiration time",
|
|
190
|
+
"pattern": "^\\d+[smhd]$",
|
|
191
|
+
"default": "7d"
|
|
222
192
|
}
|
|
223
193
|
},
|
|
224
|
-
"additionalProperties": false
|
|
225
|
-
"deprecated": true
|
|
194
|
+
"additionalProperties": false
|
|
226
195
|
},
|
|
227
196
|
"database": {
|
|
228
197
|
"type": "object",
|
|
@@ -230,8 +199,8 @@
|
|
|
230
199
|
"properties": {
|
|
231
200
|
"uri": {
|
|
232
201
|
"type": "string",
|
|
233
|
-
"description": "Database connection URI (should be set via environment variable)
|
|
234
|
-
"
|
|
202
|
+
"description": "Database connection URI (should be set via environment variable)",
|
|
203
|
+
"format": "uri"
|
|
235
204
|
},
|
|
236
205
|
"mongoDB": {
|
|
237
206
|
"type": "object",
|
|
@@ -244,8 +213,7 @@
|
|
|
244
213
|
},
|
|
245
214
|
"uri": {
|
|
246
215
|
"type": "string",
|
|
247
|
-
"description": "MongoDB connection URI
|
|
248
|
-
"deprecated": true
|
|
216
|
+
"description": "MongoDB connection URI"
|
|
249
217
|
}
|
|
250
218
|
},
|
|
251
219
|
"additionalProperties": true
|
|
@@ -273,16 +241,18 @@
|
|
|
273
241
|
"properties": {
|
|
274
242
|
"enable": {
|
|
275
243
|
"type": "boolean",
|
|
276
|
-
"description": "
|
|
244
|
+
"description": "Enable PostgreSQL database",
|
|
245
|
+
"default": false
|
|
277
246
|
},
|
|
278
247
|
"management": {
|
|
279
248
|
"type": "string",
|
|
280
|
-
"description": "How
|
|
281
|
-
"enum": ["discover", "
|
|
249
|
+
"description": "How to manage the PostgreSQL database",
|
|
250
|
+
"enum": ["discover", "create-new", "existing"],
|
|
251
|
+
"default": "discover"
|
|
282
252
|
},
|
|
283
253
|
"endpoint": {
|
|
284
254
|
"type": "string",
|
|
285
|
-
"description": "Existing database endpoint (
|
|
255
|
+
"description": "Existing database endpoint (when management='existing')",
|
|
286
256
|
"examples": ["mydb.cluster-abc123.us-east-1.rds.amazonaws.com"]
|
|
287
257
|
},
|
|
288
258
|
"port": {
|
|
@@ -300,15 +270,10 @@
|
|
|
300
270
|
"description": "Database username",
|
|
301
271
|
"default": "postgres"
|
|
302
272
|
},
|
|
303
|
-
"engineVersion": {
|
|
304
|
-
"type": "string",
|
|
305
|
-
"description": "Aurora PostgreSQL engine version for a cluster Frigg creates",
|
|
306
|
-
"default": "15.13"
|
|
307
|
-
},
|
|
308
273
|
"selfHeal": {
|
|
309
274
|
"type": "boolean",
|
|
310
|
-
"description": "Automatically fix database configuration issues
|
|
311
|
-
"
|
|
275
|
+
"description": "Automatically fix database configuration issues",
|
|
276
|
+
"default": true
|
|
312
277
|
},
|
|
313
278
|
"publiclyAccessible": {
|
|
314
279
|
"type": "boolean",
|
|
@@ -317,7 +282,7 @@
|
|
|
317
282
|
},
|
|
318
283
|
"autoCreateCredentials": {
|
|
319
284
|
"type": "boolean",
|
|
320
|
-
"description": "
|
|
285
|
+
"description": "Automatically create Secrets Manager secret and rotate Aurora password when discovering existing cluster (only applies when management='discover')",
|
|
321
286
|
"default": false
|
|
322
287
|
},
|
|
323
288
|
"minCapacity": {
|
|
@@ -332,65 +297,7 @@
|
|
|
332
297
|
"description": "Maximum Aurora Serverless capacity units (0.5-128)",
|
|
333
298
|
"minimum": 0.5,
|
|
334
299
|
"maximum": 128,
|
|
335
|
-
"default":
|
|
336
|
-
},
|
|
337
|
-
"clusterId": {
|
|
338
|
-
"type": "string",
|
|
339
|
-
"description": "Only discover the Aurora cluster with this identifier"
|
|
340
|
-
},
|
|
341
|
-
"instanceId": {
|
|
342
|
-
"type": "string",
|
|
343
|
-
"description": "Only discover the Aurora instance with this identifier"
|
|
344
|
-
},
|
|
345
|
-
"ownership": {
|
|
346
|
-
"type": "object",
|
|
347
|
-
"description": "Per-resource ownership. When set, `management` is not translated.",
|
|
348
|
-
"properties": {
|
|
349
|
-
"cluster": {
|
|
350
|
-
"type": "string",
|
|
351
|
-
"enum": ["stack", "external", "auto"],
|
|
352
|
-
"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)"
|
|
353
|
-
},
|
|
354
|
-
"instance": {
|
|
355
|
-
"type": "string",
|
|
356
|
-
"enum": ["stack", "external", "auto"],
|
|
357
|
-
"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)"
|
|
358
|
-
},
|
|
359
|
-
"subnetGroup": {
|
|
360
|
-
"type": "string",
|
|
361
|
-
"enum": ["stack", "external", "auto"],
|
|
362
|
-
"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)"
|
|
363
|
-
},
|
|
364
|
-
"secret": {
|
|
365
|
-
"type": "string",
|
|
366
|
-
"enum": ["stack", "external", "auto"],
|
|
367
|
-
"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)"
|
|
368
|
-
}
|
|
369
|
-
},
|
|
370
|
-
"additionalProperties": false
|
|
371
|
-
},
|
|
372
|
-
"external": {
|
|
373
|
-
"type": "object",
|
|
374
|
-
"description": "Ids of externally owned resources (ownership 'external')",
|
|
375
|
-
"properties": {
|
|
376
|
-
"clusterIdentifier": {"type": "string"},
|
|
377
|
-
"instanceIdentifier": {"type": "string"},
|
|
378
|
-
"subnetGroupName": {"type": "string"},
|
|
379
|
-
"secretArn": {"type": "string"}
|
|
380
|
-
},
|
|
381
|
-
"additionalProperties": false
|
|
382
|
-
}
|
|
383
|
-
},
|
|
384
|
-
"additionalProperties": false
|
|
385
|
-
},
|
|
386
|
-
"dynamodb": {
|
|
387
|
-
"type": "object",
|
|
388
|
-
"description": "DynamoDB access from inside the VPC",
|
|
389
|
-
"properties": {
|
|
390
|
-
"enable": {
|
|
391
|
-
"type": "boolean",
|
|
392
|
-
"description": "Add a DynamoDB VPC endpoint",
|
|
393
|
-
"default": false
|
|
300
|
+
"default": 1
|
|
394
301
|
}
|
|
395
302
|
},
|
|
396
303
|
"additionalProperties": false
|
|
@@ -404,12 +311,14 @@
|
|
|
404
311
|
"properties": {
|
|
405
312
|
"fieldLevelEncryptionMethod": {
|
|
406
313
|
"type": "string",
|
|
407
|
-
"description": "
|
|
408
|
-
"enum": ["kms", "aes",
|
|
314
|
+
"description": "Method for field-level encryption",
|
|
315
|
+
"enum": ["kms", "aes"],
|
|
316
|
+
"default": "aes"
|
|
409
317
|
},
|
|
410
318
|
"createResourceIfNoneFound": {
|
|
411
319
|
"type": "boolean",
|
|
412
|
-
"description": "
|
|
320
|
+
"description": "Create KMS key if none found during discovery",
|
|
321
|
+
"default": false
|
|
413
322
|
},
|
|
414
323
|
"schema": {
|
|
415
324
|
"type": "object",
|
|
@@ -446,48 +355,6 @@
|
|
|
446
355
|
}
|
|
447
356
|
}
|
|
448
357
|
]
|
|
449
|
-
},
|
|
450
|
-
"ownership": {
|
|
451
|
-
"type": "object",
|
|
452
|
-
"description": "Per-resource ownership. When set, createResourceIfNoneFound is not translated.",
|
|
453
|
-
"properties": {
|
|
454
|
-
"key": {
|
|
455
|
-
"type": "string",
|
|
456
|
-
"enum": ["stack", "external", "auto"],
|
|
457
|
-
"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)"
|
|
458
|
-
}
|
|
459
|
-
},
|
|
460
|
-
"additionalProperties": false
|
|
461
|
-
},
|
|
462
|
-
"kmsKeyAlias": {
|
|
463
|
-
"type": "boolean",
|
|
464
|
-
"description": "Create an alias for a KMS key Frigg creates",
|
|
465
|
-
"default": false
|
|
466
|
-
},
|
|
467
|
-
"keyAlias": {
|
|
468
|
-
"type": "string",
|
|
469
|
-
"description": "Only discover the KMS key with this alias",
|
|
470
|
-
"pattern": "^alias/",
|
|
471
|
-
"examples": ["alias/my-app-key"]
|
|
472
|
-
},
|
|
473
|
-
"disable": {
|
|
474
|
-
"type": "object",
|
|
475
|
-
"description": "Opt specific core-encrypted fields out of encryption: { Model: ['field.path'] }. Existing encrypted values still decrypt.",
|
|
476
|
-
"patternProperties": {
|
|
477
|
-
"^[A-Z][a-zA-Z0-9]*$": {
|
|
478
|
-
"type": "array",
|
|
479
|
-
"items": {
|
|
480
|
-
"type": "string",
|
|
481
|
-
"minLength": 1
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
},
|
|
485
|
-
"additionalProperties": false
|
|
486
|
-
},
|
|
487
|
-
"enable": {
|
|
488
|
-
"type": "boolean",
|
|
489
|
-
"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.",
|
|
490
|
-
"deprecated": true
|
|
491
358
|
}
|
|
492
359
|
},
|
|
493
360
|
"additionalProperties": false
|
|
@@ -498,23 +365,24 @@
|
|
|
498
365
|
"properties": {
|
|
499
366
|
"enable": {
|
|
500
367
|
"type": "boolean",
|
|
501
|
-
"description": "
|
|
368
|
+
"description": "Enable VPC for Lambda functions",
|
|
502
369
|
"default": false
|
|
503
370
|
},
|
|
504
371
|
"management": {
|
|
505
372
|
"type": "string",
|
|
506
|
-
"description": "How
|
|
507
|
-
"enum": ["discover", "create-new", "
|
|
373
|
+
"description": "How to manage VPC infrastructure",
|
|
374
|
+
"enum": ["discover", "create-new", "existing"],
|
|
375
|
+
"default": "discover"
|
|
508
376
|
},
|
|
509
377
|
"vpcId": {
|
|
510
378
|
"type": "string",
|
|
511
|
-
"description": "Existing VPC ID (
|
|
379
|
+
"description": "Existing VPC ID (when management='existing')",
|
|
512
380
|
"pattern": "^vpc-[a-z0-9]+$",
|
|
513
381
|
"examples": ["vpc-abc123"]
|
|
514
382
|
},
|
|
515
383
|
"cidrBlock": {
|
|
516
384
|
"type": "string",
|
|
517
|
-
"description": "CIDR block for
|
|
385
|
+
"description": "CIDR block for VPC (when management='create-new')",
|
|
518
386
|
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",
|
|
519
387
|
"default": "10.0.0.0/16"
|
|
520
388
|
},
|
|
@@ -525,9 +393,7 @@
|
|
|
525
393
|
"type": "string",
|
|
526
394
|
"pattern": "^sg-[a-z0-9]+$"
|
|
527
395
|
},
|
|
528
|
-
"examples": [
|
|
529
|
-
["sg-abc123", "sg-def456"]
|
|
530
|
-
]
|
|
396
|
+
"examples": [["sg-abc123", "sg-def456"]]
|
|
531
397
|
},
|
|
532
398
|
"subnets": {
|
|
533
399
|
"type": "object",
|
|
@@ -535,20 +401,19 @@
|
|
|
535
401
|
"properties": {
|
|
536
402
|
"management": {
|
|
537
403
|
"type": "string",
|
|
538
|
-
"description": "
|
|
539
|
-
"enum": ["
|
|
404
|
+
"description": "How to manage subnets",
|
|
405
|
+
"enum": ["discover", "create-new", "existing"],
|
|
406
|
+
"default": "discover"
|
|
540
407
|
},
|
|
541
408
|
"ids": {
|
|
542
409
|
"type": "array",
|
|
543
|
-
"description": "Existing subnet IDs
|
|
410
|
+
"description": "Existing subnet IDs",
|
|
544
411
|
"items": {
|
|
545
412
|
"type": "string",
|
|
546
413
|
"pattern": "^subnet-[a-z0-9]+$"
|
|
547
414
|
},
|
|
548
415
|
"minItems": 2,
|
|
549
|
-
"examples": [
|
|
550
|
-
["subnet-abc123", "subnet-def456"]
|
|
551
|
-
]
|
|
416
|
+
"examples": [["subnet-abc123", "subnet-def456"]]
|
|
552
417
|
}
|
|
553
418
|
},
|
|
554
419
|
"additionalProperties": false
|
|
@@ -559,12 +424,13 @@
|
|
|
559
424
|
"properties": {
|
|
560
425
|
"management": {
|
|
561
426
|
"type": "string",
|
|
562
|
-
"description": "
|
|
563
|
-
"enum": ["
|
|
427
|
+
"description": "How to manage NAT Gateway",
|
|
428
|
+
"enum": ["discover", "create-new", "existing"],
|
|
429
|
+
"default": "discover"
|
|
564
430
|
},
|
|
565
431
|
"id": {
|
|
566
432
|
"type": "string",
|
|
567
|
-
"description": "Existing NAT Gateway ID
|
|
433
|
+
"description": "Existing NAT Gateway ID",
|
|
568
434
|
"pattern": "^nat-[a-z0-9]+$",
|
|
569
435
|
"examples": ["nat-abc123"]
|
|
570
436
|
}
|
|
@@ -573,112 +439,13 @@
|
|
|
573
439
|
},
|
|
574
440
|
"enableVPCEndpoints": {
|
|
575
441
|
"type": "boolean",
|
|
576
|
-
"description": "Create VPC endpoints for AWS services (S3, DynamoDB, KMS, Secrets Manager)
|
|
442
|
+
"description": "Create VPC endpoints for AWS services (S3, DynamoDB, KMS, Secrets Manager)",
|
|
577
443
|
"default": true
|
|
578
444
|
},
|
|
579
445
|
"selfHeal": {
|
|
580
446
|
"type": "boolean",
|
|
581
|
-
"description": "
|
|
582
|
-
|
|
583
|
-
"shareAcrossStages": {
|
|
584
|
-
"type": "boolean",
|
|
585
|
-
"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."
|
|
586
|
-
},
|
|
587
|
-
"ownership": {
|
|
588
|
-
"type": "object",
|
|
589
|
-
"description": "Per-resource ownership. When set, management, subnets, natGateway, shareAcrossStages, enableVPCEndpoints and selfHeal are not translated; use `config` instead.",
|
|
590
|
-
"properties": {
|
|
591
|
-
"vpc": {
|
|
592
|
-
"type": "string",
|
|
593
|
-
"enum": ["stack", "external", "auto"],
|
|
594
|
-
"description": "VPC. Who owns the resource: 'stack' (this stack creates it), 'external' (use the id in `external`), 'auto' (reuse what discovery finds, else create)"
|
|
595
|
-
},
|
|
596
|
-
"securityGroup": {
|
|
597
|
-
"type": "string",
|
|
598
|
-
"enum": ["stack", "external", "auto"],
|
|
599
|
-
"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)"
|
|
600
|
-
},
|
|
601
|
-
"subnets": {
|
|
602
|
-
"type": "string",
|
|
603
|
-
"enum": ["stack", "external", "auto"],
|
|
604
|
-
"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)"
|
|
605
|
-
},
|
|
606
|
-
"natGateway": {
|
|
607
|
-
"type": "string",
|
|
608
|
-
"enum": ["stack", "external", "auto"],
|
|
609
|
-
"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)"
|
|
610
|
-
},
|
|
611
|
-
"vpcEndpoints": {
|
|
612
|
-
"type": "string",
|
|
613
|
-
"enum": ["stack", "external", "auto"],
|
|
614
|
-
"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)"
|
|
615
|
-
}
|
|
616
|
-
},
|
|
617
|
-
"additionalProperties": false
|
|
618
|
-
},
|
|
619
|
-
"external": {
|
|
620
|
-
"type": "object",
|
|
621
|
-
"description": "Ids of externally owned resources (ownership 'external'); discovered ids are used when omitted",
|
|
622
|
-
"properties": {
|
|
623
|
-
"vpcId": {
|
|
624
|
-
"type": "string",
|
|
625
|
-
"pattern": "^vpc-[a-z0-9]+$"
|
|
626
|
-
},
|
|
627
|
-
"securityGroupIds": {
|
|
628
|
-
"type": "array",
|
|
629
|
-
"items": {
|
|
630
|
-
"type": "string",
|
|
631
|
-
"pattern": "^sg-[a-z0-9]+$"
|
|
632
|
-
}
|
|
633
|
-
},
|
|
634
|
-
"subnetIds": {
|
|
635
|
-
"type": "array",
|
|
636
|
-
"items": {
|
|
637
|
-
"type": "string",
|
|
638
|
-
"pattern": "^subnet-[a-z0-9]+$"
|
|
639
|
-
}
|
|
640
|
-
},
|
|
641
|
-
"natGatewayId": {
|
|
642
|
-
"type": "string",
|
|
643
|
-
"pattern": "^nat-[a-z0-9]+$"
|
|
644
|
-
},
|
|
645
|
-
"vpcEndpointIds": {
|
|
646
|
-
"type": "object",
|
|
647
|
-
"description": "Endpoint ids by type (s3, dynamodb, kms, secretsManager, sqs)",
|
|
648
|
-
"additionalProperties": {"type": "string"}
|
|
649
|
-
}
|
|
650
|
-
},
|
|
651
|
-
"additionalProperties": false
|
|
652
|
-
},
|
|
653
|
-
"config": {
|
|
654
|
-
"type": "object",
|
|
655
|
-
"description": "Settings for the ownership-based VPC configuration",
|
|
656
|
-
"properties": {
|
|
657
|
-
"cidrBlock": {
|
|
658
|
-
"type": "string",
|
|
659
|
-
"description": "CIDR block for a VPC Frigg creates (wins over vpc.cidrBlock)",
|
|
660
|
-
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$"
|
|
661
|
-
},
|
|
662
|
-
"selfHeal": {
|
|
663
|
-
"type": "boolean",
|
|
664
|
-
"description": "Recreate missing stack-owned subnets. Enabled unless false."
|
|
665
|
-
},
|
|
666
|
-
"natGateway": {
|
|
667
|
-
"type": "object",
|
|
668
|
-
"properties": {
|
|
669
|
-
"enable": {
|
|
670
|
-
"type": "boolean",
|
|
671
|
-
"description": "Resolve a NAT gateway. Enabled unless false."
|
|
672
|
-
}
|
|
673
|
-
},
|
|
674
|
-
"additionalProperties": false
|
|
675
|
-
},
|
|
676
|
-
"enableVpcEndpoints": {
|
|
677
|
-
"type": "boolean",
|
|
678
|
-
"description": "Create VPC endpoints. Enabled unless false."
|
|
679
|
-
}
|
|
680
|
-
},
|
|
681
|
-
"additionalProperties": false
|
|
447
|
+
"description": "Automatically fix VPC configuration issues",
|
|
448
|
+
"default": false
|
|
682
449
|
}
|
|
683
450
|
},
|
|
684
451
|
"additionalProperties": false
|
|
@@ -723,7 +490,9 @@
|
|
|
723
490
|
"enum": ["standard", "advanced"],
|
|
724
491
|
"default": "standard"
|
|
725
492
|
},
|
|
726
|
-
"description": {
|
|
493
|
+
"description": {
|
|
494
|
+
"type": "string"
|
|
495
|
+
}
|
|
727
496
|
}
|
|
728
497
|
}
|
|
729
498
|
},
|
|
@@ -734,15 +503,15 @@
|
|
|
734
503
|
},
|
|
735
504
|
"secretsManager": {
|
|
736
505
|
"type": "object",
|
|
737
|
-
"description": "AWS Secrets Manager configuration
|
|
506
|
+
"description": "AWS Secrets Manager configuration",
|
|
738
507
|
"properties": {
|
|
739
508
|
"enable": {
|
|
740
509
|
"type": "boolean",
|
|
741
|
-
"description": "Enable AWS Secrets Manager for secure credential storage"
|
|
510
|
+
"description": "Enable AWS Secrets Manager for secure credential storage",
|
|
511
|
+
"default": false
|
|
742
512
|
}
|
|
743
513
|
},
|
|
744
|
-
"additionalProperties": false
|
|
745
|
-
"deprecated": true
|
|
514
|
+
"additionalProperties": false
|
|
746
515
|
},
|
|
747
516
|
"lambda": {
|
|
748
517
|
"type": "object",
|
|
@@ -752,11 +521,6 @@
|
|
|
752
521
|
"type": "boolean",
|
|
753
522
|
"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",
|
|
754
523
|
"default": false
|
|
755
|
-
},
|
|
756
|
-
"keepNestedNodeModules": {
|
|
757
|
-
"type": "boolean",
|
|
758
|
-
"description": "Keep nested node_modules in function packages (nested Frigg, AWS SDK and Prisma packages are still excluded). Set false to exclude every nested node_modules",
|
|
759
|
-
"default": true
|
|
760
524
|
}
|
|
761
525
|
},
|
|
762
526
|
"additionalProperties": false
|
|
@@ -772,15 +536,15 @@
|
|
|
772
536
|
},
|
|
773
537
|
"routeSelectionExpression": {
|
|
774
538
|
"type": "string",
|
|
775
|
-
"description": "Route selection expression for WebSocket
|
|
776
|
-
"
|
|
539
|
+
"description": "Route selection expression for WebSocket",
|
|
540
|
+
"default": "$request.body.action"
|
|
777
541
|
}
|
|
778
542
|
},
|
|
779
543
|
"additionalProperties": false
|
|
780
544
|
},
|
|
781
545
|
"security": {
|
|
782
546
|
"type": "object",
|
|
783
|
-
"description": "Security settings for the application
|
|
547
|
+
"description": "Security settings for the application",
|
|
784
548
|
"properties": {
|
|
785
549
|
"cors": {
|
|
786
550
|
"type": "object",
|
|
@@ -789,17 +553,16 @@
|
|
|
789
553
|
"origin": {
|
|
790
554
|
"oneOf": [
|
|
791
555
|
{"type": "string"},
|
|
792
|
-
{
|
|
793
|
-
"type": "array",
|
|
794
|
-
"items": {"type": "string"}
|
|
795
|
-
},
|
|
556
|
+
{"type": "array", "items": {"type": "string"}},
|
|
796
557
|
{"type": "boolean"}
|
|
797
558
|
],
|
|
798
|
-
"description": "Allowed origins for CORS requests"
|
|
559
|
+
"description": "Allowed origins for CORS requests",
|
|
560
|
+
"default": "http://localhost:3000"
|
|
799
561
|
},
|
|
800
562
|
"credentials": {
|
|
801
563
|
"type": "boolean",
|
|
802
|
-
"description": "Allow credentials in CORS requests"
|
|
564
|
+
"description": "Allow credentials in CORS requests",
|
|
565
|
+
"default": true
|
|
803
566
|
},
|
|
804
567
|
"methods": {
|
|
805
568
|
"type": "array",
|
|
@@ -824,23 +587,24 @@
|
|
|
824
587
|
"windowMs": {
|
|
825
588
|
"type": "integer",
|
|
826
589
|
"description": "Time window in milliseconds",
|
|
827
|
-
"minimum": 1000
|
|
590
|
+
"minimum": 1000,
|
|
591
|
+
"default": 900000
|
|
828
592
|
},
|
|
829
593
|
"max": {
|
|
830
|
-
"type": "integer",
|
|
594
|
+
"type": "integer",
|
|
831
595
|
"description": "Maximum requests per window",
|
|
832
|
-
"minimum": 1
|
|
596
|
+
"minimum": 1,
|
|
597
|
+
"default": 100
|
|
833
598
|
}
|
|
834
599
|
},
|
|
835
600
|
"additionalProperties": false
|
|
836
601
|
}
|
|
837
602
|
},
|
|
838
|
-
"additionalProperties": false
|
|
839
|
-
"deprecated": true
|
|
603
|
+
"additionalProperties": false
|
|
840
604
|
},
|
|
841
605
|
"webhooks": {
|
|
842
606
|
"type": "object",
|
|
843
|
-
"description": "Webhook handling configuration
|
|
607
|
+
"description": "Webhook handling configuration",
|
|
844
608
|
"properties": {
|
|
845
609
|
"secret": {
|
|
846
610
|
"type": "string",
|
|
@@ -849,11 +613,11 @@
|
|
|
849
613
|
"prefix": {
|
|
850
614
|
"type": "string",
|
|
851
615
|
"description": "Webhook endpoint prefix",
|
|
852
|
-
"pattern": "^/[a-zA-Z0-9/_-]*$"
|
|
616
|
+
"pattern": "^/[a-zA-Z0-9/_-]*$",
|
|
617
|
+
"default": "/webhooks"
|
|
853
618
|
}
|
|
854
619
|
},
|
|
855
|
-
"additionalProperties": false
|
|
856
|
-
"deprecated": true
|
|
620
|
+
"additionalProperties": false
|
|
857
621
|
},
|
|
858
622
|
"logging": {
|
|
859
623
|
"type": "object",
|
|
@@ -861,8 +625,9 @@
|
|
|
861
625
|
"properties": {
|
|
862
626
|
"level": {
|
|
863
627
|
"type": "string",
|
|
864
|
-
"description": "Minimum log level, in lower or upper case. Sets FRIGG_LOG_LEVEL (when not info) and the Lambda application log level.
|
|
865
|
-
"enum": ["trace", "debug", "info", "warn", "error", "fatal", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"]
|
|
628
|
+
"description": "Minimum log level, in lower or upper case. Sets FRIGG_LOG_LEVEL (when not info) and the Lambda application log level.",
|
|
629
|
+
"enum": ["trace", "debug", "info", "warn", "error", "fatal", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"],
|
|
630
|
+
"default": "info"
|
|
866
631
|
},
|
|
867
632
|
"retentionInDays": {
|
|
868
633
|
"type": "integer",
|
|
@@ -871,225 +636,46 @@
|
|
|
871
636
|
},
|
|
872
637
|
"format": {
|
|
873
638
|
"type": "string",
|
|
874
|
-
"description": "Log format. Records are always JSON lines
|
|
875
|
-
"enum": ["json"]
|
|
876
|
-
|
|
877
|
-
},
|
|
878
|
-
"additionalProperties": false
|
|
879
|
-
},
|
|
880
|
-
"scheduler": {
|
|
881
|
-
"type": "object",
|
|
882
|
-
"description": "EventBridge Scheduler resources for one-time jobs. Also enabled automatically when an integration declares webhooks.",
|
|
883
|
-
"properties": {
|
|
884
|
-
"enable": {
|
|
885
|
-
"type": "boolean",
|
|
886
|
-
"description": "Provision the scheduler role and dead-letter queue",
|
|
887
|
-
"default": false
|
|
888
|
-
}
|
|
889
|
-
},
|
|
890
|
-
"additionalProperties": false
|
|
891
|
-
},
|
|
892
|
-
"aws": {
|
|
893
|
-
"type": "object",
|
|
894
|
-
"description": "AWS options for the build",
|
|
895
|
-
"properties": {
|
|
896
|
-
"discovery": {
|
|
897
|
-
"type": "object",
|
|
898
|
-
"description": "AWS resource discovery during build/deploy",
|
|
899
|
-
"properties": {
|
|
900
|
-
"enabled": {
|
|
901
|
-
"type": "boolean",
|
|
902
|
-
"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."
|
|
903
|
-
},
|
|
904
|
-
"failOnError": {
|
|
905
|
-
"type": "boolean",
|
|
906
|
-
"description": "Fail the build when discovery fails",
|
|
907
|
-
"default": false
|
|
908
|
-
}
|
|
909
|
-
},
|
|
910
|
-
"additionalProperties": false
|
|
911
|
-
}
|
|
912
|
-
},
|
|
913
|
-
"additionalProperties": false
|
|
914
|
-
},
|
|
915
|
-
"migration": {
|
|
916
|
-
"type": "object",
|
|
917
|
-
"description": "Database migration resources",
|
|
918
|
-
"properties": {
|
|
919
|
-
"ownership": {
|
|
920
|
-
"type": "object",
|
|
921
|
-
"properties": {
|
|
922
|
-
"bucket": {
|
|
923
|
-
"type": "string",
|
|
924
|
-
"enum": ["stack", "external", "auto"],
|
|
925
|
-
"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)"
|
|
926
|
-
},
|
|
927
|
-
"queue": {
|
|
928
|
-
"type": "string",
|
|
929
|
-
"enum": ["stack", "external", "auto"],
|
|
930
|
-
"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)"
|
|
931
|
-
}
|
|
932
|
-
},
|
|
933
|
-
"additionalProperties": false
|
|
934
|
-
}
|
|
935
|
-
},
|
|
936
|
-
"additionalProperties": false
|
|
937
|
-
},
|
|
938
|
-
"telemetry": {
|
|
939
|
-
"type": "object",
|
|
940
|
-
"description": "Telemetry and usage tracking (ADR-011). An invalid block disables telemetry at runtime instead of failing.",
|
|
941
|
-
"properties": {
|
|
942
|
-
"exporter": {
|
|
943
|
-
"type": "object",
|
|
944
|
-
"description": "Where traces and metrics go. When omitted: 'console' for STAGE=local, else 'none'.",
|
|
945
|
-
"properties": {
|
|
946
|
-
"type": {
|
|
947
|
-
"type": "string",
|
|
948
|
-
"enum": ["none", "noop", "console", "otlp", "honeycomb", "datadog"]
|
|
949
|
-
},
|
|
950
|
-
"endpoint": {
|
|
951
|
-
"type": "string",
|
|
952
|
-
"description": "OTLP endpoint (honeycomb defaults to https://api.honeycomb.io)"
|
|
953
|
-
},
|
|
954
|
-
"headers": {
|
|
955
|
-
"type": "object",
|
|
956
|
-
"additionalProperties": {"type": "string"}
|
|
957
|
-
},
|
|
958
|
-
"apiKey": {
|
|
959
|
-
"type": "string",
|
|
960
|
-
"description": "Honeycomb API key (sent as x-honeycomb-team)"
|
|
961
|
-
},
|
|
962
|
-
"traceExporter": {
|
|
963
|
-
"description": "A pre-built OTel trace exporter instance (advanced)"
|
|
964
|
-
},
|
|
965
|
-
"metricExporter": {
|
|
966
|
-
"description": "A pre-built OTel metric exporter instance (advanced)"
|
|
967
|
-
}
|
|
968
|
-
},
|
|
969
|
-
"additionalProperties": false
|
|
970
|
-
},
|
|
971
|
-
"sampleRatio": {
|
|
972
|
-
"type": "number",
|
|
973
|
-
"description": "Fraction of traces exported",
|
|
974
|
-
"minimum": 0,
|
|
975
|
-
"maximum": 1,
|
|
976
|
-
"default": 1
|
|
977
|
-
},
|
|
978
|
-
"northStar": {
|
|
979
|
-
"type": "object",
|
|
980
|
-
"description": "The usage counter that measures each integration type's value: { default: { name }, byType: { <type>: { name } } }",
|
|
981
|
-
"properties": {
|
|
982
|
-
"default": {
|
|
983
|
-
"type": "object",
|
|
984
|
-
"required": ["name"],
|
|
985
|
-
"properties": {
|
|
986
|
-
"name": {"type": "string"}
|
|
987
|
-
}
|
|
988
|
-
},
|
|
989
|
-
"byType": {
|
|
990
|
-
"type": "object",
|
|
991
|
-
"additionalProperties": {
|
|
992
|
-
"type": "object",
|
|
993
|
-
"required": ["name"],
|
|
994
|
-
"properties": {
|
|
995
|
-
"name": {"type": "string"}
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
},
|
|
1000
|
-
"additionalProperties": false
|
|
1001
|
-
},
|
|
1002
|
-
"subscribers": {
|
|
1003
|
-
"type": "array",
|
|
1004
|
-
"description": "Telemetry event subscribers: functions or { handler } objects",
|
|
1005
|
-
"items": {
|
|
1006
|
-
"description": "A function or { handler }"
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
},
|
|
1010
|
-
"additionalProperties": false
|
|
1011
|
-
},
|
|
1012
|
-
"admin": {
|
|
1013
|
-
"type": "object",
|
|
1014
|
-
"description": "Admin Script Runner options (ADR-005, ADR-010)",
|
|
1015
|
-
"properties": {
|
|
1016
|
-
"includeBuiltinReports": {
|
|
1017
|
-
"type": "boolean",
|
|
1018
|
-
"description": "Register Frigg's built-in reports",
|
|
1019
|
-
"default": false
|
|
1020
|
-
},
|
|
1021
|
-
"enableScheduling": {
|
|
1022
|
-
"type": "boolean",
|
|
1023
|
-
"description": "Provision scheduling for admin scripts"
|
|
1024
|
-
}
|
|
1025
|
-
},
|
|
1026
|
-
"additionalProperties": false
|
|
1027
|
-
},
|
|
1028
|
-
"adminScripts": {
|
|
1029
|
-
"type": "array",
|
|
1030
|
-
"description": "Admin script classes (each with a static Definition). Validators see each class as { Definition }.",
|
|
1031
|
-
"items": {
|
|
1032
|
-
"type": "object",
|
|
1033
|
-
"required": ["Definition"],
|
|
1034
|
-
"properties": {
|
|
1035
|
-
"Definition": {"type": "object"}
|
|
1036
|
-
}
|
|
1037
|
-
},
|
|
1038
|
-
"default": []
|
|
1039
|
-
},
|
|
1040
|
-
"reports": {
|
|
1041
|
-
"type": "array",
|
|
1042
|
-
"description": "Report classes (each with a static Definition). Validators see each class as { Definition }.",
|
|
1043
|
-
"items": {
|
|
1044
|
-
"type": "object",
|
|
1045
|
-
"required": ["Definition"],
|
|
1046
|
-
"properties": {
|
|
1047
|
-
"Definition": {"type": "object"}
|
|
1048
|
-
}
|
|
1049
|
-
},
|
|
1050
|
-
"default": []
|
|
1051
|
-
},
|
|
1052
|
-
"deployment": {
|
|
1053
|
-
"type": "object",
|
|
1054
|
-
"description": "`frigg deploy` options",
|
|
1055
|
-
"properties": {
|
|
1056
|
-
"skipPostDeploymentHealthCheck": {
|
|
1057
|
-
"type": "boolean",
|
|
1058
|
-
"description": "Skip `frigg doctor` after a deploy",
|
|
1059
|
-
"default": false
|
|
639
|
+
"description": "Log format. Records are always JSON lines.",
|
|
640
|
+
"enum": ["json"],
|
|
641
|
+
"default": "json"
|
|
1060
642
|
}
|
|
1061
643
|
},
|
|
1062
644
|
"additionalProperties": false
|
|
1063
645
|
},
|
|
1064
646
|
"custom": {
|
|
1065
647
|
"type": "object",
|
|
1066
|
-
"description": "Custom application-specific configuration
|
|
648
|
+
"description": "Custom application-specific configuration",
|
|
1067
649
|
"properties": {
|
|
1068
650
|
"appName": {
|
|
1069
651
|
"type": "string",
|
|
1070
|
-
"description": "Application display name"
|
|
652
|
+
"description": "Application display name",
|
|
653
|
+
"default": "My Frigg Application"
|
|
1071
654
|
},
|
|
1072
655
|
"version": {
|
|
1073
656
|
"type": "string",
|
|
1074
657
|
"description": "Application version",
|
|
1075
|
-
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$"
|
|
658
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$",
|
|
659
|
+
"default": "1.0.0"
|
|
1076
660
|
},
|
|
1077
661
|
"environment": {
|
|
1078
662
|
"type": "string",
|
|
1079
663
|
"description": "Deployment environment/stage",
|
|
1080
|
-
"enum": ["development", "staging", "production", "test"]
|
|
664
|
+
"enum": ["development", "staging", "production", "test"],
|
|
665
|
+
"default": "development"
|
|
1081
666
|
},
|
|
1082
667
|
"features": {
|
|
1083
668
|
"type": "object",
|
|
1084
669
|
"description": "Feature flags and toggles",
|
|
1085
670
|
"patternProperties": {
|
|
1086
|
-
"^[a-zA-Z][a-zA-Z0-9_]*$": {
|
|
671
|
+
"^[a-zA-Z][a-zA-Z0-9_]*$": {
|
|
672
|
+
"type": "boolean"
|
|
673
|
+
}
|
|
1087
674
|
},
|
|
1088
675
|
"additionalProperties": false
|
|
1089
676
|
}
|
|
1090
677
|
},
|
|
1091
|
-
"additionalProperties": true
|
|
1092
|
-
"deprecated": true
|
|
678
|
+
"additionalProperties": true
|
|
1093
679
|
}
|
|
1094
680
|
},
|
|
1095
681
|
"additionalProperties": false,
|
|
@@ -1103,15 +689,12 @@
|
|
|
1103
689
|
},
|
|
1104
690
|
"integrations": [],
|
|
1105
691
|
"user": {
|
|
1106
|
-
"
|
|
1107
|
-
"primary": "individual",
|
|
1108
|
-
"individualUserRequired": true,
|
|
1109
|
-
"organizationUserRequired": false
|
|
692
|
+
"password": true
|
|
1110
693
|
},
|
|
1111
694
|
"database": {
|
|
1112
695
|
"postgres": {
|
|
1113
696
|
"enable": true,
|
|
1114
|
-
"management": "
|
|
697
|
+
"management": "create-new"
|
|
1115
698
|
}
|
|
1116
699
|
},
|
|
1117
700
|
"encryption": {
|
|
@@ -1124,8 +707,18 @@
|
|
|
1124
707
|
"cidrBlock": "10.0.0.0/16",
|
|
1125
708
|
"enableVPCEndpoints": true
|
|
1126
709
|
},
|
|
1127
|
-
"ssm": {
|
|
1128
|
-
|
|
710
|
+
"ssm": {
|
|
711
|
+
"enable": true
|
|
712
|
+
},
|
|
713
|
+
"websockets": {
|
|
714
|
+
"enable": true
|
|
715
|
+
},
|
|
716
|
+
"security": {
|
|
717
|
+
"cors": {
|
|
718
|
+
"origin": "http://localhost:3000",
|
|
719
|
+
"credentials": true
|
|
720
|
+
}
|
|
721
|
+
},
|
|
1129
722
|
"logging": {
|
|
1130
723
|
"level": "info",
|
|
1131
724
|
"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
|
-
};
|