@fabrika/provider-zerops 0.3.3 → 0.4.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/package.json +7 -6
- package/src/api/client.ts +11 -2
- package/src/api/types.ts +13 -0
- package/src/cli.ts +21 -4
- package/src/collaborators.ts +4 -0
- package/src/control.ts +37 -8
- package/src/execution.ts +371 -0
- package/src/exposure.ts +95 -0
- package/src/installation/deploy-options.ts +12 -1
- package/src/installation/deploy.ts +42 -18
- package/src/installation/generated/platform-console-schema.ts +4 -0
- package/src/installation/generated/platform-proxy-manifest.ts +533 -33
- package/src/installation/index.ts +11 -0
- package/src/installation/install-environment.ts +1 -2
- package/src/installation/machine-key.ts +3 -4
- package/src/installation/manifest.ts +1 -1
- package/src/installation/mcp.ts +102 -0
- package/src/installation/placement-options.ts +2 -1
- package/src/installation/proxy-manifest.ts +124 -23
- package/src/installation/secrets.ts +2 -2
- package/src/installation/templates/README.md +20 -11
- package/src/installation/templates/platform.yml +2 -0
- package/src/installation/topology/setups.ts +5 -5
- package/src/managed-env.ts +94 -6
- package/src/manifest.ts +248 -14
- package/src/namespace/codec.ts +23 -12
- package/src/namespace/errors.ts +1 -1
- package/src/namespace/manifest.ts +25 -6
- package/src/namespace/provisioning.ts +10 -29
- package/src/namespace/proxy-attempt.ts +13 -2
- package/src/namespace/proxy-secrets.ts +21 -0
- package/src/namespace/update.ts +212 -0
- package/src/namespace/validation.ts +43 -0
- package/src/plan.ts +6 -0
- package/src/provider.ts +160 -12
- package/src/types.ts +14 -3
|
@@ -4,13 +4,17 @@
|
|
|
4
4
|
// Regenerate: bun run --filter @fabrika/platform-artifacts gen
|
|
5
5
|
//
|
|
6
6
|
// The installation-independent half of `FABRIKA_PROXY_MANIFEST_JSON`: which apps the platform proxy
|
|
7
|
-
// fronts, at which private upstream, on which public listener, under which
|
|
8
|
-
// browser-facing scheme belong to ONE installation and are supplied at deploy time —
|
|
7
|
+
// fronts, at which private upstream, on which public listener, under which service table. The hosts and
|
|
8
|
+
// the browser-facing scheme belong to ONE installation and are supplied at deploy time —
|
|
9
9
|
// `resolvePlatformProxyManifest` binds them.
|
|
10
10
|
//
|
|
11
|
-
// The
|
|
12
|
-
//
|
|
13
|
-
//
|
|
11
|
+
// The tables below are the services' own service contracts as of the last regeneration, copied on
|
|
12
|
+
// purpose: a PUBLISHED deploy command may not import the private packages that own them. `gen:check` in
|
|
13
|
+
// CI is what makes the copy a fact rather than a hope.
|
|
14
|
+
//
|
|
15
|
+
// The console's `oauthResource` is its MCP endpoint, copied the same way. A deploy publishes the console's
|
|
16
|
+
// `table` and registers the resource only on an installation that enables MCP authoring, and its
|
|
17
|
+
// `tableWithoutOAuth` otherwise.
|
|
14
18
|
|
|
15
19
|
import type { PlatformProxyManifestTemplate } from '../proxy-manifest'
|
|
16
20
|
|
|
@@ -21,10 +25,170 @@ export const PLATFORM_PROXY_MANIFEST_TEMPLATE: PlatformProxyManifestTemplate = {
|
|
|
21
25
|
service: 'iam',
|
|
22
26
|
port: 8080,
|
|
23
27
|
upstream: 'iam:3000',
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{
|
|
28
|
+
table: {
|
|
29
|
+
endpoints: [
|
|
30
|
+
{
|
|
31
|
+
id: 'health',
|
|
32
|
+
kind: 'health',
|
|
33
|
+
method: '*',
|
|
34
|
+
path: '/healthz',
|
|
35
|
+
callers: [],
|
|
36
|
+
requirement: null,
|
|
37
|
+
admission: null,
|
|
38
|
+
oauth: null,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'jwks',
|
|
42
|
+
kind: 'protocol',
|
|
43
|
+
method: '*',
|
|
44
|
+
path: '/.well-known/jwks.json',
|
|
45
|
+
callers: [],
|
|
46
|
+
requirement: null,
|
|
47
|
+
admission: null,
|
|
48
|
+
oauth: null,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'oauth-metadata',
|
|
52
|
+
kind: 'protocol',
|
|
53
|
+
method: '*',
|
|
54
|
+
path: '/.well-known/oauth-authorization-server',
|
|
55
|
+
callers: [],
|
|
56
|
+
requirement: null,
|
|
57
|
+
admission: null,
|
|
58
|
+
oauth: null,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'oauth',
|
|
62
|
+
kind: 'protocol',
|
|
63
|
+
method: '*',
|
|
64
|
+
path: '/oauth/*',
|
|
65
|
+
callers: [],
|
|
66
|
+
requirement: null,
|
|
67
|
+
admission: null,
|
|
68
|
+
oauth: null,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'auth-root',
|
|
72
|
+
kind: 'protocol',
|
|
73
|
+
method: '*',
|
|
74
|
+
path: '/auth',
|
|
75
|
+
callers: [],
|
|
76
|
+
requirement: null,
|
|
77
|
+
admission: null,
|
|
78
|
+
oauth: null,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 'auth',
|
|
82
|
+
kind: 'protocol',
|
|
83
|
+
method: '*',
|
|
84
|
+
path: '/auth/*',
|
|
85
|
+
callers: [],
|
|
86
|
+
requirement: null,
|
|
87
|
+
admission: null,
|
|
88
|
+
oauth: null,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: 'mint-session',
|
|
92
|
+
kind: 'protocol',
|
|
93
|
+
method: '*',
|
|
94
|
+
path: '/auth/mint/session',
|
|
95
|
+
callers: [],
|
|
96
|
+
requirement: null,
|
|
97
|
+
admission: null,
|
|
98
|
+
oauth: null,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
id: 'mint-key',
|
|
102
|
+
kind: 'protocol',
|
|
103
|
+
method: '*',
|
|
104
|
+
path: '/auth/mint/key',
|
|
105
|
+
callers: [],
|
|
106
|
+
requirement: null,
|
|
107
|
+
admission: null,
|
|
108
|
+
oauth: null,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: 'mint-exchange',
|
|
112
|
+
kind: 'protocol',
|
|
113
|
+
method: '*',
|
|
114
|
+
path: '/auth/mint/exchange',
|
|
115
|
+
callers: [],
|
|
116
|
+
requirement: null,
|
|
117
|
+
admission: null,
|
|
118
|
+
oauth: null,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: 'mint-delegation',
|
|
122
|
+
kind: 'protocol',
|
|
123
|
+
method: '*',
|
|
124
|
+
path: '/auth/mint/delegation',
|
|
125
|
+
callers: [],
|
|
126
|
+
requirement: null,
|
|
127
|
+
admission: null,
|
|
128
|
+
oauth: null,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
id: 'admin-rpc',
|
|
132
|
+
kind: 'protocol',
|
|
133
|
+
method: 'POST',
|
|
134
|
+
path: '/admin/rpc',
|
|
135
|
+
callers: [],
|
|
136
|
+
requirement: null,
|
|
137
|
+
admission: null,
|
|
138
|
+
oauth: null,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: 'admin-root',
|
|
142
|
+
kind: 'protocol',
|
|
143
|
+
method: '*',
|
|
144
|
+
path: '/admin',
|
|
145
|
+
callers: [],
|
|
146
|
+
requirement: null,
|
|
147
|
+
admission: null,
|
|
148
|
+
oauth: null,
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: 'admin',
|
|
152
|
+
kind: 'protocol',
|
|
153
|
+
method: '*',
|
|
154
|
+
path: '/admin/*',
|
|
155
|
+
callers: [],
|
|
156
|
+
requirement: null,
|
|
157
|
+
admission: null,
|
|
158
|
+
oauth: null,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: 'membership',
|
|
162
|
+
kind: 'protocol',
|
|
163
|
+
method: '*',
|
|
164
|
+
path: '/membership/*',
|
|
165
|
+
callers: [],
|
|
166
|
+
requirement: null,
|
|
167
|
+
admission: null,
|
|
168
|
+
oauth: null,
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: 'rpc-root',
|
|
172
|
+
kind: 'protocol',
|
|
173
|
+
method: '*',
|
|
174
|
+
path: '/rpc',
|
|
175
|
+
callers: [],
|
|
176
|
+
requirement: null,
|
|
177
|
+
admission: null,
|
|
178
|
+
oauth: null,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: 'rpc',
|
|
182
|
+
kind: 'protocol',
|
|
183
|
+
method: '*',
|
|
184
|
+
path: '/rpc/*',
|
|
185
|
+
callers: [],
|
|
186
|
+
requirement: null,
|
|
187
|
+
admission: null,
|
|
188
|
+
oauth: null,
|
|
189
|
+
},
|
|
27
190
|
],
|
|
191
|
+
reservedPrefixes: ['/auth/mint', '/rpc'],
|
|
28
192
|
},
|
|
29
193
|
},
|
|
30
194
|
{
|
|
@@ -32,28 +196,345 @@ export const PLATFORM_PROXY_MANIFEST_TEMPLATE: PlatformProxyManifestTemplate = {
|
|
|
32
196
|
service: 'control',
|
|
33
197
|
port: 8082,
|
|
34
198
|
upstream: 'control:3000',
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
199
|
+
table: {
|
|
200
|
+
endpoints: [
|
|
201
|
+
{
|
|
202
|
+
id: 'health',
|
|
203
|
+
kind: 'health',
|
|
204
|
+
method: '*',
|
|
205
|
+
path: '/healthz',
|
|
206
|
+
callers: [],
|
|
207
|
+
requirement: null,
|
|
208
|
+
admission: null,
|
|
209
|
+
oauth: null,
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
id: 'api-health',
|
|
213
|
+
kind: 'health',
|
|
214
|
+
method: '*',
|
|
215
|
+
path: '/api/health',
|
|
216
|
+
callers: [],
|
|
217
|
+
requirement: null,
|
|
218
|
+
admission: null,
|
|
219
|
+
oauth: null,
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
id: 'builder-discovery',
|
|
223
|
+
kind: 'protocol',
|
|
224
|
+
method: '*',
|
|
225
|
+
path: '/.well-known/fabrika-builder',
|
|
226
|
+
callers: [],
|
|
227
|
+
requirement: null,
|
|
228
|
+
admission: null,
|
|
229
|
+
oauth: null,
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: 'builder-connect',
|
|
233
|
+
kind: 'protocol',
|
|
234
|
+
method: '*',
|
|
235
|
+
path: '/builder/connect',
|
|
236
|
+
callers: [],
|
|
237
|
+
requirement: null,
|
|
238
|
+
admission: null,
|
|
239
|
+
oauth: null,
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
id: 'github-webhook',
|
|
243
|
+
kind: 'protocol',
|
|
244
|
+
method: 'POST',
|
|
245
|
+
path: '/webhooks/github/:connectionId',
|
|
246
|
+
callers: [],
|
|
247
|
+
requirement: null,
|
|
248
|
+
admission: null,
|
|
249
|
+
oauth: null,
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
id: 'webhooks-root',
|
|
253
|
+
kind: 'service',
|
|
254
|
+
method: '*',
|
|
255
|
+
path: '/webhooks',
|
|
256
|
+
callers: ['human'],
|
|
257
|
+
requirement: { kind: 'authenticated' },
|
|
258
|
+
admission: null,
|
|
259
|
+
oauth: null,
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
id: 'github-manifest',
|
|
263
|
+
kind: 'service',
|
|
264
|
+
method: 'GET',
|
|
265
|
+
path: '/api/source/github/manifest/:connectionId',
|
|
266
|
+
callers: ['human'],
|
|
267
|
+
requirement: { kind: 'authenticated' },
|
|
268
|
+
admission: null,
|
|
269
|
+
oauth: null,
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
id: 'github-callback',
|
|
273
|
+
kind: 'service',
|
|
274
|
+
method: 'GET',
|
|
275
|
+
path: '/api/source/github/callback',
|
|
276
|
+
callers: ['human'],
|
|
277
|
+
requirement: { kind: 'authenticated' },
|
|
278
|
+
admission: null,
|
|
279
|
+
oauth: null,
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
id: 'rpc',
|
|
283
|
+
kind: 'service',
|
|
284
|
+
method: 'POST',
|
|
285
|
+
path: '/api/rpc',
|
|
286
|
+
callers: ['human', 'machine'],
|
|
287
|
+
requirement: { kind: 'authenticated' },
|
|
288
|
+
admission: { contentTypes: ['application/json'], maxBytes: null },
|
|
289
|
+
oauth: null,
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
id: 'api-root',
|
|
293
|
+
kind: 'service',
|
|
294
|
+
method: '*',
|
|
295
|
+
path: '/api',
|
|
296
|
+
callers: ['human'],
|
|
297
|
+
requirement: { kind: 'authenticated' },
|
|
298
|
+
admission: null,
|
|
299
|
+
oauth: null,
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
id: 'iam-admin-rpc',
|
|
303
|
+
kind: 'service',
|
|
304
|
+
method: 'POST',
|
|
305
|
+
path: '/iam/admin/rpc',
|
|
306
|
+
callers: ['human', 'machine'],
|
|
307
|
+
requirement: { kind: 'authenticated' },
|
|
308
|
+
admission: { contentTypes: ['application/json'], maxBytes: null },
|
|
309
|
+
oauth: null,
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
id: 'iam-admin-root',
|
|
313
|
+
kind: 'service',
|
|
314
|
+
method: '*',
|
|
315
|
+
path: '/iam/admin',
|
|
316
|
+
callers: ['human', 'machine'],
|
|
317
|
+
requirement: { kind: 'authenticated' },
|
|
318
|
+
admission: null,
|
|
319
|
+
oauth: null,
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
id: 'operations-rpc',
|
|
323
|
+
kind: 'service',
|
|
324
|
+
method: 'POST',
|
|
325
|
+
path: '/operations/api/rpc',
|
|
326
|
+
callers: ['human', 'machine'],
|
|
327
|
+
requirement: { kind: 'authenticated' },
|
|
328
|
+
admission: { contentTypes: ['application/json'], maxBytes: null },
|
|
329
|
+
oauth: null,
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
id: 'operations-api-root',
|
|
333
|
+
kind: 'service',
|
|
334
|
+
method: '*',
|
|
335
|
+
path: '/operations/api',
|
|
336
|
+
callers: ['human', 'machine'],
|
|
337
|
+
requirement: { kind: 'authenticated' },
|
|
338
|
+
admission: null,
|
|
339
|
+
oauth: null,
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
id: 'console',
|
|
343
|
+
kind: 'service',
|
|
344
|
+
method: 'GET',
|
|
345
|
+
path: '/*',
|
|
346
|
+
callers: ['human'],
|
|
347
|
+
requirement: { kind: 'authenticated' },
|
|
348
|
+
admission: null,
|
|
349
|
+
oauth: null,
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
id: 'mcp',
|
|
353
|
+
kind: 'service',
|
|
354
|
+
method: '*',
|
|
355
|
+
path: '/mcp',
|
|
356
|
+
callers: ['oauth'],
|
|
357
|
+
requirement: { kind: 'authenticated' },
|
|
358
|
+
admission: null,
|
|
359
|
+
oauth: { scopes: ['authoring'] },
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
reservedPrefixes: ['/api', '/iam/admin', '/operations/api', '/webhooks', '/mcp'],
|
|
363
|
+
},
|
|
364
|
+
oauthResource: {
|
|
365
|
+
path: '/mcp',
|
|
366
|
+
scopes: ['authoring'],
|
|
367
|
+
scopeGrants: [
|
|
368
|
+
{
|
|
369
|
+
scope: 'authoring',
|
|
370
|
+
actions: ['source.workspace.read', 'source.workspace.write', 'source.pull-request.create', 'deploy.trigger', 'deploy.read'],
|
|
371
|
+
},
|
|
372
|
+
],
|
|
373
|
+
},
|
|
374
|
+
tableWithoutOAuth: {
|
|
375
|
+
endpoints: [
|
|
376
|
+
{
|
|
377
|
+
id: 'health',
|
|
378
|
+
kind: 'health',
|
|
379
|
+
method: '*',
|
|
380
|
+
path: '/healthz',
|
|
381
|
+
callers: [],
|
|
382
|
+
requirement: null,
|
|
383
|
+
admission: null,
|
|
384
|
+
oauth: null,
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
id: 'api-health',
|
|
388
|
+
kind: 'health',
|
|
389
|
+
method: '*',
|
|
390
|
+
path: '/api/health',
|
|
391
|
+
callers: [],
|
|
392
|
+
requirement: null,
|
|
393
|
+
admission: null,
|
|
394
|
+
oauth: null,
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
id: 'builder-discovery',
|
|
398
|
+
kind: 'protocol',
|
|
399
|
+
method: '*',
|
|
400
|
+
path: '/.well-known/fabrika-builder',
|
|
401
|
+
callers: [],
|
|
402
|
+
requirement: null,
|
|
403
|
+
admission: null,
|
|
404
|
+
oauth: null,
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
id: 'builder-connect',
|
|
408
|
+
kind: 'protocol',
|
|
409
|
+
method: '*',
|
|
410
|
+
path: '/builder/connect',
|
|
411
|
+
callers: [],
|
|
412
|
+
requirement: null,
|
|
413
|
+
admission: null,
|
|
414
|
+
oauth: null,
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
id: 'github-webhook',
|
|
418
|
+
kind: 'protocol',
|
|
419
|
+
method: 'POST',
|
|
420
|
+
path: '/webhooks/github/:connectionId',
|
|
421
|
+
callers: [],
|
|
422
|
+
requirement: null,
|
|
423
|
+
admission: null,
|
|
424
|
+
oauth: null,
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
id: 'webhooks-root',
|
|
428
|
+
kind: 'service',
|
|
429
|
+
method: '*',
|
|
430
|
+
path: '/webhooks',
|
|
431
|
+
callers: ['human'],
|
|
432
|
+
requirement: { kind: 'authenticated' },
|
|
433
|
+
admission: null,
|
|
434
|
+
oauth: null,
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
id: 'github-manifest',
|
|
438
|
+
kind: 'service',
|
|
439
|
+
method: 'GET',
|
|
440
|
+
path: '/api/source/github/manifest/:connectionId',
|
|
441
|
+
callers: ['human'],
|
|
442
|
+
requirement: { kind: 'authenticated' },
|
|
443
|
+
admission: null,
|
|
444
|
+
oauth: null,
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
id: 'github-callback',
|
|
448
|
+
kind: 'service',
|
|
449
|
+
method: 'GET',
|
|
450
|
+
path: '/api/source/github/callback',
|
|
451
|
+
callers: ['human'],
|
|
452
|
+
requirement: { kind: 'authenticated' },
|
|
453
|
+
admission: null,
|
|
454
|
+
oauth: null,
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
id: 'rpc',
|
|
458
|
+
kind: 'service',
|
|
459
|
+
method: 'POST',
|
|
460
|
+
path: '/api/rpc',
|
|
461
|
+
callers: ['human', 'machine'],
|
|
462
|
+
requirement: { kind: 'authenticated' },
|
|
463
|
+
admission: { contentTypes: ['application/json'], maxBytes: null },
|
|
464
|
+
oauth: null,
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
id: 'api-root',
|
|
468
|
+
kind: 'service',
|
|
469
|
+
method: '*',
|
|
470
|
+
path: '/api',
|
|
471
|
+
callers: ['human'],
|
|
472
|
+
requirement: { kind: 'authenticated' },
|
|
473
|
+
admission: null,
|
|
474
|
+
oauth: null,
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
id: 'iam-admin-rpc',
|
|
478
|
+
kind: 'service',
|
|
479
|
+
method: 'POST',
|
|
480
|
+
path: '/iam/admin/rpc',
|
|
481
|
+
callers: ['human', 'machine'],
|
|
482
|
+
requirement: { kind: 'authenticated' },
|
|
483
|
+
admission: { contentTypes: ['application/json'], maxBytes: null },
|
|
484
|
+
oauth: null,
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
id: 'iam-admin-root',
|
|
488
|
+
kind: 'service',
|
|
489
|
+
method: '*',
|
|
490
|
+
path: '/iam/admin',
|
|
491
|
+
callers: ['human', 'machine'],
|
|
492
|
+
requirement: { kind: 'authenticated' },
|
|
493
|
+
admission: null,
|
|
494
|
+
oauth: null,
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
id: 'operations-rpc',
|
|
498
|
+
kind: 'service',
|
|
499
|
+
method: 'POST',
|
|
500
|
+
path: '/operations/api/rpc',
|
|
501
|
+
callers: ['human', 'machine'],
|
|
502
|
+
requirement: { kind: 'authenticated' },
|
|
503
|
+
admission: { contentTypes: ['application/json'], maxBytes: null },
|
|
504
|
+
oauth: null,
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
id: 'operations-api-root',
|
|
508
|
+
kind: 'service',
|
|
509
|
+
method: '*',
|
|
510
|
+
path: '/operations/api',
|
|
511
|
+
callers: ['human', 'machine'],
|
|
512
|
+
requirement: { kind: 'authenticated' },
|
|
513
|
+
admission: null,
|
|
514
|
+
oauth: null,
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
id: 'console',
|
|
518
|
+
kind: 'service',
|
|
519
|
+
method: 'GET',
|
|
520
|
+
path: '/*',
|
|
521
|
+
callers: ['human'],
|
|
522
|
+
requirement: { kind: 'authenticated' },
|
|
523
|
+
admission: null,
|
|
524
|
+
oauth: null,
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
id: 'mcp',
|
|
528
|
+
kind: 'service',
|
|
529
|
+
method: '*',
|
|
530
|
+
path: '/mcp',
|
|
531
|
+
callers: ['human'],
|
|
532
|
+
requirement: { kind: 'authenticated' },
|
|
533
|
+
admission: null,
|
|
534
|
+
oauth: null,
|
|
535
|
+
},
|
|
56
536
|
],
|
|
537
|
+
reservedPrefixes: ['/api', '/iam/admin', '/operations/api', '/webhooks', '/mcp'],
|
|
57
538
|
},
|
|
58
539
|
},
|
|
59
540
|
{
|
|
@@ -61,11 +542,30 @@ export const PLATFORM_PROXY_MANIFEST_TEMPLATE: PlatformProxyManifestTemplate = {
|
|
|
61
542
|
service: 'operations',
|
|
62
543
|
port: 8083,
|
|
63
544
|
upstream: 'operations:3000',
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{
|
|
67
|
-
|
|
545
|
+
table: {
|
|
546
|
+
endpoints: [
|
|
547
|
+
{
|
|
548
|
+
id: 'ingest',
|
|
549
|
+
kind: 'protocol',
|
|
550
|
+
method: '*',
|
|
551
|
+
path: '/api/:projectId/envelope/',
|
|
552
|
+
callers: [],
|
|
553
|
+
requirement: null,
|
|
554
|
+
admission: null,
|
|
555
|
+
oauth: null,
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
id: 'source-map-upload',
|
|
559
|
+
kind: 'protocol',
|
|
560
|
+
method: '*',
|
|
561
|
+
path: '/api/artifacts/source-maps/',
|
|
562
|
+
callers: [],
|
|
563
|
+
requirement: null,
|
|
564
|
+
admission: null,
|
|
565
|
+
oauth: null,
|
|
566
|
+
},
|
|
68
567
|
],
|
|
568
|
+
reservedPrefixes: [],
|
|
69
569
|
},
|
|
70
570
|
},
|
|
71
571
|
],
|
|
@@ -28,13 +28,17 @@ import { parsePlatformUpgradeArgs, UPGRADE_DRY_RUN_FLAG } from './upgrade-option
|
|
|
28
28
|
export { PLATFORM_CONCURRENT_DEPLOY, PLATFORM_DEPLOY_ORDER, PLATFORM_PROXY_SERVICE, PLATFORM_SEQUENTIAL_DEPLOY } from './deploy'
|
|
29
29
|
export { PLATFORM_CONSOLE_APP_SCHEMA } from './generated/platform-console-schema'
|
|
30
30
|
export { PLATFORM_PROXY_MANIFEST_TEMPLATE } from './generated/platform-proxy-manifest'
|
|
31
|
+
export { type IamOAuthConfig, type McpClient, parseMcpClientsJson, platformIamOAuthConfig } from './mcp'
|
|
31
32
|
export {
|
|
33
|
+
type PlatformOAuthResourceTemplate,
|
|
32
34
|
type PlatformProxyApp,
|
|
33
35
|
platformProxyAppFor,
|
|
34
36
|
type PlatformProxyComposition,
|
|
37
|
+
type PlatformProxyManifest,
|
|
35
38
|
type PlatformProxyManifestTemplate,
|
|
36
39
|
type PlatformProxyPlacement,
|
|
37
40
|
type PlatformProxyService,
|
|
41
|
+
platformServiceTableDigest,
|
|
38
42
|
resolvePlatformProxyManifest,
|
|
39
43
|
} from './proxy-manifest'
|
|
40
44
|
|
|
@@ -201,6 +205,7 @@ Options (a flag beats the environment variable beside it):
|
|
|
201
205
|
--operations-host=<host> FABRIKA_PLATFORM_OPERATIONS_HOST
|
|
202
206
|
--scheme=<http|https> FABRIKA_PLATFORM_SCHEME default https
|
|
203
207
|
--source-dir=<checkout> required clean full checkout running this CLI
|
|
208
|
+
--mcp-clients=<json> FABRIKA_PLATFORM_MCP_CLIENTS_JSON MCP authoring clients; unset = off
|
|
204
209
|
--dry-run read everything, change nothing
|
|
205
210
|
|
|
206
211
|
Naming NO host derives all three from the proxy service's Zerops subdomains and makes this a
|
|
@@ -208,6 +213,12 @@ Naming NO host derives all three from the proxy service's Zerops subdomains and
|
|
|
208
213
|
\`custom-domain\` installation: the domains are bound to the project balancer out of band and no
|
|
209
214
|
subdomain is published.
|
|
210
215
|
|
|
216
|
+
MCP authoring (ADR-0049) is opt-in. --mcp-clients takes a JSON array of the MCP clients this
|
|
217
|
+
installation trusts: [{"provider":"claude"|"chatgpt","clientId":"<https CIMD URL>","redirectUris":[...],
|
|
218
|
+
"metadataUrl":"<https URL>"?}]. With it, the console's /mcp admits OAuth bearers and IAM gets
|
|
219
|
+
FABRIKA_IAM_OAUTH_CONFIG. Without it, /mcp admits only a signed-in person and FABRIKA_IAM_OAUTH_CONFIG on
|
|
220
|
+
iam is left as it is.
|
|
221
|
+
|
|
211
222
|
Credentials are read from the ENVIRONMENT ONLY and have no flag, so they cannot reach a CI log or a
|
|
212
223
|
process listing:
|
|
213
224
|
|
|
@@ -75,8 +75,7 @@ export const installationServiceEnv = (input: InstallationEnvInput): ReadonlyMap
|
|
|
75
75
|
const control = new Map([
|
|
76
76
|
['FABRIKA_CONTROL_DATABASE_URL', POSTGRES_URL],
|
|
77
77
|
['ENVIRONMENT', input.environment],
|
|
78
|
-
// A bare HOST, not an origin: `controlPublicOrigin` accepts either
|
|
79
|
-
// same-origin check on both first-party gateways is decided against.
|
|
78
|
+
// A bare HOST, not an origin: `controlPublicOrigin` accepts either.
|
|
80
79
|
['FABRIKA_CONTROL_DOMAIN', input.hosts.control],
|
|
81
80
|
['FABRIKA_IAM_ISSUER', iamOrigin],
|
|
82
81
|
['OPERATIONS_ARTIFACT_ORIGIN', operationsOrigin],
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
// The acceptance is a fresh shell holding nothing: paste the block, supply the two keys, mint a key on
|
|
12
12
|
// the first try. So the origin is an `export` — a bare `NAME=value` sets a shell variable the child
|
|
13
13
|
// process never sees — and EVERY other line is a `#` comment. The command line is commented too, and
|
|
14
|
-
// that is not timidity: `--label=<name>` is a shell redirection, and
|
|
15
|
-
// a `>` that would create a file called `]` in whatever directory the operator pasted into.
|
|
14
|
+
// that is not timidity: `--label=<name>` is a shell redirection, and so is every other `<…>` placeholder.
|
|
16
15
|
//
|
|
17
16
|
// HARD RULE: no function here takes a key. The block is composed from an ORIGIN and variable NAMES,
|
|
18
17
|
// so a caller that is holding the real values (both verbs are) cannot leak one through it.
|
|
@@ -28,8 +27,8 @@ export interface MachineKeyNextStep {
|
|
|
28
27
|
/** The boxed hand-off's title. Exported so a test names it once. */
|
|
29
28
|
export const MACHINE_KEY_NEXT_STEP_TITLE = 'NEXT — mint a machine key for `fabrika control`'
|
|
30
29
|
|
|
31
|
-
/** The command the block leads to, with the
|
|
32
|
-
export const MACHINE_KEY_ISSUE_COMMAND = 'fabrika control key issue --label=<name> --permissions=<a,b,c>
|
|
30
|
+
/** The command the block leads to, with the three flags `key issue` requires. */
|
|
31
|
+
export const MACHINE_KEY_ISSUE_COMMAND = 'fabrika control key issue --label=<name> --permissions=<a,b,c> --expires-in=<seconds>'
|
|
33
32
|
|
|
34
33
|
const WIDEST_NAME = 'FABRIKA_IAM_PROVISIONING_KEY'.length + 1
|
|
35
34
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// On the `light` tier an application shares the platform's project and therefore the platform proxy's
|
|
6
6
|
// single `FABRIKA_PROXY_MANIFEST_JSON`. The live document on `fabrika-test` carries a fourth app —
|
|
7
7
|
// `notes` → `notesapi:3000` on listener 8084 — beside the three platform ones. `platformProxyManifest`
|
|
8
|
-
// deliberately emits only the platform apps (it is generated from the platform's own
|
|
8
|
+
// deliberately emits only the platform apps (it is generated from the platform's own service contracts and
|
|
9
9
|
// knows nothing about applications), so writing it alone would DELETE every application entry and take
|
|
10
10
|
// the deployed applications offline at the next proxy build.
|
|
11
11
|
//
|