@friggframework/schemas 2.0.0-next.78 → 2.0.0-next.80
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/index.js +232 -5
- package/middleware/__tests__/schema-validation.test.js +508 -0
- package/middleware/schema-validation.js +388 -0
- package/mocks/README.md +280 -0
- package/mocks/__tests__/authorization-mocks.test.js +311 -0
- package/mocks/authorization-mocks.js +339 -0
- package/package.json +4 -2
- package/schemas/api-authorization.schema.json +302 -0
- package/schemas/api-credentials.schema.json +176 -0
- package/schemas/api-entities.schema.json +292 -0
- package/schemas/api-proxy.schema.json +251 -0
- package/schemas/app-definition.schema.json +19 -0
- package/schemas/core-models.schema.json +16 -16
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://friggframework.org/schemas/api-entities.json",
|
|
4
|
+
"title": "Frigg Entities API Schemas",
|
|
5
|
+
"description": "JSON schemas for entities API requests and responses",
|
|
6
|
+
"definitions": {
|
|
7
|
+
"entity": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"description": "A connected account/entity object representing an external integration",
|
|
10
|
+
"required": ["id", "type", "credentialId", "userId"],
|
|
11
|
+
"properties": {
|
|
12
|
+
"id": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Unique entity identifier"
|
|
15
|
+
},
|
|
16
|
+
"type": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Module/entity type name (e.g., 'hubspot', 'salesforce')"
|
|
19
|
+
},
|
|
20
|
+
"name": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Display name for the entity"
|
|
23
|
+
},
|
|
24
|
+
"externalId": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "ID from the external system (e.g., HubSpot portal ID)"
|
|
27
|
+
},
|
|
28
|
+
"credentialId": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "ID of the linked credential"
|
|
31
|
+
},
|
|
32
|
+
"userId": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "ID of the user who owns this entity"
|
|
35
|
+
},
|
|
36
|
+
"authIsValid": {
|
|
37
|
+
"type": "boolean",
|
|
38
|
+
"description": "Whether authentication is currently valid"
|
|
39
|
+
},
|
|
40
|
+
"createdAt": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"format": "date-time",
|
|
43
|
+
"description": "Entity creation timestamp"
|
|
44
|
+
},
|
|
45
|
+
"updatedAt": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"format": "date-time",
|
|
48
|
+
"description": "Last update timestamp"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"listEntitiesResponse": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"description": "Response from GET /api/entities",
|
|
55
|
+
"required": ["entities"],
|
|
56
|
+
"properties": {
|
|
57
|
+
"entities": {
|
|
58
|
+
"type": "array",
|
|
59
|
+
"items": {
|
|
60
|
+
"$ref": "#/definitions/entity"
|
|
61
|
+
},
|
|
62
|
+
"description": "List of entities for the authenticated user"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"createEntityRequest": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"description": "Request to POST /api/entities",
|
|
69
|
+
"required": ["entityType", "data"],
|
|
70
|
+
"properties": {
|
|
71
|
+
"entityType": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"description": "Type of entity to create (module name)"
|
|
74
|
+
},
|
|
75
|
+
"data": {
|
|
76
|
+
"type": "object",
|
|
77
|
+
"description": "Entity creation data (must contain credential_id)",
|
|
78
|
+
"required": ["credential_id"],
|
|
79
|
+
"properties": {
|
|
80
|
+
"credential_id": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"description": "ID of the credential to link to this entity"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"additionalProperties": true
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"createEntityResponse": {
|
|
90
|
+
"type": "object",
|
|
91
|
+
"description": "Response from POST /api/entities",
|
|
92
|
+
"required": ["entity_id", "credential_id", "type"],
|
|
93
|
+
"properties": {
|
|
94
|
+
"entity_id": {
|
|
95
|
+
"type": "string",
|
|
96
|
+
"description": "ID of the created entity"
|
|
97
|
+
},
|
|
98
|
+
"credential_id": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"description": "ID of the linked credential"
|
|
101
|
+
},
|
|
102
|
+
"type": {
|
|
103
|
+
"type": "string",
|
|
104
|
+
"description": "Entity type (module name)"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"entityType": {
|
|
109
|
+
"type": "object",
|
|
110
|
+
"description": "Metadata about an available entity type",
|
|
111
|
+
"required": ["type", "name"],
|
|
112
|
+
"properties": {
|
|
113
|
+
"type": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"description": "Module name (e.g., 'hubspot', 'salesforce')"
|
|
116
|
+
},
|
|
117
|
+
"name": {
|
|
118
|
+
"type": "string",
|
|
119
|
+
"description": "Display name for the entity type"
|
|
120
|
+
},
|
|
121
|
+
"description": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Description of the entity type"
|
|
124
|
+
},
|
|
125
|
+
"authType": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"enum": ["oauth2", "form", "api-key", "basic"],
|
|
128
|
+
"description": "Type of authentication required"
|
|
129
|
+
},
|
|
130
|
+
"isMultiStep": {
|
|
131
|
+
"type": "boolean",
|
|
132
|
+
"description": "Whether this entity type uses multi-step authentication"
|
|
133
|
+
},
|
|
134
|
+
"stepCount": {
|
|
135
|
+
"type": "integer",
|
|
136
|
+
"minimum": 1,
|
|
137
|
+
"description": "Number of steps in the authentication flow"
|
|
138
|
+
},
|
|
139
|
+
"capabilities": {
|
|
140
|
+
"type": "array",
|
|
141
|
+
"items": {
|
|
142
|
+
"type": "string"
|
|
143
|
+
},
|
|
144
|
+
"description": "List of capabilities this entity type supports"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
"listEntityTypesResponse": {
|
|
149
|
+
"type": "object",
|
|
150
|
+
"description": "Response from GET /api/entities/types",
|
|
151
|
+
"required": ["types"],
|
|
152
|
+
"properties": {
|
|
153
|
+
"types": {
|
|
154
|
+
"type": "array",
|
|
155
|
+
"items": {
|
|
156
|
+
"$ref": "#/definitions/entityType"
|
|
157
|
+
},
|
|
158
|
+
"description": "List of available entity types"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"getEntityTypeResponse": {
|
|
163
|
+
"type": "object",
|
|
164
|
+
"description": "Response from GET /api/entities/types/:typeName",
|
|
165
|
+
"required": ["type", "name"],
|
|
166
|
+
"properties": {
|
|
167
|
+
"type": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"description": "Module name (e.g., 'hubspot', 'salesforce')"
|
|
170
|
+
},
|
|
171
|
+
"name": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"description": "Display name for the entity type"
|
|
174
|
+
},
|
|
175
|
+
"description": {
|
|
176
|
+
"type": "string",
|
|
177
|
+
"description": "Description of the entity type"
|
|
178
|
+
},
|
|
179
|
+
"authType": {
|
|
180
|
+
"type": "string",
|
|
181
|
+
"enum": ["oauth2", "form", "api-key", "basic"],
|
|
182
|
+
"description": "Type of authentication required"
|
|
183
|
+
},
|
|
184
|
+
"isMultiStep": {
|
|
185
|
+
"type": "boolean",
|
|
186
|
+
"description": "Whether this entity type uses multi-step authentication"
|
|
187
|
+
},
|
|
188
|
+
"stepCount": {
|
|
189
|
+
"type": "integer",
|
|
190
|
+
"minimum": 1,
|
|
191
|
+
"description": "Number of steps in the authentication flow"
|
|
192
|
+
},
|
|
193
|
+
"capabilities": {
|
|
194
|
+
"type": "array",
|
|
195
|
+
"items": {
|
|
196
|
+
"type": "string"
|
|
197
|
+
},
|
|
198
|
+
"description": "List of capabilities this entity type supports"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
"reauthorizeEntityRequest": {
|
|
203
|
+
"type": "object",
|
|
204
|
+
"description": "Request to POST /api/entities/:id/reauthorize",
|
|
205
|
+
"required": ["data"],
|
|
206
|
+
"properties": {
|
|
207
|
+
"data": {
|
|
208
|
+
"type": "object",
|
|
209
|
+
"description": "Authentication data (OAuth code, form fields, API keys, etc.)",
|
|
210
|
+
"additionalProperties": true
|
|
211
|
+
},
|
|
212
|
+
"step": {
|
|
213
|
+
"type": "integer",
|
|
214
|
+
"minimum": 1,
|
|
215
|
+
"default": 1,
|
|
216
|
+
"description": "Current step number for multi-step flows"
|
|
217
|
+
},
|
|
218
|
+
"sessionId": {
|
|
219
|
+
"type": "string",
|
|
220
|
+
"description": "Session ID from previous step (required for step > 1)"
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"reauthorizeEntityResponse": {
|
|
225
|
+
"type": "object",
|
|
226
|
+
"description": "Response from POST /api/entities/:id/reauthorize (success or next step)",
|
|
227
|
+
"oneOf": [
|
|
228
|
+
{
|
|
229
|
+
"$ref": "#/definitions/reauthorizeEntitySuccess"
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"$ref": "#/definitions/reauthorizeEntityNextStep"
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
"reauthorizeEntitySuccess": {
|
|
237
|
+
"type": "object",
|
|
238
|
+
"description": "Successful reauthorization completion",
|
|
239
|
+
"required": ["success", "credential_id", "entity_id", "authIsValid"],
|
|
240
|
+
"properties": {
|
|
241
|
+
"success": {
|
|
242
|
+
"type": "boolean",
|
|
243
|
+
"const": true,
|
|
244
|
+
"description": "Indicates successful reauthorization"
|
|
245
|
+
},
|
|
246
|
+
"credential_id": {
|
|
247
|
+
"type": "string",
|
|
248
|
+
"description": "ID of the updated credential"
|
|
249
|
+
},
|
|
250
|
+
"entity_id": {
|
|
251
|
+
"type": "string",
|
|
252
|
+
"description": "ID of the reauthorized entity"
|
|
253
|
+
},
|
|
254
|
+
"authIsValid": {
|
|
255
|
+
"type": "boolean",
|
|
256
|
+
"const": true,
|
|
257
|
+
"description": "Confirms authentication is now valid"
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
"reauthorizeEntityNextStep": {
|
|
262
|
+
"type": "object",
|
|
263
|
+
"description": "Next step in multi-step reauthorization",
|
|
264
|
+
"required": ["step", "totalSteps", "sessionId", "requirements"],
|
|
265
|
+
"properties": {
|
|
266
|
+
"step": {
|
|
267
|
+
"type": "integer",
|
|
268
|
+
"minimum": 2,
|
|
269
|
+
"description": "Next step number"
|
|
270
|
+
},
|
|
271
|
+
"totalSteps": {
|
|
272
|
+
"type": "integer",
|
|
273
|
+
"minimum": 2,
|
|
274
|
+
"description": "Total number of steps in the flow"
|
|
275
|
+
},
|
|
276
|
+
"sessionId": {
|
|
277
|
+
"type": "string",
|
|
278
|
+
"description": "Session ID to use for next step"
|
|
279
|
+
},
|
|
280
|
+
"requirements": {
|
|
281
|
+
"type": "object",
|
|
282
|
+
"description": "Requirements for the next step (varies by auth type)",
|
|
283
|
+
"additionalProperties": true
|
|
284
|
+
},
|
|
285
|
+
"message": {
|
|
286
|
+
"type": "string",
|
|
287
|
+
"description": "Message to display to user (e.g., 'OTP sent to your email')"
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://friggframework.org/schemas/api-proxy.json",
|
|
4
|
+
"title": "Frigg Proxy API Schemas",
|
|
5
|
+
"description": "JSON schemas for proxy API requests and responses that forward calls to external APIs",
|
|
6
|
+
"definitions": {
|
|
7
|
+
"proxyRequest": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"description": "Proxy request to POST /api/entities/:id/proxy or POST /api/credentials/:id/proxy",
|
|
10
|
+
"required": ["method", "path"],
|
|
11
|
+
"properties": {
|
|
12
|
+
"method": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"enum": ["GET", "POST", "PUT", "PATCH", "DELETE"],
|
|
15
|
+
"description": "HTTP method to use for the upstream API request"
|
|
16
|
+
},
|
|
17
|
+
"path": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "API path to call on the upstream service (e.g., '/v3/contacts' or '/api/users')",
|
|
20
|
+
"pattern": "^/",
|
|
21
|
+
"minLength": 1
|
|
22
|
+
},
|
|
23
|
+
"query": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"description": "Query parameters to include in the request as key-value pairs",
|
|
26
|
+
"additionalProperties": {
|
|
27
|
+
"oneOf": [
|
|
28
|
+
{ "type": "string" },
|
|
29
|
+
{ "type": "number" },
|
|
30
|
+
{ "type": "boolean" },
|
|
31
|
+
{
|
|
32
|
+
"type": "array",
|
|
33
|
+
"items": { "type": "string" }
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"headers": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"description": "Additional headers to include in the upstream request (authorization headers are added automatically)",
|
|
41
|
+
"additionalProperties": { "type": "string" }
|
|
42
|
+
},
|
|
43
|
+
"body": {
|
|
44
|
+
"description": "Request body for POST, PUT, or PATCH requests (can be object, array, string, or null)",
|
|
45
|
+
"oneOf": [
|
|
46
|
+
{ "type": "object" },
|
|
47
|
+
{ "type": "array" },
|
|
48
|
+
{ "type": "string" },
|
|
49
|
+
{ "type": "null" }
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"examples": [
|
|
54
|
+
{
|
|
55
|
+
"method": "GET",
|
|
56
|
+
"path": "/v3/contacts",
|
|
57
|
+
"query": {
|
|
58
|
+
"limit": "10",
|
|
59
|
+
"archived": "false"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"method": "POST",
|
|
64
|
+
"path": "/v3/contacts",
|
|
65
|
+
"headers": {
|
|
66
|
+
"Content-Type": "application/json"
|
|
67
|
+
},
|
|
68
|
+
"body": {
|
|
69
|
+
"properties": {
|
|
70
|
+
"email": "contact@example.com",
|
|
71
|
+
"firstname": "John",
|
|
72
|
+
"lastname": "Doe"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"method": "PATCH",
|
|
78
|
+
"path": "/api/v1/users/12345",
|
|
79
|
+
"body": {
|
|
80
|
+
"status": "active"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
"proxyResponse": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"description": "Successful proxy response with data from upstream API",
|
|
88
|
+
"required": ["success", "status", "data"],
|
|
89
|
+
"properties": {
|
|
90
|
+
"success": {
|
|
91
|
+
"type": "boolean",
|
|
92
|
+
"const": true,
|
|
93
|
+
"description": "Indicates successful proxy operation"
|
|
94
|
+
},
|
|
95
|
+
"status": {
|
|
96
|
+
"type": "integer",
|
|
97
|
+
"minimum": 200,
|
|
98
|
+
"maximum": 299,
|
|
99
|
+
"description": "HTTP status code from the upstream API response"
|
|
100
|
+
},
|
|
101
|
+
"headers": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"description": "Response headers from the upstream API",
|
|
104
|
+
"additionalProperties": { "type": "string" }
|
|
105
|
+
},
|
|
106
|
+
"data": {
|
|
107
|
+
"description": "Response body from the upstream API (can be any valid JSON type)",
|
|
108
|
+
"oneOf": [
|
|
109
|
+
{ "type": "object" },
|
|
110
|
+
{ "type": "array" },
|
|
111
|
+
{ "type": "string" },
|
|
112
|
+
{ "type": "number" },
|
|
113
|
+
{ "type": "boolean" },
|
|
114
|
+
{ "type": "null" }
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"examples": [
|
|
119
|
+
{
|
|
120
|
+
"success": true,
|
|
121
|
+
"status": 200,
|
|
122
|
+
"headers": {
|
|
123
|
+
"content-type": "application/json",
|
|
124
|
+
"x-rate-limit-remaining": "998"
|
|
125
|
+
},
|
|
126
|
+
"data": {
|
|
127
|
+
"results": [
|
|
128
|
+
{
|
|
129
|
+
"id": "123",
|
|
130
|
+
"properties": {
|
|
131
|
+
"email": "contact@example.com",
|
|
132
|
+
"firstname": "John",
|
|
133
|
+
"lastname": "Doe"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"success": true,
|
|
141
|
+
"status": 201,
|
|
142
|
+
"data": {
|
|
143
|
+
"id": "456",
|
|
144
|
+
"created_at": "2025-01-15T10:30:00Z",
|
|
145
|
+
"status": "active"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
"proxyErrorResponse": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"description": "Error response from proxy operation",
|
|
153
|
+
"required": ["success", "status", "error"],
|
|
154
|
+
"properties": {
|
|
155
|
+
"success": {
|
|
156
|
+
"type": "boolean",
|
|
157
|
+
"const": false,
|
|
158
|
+
"description": "Indicates failed proxy operation"
|
|
159
|
+
},
|
|
160
|
+
"status": {
|
|
161
|
+
"type": "integer",
|
|
162
|
+
"minimum": 400,
|
|
163
|
+
"maximum": 599,
|
|
164
|
+
"description": "HTTP status code (either from upstream API or Frigg proxy error)"
|
|
165
|
+
},
|
|
166
|
+
"error": {
|
|
167
|
+
"type": "object",
|
|
168
|
+
"required": ["code", "message"],
|
|
169
|
+
"properties": {
|
|
170
|
+
"code": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"description": "Error code identifying the type of failure",
|
|
173
|
+
"enum": [
|
|
174
|
+
"INVALID_AUTH",
|
|
175
|
+
"EXPIRED_TOKEN",
|
|
176
|
+
"UPSTREAM_ERROR",
|
|
177
|
+
"TIMEOUT",
|
|
178
|
+
"NETWORK_ERROR",
|
|
179
|
+
"RATE_LIMITED",
|
|
180
|
+
"INVALID_REQUEST",
|
|
181
|
+
"NOT_FOUND",
|
|
182
|
+
"PERMISSION_DENIED",
|
|
183
|
+
"INVALID_CREDENTIALS",
|
|
184
|
+
"SERVICE_UNAVAILABLE"
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
"message": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"description": "Human-readable error message"
|
|
190
|
+
},
|
|
191
|
+
"details": {
|
|
192
|
+
"description": "Additional error details from upstream API or internal error information",
|
|
193
|
+
"oneOf": [
|
|
194
|
+
{ "type": "object" },
|
|
195
|
+
{ "type": "array" },
|
|
196
|
+
{ "type": "string" },
|
|
197
|
+
{ "type": "null" }
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
"upstreamStatus": {
|
|
201
|
+
"type": "integer",
|
|
202
|
+
"description": "Original HTTP status code from upstream API (if available)"
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
"examples": [
|
|
208
|
+
{
|
|
209
|
+
"success": false,
|
|
210
|
+
"status": 401,
|
|
211
|
+
"error": {
|
|
212
|
+
"code": "INVALID_AUTH",
|
|
213
|
+
"message": "Authentication credentials are invalid or expired",
|
|
214
|
+
"details": {
|
|
215
|
+
"category": "INVALID_AUTHENTICATION",
|
|
216
|
+
"message": "The access token provided is invalid or has expired"
|
|
217
|
+
},
|
|
218
|
+
"upstreamStatus": 401
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"success": false,
|
|
223
|
+
"status": 429,
|
|
224
|
+
"error": {
|
|
225
|
+
"code": "RATE_LIMITED",
|
|
226
|
+
"message": "Rate limit exceeded for this API",
|
|
227
|
+
"details": {
|
|
228
|
+
"retry_after": 60,
|
|
229
|
+
"limit": "100 requests per minute"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"success": false,
|
|
235
|
+
"status": 504,
|
|
236
|
+
"error": {
|
|
237
|
+
"code": "TIMEOUT",
|
|
238
|
+
"message": "Request to upstream API timed out after 30 seconds"
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
"proxyResponseUnion": {
|
|
244
|
+
"description": "Union type representing either success or error proxy response",
|
|
245
|
+
"oneOf": [
|
|
246
|
+
{ "$ref": "#/definitions/proxyResponse" },
|
|
247
|
+
{ "$ref": "#/definitions/proxyErrorResponse" }
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -20,6 +20,25 @@
|
|
|
20
20
|
"enum": ["aws"],
|
|
21
21
|
"default": "aws"
|
|
22
22
|
},
|
|
23
|
+
"label": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"description": "Human-readable display name for the application",
|
|
26
|
+
"minLength": 1,
|
|
27
|
+
"maxLength": 200,
|
|
28
|
+
"examples": ["My Frigg Application", "Customer Portal Integrations"]
|
|
29
|
+
},
|
|
30
|
+
"managementMode": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "Infrastructure management mode: 'managed' lets Frigg manage resources, 'discover' uses existing resources, 'custom' for manual configuration",
|
|
33
|
+
"enum": ["managed", "discover", "custom"],
|
|
34
|
+
"default": "managed"
|
|
35
|
+
},
|
|
36
|
+
"vpcIsolation": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "VPC isolation strategy: 'isolated' creates separate VPC per stage, 'shared' reuses VPC across stages",
|
|
39
|
+
"enum": ["isolated", "shared"],
|
|
40
|
+
"default": "isolated"
|
|
41
|
+
},
|
|
23
42
|
"environment": {
|
|
24
43
|
"type": "object",
|
|
25
44
|
"description": "Environment variable configuration (key: true/false flags)",
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"type": "object",
|
|
19
19
|
"description": "Frigg User model schema",
|
|
20
20
|
"required": [
|
|
21
|
-
"
|
|
21
|
+
"id"
|
|
22
22
|
],
|
|
23
23
|
"properties": {
|
|
24
|
-
"
|
|
24
|
+
"id": {
|
|
25
25
|
"$ref": "#/definitions/objectId",
|
|
26
|
-
"description": "Unique user identifier"
|
|
26
|
+
"description": "Unique user identifier (maps to _id in MongoDB)"
|
|
27
27
|
},
|
|
28
28
|
"email": {
|
|
29
29
|
"type": "string",
|
|
@@ -148,13 +148,13 @@
|
|
|
148
148
|
"type": "object",
|
|
149
149
|
"description": "Frigg Credential model schema",
|
|
150
150
|
"required": [
|
|
151
|
-
"
|
|
151
|
+
"id",
|
|
152
152
|
"userId"
|
|
153
153
|
],
|
|
154
154
|
"properties": {
|
|
155
|
-
"
|
|
155
|
+
"id": {
|
|
156
156
|
"$ref": "#/definitions/objectId",
|
|
157
|
-
"description": "Unique credential identifier"
|
|
157
|
+
"description": "Unique credential identifier (maps to _id in MongoDB)"
|
|
158
158
|
},
|
|
159
159
|
"userId": {
|
|
160
160
|
"$ref": "#/definitions/objectId",
|
|
@@ -165,12 +165,12 @@
|
|
|
165
165
|
"description": "External system identifier",
|
|
166
166
|
"maxLength": 255
|
|
167
167
|
},
|
|
168
|
-
"
|
|
168
|
+
"authIsValid": {
|
|
169
169
|
"type": "boolean",
|
|
170
170
|
"description": "Whether authentication is currently valid",
|
|
171
171
|
"default": false
|
|
172
172
|
},
|
|
173
|
-
"
|
|
173
|
+
"data": {
|
|
174
174
|
"type": "object",
|
|
175
175
|
"description": "Encrypted authentication data",
|
|
176
176
|
"properties": {
|
|
@@ -263,14 +263,14 @@
|
|
|
263
263
|
"type": "object",
|
|
264
264
|
"description": "Frigg Entity model schema",
|
|
265
265
|
"required": [
|
|
266
|
-
"
|
|
266
|
+
"id",
|
|
267
267
|
"credentialId",
|
|
268
268
|
"userId"
|
|
269
269
|
],
|
|
270
270
|
"properties": {
|
|
271
|
-
"
|
|
271
|
+
"id": {
|
|
272
272
|
"$ref": "#/definitions/objectId",
|
|
273
|
-
"description": "Unique entity identifier"
|
|
273
|
+
"description": "Unique entity identifier (maps to _id in MongoDB)"
|
|
274
274
|
},
|
|
275
275
|
"credentialId": {
|
|
276
276
|
"$ref": "#/definitions/objectId",
|
|
@@ -423,7 +423,7 @@
|
|
|
423
423
|
"examples": [
|
|
424
424
|
{
|
|
425
425
|
"user": {
|
|
426
|
-
"
|
|
426
|
+
"id": "507f1f77bcf86cd799439011",
|
|
427
427
|
"email": "user@example.com",
|
|
428
428
|
"firstName": "John",
|
|
429
429
|
"lastName": "Doe",
|
|
@@ -446,11 +446,11 @@
|
|
|
446
446
|
"updatedAt": "2023-01-01T00:00:00Z"
|
|
447
447
|
},
|
|
448
448
|
"credential": {
|
|
449
|
-
"
|
|
449
|
+
"id": "507f1f77bcf86cd799439012",
|
|
450
450
|
"userId": "507f1f77bcf86cd799439011",
|
|
451
451
|
"externalId": "12345",
|
|
452
|
-
"
|
|
453
|
-
"
|
|
452
|
+
"authIsValid": true,
|
|
453
|
+
"data": {
|
|
454
454
|
"access_token": "encrypted_access_token",
|
|
455
455
|
"refresh_token": "encrypted_refresh_token",
|
|
456
456
|
"token_type": "Bearer",
|
|
@@ -466,7 +466,7 @@
|
|
|
466
466
|
"updatedAt": "2023-01-01T00:00:00Z"
|
|
467
467
|
},
|
|
468
468
|
"entity": {
|
|
469
|
-
"
|
|
469
|
+
"id": "507f1f77bcf86cd799439013",
|
|
470
470
|
"credentialId": "507f1f77bcf86cd799439012",
|
|
471
471
|
"userId": "507f1f77bcf86cd799439011",
|
|
472
472
|
"name": "HubSpot Contacts",
|