@friggframework/schemas 2.0.0--canary.701.00d6b2c.0 → 2.0.0--canary.702.3f342da.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 +26 -0
- package/app-definition.js +113 -0
- package/index.js +14 -2
- package/package.json +3 -2
- package/schemas/app-definition.schema.json +533 -130
package/README.md
CHANGED
|
@@ -41,6 +41,32 @@ 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
|
+
|
|
44
70
|
### Advanced Validation
|
|
45
71
|
|
|
46
72
|
```javascript
|
|
@@ -0,0 +1,113 @@
|
|
|
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
|
+
};
|
package/index.js
CHANGED
|
@@ -12,6 +12,10 @@ 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');
|
|
15
19
|
const {
|
|
16
20
|
toApiModuleDefinitionSchemaView,
|
|
17
21
|
} = require('./api-module-definition');
|
|
@@ -79,7 +83,13 @@ function validate(schemaName, data) {
|
|
|
79
83
|
* @returns {object} - Validation result
|
|
80
84
|
*/
|
|
81
85
|
function validateAppDefinition(appDefinition) {
|
|
82
|
-
|
|
86
|
+
// Apps list integration classes, which JSON Schema cannot describe:
|
|
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 };
|
|
83
93
|
}
|
|
84
94
|
|
|
85
95
|
/**
|
|
@@ -94,7 +104,7 @@ function validateIntegrationDefinition(integrationDefinition) {
|
|
|
94
104
|
/**
|
|
95
105
|
* Validate API Module Definition.
|
|
96
106
|
* Real Definitions carry classes and functions; validate the serialisable
|
|
97
|
-
* view and return the original definition.
|
|
107
|
+
* view and return the original definition (same pattern as validateAppDefinition).
|
|
98
108
|
* @param {object} apiModuleDefinition - API module definition object to validate
|
|
99
109
|
* @returns {object} - Validation result
|
|
100
110
|
*/
|
|
@@ -366,6 +376,8 @@ module.exports = {
|
|
|
366
376
|
// Validation functions
|
|
367
377
|
validate,
|
|
368
378
|
validateAppDefinition,
|
|
379
|
+
applyAppDefinitionDefaults,
|
|
380
|
+
toAppDefinitionSchemaView,
|
|
369
381
|
toApiModuleDefinitionSchemaView,
|
|
370
382
|
validateIntegrationDefinition,
|
|
371
383
|
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.702.3f342da.0",
|
|
4
4
|
"description": "Canonical JSON Schema definitions for Frigg Framework",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "",
|
|
@@ -39,8 +39,9 @@
|
|
|
39
39
|
"validators/",
|
|
40
40
|
"mocks/",
|
|
41
41
|
"middleware/",
|
|
42
|
+
"app-definition.js",
|
|
42
43
|
"api-module-definition.js",
|
|
43
44
|
"index.js"
|
|
44
45
|
],
|
|
45
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "3f342daf8aac3124f25936bb8b327b447024ca4c"
|
|
46
47
|
}
|
|
@@ -22,22 +22,35 @@
|
|
|
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. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
26
26
|
"minLength": 1,
|
|
27
27
|
"maxLength": 200,
|
|
28
|
-
"examples": ["My Frigg Application", "Customer Portal Integrations"]
|
|
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`."
|
|
29
39
|
},
|
|
30
40
|
"managementMode": {
|
|
31
41
|
"type": "string",
|
|
32
|
-
"description": "Infrastructure management mode
|
|
33
|
-
"enum": ["managed", "discover", "custom"]
|
|
34
|
-
"default": "managed"
|
|
42
|
+
"description": "Infrastructure management mode. 'managed': Frigg creates and owns the VPC, database and KMS key it needs (with vpcIsolation 'isolated', per stage). 'existing': use existing resources given by id. 'discover' (also the behaviour when omitted): find existing resources and create what is missing. 'custom' is accepted for compatibility and behaves like 'discover'.",
|
|
43
|
+
"enum": ["managed", "discover", "existing", "custom"]
|
|
35
44
|
},
|
|
36
45
|
"vpcIsolation": {
|
|
37
46
|
"type": "string",
|
|
38
|
-
"description": "
|
|
39
|
-
"enum": ["isolated", "shared"]
|
|
40
|
-
|
|
47
|
+
"description": "With managementMode 'managed': 'isolated' gives each stage its own VPC, database and key; 'shared' reuses them across stages. Set it explicitly: when it is omitted the builders do not agree on a default (see ADR-051).",
|
|
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
|
|
41
54
|
},
|
|
42
55
|
"environment": {
|
|
43
56
|
"type": "object",
|
|
@@ -68,10 +81,17 @@
|
|
|
68
81
|
},
|
|
69
82
|
"integrations": {
|
|
70
83
|
"type": "array",
|
|
71
|
-
"description": "
|
|
84
|
+
"description": "The IntegrationBase subclasses this application exposes. JSON Schema cannot describe a JavaScript class, so validateAppDefinition checks a serialisable view in which each class is replaced by { Definition: <its static Definition> }; `frigg validate` checks each Definition structurally (name, version, modules and their API module definitions).",
|
|
72
85
|
"items": {
|
|
73
86
|
"type": "object",
|
|
74
|
-
"description": "
|
|
87
|
+
"description": "An integration class, seen as { Definition } (see the integrations 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
|
+
}
|
|
75
95
|
},
|
|
76
96
|
"default": []
|
|
77
97
|
},
|
|
@@ -110,51 +130,56 @@
|
|
|
110
130
|
},
|
|
111
131
|
"user": {
|
|
112
132
|
"type": "object",
|
|
113
|
-
"description": "User management and authentication
|
|
133
|
+
"description": "User management and authentication. Read by core when it loads the app definition; an omitted block gets the defaults below (ADR-051).",
|
|
114
134
|
"properties": {
|
|
115
135
|
"usePassword": {
|
|
116
136
|
"type": "boolean",
|
|
117
|
-
"description": "
|
|
118
|
-
"default":
|
|
137
|
+
"description": "Users log in with username and password (POST /user/login). false: users are identified by appUserId (x-frigg-appuserid) instead.",
|
|
138
|
+
"default": false
|
|
119
139
|
},
|
|
120
140
|
"password": {
|
|
121
141
|
"type": "boolean",
|
|
122
|
-
"description": "DEPRECATED:
|
|
123
|
-
"
|
|
142
|
+
"description": "DEPRECATED alias of usePassword: when usePassword is not set, the loader copies this value into it.",
|
|
143
|
+
"deprecated": true
|
|
124
144
|
},
|
|
125
145
|
"primary": {
|
|
126
146
|
"type": "string",
|
|
127
|
-
"description": "Primary user type
|
|
147
|
+
"description": "Primary user type. Any value other than 'organization' is treated as 'individual'.",
|
|
128
148
|
"enum": ["individual", "organization"],
|
|
129
149
|
"default": "individual"
|
|
130
150
|
},
|
|
131
151
|
"individualUserRequired": {
|
|
132
152
|
"type": "boolean",
|
|
133
|
-
"description": "Require individual user
|
|
153
|
+
"description": "Require an individual user. POST /user/login logs in individual users only when this is true.",
|
|
134
154
|
"default": true
|
|
135
155
|
},
|
|
136
156
|
"organizationUserRequired": {
|
|
137
157
|
"type": "boolean",
|
|
138
|
-
"description": "Require organization user
|
|
158
|
+
"description": "Require an organization user (looked up by appOrgId).",
|
|
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.",
|
|
139
164
|
"default": false
|
|
140
165
|
},
|
|
141
166
|
"authModes": {
|
|
142
167
|
"type": "object",
|
|
143
|
-
"description": "Authentication
|
|
168
|
+
"description": "Authentication modes. When the block is omitted, Frigg tokens and the shared secret are accepted. x-frigg-appUserId and x-frigg-appOrgId headers identify the user with any mode.",
|
|
144
169
|
"properties": {
|
|
145
170
|
"friggToken": {
|
|
146
171
|
"type": "boolean",
|
|
147
|
-
"description": "
|
|
172
|
+
"description": "Accept Frigg bearer tokens from /user/login. Enabled unless false.",
|
|
148
173
|
"default": true
|
|
149
174
|
},
|
|
150
175
|
"sharedSecret": {
|
|
151
176
|
"type": "boolean",
|
|
152
|
-
"description": "
|
|
153
|
-
"default":
|
|
177
|
+
"description": "Accept the x-frigg-api-key header (checked against FRIGG_API_KEY) for backend-to-backend calls. Enabled unless false.",
|
|
178
|
+
"default": true
|
|
154
179
|
},
|
|
155
180
|
"adopterJwt": {
|
|
156
181
|
"type": "boolean",
|
|
157
|
-
"description": "
|
|
182
|
+
"description": "Accept JWTs from the adopter's own auth system (requires jwtConfig). Enabled only when true.",
|
|
158
183
|
"default": false
|
|
159
184
|
}
|
|
160
185
|
},
|
|
@@ -190,22 +215,25 @@
|
|
|
190
215
|
},
|
|
191
216
|
"fields": {
|
|
192
217
|
"type": "array",
|
|
193
|
-
"description": "Additional user fields",
|
|
194
|
-
"items": {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
218
|
+
"description": "Additional user fields. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
219
|
+
"items": {"type": "string"},
|
|
220
|
+
"examples": [
|
|
221
|
+
["email", "firstName", "lastName"]
|
|
222
|
+
],
|
|
223
|
+
"deprecated": true
|
|
198
224
|
},
|
|
199
225
|
"model": {
|
|
200
226
|
"type": "object",
|
|
201
|
-
"description": "Custom user model class"
|
|
227
|
+
"description": "Custom user model class. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
228
|
+
"deprecated": true
|
|
202
229
|
}
|
|
203
230
|
},
|
|
204
|
-
"additionalProperties": false
|
|
231
|
+
"additionalProperties": false,
|
|
232
|
+
"default": {}
|
|
205
233
|
},
|
|
206
234
|
"auth": {
|
|
207
235
|
"type": "object",
|
|
208
|
-
"description": "Authentication configuration
|
|
236
|
+
"description": "Authentication configuration. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
209
237
|
"properties": {
|
|
210
238
|
"jwtSecret": {
|
|
211
239
|
"type": "string",
|
|
@@ -214,17 +242,16 @@
|
|
|
214
242
|
"tokenExpiry": {
|
|
215
243
|
"type": "string",
|
|
216
244
|
"description": "Token expiration time",
|
|
217
|
-
"pattern": "^\\d+[smhd]$"
|
|
218
|
-
"default": "24h"
|
|
245
|
+
"pattern": "^\\d+[smhd]$"
|
|
219
246
|
},
|
|
220
247
|
"refreshTokenExpiry": {
|
|
221
248
|
"type": "string",
|
|
222
|
-
"description": "Refresh token expiration time",
|
|
223
|
-
"pattern": "^\\d+[smhd]$"
|
|
224
|
-
"default": "7d"
|
|
249
|
+
"description": "Refresh token expiration time",
|
|
250
|
+
"pattern": "^\\d+[smhd]$"
|
|
225
251
|
}
|
|
226
252
|
},
|
|
227
|
-
"additionalProperties": false
|
|
253
|
+
"additionalProperties": false,
|
|
254
|
+
"deprecated": true
|
|
228
255
|
},
|
|
229
256
|
"database": {
|
|
230
257
|
"type": "object",
|
|
@@ -232,8 +259,8 @@
|
|
|
232
259
|
"properties": {
|
|
233
260
|
"uri": {
|
|
234
261
|
"type": "string",
|
|
235
|
-
"description": "Database connection URI (should be set via environment variable)",
|
|
236
|
-
"
|
|
262
|
+
"description": "Database connection URI (should be set via environment variable). Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
263
|
+
"deprecated": true
|
|
237
264
|
},
|
|
238
265
|
"mongoDB": {
|
|
239
266
|
"type": "object",
|
|
@@ -246,7 +273,8 @@
|
|
|
246
273
|
},
|
|
247
274
|
"uri": {
|
|
248
275
|
"type": "string",
|
|
249
|
-
"description": "MongoDB connection URI"
|
|
276
|
+
"description": "MongoDB connection URI. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set. The connection string comes from DATABASE_URL.",
|
|
277
|
+
"deprecated": true
|
|
250
278
|
}
|
|
251
279
|
},
|
|
252
280
|
"additionalProperties": true
|
|
@@ -274,18 +302,16 @@
|
|
|
274
302
|
"properties": {
|
|
275
303
|
"enable": {
|
|
276
304
|
"type": "boolean",
|
|
277
|
-
"description": "
|
|
278
|
-
"default": false
|
|
305
|
+
"description": "Use PostgreSQL. true provisions or discovers Aurora (unless management says otherwise). When omitted, Aurora is not provisioned, but migrations and the Prisma layer still include PostgreSQL; set false for a MongoDB/DocumentDB app."
|
|
279
306
|
},
|
|
280
307
|
"management": {
|
|
281
308
|
"type": "string",
|
|
282
|
-
"description": "How
|
|
283
|
-
"enum": ["discover", "
|
|
284
|
-
"default": "discover"
|
|
309
|
+
"description": "How Frigg gets the Aurora cluster (ignored when managementMode is 'managed' or 'existing'). 'discover' (also when omitted): find one, else create one in the stack. 'managed': create it in the stack. 'use-existing': connect to `endpoint` without creating anything.",
|
|
310
|
+
"enum": ["discover", "managed", "use-existing"]
|
|
285
311
|
},
|
|
286
312
|
"endpoint": {
|
|
287
313
|
"type": "string",
|
|
288
|
-
"description": "Existing database endpoint (when management='existing')",
|
|
314
|
+
"description": "Existing database endpoint (required when management='use-existing')",
|
|
289
315
|
"examples": ["mydb.cluster-abc123.us-east-1.rds.amazonaws.com"]
|
|
290
316
|
},
|
|
291
317
|
"port": {
|
|
@@ -303,10 +329,15 @@
|
|
|
303
329
|
"description": "Database username",
|
|
304
330
|
"default": "postgres"
|
|
305
331
|
},
|
|
332
|
+
"engineVersion": {
|
|
333
|
+
"type": "string",
|
|
334
|
+
"description": "Aurora PostgreSQL engine version for a cluster Frigg creates",
|
|
335
|
+
"default": "15.13"
|
|
336
|
+
},
|
|
306
337
|
"selfHeal": {
|
|
307
338
|
"type": "boolean",
|
|
308
|
-
"description": "Automatically fix database configuration issues",
|
|
309
|
-
"
|
|
339
|
+
"description": "Automatically fix database configuration issues. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
340
|
+
"deprecated": true
|
|
310
341
|
},
|
|
311
342
|
"publiclyAccessible": {
|
|
312
343
|
"type": "boolean",
|
|
@@ -315,7 +346,7 @@
|
|
|
315
346
|
},
|
|
316
347
|
"autoCreateCredentials": {
|
|
317
348
|
"type": "boolean",
|
|
318
|
-
"description": "
|
|
349
|
+
"description": "Create a Secrets Manager secret and rotate the Aurora password when a discovered cluster has none (management='discover' only)",
|
|
319
350
|
"default": false
|
|
320
351
|
},
|
|
321
352
|
"minCapacity": {
|
|
@@ -330,7 +361,65 @@
|
|
|
330
361
|
"description": "Maximum Aurora Serverless capacity units (0.5-128)",
|
|
331
362
|
"minimum": 0.5,
|
|
332
363
|
"maximum": 128,
|
|
333
|
-
"default":
|
|
364
|
+
"default": 4
|
|
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
|
|
334
423
|
}
|
|
335
424
|
},
|
|
336
425
|
"additionalProperties": false
|
|
@@ -344,14 +433,12 @@
|
|
|
344
433
|
"properties": {
|
|
345
434
|
"fieldLevelEncryptionMethod": {
|
|
346
435
|
"type": "string",
|
|
347
|
-
"description": "
|
|
348
|
-
"enum": ["kms", "aes"]
|
|
349
|
-
"default": "aes"
|
|
436
|
+
"description": "Field-level encryption key. 'kms': Frigg creates or discovers a KMS key and sets KMS_KEY_ARN. 'aes': the app supplies AES_KEY_ID and AES_KEY (list both in `environment`). Omitted: no key is provisioned and deployed stages store sensitive fields unencrypted (core logs a warning). Stages dev, test and local never encrypt.",
|
|
437
|
+
"enum": ["kms", "aes"]
|
|
350
438
|
},
|
|
351
439
|
"createResourceIfNoneFound": {
|
|
352
440
|
"type": "boolean",
|
|
353
|
-
"description": "
|
|
354
|
-
"default": false
|
|
441
|
+
"description": "With 'kms' outside managementMode 'managed': create a KMS key when discovery finds none. When omitted, KMS_KEY_ARN falls back to the AWS_DISCOVERY_KMS_KEY_ID environment variable."
|
|
355
442
|
},
|
|
356
443
|
"schema": {
|
|
357
444
|
"type": "object",
|
|
@@ -388,6 +475,48 @@
|
|
|
388
475
|
}
|
|
389
476
|
}
|
|
390
477
|
]
|
|
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
|
|
391
520
|
}
|
|
392
521
|
},
|
|
393
522
|
"additionalProperties": false
|
|
@@ -398,24 +527,23 @@
|
|
|
398
527
|
"properties": {
|
|
399
528
|
"enable": {
|
|
400
529
|
"type": "boolean",
|
|
401
|
-
"description": "
|
|
530
|
+
"description": "Run the Lambda functions in a VPC",
|
|
402
531
|
"default": false
|
|
403
532
|
},
|
|
404
533
|
"management": {
|
|
405
534
|
"type": "string",
|
|
406
|
-
"description": "How
|
|
407
|
-
"enum": ["discover", "create-new", "existing"]
|
|
408
|
-
"default": "discover"
|
|
535
|
+
"description": "How Frigg gets the VPC. 'discover' (also when omitted): find one (discovery fails if none exists). 'create-new': create VPC, security group and subnets in the stack. 'use-existing': use `vpcId` (and securityGroupIds / subnets.ids when given). Ignored when `ownership` is set.",
|
|
536
|
+
"enum": ["discover", "create-new", "use-existing"]
|
|
409
537
|
},
|
|
410
538
|
"vpcId": {
|
|
411
539
|
"type": "string",
|
|
412
|
-
"description": "Existing VPC ID (when management='existing')",
|
|
540
|
+
"description": "Existing VPC ID (required when management='use-existing')",
|
|
413
541
|
"pattern": "^vpc-[a-z0-9]+$",
|
|
414
542
|
"examples": ["vpc-abc123"]
|
|
415
543
|
},
|
|
416
544
|
"cidrBlock": {
|
|
417
545
|
"type": "string",
|
|
418
|
-
"description": "CIDR block for VPC
|
|
546
|
+
"description": "CIDR block for a VPC Frigg creates",
|
|
419
547
|
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",
|
|
420
548
|
"default": "10.0.0.0/16"
|
|
421
549
|
},
|
|
@@ -426,7 +554,9 @@
|
|
|
426
554
|
"type": "string",
|
|
427
555
|
"pattern": "^sg-[a-z0-9]+$"
|
|
428
556
|
},
|
|
429
|
-
"examples": [
|
|
557
|
+
"examples": [
|
|
558
|
+
["sg-abc123", "sg-def456"]
|
|
559
|
+
]
|
|
430
560
|
},
|
|
431
561
|
"subnets": {
|
|
432
562
|
"type": "object",
|
|
@@ -434,19 +564,20 @@
|
|
|
434
564
|
"properties": {
|
|
435
565
|
"management": {
|
|
436
566
|
"type": "string",
|
|
437
|
-
"description": "
|
|
438
|
-
"enum": ["discover", "create-new", "existing"]
|
|
439
|
-
"default": "discover"
|
|
567
|
+
"description": "'create': create the subnets in the stack. 'use-existing': use `ids` (at least 2). 'discover', 'create-new' and 'existing' are accepted for compatibility but have no effect (`frigg validate` warns).",
|
|
568
|
+
"enum": ["create", "use-existing", "discover", "create-new", "existing"]
|
|
440
569
|
},
|
|
441
570
|
"ids": {
|
|
442
571
|
"type": "array",
|
|
443
|
-
"description": "Existing subnet IDs",
|
|
572
|
+
"description": "Existing subnet IDs (management='use-existing')",
|
|
444
573
|
"items": {
|
|
445
574
|
"type": "string",
|
|
446
575
|
"pattern": "^subnet-[a-z0-9]+$"
|
|
447
576
|
},
|
|
448
577
|
"minItems": 2,
|
|
449
|
-
"examples": [
|
|
578
|
+
"examples": [
|
|
579
|
+
["subnet-abc123", "subnet-def456"]
|
|
580
|
+
]
|
|
450
581
|
}
|
|
451
582
|
},
|
|
452
583
|
"additionalProperties": false
|
|
@@ -457,13 +588,12 @@
|
|
|
457
588
|
"properties": {
|
|
458
589
|
"management": {
|
|
459
590
|
"type": "string",
|
|
460
|
-
"description": "
|
|
461
|
-
"enum": ["discover", "create-new", "existing"]
|
|
462
|
-
"default": "discover"
|
|
591
|
+
"description": "'createAndManage': reuse a well-placed NAT gateway or create one. 'discover', 'create-new' and 'existing' are accepted for compatibility but have no effect (`frigg validate` warns). Set `id` to use an existing NAT gateway.",
|
|
592
|
+
"enum": ["createAndManage", "discover", "create-new", "existing"]
|
|
463
593
|
},
|
|
464
594
|
"id": {
|
|
465
595
|
"type": "string",
|
|
466
|
-
"description": "Existing NAT Gateway ID",
|
|
596
|
+
"description": "Existing NAT Gateway ID (makes the NAT gateway external)",
|
|
467
597
|
"pattern": "^nat-[a-z0-9]+$",
|
|
468
598
|
"examples": ["nat-abc123"]
|
|
469
599
|
}
|
|
@@ -472,13 +602,112 @@
|
|
|
472
602
|
},
|
|
473
603
|
"enableVPCEndpoints": {
|
|
474
604
|
"type": "boolean",
|
|
475
|
-
"description": "Create VPC endpoints for AWS services (S3, DynamoDB, KMS, Secrets Manager)",
|
|
605
|
+
"description": "Create VPC endpoints for AWS services (S3, DynamoDB, KMS, Secrets Manager). Enabled unless false.",
|
|
476
606
|
"default": true
|
|
477
607
|
},
|
|
478
608
|
"selfHeal": {
|
|
479
609
|
"type": "boolean",
|
|
480
|
-
"description": "
|
|
481
|
-
|
|
610
|
+
"description": "Repair VPC configuration issues (route table associations) during discovery. When omitted, self-healing of stack-owned subnets is on."
|
|
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
|
|
482
711
|
}
|
|
483
712
|
},
|
|
484
713
|
"additionalProperties": false
|
|
@@ -523,9 +752,7 @@
|
|
|
523
752
|
"enum": ["standard", "advanced"],
|
|
524
753
|
"default": "standard"
|
|
525
754
|
},
|
|
526
|
-
"description": {
|
|
527
|
-
"type": "string"
|
|
528
|
-
}
|
|
755
|
+
"description": {"type": "string"}
|
|
529
756
|
}
|
|
530
757
|
}
|
|
531
758
|
},
|
|
@@ -536,15 +763,15 @@
|
|
|
536
763
|
},
|
|
537
764
|
"secretsManager": {
|
|
538
765
|
"type": "object",
|
|
539
|
-
"description": "AWS Secrets Manager configuration",
|
|
766
|
+
"description": "AWS Secrets Manager configuration. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
540
767
|
"properties": {
|
|
541
768
|
"enable": {
|
|
542
769
|
"type": "boolean",
|
|
543
|
-
"description": "Enable AWS Secrets Manager for secure credential storage"
|
|
544
|
-
"default": false
|
|
770
|
+
"description": "Enable AWS Secrets Manager for secure credential storage"
|
|
545
771
|
}
|
|
546
772
|
},
|
|
547
|
-
"additionalProperties": false
|
|
773
|
+
"additionalProperties": false,
|
|
774
|
+
"deprecated": true
|
|
548
775
|
},
|
|
549
776
|
"lambda": {
|
|
550
777
|
"type": "object",
|
|
@@ -554,6 +781,11 @@
|
|
|
554
781
|
"type": "boolean",
|
|
555
782
|
"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",
|
|
556
783
|
"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
|
|
557
789
|
}
|
|
558
790
|
},
|
|
559
791
|
"additionalProperties": false
|
|
@@ -569,15 +801,15 @@
|
|
|
569
801
|
},
|
|
570
802
|
"routeSelectionExpression": {
|
|
571
803
|
"type": "string",
|
|
572
|
-
"description": "Route selection expression for WebSocket",
|
|
573
|
-
"
|
|
804
|
+
"description": "Route selection expression for WebSocket. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
805
|
+
"deprecated": true
|
|
574
806
|
}
|
|
575
807
|
},
|
|
576
808
|
"additionalProperties": false
|
|
577
809
|
},
|
|
578
810
|
"security": {
|
|
579
811
|
"type": "object",
|
|
580
|
-
"description": "Security settings for the application",
|
|
812
|
+
"description": "Security settings for the application. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
581
813
|
"properties": {
|
|
582
814
|
"cors": {
|
|
583
815
|
"type": "object",
|
|
@@ -586,16 +818,17 @@
|
|
|
586
818
|
"origin": {
|
|
587
819
|
"oneOf": [
|
|
588
820
|
{"type": "string"},
|
|
589
|
-
{
|
|
821
|
+
{
|
|
822
|
+
"type": "array",
|
|
823
|
+
"items": {"type": "string"}
|
|
824
|
+
},
|
|
590
825
|
{"type": "boolean"}
|
|
591
826
|
],
|
|
592
|
-
"description": "Allowed origins for CORS requests"
|
|
593
|
-
"default": "http://localhost:3000"
|
|
827
|
+
"description": "Allowed origins for CORS requests"
|
|
594
828
|
},
|
|
595
829
|
"credentials": {
|
|
596
830
|
"type": "boolean",
|
|
597
|
-
"description": "Allow credentials in CORS requests"
|
|
598
|
-
"default": true
|
|
831
|
+
"description": "Allow credentials in CORS requests"
|
|
599
832
|
},
|
|
600
833
|
"methods": {
|
|
601
834
|
"type": "array",
|
|
@@ -620,24 +853,23 @@
|
|
|
620
853
|
"windowMs": {
|
|
621
854
|
"type": "integer",
|
|
622
855
|
"description": "Time window in milliseconds",
|
|
623
|
-
"minimum": 1000
|
|
624
|
-
"default": 900000
|
|
856
|
+
"minimum": 1000
|
|
625
857
|
},
|
|
626
858
|
"max": {
|
|
627
|
-
"type": "integer",
|
|
859
|
+
"type": "integer",
|
|
628
860
|
"description": "Maximum requests per window",
|
|
629
|
-
"minimum": 1
|
|
630
|
-
"default": 100
|
|
861
|
+
"minimum": 1
|
|
631
862
|
}
|
|
632
863
|
},
|
|
633
864
|
"additionalProperties": false
|
|
634
865
|
}
|
|
635
866
|
},
|
|
636
|
-
"additionalProperties": false
|
|
867
|
+
"additionalProperties": false,
|
|
868
|
+
"deprecated": true
|
|
637
869
|
},
|
|
638
870
|
"webhooks": {
|
|
639
871
|
"type": "object",
|
|
640
|
-
"description": "Webhook handling configuration",
|
|
872
|
+
"description": "Webhook handling configuration. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set. Webhooks are declared per integration (Definition.webhooks).",
|
|
641
873
|
"properties": {
|
|
642
874
|
"secret": {
|
|
643
875
|
"type": "string",
|
|
@@ -646,11 +878,11 @@
|
|
|
646
878
|
"prefix": {
|
|
647
879
|
"type": "string",
|
|
648
880
|
"description": "Webhook endpoint prefix",
|
|
649
|
-
"pattern": "^/[a-zA-Z0-9/_-]*$"
|
|
650
|
-
"default": "/webhooks"
|
|
881
|
+
"pattern": "^/[a-zA-Z0-9/_-]*$"
|
|
651
882
|
}
|
|
652
883
|
},
|
|
653
|
-
"additionalProperties": false
|
|
884
|
+
"additionalProperties": false,
|
|
885
|
+
"deprecated": true
|
|
654
886
|
},
|
|
655
887
|
"logging": {
|
|
656
888
|
"type": "object",
|
|
@@ -658,9 +890,8 @@
|
|
|
658
890
|
"properties": {
|
|
659
891
|
"level": {
|
|
660
892
|
"type": "string",
|
|
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"
|
|
893
|
+
"description": "Minimum log level, in lower or upper case. Sets FRIGG_LOG_LEVEL (when not info) and the Lambda application log level. When omitted, core logs at info and no Lambda log level is set.",
|
|
894
|
+
"enum": ["trace", "debug", "info", "warn", "error", "fatal", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"]
|
|
664
895
|
},
|
|
665
896
|
"retentionInDays": {
|
|
666
897
|
"type": "integer",
|
|
@@ -669,46 +900,225 @@
|
|
|
669
900
|
},
|
|
670
901
|
"format": {
|
|
671
902
|
"type": "string",
|
|
672
|
-
"description": "Log format. Records are always JSON lines.",
|
|
673
|
-
"enum": ["json"]
|
|
674
|
-
|
|
903
|
+
"description": "Log format. Records are always JSON lines; this key is informational and has no default.",
|
|
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
|
|
675
1089
|
}
|
|
676
1090
|
},
|
|
677
1091
|
"additionalProperties": false
|
|
678
1092
|
},
|
|
679
1093
|
"custom": {
|
|
680
1094
|
"type": "object",
|
|
681
|
-
"description": "Custom application-specific configuration",
|
|
1095
|
+
"description": "Custom application-specific configuration. Not read by the Frigg runtime: it has no effect. Kept so existing definitions stay valid; `frigg validate` warns when it is set.",
|
|
682
1096
|
"properties": {
|
|
683
1097
|
"appName": {
|
|
684
1098
|
"type": "string",
|
|
685
|
-
"description": "Application display name"
|
|
686
|
-
"default": "My Frigg Application"
|
|
1099
|
+
"description": "Application display name"
|
|
687
1100
|
},
|
|
688
1101
|
"version": {
|
|
689
1102
|
"type": "string",
|
|
690
1103
|
"description": "Application version",
|
|
691
|
-
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$"
|
|
692
|
-
"default": "1.0.0"
|
|
1104
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$"
|
|
693
1105
|
},
|
|
694
1106
|
"environment": {
|
|
695
1107
|
"type": "string",
|
|
696
1108
|
"description": "Deployment environment/stage",
|
|
697
|
-
"enum": ["development", "staging", "production", "test"]
|
|
698
|
-
"default": "development"
|
|
1109
|
+
"enum": ["development", "staging", "production", "test"]
|
|
699
1110
|
},
|
|
700
1111
|
"features": {
|
|
701
1112
|
"type": "object",
|
|
702
1113
|
"description": "Feature flags and toggles",
|
|
703
1114
|
"patternProperties": {
|
|
704
|
-
"^[a-zA-Z][a-zA-Z0-9_]*$": {
|
|
705
|
-
"type": "boolean"
|
|
706
|
-
}
|
|
1115
|
+
"^[a-zA-Z][a-zA-Z0-9_]*$": {"type": "boolean"}
|
|
707
1116
|
},
|
|
708
1117
|
"additionalProperties": false
|
|
709
1118
|
}
|
|
710
1119
|
},
|
|
711
|
-
"additionalProperties": true
|
|
1120
|
+
"additionalProperties": true,
|
|
1121
|
+
"deprecated": true
|
|
712
1122
|
}
|
|
713
1123
|
},
|
|
714
1124
|
"additionalProperties": false,
|
|
@@ -722,12 +1132,15 @@
|
|
|
722
1132
|
},
|
|
723
1133
|
"integrations": [],
|
|
724
1134
|
"user": {
|
|
725
|
-
"
|
|
1135
|
+
"usePassword": true,
|
|
1136
|
+
"primary": "individual",
|
|
1137
|
+
"individualUserRequired": true,
|
|
1138
|
+
"organizationUserRequired": false
|
|
726
1139
|
},
|
|
727
1140
|
"database": {
|
|
728
1141
|
"postgres": {
|
|
729
1142
|
"enable": true,
|
|
730
|
-
"management": "
|
|
1143
|
+
"management": "managed"
|
|
731
1144
|
}
|
|
732
1145
|
},
|
|
733
1146
|
"encryption": {
|
|
@@ -740,18 +1153,8 @@
|
|
|
740
1153
|
"cidrBlock": "10.0.0.0/16",
|
|
741
1154
|
"enableVPCEndpoints": true
|
|
742
1155
|
},
|
|
743
|
-
"ssm": {
|
|
744
|
-
|
|
745
|
-
},
|
|
746
|
-
"websockets": {
|
|
747
|
-
"enable": true
|
|
748
|
-
},
|
|
749
|
-
"security": {
|
|
750
|
-
"cors": {
|
|
751
|
-
"origin": "http://localhost:3000",
|
|
752
|
-
"credentials": true
|
|
753
|
-
}
|
|
754
|
-
},
|
|
1156
|
+
"ssm": {"enable": true},
|
|
1157
|
+
"websockets": {"enable": true},
|
|
755
1158
|
"logging": {
|
|
756
1159
|
"level": "info",
|
|
757
1160
|
"retentionInDays": 30
|