@friggframework/schemas 2.0.0--canary.657.f16d20b.0 → 2.0.0--canary.737.83b4e17.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 +13 -1
- package/package.json +3 -2
- package/schemas/app-definition.schema.json +539 -132
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
|
|
|
16
20
|
// Initialize AJV with formats
|
|
17
21
|
const ajv = new Ajv({
|
|
@@ -76,7 +80,13 @@ function validate(schemaName, data) {
|
|
|
76
80
|
* @returns {object} - Validation result
|
|
77
81
|
*/
|
|
78
82
|
function validateAppDefinition(appDefinition) {
|
|
79
|
-
|
|
83
|
+
// Apps list integration classes, which JSON Schema cannot describe:
|
|
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 };
|
|
80
90
|
}
|
|
81
91
|
|
|
82
92
|
/**
|
|
@@ -357,6 +367,8 @@ module.exports = {
|
|
|
357
367
|
// Validation functions
|
|
358
368
|
validate,
|
|
359
369
|
validateAppDefinition,
|
|
370
|
+
applyAppDefinitionDefaults,
|
|
371
|
+
toAppDefinitionSchemaView,
|
|
360
372
|
validateIntegrationDefinition,
|
|
361
373
|
validateApiModuleDefinition,
|
|
362
374
|
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.737.83b4e17.0",
|
|
4
4
|
"description": "Canonical JSON Schema definitions for Frigg Framework",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"validators/",
|
|
40
40
|
"mocks/",
|
|
41
41
|
"middleware/",
|
|
42
|
+
"app-definition.js",
|
|
42
43
|
"index.js"
|
|
43
44
|
],
|
|
44
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "83b4e17ac7ec4481bd8143508a2a532e399fcce8"
|
|
45
46
|
}
|
|
@@ -22,22 +22,40 @@
|
|
|
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
|
|
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"]
|
|
41
59
|
},
|
|
42
60
|
"environment": {
|
|
43
61
|
"type": "object",
|
|
@@ -68,60 +86,72 @@
|
|
|
68
86
|
},
|
|
69
87
|
"integrations": {
|
|
70
88
|
"type": "array",
|
|
71
|
-
"description": "
|
|
89
|
+
"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
90
|
"items": {
|
|
73
91
|
"type": "object",
|
|
74
|
-
"description": "
|
|
92
|
+
"description": "An integration class, seen as { Definition } (see the integrations 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
|
+
}
|
|
75
100
|
},
|
|
76
101
|
"default": []
|
|
77
102
|
},
|
|
78
103
|
"user": {
|
|
79
104
|
"type": "object",
|
|
80
|
-
"description": "User management and authentication
|
|
105
|
+
"description": "User management and authentication. Read by core when it loads the app definition; an omitted block gets the defaults below (ADR-051).",
|
|
81
106
|
"properties": {
|
|
82
107
|
"usePassword": {
|
|
83
108
|
"type": "boolean",
|
|
84
|
-
"description": "
|
|
85
|
-
"default":
|
|
109
|
+
"description": "Users log in with username and password (POST /user/login). false: users are identified by appUserId (x-frigg-appuserid) instead.",
|
|
110
|
+
"default": false
|
|
86
111
|
},
|
|
87
112
|
"password": {
|
|
88
113
|
"type": "boolean",
|
|
89
|
-
"description": "DEPRECATED:
|
|
90
|
-
"
|
|
114
|
+
"description": "DEPRECATED alias of usePassword: when usePassword is not set, the loader copies this value into it.",
|
|
115
|
+
"deprecated": true
|
|
91
116
|
},
|
|
92
117
|
"primary": {
|
|
93
118
|
"type": "string",
|
|
94
|
-
"description": "Primary user type
|
|
119
|
+
"description": "Primary user type. Any value other than 'organization' is treated as 'individual'.",
|
|
95
120
|
"enum": ["individual", "organization"],
|
|
96
121
|
"default": "individual"
|
|
97
122
|
},
|
|
98
123
|
"individualUserRequired": {
|
|
99
124
|
"type": "boolean",
|
|
100
|
-
"description": "Require individual user
|
|
125
|
+
"description": "Require an individual user. POST /user/login logs in individual users only when this is true.",
|
|
101
126
|
"default": true
|
|
102
127
|
},
|
|
103
128
|
"organizationUserRequired": {
|
|
104
129
|
"type": "boolean",
|
|
105
|
-
"description": "Require organization user
|
|
130
|
+
"description": "Require an organization user (looked up by appOrgId).",
|
|
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.",
|
|
106
136
|
"default": false
|
|
107
137
|
},
|
|
108
138
|
"authModes": {
|
|
109
139
|
"type": "object",
|
|
110
|
-
"description": "Authentication
|
|
140
|
+
"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.",
|
|
111
141
|
"properties": {
|
|
112
142
|
"friggToken": {
|
|
113
143
|
"type": "boolean",
|
|
114
|
-
"description": "
|
|
144
|
+
"description": "Accept Frigg bearer tokens from /user/login. Enabled unless false.",
|
|
115
145
|
"default": true
|
|
116
146
|
},
|
|
117
147
|
"sharedSecret": {
|
|
118
148
|
"type": "boolean",
|
|
119
|
-
"description": "
|
|
120
|
-
"default":
|
|
149
|
+
"description": "Accept the x-frigg-api-key header (checked against FRIGG_API_KEY) for backend-to-backend calls. Enabled unless false.",
|
|
150
|
+
"default": true
|
|
121
151
|
},
|
|
122
152
|
"adopterJwt": {
|
|
123
153
|
"type": "boolean",
|
|
124
|
-
"description": "
|
|
154
|
+
"description": "Accept JWTs from the adopter's own auth system (requires jwtConfig). Enabled only when true.",
|
|
125
155
|
"default": false
|
|
126
156
|
}
|
|
127
157
|
},
|
|
@@ -133,7 +163,7 @@
|
|
|
133
163
|
"properties": {
|
|
134
164
|
"secret": {
|
|
135
165
|
"type": "string",
|
|
136
|
-
"description": "JWT secret key for signature validation (
|
|
166
|
+
"description": "JWT secret key for signature validation, usually `process.env.JWT_SECRET`. Required when authModes.adopterJwt is true; `frigg validate` errors when the key is missing from the definition and warns when its value is empty in the shell that runs it (build and deploy validate before `.env` is loaded)."
|
|
137
167
|
},
|
|
138
168
|
"userIdClaim": {
|
|
139
169
|
"type": "string",
|
|
@@ -152,27 +182,29 @@
|
|
|
152
182
|
"default": "HS256"
|
|
153
183
|
}
|
|
154
184
|
},
|
|
155
|
-
"required": ["secret"],
|
|
156
185
|
"additionalProperties": false
|
|
157
186
|
},
|
|
158
187
|
"fields": {
|
|
159
188
|
"type": "array",
|
|
160
|
-
"description": "Additional user fields",
|
|
161
|
-
"items": {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
189
|
+
"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.",
|
|
190
|
+
"items": {"type": "string"},
|
|
191
|
+
"examples": [
|
|
192
|
+
["email", "firstName", "lastName"]
|
|
193
|
+
],
|
|
194
|
+
"deprecated": true
|
|
165
195
|
},
|
|
166
196
|
"model": {
|
|
167
197
|
"type": "object",
|
|
168
|
-
"description": "Custom user model class"
|
|
198
|
+
"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.",
|
|
199
|
+
"deprecated": true
|
|
169
200
|
}
|
|
170
201
|
},
|
|
171
|
-
"additionalProperties": false
|
|
202
|
+
"additionalProperties": false,
|
|
203
|
+
"default": {}
|
|
172
204
|
},
|
|
173
205
|
"auth": {
|
|
174
206
|
"type": "object",
|
|
175
|
-
"description": "Authentication configuration
|
|
207
|
+
"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.",
|
|
176
208
|
"properties": {
|
|
177
209
|
"jwtSecret": {
|
|
178
210
|
"type": "string",
|
|
@@ -181,17 +213,16 @@
|
|
|
181
213
|
"tokenExpiry": {
|
|
182
214
|
"type": "string",
|
|
183
215
|
"description": "Token expiration time",
|
|
184
|
-
"pattern": "^\\d+[smhd]$"
|
|
185
|
-
"default": "24h"
|
|
216
|
+
"pattern": "^\\d+[smhd]$"
|
|
186
217
|
},
|
|
187
218
|
"refreshTokenExpiry": {
|
|
188
219
|
"type": "string",
|
|
189
|
-
"description": "Refresh token expiration time",
|
|
190
|
-
"pattern": "^\\d+[smhd]$"
|
|
191
|
-
"default": "7d"
|
|
220
|
+
"description": "Refresh token expiration time",
|
|
221
|
+
"pattern": "^\\d+[smhd]$"
|
|
192
222
|
}
|
|
193
223
|
},
|
|
194
|
-
"additionalProperties": false
|
|
224
|
+
"additionalProperties": false,
|
|
225
|
+
"deprecated": true
|
|
195
226
|
},
|
|
196
227
|
"database": {
|
|
197
228
|
"type": "object",
|
|
@@ -199,8 +230,8 @@
|
|
|
199
230
|
"properties": {
|
|
200
231
|
"uri": {
|
|
201
232
|
"type": "string",
|
|
202
|
-
"description": "Database connection URI (should be set via environment variable)",
|
|
203
|
-
"
|
|
233
|
+
"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.",
|
|
234
|
+
"deprecated": true
|
|
204
235
|
},
|
|
205
236
|
"mongoDB": {
|
|
206
237
|
"type": "object",
|
|
@@ -213,7 +244,8 @@
|
|
|
213
244
|
},
|
|
214
245
|
"uri": {
|
|
215
246
|
"type": "string",
|
|
216
|
-
"description": "MongoDB connection URI"
|
|
247
|
+
"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.",
|
|
248
|
+
"deprecated": true
|
|
217
249
|
}
|
|
218
250
|
},
|
|
219
251
|
"additionalProperties": true
|
|
@@ -241,18 +273,16 @@
|
|
|
241
273
|
"properties": {
|
|
242
274
|
"enable": {
|
|
243
275
|
"type": "boolean",
|
|
244
|
-
"description": "
|
|
245
|
-
"default": false
|
|
276
|
+
"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."
|
|
246
277
|
},
|
|
247
278
|
"management": {
|
|
248
279
|
"type": "string",
|
|
249
|
-
"description": "How to
|
|
250
|
-
"enum": ["discover", "
|
|
251
|
-
"default": "discover"
|
|
280
|
+
"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. 'external': Frigg provisions and discovers no database (no RDS/Aurora, no VPC requirement); the app connects to any PostgreSQL through the DATABASE_URL environment variable.",
|
|
281
|
+
"enum": ["discover", "managed", "use-existing", "external"]
|
|
252
282
|
},
|
|
253
283
|
"endpoint": {
|
|
254
284
|
"type": "string",
|
|
255
|
-
"description": "Existing database endpoint (when management='existing')",
|
|
285
|
+
"description": "Existing database endpoint (required when management='use-existing')",
|
|
256
286
|
"examples": ["mydb.cluster-abc123.us-east-1.rds.amazonaws.com"]
|
|
257
287
|
},
|
|
258
288
|
"port": {
|
|
@@ -270,10 +300,15 @@
|
|
|
270
300
|
"description": "Database username",
|
|
271
301
|
"default": "postgres"
|
|
272
302
|
},
|
|
303
|
+
"engineVersion": {
|
|
304
|
+
"type": "string",
|
|
305
|
+
"description": "Aurora PostgreSQL engine version for a cluster Frigg creates",
|
|
306
|
+
"default": "15.13"
|
|
307
|
+
},
|
|
273
308
|
"selfHeal": {
|
|
274
309
|
"type": "boolean",
|
|
275
|
-
"description": "Automatically fix database configuration issues",
|
|
276
|
-
"
|
|
310
|
+
"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.",
|
|
311
|
+
"deprecated": true
|
|
277
312
|
},
|
|
278
313
|
"publiclyAccessible": {
|
|
279
314
|
"type": "boolean",
|
|
@@ -282,7 +317,7 @@
|
|
|
282
317
|
},
|
|
283
318
|
"autoCreateCredentials": {
|
|
284
319
|
"type": "boolean",
|
|
285
|
-
"description": "
|
|
320
|
+
"description": "Create a Secrets Manager secret and rotate the Aurora password when a discovered cluster has none (management='discover' only)",
|
|
286
321
|
"default": false
|
|
287
322
|
},
|
|
288
323
|
"minCapacity": {
|
|
@@ -297,7 +332,65 @@
|
|
|
297
332
|
"description": "Maximum Aurora Serverless capacity units (0.5-128)",
|
|
298
333
|
"minimum": 0.5,
|
|
299
334
|
"maximum": 128,
|
|
300
|
-
"default":
|
|
335
|
+
"default": 4
|
|
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
|
|
301
394
|
}
|
|
302
395
|
},
|
|
303
396
|
"additionalProperties": false
|
|
@@ -311,14 +404,12 @@
|
|
|
311
404
|
"properties": {
|
|
312
405
|
"fieldLevelEncryptionMethod": {
|
|
313
406
|
"type": "string",
|
|
314
|
-
"description": "
|
|
315
|
-
"enum": ["kms", "aes"]
|
|
316
|
-
"default": "aes"
|
|
407
|
+
"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`). 'none': no field-level encryption, chosen explicitly; no key is provisioned and deployed stages store sensitive fields unencrypted. Omitted: no key is provisioned and deployed stages store sensitive fields unencrypted (core logs a warning). Stages dev, test and local never encrypt.",
|
|
408
|
+
"enum": ["kms", "aes", "none"]
|
|
317
409
|
},
|
|
318
410
|
"createResourceIfNoneFound": {
|
|
319
411
|
"type": "boolean",
|
|
320
|
-
"description": "
|
|
321
|
-
"default": false
|
|
412
|
+
"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."
|
|
322
413
|
},
|
|
323
414
|
"schema": {
|
|
324
415
|
"type": "object",
|
|
@@ -355,6 +446,48 @@
|
|
|
355
446
|
}
|
|
356
447
|
}
|
|
357
448
|
]
|
|
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
|
|
358
491
|
}
|
|
359
492
|
},
|
|
360
493
|
"additionalProperties": false
|
|
@@ -365,24 +498,23 @@
|
|
|
365
498
|
"properties": {
|
|
366
499
|
"enable": {
|
|
367
500
|
"type": "boolean",
|
|
368
|
-
"description": "
|
|
501
|
+
"description": "Run the Lambda functions in a VPC",
|
|
369
502
|
"default": false
|
|
370
503
|
},
|
|
371
504
|
"management": {
|
|
372
505
|
"type": "string",
|
|
373
|
-
"description": "How
|
|
374
|
-
"enum": ["discover", "create-new", "existing"]
|
|
375
|
-
"default": "discover"
|
|
506
|
+
"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.",
|
|
507
|
+
"enum": ["discover", "create-new", "use-existing"]
|
|
376
508
|
},
|
|
377
509
|
"vpcId": {
|
|
378
510
|
"type": "string",
|
|
379
|
-
"description": "Existing VPC ID (when management='existing')",
|
|
511
|
+
"description": "Existing VPC ID (required when management='use-existing')",
|
|
380
512
|
"pattern": "^vpc-[a-z0-9]+$",
|
|
381
513
|
"examples": ["vpc-abc123"]
|
|
382
514
|
},
|
|
383
515
|
"cidrBlock": {
|
|
384
516
|
"type": "string",
|
|
385
|
-
"description": "CIDR block for VPC
|
|
517
|
+
"description": "CIDR block for a VPC Frigg creates",
|
|
386
518
|
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",
|
|
387
519
|
"default": "10.0.0.0/16"
|
|
388
520
|
},
|
|
@@ -393,7 +525,9 @@
|
|
|
393
525
|
"type": "string",
|
|
394
526
|
"pattern": "^sg-[a-z0-9]+$"
|
|
395
527
|
},
|
|
396
|
-
"examples": [
|
|
528
|
+
"examples": [
|
|
529
|
+
["sg-abc123", "sg-def456"]
|
|
530
|
+
]
|
|
397
531
|
},
|
|
398
532
|
"subnets": {
|
|
399
533
|
"type": "object",
|
|
@@ -401,19 +535,20 @@
|
|
|
401
535
|
"properties": {
|
|
402
536
|
"management": {
|
|
403
537
|
"type": "string",
|
|
404
|
-
"description": "
|
|
405
|
-
"enum": ["discover", "create-new", "existing"]
|
|
406
|
-
"default": "discover"
|
|
538
|
+
"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).",
|
|
539
|
+
"enum": ["create", "use-existing", "discover", "create-new", "existing"]
|
|
407
540
|
},
|
|
408
541
|
"ids": {
|
|
409
542
|
"type": "array",
|
|
410
|
-
"description": "Existing subnet IDs",
|
|
543
|
+
"description": "Existing subnet IDs (management='use-existing')",
|
|
411
544
|
"items": {
|
|
412
545
|
"type": "string",
|
|
413
546
|
"pattern": "^subnet-[a-z0-9]+$"
|
|
414
547
|
},
|
|
415
548
|
"minItems": 2,
|
|
416
|
-
"examples": [
|
|
549
|
+
"examples": [
|
|
550
|
+
["subnet-abc123", "subnet-def456"]
|
|
551
|
+
]
|
|
417
552
|
}
|
|
418
553
|
},
|
|
419
554
|
"additionalProperties": false
|
|
@@ -424,13 +559,12 @@
|
|
|
424
559
|
"properties": {
|
|
425
560
|
"management": {
|
|
426
561
|
"type": "string",
|
|
427
|
-
"description": "
|
|
428
|
-
"enum": ["discover", "create-new", "existing"]
|
|
429
|
-
"default": "discover"
|
|
562
|
+
"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.",
|
|
563
|
+
"enum": ["createAndManage", "discover", "create-new", "existing"]
|
|
430
564
|
},
|
|
431
565
|
"id": {
|
|
432
566
|
"type": "string",
|
|
433
|
-
"description": "Existing NAT Gateway ID",
|
|
567
|
+
"description": "Existing NAT Gateway ID (makes the NAT gateway external)",
|
|
434
568
|
"pattern": "^nat-[a-z0-9]+$",
|
|
435
569
|
"examples": ["nat-abc123"]
|
|
436
570
|
}
|
|
@@ -439,13 +573,112 @@
|
|
|
439
573
|
},
|
|
440
574
|
"enableVPCEndpoints": {
|
|
441
575
|
"type": "boolean",
|
|
442
|
-
"description": "Create VPC endpoints for AWS services (S3, DynamoDB, KMS, Secrets Manager)",
|
|
576
|
+
"description": "Create VPC endpoints for AWS services (S3, DynamoDB, KMS, Secrets Manager). Enabled unless false.",
|
|
443
577
|
"default": true
|
|
444
578
|
},
|
|
445
579
|
"selfHeal": {
|
|
446
580
|
"type": "boolean",
|
|
447
|
-
"description": "
|
|
448
|
-
|
|
581
|
+
"description": "Repair VPC configuration issues (route table associations) during discovery. When omitted, self-healing of stack-owned subnets is on."
|
|
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
|
|
449
682
|
}
|
|
450
683
|
},
|
|
451
684
|
"additionalProperties": false
|
|
@@ -490,9 +723,7 @@
|
|
|
490
723
|
"enum": ["standard", "advanced"],
|
|
491
724
|
"default": "standard"
|
|
492
725
|
},
|
|
493
|
-
"description": {
|
|
494
|
-
"type": "string"
|
|
495
|
-
}
|
|
726
|
+
"description": {"type": "string"}
|
|
496
727
|
}
|
|
497
728
|
}
|
|
498
729
|
},
|
|
@@ -503,15 +734,15 @@
|
|
|
503
734
|
},
|
|
504
735
|
"secretsManager": {
|
|
505
736
|
"type": "object",
|
|
506
|
-
"description": "AWS Secrets Manager configuration",
|
|
737
|
+
"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.",
|
|
507
738
|
"properties": {
|
|
508
739
|
"enable": {
|
|
509
740
|
"type": "boolean",
|
|
510
|
-
"description": "Enable AWS Secrets Manager for secure credential storage"
|
|
511
|
-
"default": false
|
|
741
|
+
"description": "Enable AWS Secrets Manager for secure credential storage"
|
|
512
742
|
}
|
|
513
743
|
},
|
|
514
|
-
"additionalProperties": false
|
|
744
|
+
"additionalProperties": false,
|
|
745
|
+
"deprecated": true
|
|
515
746
|
},
|
|
516
747
|
"lambda": {
|
|
517
748
|
"type": "object",
|
|
@@ -521,6 +752,11 @@
|
|
|
521
752
|
"type": "boolean",
|
|
522
753
|
"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",
|
|
523
754
|
"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
|
|
524
760
|
}
|
|
525
761
|
},
|
|
526
762
|
"additionalProperties": false
|
|
@@ -536,15 +772,15 @@
|
|
|
536
772
|
},
|
|
537
773
|
"routeSelectionExpression": {
|
|
538
774
|
"type": "string",
|
|
539
|
-
"description": "Route selection expression for WebSocket",
|
|
540
|
-
"
|
|
775
|
+
"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.",
|
|
776
|
+
"deprecated": true
|
|
541
777
|
}
|
|
542
778
|
},
|
|
543
779
|
"additionalProperties": false
|
|
544
780
|
},
|
|
545
781
|
"security": {
|
|
546
782
|
"type": "object",
|
|
547
|
-
"description": "Security settings for the application",
|
|
783
|
+
"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.",
|
|
548
784
|
"properties": {
|
|
549
785
|
"cors": {
|
|
550
786
|
"type": "object",
|
|
@@ -553,16 +789,17 @@
|
|
|
553
789
|
"origin": {
|
|
554
790
|
"oneOf": [
|
|
555
791
|
{"type": "string"},
|
|
556
|
-
{
|
|
792
|
+
{
|
|
793
|
+
"type": "array",
|
|
794
|
+
"items": {"type": "string"}
|
|
795
|
+
},
|
|
557
796
|
{"type": "boolean"}
|
|
558
797
|
],
|
|
559
|
-
"description": "Allowed origins for CORS requests"
|
|
560
|
-
"default": "http://localhost:3000"
|
|
798
|
+
"description": "Allowed origins for CORS requests"
|
|
561
799
|
},
|
|
562
800
|
"credentials": {
|
|
563
801
|
"type": "boolean",
|
|
564
|
-
"description": "Allow credentials in CORS requests"
|
|
565
|
-
"default": true
|
|
802
|
+
"description": "Allow credentials in CORS requests"
|
|
566
803
|
},
|
|
567
804
|
"methods": {
|
|
568
805
|
"type": "array",
|
|
@@ -587,24 +824,23 @@
|
|
|
587
824
|
"windowMs": {
|
|
588
825
|
"type": "integer",
|
|
589
826
|
"description": "Time window in milliseconds",
|
|
590
|
-
"minimum": 1000
|
|
591
|
-
"default": 900000
|
|
827
|
+
"minimum": 1000
|
|
592
828
|
},
|
|
593
829
|
"max": {
|
|
594
|
-
"type": "integer",
|
|
830
|
+
"type": "integer",
|
|
595
831
|
"description": "Maximum requests per window",
|
|
596
|
-
"minimum": 1
|
|
597
|
-
"default": 100
|
|
832
|
+
"minimum": 1
|
|
598
833
|
}
|
|
599
834
|
},
|
|
600
835
|
"additionalProperties": false
|
|
601
836
|
}
|
|
602
837
|
},
|
|
603
|
-
"additionalProperties": false
|
|
838
|
+
"additionalProperties": false,
|
|
839
|
+
"deprecated": true
|
|
604
840
|
},
|
|
605
841
|
"webhooks": {
|
|
606
842
|
"type": "object",
|
|
607
|
-
"description": "Webhook handling configuration",
|
|
843
|
+
"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).",
|
|
608
844
|
"properties": {
|
|
609
845
|
"secret": {
|
|
610
846
|
"type": "string",
|
|
@@ -613,11 +849,11 @@
|
|
|
613
849
|
"prefix": {
|
|
614
850
|
"type": "string",
|
|
615
851
|
"description": "Webhook endpoint prefix",
|
|
616
|
-
"pattern": "^/[a-zA-Z0-9/_-]*$"
|
|
617
|
-
"default": "/webhooks"
|
|
852
|
+
"pattern": "^/[a-zA-Z0-9/_-]*$"
|
|
618
853
|
}
|
|
619
854
|
},
|
|
620
|
-
"additionalProperties": false
|
|
855
|
+
"additionalProperties": false,
|
|
856
|
+
"deprecated": true
|
|
621
857
|
},
|
|
622
858
|
"logging": {
|
|
623
859
|
"type": "object",
|
|
@@ -625,9 +861,8 @@
|
|
|
625
861
|
"properties": {
|
|
626
862
|
"level": {
|
|
627
863
|
"type": "string",
|
|
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"
|
|
864
|
+
"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.",
|
|
865
|
+
"enum": ["trace", "debug", "info", "warn", "error", "fatal", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"]
|
|
631
866
|
},
|
|
632
867
|
"retentionInDays": {
|
|
633
868
|
"type": "integer",
|
|
@@ -636,46 +871,225 @@
|
|
|
636
871
|
},
|
|
637
872
|
"format": {
|
|
638
873
|
"type": "string",
|
|
639
|
-
"description": "Log format. Records are always JSON lines.",
|
|
640
|
-
"enum": ["json"]
|
|
641
|
-
|
|
874
|
+
"description": "Log format. Records are always JSON lines; this key is informational and has no default.",
|
|
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
|
|
642
1060
|
}
|
|
643
1061
|
},
|
|
644
1062
|
"additionalProperties": false
|
|
645
1063
|
},
|
|
646
1064
|
"custom": {
|
|
647
1065
|
"type": "object",
|
|
648
|
-
"description": "Custom application-specific configuration",
|
|
1066
|
+
"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.",
|
|
649
1067
|
"properties": {
|
|
650
1068
|
"appName": {
|
|
651
1069
|
"type": "string",
|
|
652
|
-
"description": "Application display name"
|
|
653
|
-
"default": "My Frigg Application"
|
|
1070
|
+
"description": "Application display name"
|
|
654
1071
|
},
|
|
655
1072
|
"version": {
|
|
656
1073
|
"type": "string",
|
|
657
1074
|
"description": "Application version",
|
|
658
|
-
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$"
|
|
659
|
-
"default": "1.0.0"
|
|
1075
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$"
|
|
660
1076
|
},
|
|
661
1077
|
"environment": {
|
|
662
1078
|
"type": "string",
|
|
663
1079
|
"description": "Deployment environment/stage",
|
|
664
|
-
"enum": ["development", "staging", "production", "test"]
|
|
665
|
-
"default": "development"
|
|
1080
|
+
"enum": ["development", "staging", "production", "test"]
|
|
666
1081
|
},
|
|
667
1082
|
"features": {
|
|
668
1083
|
"type": "object",
|
|
669
1084
|
"description": "Feature flags and toggles",
|
|
670
1085
|
"patternProperties": {
|
|
671
|
-
"^[a-zA-Z][a-zA-Z0-9_]*$": {
|
|
672
|
-
"type": "boolean"
|
|
673
|
-
}
|
|
1086
|
+
"^[a-zA-Z][a-zA-Z0-9_]*$": {"type": "boolean"}
|
|
674
1087
|
},
|
|
675
1088
|
"additionalProperties": false
|
|
676
1089
|
}
|
|
677
1090
|
},
|
|
678
|
-
"additionalProperties": true
|
|
1091
|
+
"additionalProperties": true,
|
|
1092
|
+
"deprecated": true
|
|
679
1093
|
}
|
|
680
1094
|
},
|
|
681
1095
|
"additionalProperties": false,
|
|
@@ -689,12 +1103,15 @@
|
|
|
689
1103
|
},
|
|
690
1104
|
"integrations": [],
|
|
691
1105
|
"user": {
|
|
692
|
-
"
|
|
1106
|
+
"usePassword": true,
|
|
1107
|
+
"primary": "individual",
|
|
1108
|
+
"individualUserRequired": true,
|
|
1109
|
+
"organizationUserRequired": false
|
|
693
1110
|
},
|
|
694
1111
|
"database": {
|
|
695
1112
|
"postgres": {
|
|
696
1113
|
"enable": true,
|
|
697
|
-
"management": "
|
|
1114
|
+
"management": "managed"
|
|
698
1115
|
}
|
|
699
1116
|
},
|
|
700
1117
|
"encryption": {
|
|
@@ -707,18 +1124,8 @@
|
|
|
707
1124
|
"cidrBlock": "10.0.0.0/16",
|
|
708
1125
|
"enableVPCEndpoints": true
|
|
709
1126
|
},
|
|
710
|
-
"ssm": {
|
|
711
|
-
|
|
712
|
-
},
|
|
713
|
-
"websockets": {
|
|
714
|
-
"enable": true
|
|
715
|
-
},
|
|
716
|
-
"security": {
|
|
717
|
-
"cors": {
|
|
718
|
-
"origin": "http://localhost:3000",
|
|
719
|
-
"credentials": true
|
|
720
|
-
}
|
|
721
|
-
},
|
|
1127
|
+
"ssm": {"enable": true},
|
|
1128
|
+
"websockets": {"enable": true},
|
|
722
1129
|
"logging": {
|
|
723
1130
|
"level": "info",
|
|
724
1131
|
"retentionInDays": 30
|