@betterportal/auth-default 10.6.21 → 10.6.23

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.
Files changed (128) hide show
  1. package/README.md +140 -10
  2. package/bsb-plugin.json +1 -1
  3. package/lib/account.d.ts +16 -0
  4. package/lib/account.d.ts.map +1 -0
  5. package/lib/account.js +274 -0
  6. package/lib/account.js.map +1 -0
  7. package/lib/accountUI.d.ts +5 -0
  8. package/lib/accountUI.d.ts.map +1 -0
  9. package/lib/accountUI.js +68 -0
  10. package/lib/accountUI.js.map +1 -0
  11. package/lib/bp-contracts/org.betterportal.auth.default.json +2031 -707
  12. package/lib/clientAddress.d.ts +10 -0
  13. package/lib/clientAddress.d.ts.map +1 -0
  14. package/lib/clientAddress.js +35 -0
  15. package/lib/clientAddress.js.map +1 -0
  16. package/lib/config.d.ts +3 -0
  17. package/lib/config.d.ts.map +1 -0
  18. package/lib/config.js +28 -0
  19. package/lib/config.js.map +1 -0
  20. package/lib/defaultAuthManifest.d.ts +7 -0
  21. package/lib/defaultAuthManifest.d.ts.map +1 -1
  22. package/lib/factors.d.ts +18 -0
  23. package/lib/factors.d.ts.map +1 -0
  24. package/lib/factors.js +95 -0
  25. package/lib/factors.js.map +1 -0
  26. package/lib/identity.d.ts +106 -0
  27. package/lib/identity.d.ts.map +1 -0
  28. package/lib/identity.js +315 -0
  29. package/lib/identity.js.map +1 -0
  30. package/lib/index.d.ts +4 -0
  31. package/lib/index.d.ts.map +1 -1
  32. package/lib/index.js +4 -0
  33. package/lib/index.js.map +1 -1
  34. package/lib/mail.d.ts +19 -0
  35. package/lib/mail.d.ts.map +1 -0
  36. package/lib/mail.js +102 -0
  37. package/lib/mail.js.map +1 -0
  38. package/lib/plugins/service-betterportal-auth-default/.bp-generated/registry.d.ts +435 -11
  39. package/lib/plugins/service-betterportal-auth-default/.bp-generated/registry.d.ts.map +1 -1
  40. package/lib/plugins/service-betterportal-auth-default/.bp-generated/registry.js +85 -0
  41. package/lib/plugins/service-betterportal-auth-default/.bp-generated/registry.js.map +1 -1
  42. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/GET.d.ts +34 -0
  43. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/GET.d.ts.map +1 -0
  44. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/GET.js +25 -0
  45. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/GET.js.map +1 -0
  46. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/POST.d.ts +42 -0
  47. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/POST.d.ts.map +1 -0
  48. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/POST.js +27 -0
  49. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/POST.js.map +1 -0
  50. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/_renderer.bootstrap5/GET.d.ts +2 -0
  51. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/_renderer.bootstrap5/GET.d.ts.map +1 -0
  52. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/_renderer.bootstrap5/GET.js +2 -0
  53. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/_renderer.bootstrap5/GET.js.map +1 -0
  54. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/_renderer.bootstrap5/POST.d.ts +2 -0
  55. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/_renderer.bootstrap5/POST.d.ts.map +1 -0
  56. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/_renderer.bootstrap5/POST.js +2 -0
  57. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/_renderer.bootstrap5/POST.js.map +1 -0
  58. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/index.d.ts +3 -0
  59. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/index.d.ts.map +1 -0
  60. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/index.js +3 -0
  61. package/lib/plugins/service-betterportal-auth-default/bp-routes/account/index.js.map +1 -0
  62. package/lib/plugins/service-betterportal-auth-default/bp-routes/login/_renderer.bootstrap5/GET.d.ts.map +1 -1
  63. package/lib/plugins/service-betterportal-auth-default/bp-routes/login/_renderer.bootstrap5/GET.js +11 -8
  64. package/lib/plugins/service-betterportal-auth-default/bp-routes/login/_renderer.bootstrap5/GET.js.map +1 -1
  65. package/lib/plugins/service-betterportal-auth-default/bp-routes/refresh/POST.d.ts +3 -1
  66. package/lib/plugins/service-betterportal-auth-default/bp-routes/refresh/POST.d.ts.map +1 -1
  67. package/lib/plugins/service-betterportal-auth-default/bp-routes/refresh/POST.js +10 -23
  68. package/lib/plugins/service-betterportal-auth-default/bp-routes/refresh/POST.js.map +1 -1
  69. package/lib/plugins/service-betterportal-auth-default/bp-routes/register/_renderer.bootstrap5/GET.d.ts.map +1 -1
  70. package/lib/plugins/service-betterportal-auth-default/bp-routes/register/_renderer.bootstrap5/GET.js +2 -2
  71. package/lib/plugins/service-betterportal-auth-default/bp-routes/register/_renderer.bootstrap5/GET.js.map +1 -1
  72. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/GET.d.ts +34 -0
  73. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/GET.d.ts.map +1 -0
  74. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/GET.js +26 -0
  75. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/GET.js.map +1 -0
  76. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/POST.d.ts +31 -0
  77. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/POST.d.ts.map +1 -0
  78. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/POST.js +23 -0
  79. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/POST.js.map +1 -0
  80. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/_renderer.bootstrap5/GET.d.ts +3 -0
  81. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/_renderer.bootstrap5/GET.d.ts.map +1 -0
  82. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/_renderer.bootstrap5/GET.js +36 -0
  83. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/_renderer.bootstrap5/GET.js.map +1 -0
  84. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/index.d.ts +3 -0
  85. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/index.d.ts.map +1 -0
  86. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/index.js +3 -0
  87. package/lib/plugins/service-betterportal-auth-default/bp-routes/social/index.js.map +1 -0
  88. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/GET.d.ts +32 -0
  89. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/GET.d.ts.map +1 -0
  90. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/GET.js +39 -0
  91. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/GET.js.map +1 -0
  92. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/POST.d.ts +41 -0
  93. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/POST.d.ts.map +1 -0
  94. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/POST.js +103 -0
  95. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/POST.js.map +1 -0
  96. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/_renderer.bootstrap5/GET.d.ts +3 -0
  97. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/_renderer.bootstrap5/GET.d.ts.map +1 -0
  98. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/_renderer.bootstrap5/GET.js +19 -0
  99. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/_renderer.bootstrap5/GET.js.map +1 -0
  100. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/index.d.ts +3 -0
  101. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/index.d.ts.map +1 -0
  102. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/index.js +3 -0
  103. package/lib/plugins/service-betterportal-auth-default/bp-routes/users/index.js.map +1 -0
  104. package/lib/plugins/service-betterportal-auth-default/index.d.ts +41 -4
  105. package/lib/plugins/service-betterportal-auth-default/index.d.ts.map +1 -1
  106. package/lib/plugins/service-betterportal-auth-default/index.js +205 -9
  107. package/lib/plugins/service-betterportal-auth-default/index.js.map +1 -1
  108. package/lib/plugins/service-betterportal-auth-default/loginFlow.d.ts +17 -2
  109. package/lib/plugins/service-betterportal-auth-default/loginFlow.d.ts.map +1 -1
  110. package/lib/plugins/service-betterportal-auth-default/loginFlow.js +83 -62
  111. package/lib/plugins/service-betterportal-auth-default/loginFlow.js.map +1 -1
  112. package/lib/plugins/service-betterportal-auth-default/logoutFlow.js +1 -1
  113. package/lib/plugins/service-betterportal-auth-default/logoutFlow.js.map +1 -1
  114. package/lib/plugins/service-betterportal-auth-default/registrationFlow.d.ts +4 -2
  115. package/lib/plugins/service-betterportal-auth-default/registrationFlow.d.ts.map +1 -1
  116. package/lib/plugins/service-betterportal-auth-default/registrationFlow.js +15 -17
  117. package/lib/plugins/service-betterportal-auth-default/registrationFlow.js.map +1 -1
  118. package/lib/schemas/service-betterportal-auth-default.json +26 -2
  119. package/lib/schemas/service-betterportal-auth-default.plugin.json +27 -3
  120. package/lib/social.d.ts +40 -0
  121. package/lib/social.d.ts.map +1 -0
  122. package/lib/social.js +178 -0
  123. package/lib/social.js.map +1 -0
  124. package/lib/storage.d.ts +72 -0
  125. package/lib/storage.d.ts.map +1 -0
  126. package/lib/storage.js +427 -0
  127. package/lib/storage.js.map +1 -0
  128. package/package.json +13 -6
@@ -3,8 +3,8 @@
3
3
  "protocolVersion": 2,
4
4
  "pluginId": "org.betterportal.auth.default",
5
5
  "title": "BetterPortal Default Auth",
6
- "description": "JWT-issuing auth service (RS256 + JWKS + bcrypt user store).",
7
- "version": "10.6.21",
6
+ "description": "JWT-issuing auth service with isolated account directories, MFA and JSON/PostgreSQL storage.",
7
+ "version": "10.6.23",
8
8
  "category": "service",
9
9
  "deploymentModes": [
10
10
  "self-hosted"
@@ -25,59 +25,1475 @@
25
25
  ],
26
26
  "views": [
27
27
  {
28
- "viewId": "login.index",
29
- "title": "Login",
30
- "description": "Authenticate with username and password to receive a JWT.",
31
- "path": "/login",
28
+ "viewId": "account.index",
29
+ "title": "Account",
30
+ "description": "Register, recover and manage your account and authentication factors.",
31
+ "path": "/account",
32
32
  "pathVariants": [],
33
33
  "paramsSchema": {},
34
34
  "operations": [
35
35
  {
36
- "operationId": "auth.login.view",
36
+ "operationId": "auth.account.view",
37
37
  "method": "GET",
38
- "title": "Login",
39
- "description": "Authenticate with username and password to receive a JWT.",
38
+ "title": "Account",
39
+ "description": "Register, recover and manage your account and authentication factors.",
40
40
  "querySchema": {
41
+ "anyvaliVersion": "1.0",
42
+ "schemaVersion": "1.1",
43
+ "root": {
44
+ "kind": "object",
45
+ "properties": {
46
+ "sessionAfter": {
47
+ "kind": "optional",
48
+ "inner": {
49
+ "kind": "string"
50
+ }
51
+ },
52
+ "action": {
53
+ "kind": "optional",
54
+ "inner": {
55
+ "kind": "string"
56
+ }
57
+ },
58
+ "id": {
59
+ "kind": "optional",
60
+ "inner": {
61
+ "kind": "string"
62
+ }
63
+ },
64
+ "secret": {
65
+ "kind": "optional",
66
+ "inner": {
67
+ "kind": "string"
68
+ }
69
+ }
70
+ },
71
+ "required": [],
72
+ "unknownKeys": "strip"
73
+ },
74
+ "definitions": {},
75
+ "extensions": {}
76
+ },
77
+ "headersSchema": {},
78
+ "bodySchema": {},
79
+ "jsonResponseSchema": {
80
+ "anyvaliVersion": "1.0",
81
+ "schemaVersion": "1.1",
82
+ "root": {
83
+ "kind": "record",
84
+ "valueSchema": {
85
+ "kind": "ref",
86
+ "ref": "#/definitions/BetterPortalJsonValue"
87
+ }
88
+ },
89
+ "definitions": {
90
+ "BetterPortalJsonValue": {
91
+ "kind": "union",
92
+ "variants": [
93
+ {
94
+ "kind": "null"
95
+ },
96
+ {
97
+ "kind": "bool"
98
+ },
99
+ {
100
+ "kind": "string"
101
+ },
102
+ {
103
+ "kind": "number"
104
+ },
105
+ {
106
+ "kind": "array",
107
+ "items": {
108
+ "kind": "ref",
109
+ "ref": "#/definitions/BetterPortalJsonValue"
110
+ }
111
+ },
112
+ {
113
+ "kind": "record",
114
+ "valueSchema": {
115
+ "kind": "ref",
116
+ "ref": "#/definitions/BetterPortalJsonValue"
117
+ }
118
+ }
119
+ ]
120
+ }
121
+ },
122
+ "extensions": {}
123
+ },
124
+ "metadataResponseSchema": {},
125
+ "renderable": true,
126
+ "html": {
127
+ "renderers": {
128
+ "bootstrap5": {
129
+ "defaultRenderer": "default",
130
+ "renderModes": [
131
+ "page"
132
+ ],
133
+ "slots": [
134
+ "main"
135
+ ],
136
+ "renderers": [
137
+ {
138
+ "id": "default",
139
+ "title": "Default Content",
140
+ "slotId": "main",
141
+ "renderModes": [
142
+ "page",
143
+ "fragment"
144
+ ]
145
+ }
146
+ ]
147
+ }
148
+ }
149
+ },
150
+ "auth": {
151
+ "required": false,
152
+ "callers": [
153
+ "user"
154
+ ],
155
+ "permissions": []
156
+ },
157
+ "sitemap": {
158
+ "kind": "default"
159
+ },
160
+ "robots": [],
161
+ "role": "auth.account",
162
+ "dependencies": [
163
+ {
164
+ "operationId": "auth.account",
165
+ "method": "POST"
166
+ }
167
+ ],
168
+ "apiContracts": [],
169
+ "demoScenarios": [],
170
+ "cacheHints": {
171
+ "ttlSeconds": 0,
172
+ "varyBy": []
173
+ }
174
+ },
175
+ {
176
+ "operationId": "auth.account",
177
+ "method": "POST",
178
+ "title": "Account",
179
+ "description": "Register, recover and manage your account and authentication factors.",
180
+ "querySchema": {},
181
+ "headersSchema": {},
182
+ "bodySchema": {
41
183
  "anyvaliVersion": "1.0",
42
184
  "schemaVersion": "1.1",
43
185
  "root": {
44
186
  "kind": "object",
45
187
  "properties": {
46
188
  "action": {
189
+ "kind": "string",
190
+ "minLength": 1
191
+ },
192
+ "id": {
193
+ "kind": "optional",
194
+ "inner": {
195
+ "kind": "string"
196
+ }
197
+ },
198
+ "secret": {
199
+ "kind": "optional",
200
+ "inner": {
201
+ "kind": "string"
202
+ }
203
+ },
204
+ "email": {
205
+ "kind": "optional",
206
+ "inner": {
207
+ "kind": "string"
208
+ }
209
+ },
210
+ "name": {
211
+ "kind": "optional",
212
+ "inner": {
213
+ "kind": "string"
214
+ }
215
+ },
216
+ "password": {
217
+ "kind": "optional",
218
+ "inner": {
219
+ "kind": "string"
220
+ }
221
+ },
222
+ "currentPassword": {
223
+ "kind": "optional",
224
+ "inner": {
225
+ "kind": "string"
226
+ }
227
+ },
228
+ "next": {
229
+ "kind": "optional",
230
+ "inner": {
231
+ "kind": "string"
232
+ }
233
+ },
234
+ "method": {
235
+ "kind": "optional",
236
+ "inner": {
237
+ "kind": "string"
238
+ }
239
+ },
240
+ "code": {
241
+ "kind": "optional",
242
+ "inner": {
243
+ "kind": "string"
244
+ }
245
+ },
246
+ "credential": {
247
+ "kind": "optional",
248
+ "inner": {
249
+ "kind": "record",
250
+ "valueSchema": {
251
+ "kind": "ref",
252
+ "ref": "#/definitions/BetterPortalJsonValue"
253
+ }
254
+ }
255
+ }
256
+ },
257
+ "required": [
258
+ "action"
259
+ ],
260
+ "unknownKeys": "strip"
261
+ },
262
+ "definitions": {
263
+ "BetterPortalJsonValue": {
264
+ "kind": "union",
265
+ "variants": [
266
+ {
267
+ "kind": "null"
268
+ },
269
+ {
270
+ "kind": "bool"
271
+ },
272
+ {
273
+ "kind": "string"
274
+ },
275
+ {
276
+ "kind": "number"
277
+ },
278
+ {
279
+ "kind": "array",
280
+ "items": {
281
+ "kind": "ref",
282
+ "ref": "#/definitions/BetterPortalJsonValue"
283
+ }
284
+ },
285
+ {
286
+ "kind": "record",
287
+ "valueSchema": {
288
+ "kind": "ref",
289
+ "ref": "#/definitions/BetterPortalJsonValue"
290
+ }
291
+ }
292
+ ]
293
+ }
294
+ },
295
+ "extensions": {}
296
+ },
297
+ "jsonResponseSchema": {
298
+ "anyvaliVersion": "1.0",
299
+ "schemaVersion": "1.1",
300
+ "root": {
301
+ "kind": "record",
302
+ "valueSchema": {
303
+ "kind": "ref",
304
+ "ref": "#/definitions/BetterPortalJsonValue"
305
+ }
306
+ },
307
+ "definitions": {
308
+ "BetterPortalJsonValue": {
309
+ "kind": "union",
310
+ "variants": [
311
+ {
312
+ "kind": "null"
313
+ },
314
+ {
315
+ "kind": "bool"
316
+ },
317
+ {
318
+ "kind": "string"
319
+ },
320
+ {
321
+ "kind": "number"
322
+ },
323
+ {
324
+ "kind": "array",
325
+ "items": {
326
+ "kind": "ref",
327
+ "ref": "#/definitions/BetterPortalJsonValue"
328
+ }
329
+ },
330
+ {
331
+ "kind": "record",
332
+ "valueSchema": {
333
+ "kind": "ref",
334
+ "ref": "#/definitions/BetterPortalJsonValue"
335
+ }
336
+ }
337
+ ]
338
+ }
339
+ },
340
+ "extensions": {}
341
+ },
342
+ "metadataResponseSchema": {},
343
+ "renderable": true,
344
+ "html": {
345
+ "renderers": {
346
+ "bootstrap5": {
347
+ "defaultRenderer": "default",
348
+ "renderModes": [
349
+ "page"
350
+ ],
351
+ "slots": [
352
+ "main"
353
+ ],
354
+ "renderers": [
355
+ {
356
+ "id": "default",
357
+ "title": "Default Content",
358
+ "slotId": "main",
359
+ "renderModes": [
360
+ "page",
361
+ "fragment"
362
+ ]
363
+ }
364
+ ]
365
+ }
366
+ }
367
+ },
368
+ "auth": {
369
+ "required": false,
370
+ "callers": [
371
+ "user"
372
+ ],
373
+ "permissions": []
374
+ },
375
+ "sitemap": {
376
+ "kind": "default"
377
+ },
378
+ "robots": [],
379
+ "dependencies": [],
380
+ "apiContracts": [],
381
+ "demoScenarios": [],
382
+ "cacheHints": {
383
+ "ttlSeconds": 0,
384
+ "varyBy": []
385
+ }
386
+ }
387
+ ]
388
+ },
389
+ {
390
+ "viewId": "login.index",
391
+ "title": "Login",
392
+ "description": "Authenticate with username and password to receive a JWT.",
393
+ "path": "/login",
394
+ "pathVariants": [],
395
+ "paramsSchema": {},
396
+ "operations": [
397
+ {
398
+ "operationId": "auth.login.view",
399
+ "method": "GET",
400
+ "title": "Login",
401
+ "description": "Authenticate with username and password to receive a JWT.",
402
+ "querySchema": {
403
+ "anyvaliVersion": "1.0",
404
+ "schemaVersion": "1.1",
405
+ "root": {
406
+ "kind": "object",
407
+ "properties": {
408
+ "action": {
409
+ "kind": "optional",
410
+ "inner": {
411
+ "kind": "string"
412
+ },
413
+ "metadata": {
414
+ "description": "Optional login route action, currently supports logout."
415
+ }
416
+ },
417
+ "next": {
418
+ "kind": "optional",
419
+ "inner": {
420
+ "kind": "string"
421
+ },
422
+ "metadata": {
423
+ "description": "The view path that redirected to the login page and should be redirected back to after a successful login."
424
+ }
425
+ }
426
+ },
427
+ "required": [],
428
+ "unknownKeys": "strip"
429
+ },
430
+ "definitions": {},
431
+ "extensions": {}
432
+ },
433
+ "headersSchema": {
434
+ "anyvaliVersion": "1.0",
435
+ "schemaVersion": "1.1",
436
+ "root": {
437
+ "kind": "object",
438
+ "properties": {
439
+ "x-bp-refresh": {
440
+ "kind": "optional",
441
+ "inner": {
442
+ "kind": "string"
443
+ }
444
+ }
445
+ },
446
+ "required": [],
447
+ "unknownKeys": "strip"
448
+ },
449
+ "definitions": {},
450
+ "extensions": {}
451
+ },
452
+ "bodySchema": {},
453
+ "jsonResponseSchema": {
454
+ "anyvaliVersion": "1.0",
455
+ "schemaVersion": "1.1",
456
+ "root": {
457
+ "kind": "object",
458
+ "properties": {
459
+ "challenge": {
460
+ "kind": "optional",
461
+ "inner": {
462
+ "kind": "record",
463
+ "valueSchema": {
464
+ "kind": "ref",
465
+ "ref": "#/definitions/BetterPortalJsonValue"
466
+ }
467
+ }
468
+ },
469
+ "accountUrl": {
470
+ "kind": "optional",
471
+ "inner": {
472
+ "kind": "string"
473
+ }
474
+ },
475
+ "socialUrl": {
476
+ "kind": "optional",
477
+ "inner": {
478
+ "kind": "string"
479
+ }
480
+ },
481
+ "status": {
482
+ "kind": "enum",
483
+ "values": [
484
+ "ok",
485
+ "error"
486
+ ],
487
+ "metadata": {
488
+ "description": "Login request outcome."
489
+ }
490
+ },
491
+ "message": {
492
+ "kind": "optional",
493
+ "inner": {
494
+ "kind": "string"
495
+ },
496
+ "metadata": {
497
+ "description": "Human-readable status or error message for the renderer."
498
+ }
499
+ },
500
+ "accessToken": {
501
+ "kind": "optional",
502
+ "inner": {
503
+ "kind": "string"
504
+ },
505
+ "metadata": {
506
+ "description": "Signed JWT access token returned on successful login."
507
+ }
508
+ },
509
+ "refreshToken": {
510
+ "kind": "optional",
511
+ "inner": {
512
+ "kind": "string"
513
+ },
514
+ "metadata": {
515
+ "description": "Signed JWT refresh token returned on successful login."
516
+ }
517
+ },
518
+ "expiresInSeconds": {
519
+ "kind": "optional",
520
+ "inner": {
521
+ "kind": "int",
522
+ "min": 1
523
+ },
524
+ "metadata": {
525
+ "description": "Access token lifetime in seconds."
526
+ }
527
+ },
528
+ "user": {
529
+ "kind": "optional",
530
+ "inner": {
531
+ "kind": "object",
532
+ "properties": {
533
+ "id": {
534
+ "kind": "string",
535
+ "metadata": {
536
+ "description": "Stable UUIDv7 user id."
537
+ }
538
+ },
539
+ "username": {
540
+ "kind": "string",
541
+ "metadata": {
542
+ "description": "Account username."
543
+ }
544
+ },
545
+ "email": {
546
+ "kind": "optional",
547
+ "inner": {
548
+ "kind": "string"
549
+ },
550
+ "metadata": {
551
+ "description": "User email address, when set."
552
+ }
553
+ },
554
+ "name": {
555
+ "kind": "optional",
556
+ "inner": {
557
+ "kind": "string"
558
+ },
559
+ "metadata": {
560
+ "description": "Display name, when set."
561
+ }
562
+ }
563
+ },
564
+ "required": [
565
+ "id",
566
+ "username"
567
+ ],
568
+ "unknownKeys": "strip",
569
+ "metadata": {
570
+ "description": "Authenticated user summary."
571
+ }
572
+ }
573
+ },
574
+ "requiresFirstAdmin": {
575
+ "kind": "optional",
576
+ "inner": {
577
+ "kind": "bool"
578
+ },
579
+ "metadata": {
580
+ "description": "True while management bootstrap is incomplete; the theme renderer should redirect to first-admin registration instead of showing the login form."
581
+ }
582
+ },
583
+ "firstAdminUrl": {
584
+ "kind": "optional",
585
+ "inner": {
586
+ "kind": "string"
587
+ },
588
+ "metadata": {
589
+ "description": "Absolute self-origin URL of this auth service's register view so the theme can load it in-shell without knowing the auth origin."
590
+ }
591
+ },
592
+ "alreadyLoggedIn": {
593
+ "kind": "optional",
594
+ "inner": {
595
+ "kind": "bool"
596
+ },
597
+ "metadata": {
598
+ "description": "True when the GET request already carried a valid access token; the theme renderer should show a signed-in state instead of the login form."
599
+ }
600
+ },
601
+ "loggedOut": {
602
+ "kind": "optional",
603
+ "inner": {
604
+ "kind": "bool"
605
+ },
606
+ "metadata": {
607
+ "description": "True after the login route handled ?action=logout."
608
+ }
609
+ },
610
+ "logoutUrl": {
611
+ "kind": "optional",
612
+ "inner": {
613
+ "kind": "string"
614
+ },
615
+ "metadata": {
616
+ "description": "Tenant-app path of the logout view from app auth config."
617
+ }
618
+ },
619
+ "nextUrl": {
620
+ "kind": "optional",
621
+ "inner": {
622
+ "kind": "string"
623
+ },
624
+ "metadata": {
625
+ "description": "Echo of the next path when already signed in; the theme renderer should redirect there immediately."
626
+ }
627
+ }
628
+ },
629
+ "required": [
630
+ "status"
631
+ ],
632
+ "unknownKeys": "strip"
633
+ },
634
+ "definitions": {
635
+ "BetterPortalJsonValue": {
636
+ "kind": "union",
637
+ "variants": [
638
+ {
639
+ "kind": "null"
640
+ },
641
+ {
642
+ "kind": "bool"
643
+ },
644
+ {
645
+ "kind": "string"
646
+ },
647
+ {
648
+ "kind": "number"
649
+ },
650
+ {
651
+ "kind": "array",
652
+ "items": {
653
+ "kind": "ref",
654
+ "ref": "#/definitions/BetterPortalJsonValue"
655
+ }
656
+ },
657
+ {
658
+ "kind": "record",
659
+ "valueSchema": {
660
+ "kind": "ref",
661
+ "ref": "#/definitions/BetterPortalJsonValue"
662
+ }
663
+ }
664
+ ]
665
+ }
666
+ },
667
+ "extensions": {}
668
+ },
669
+ "metadataResponseSchema": {},
670
+ "renderable": true,
671
+ "html": {
672
+ "renderers": {
673
+ "bootstrap5": {
674
+ "defaultRenderer": "default",
675
+ "renderModes": [
676
+ "page",
677
+ "fragment"
678
+ ],
679
+ "slots": [
680
+ "main",
681
+ "nav.profile"
682
+ ],
683
+ "renderers": [
684
+ {
685
+ "id": "default",
686
+ "title": "Default Content",
687
+ "slotId": "main",
688
+ "renderModes": [
689
+ "page",
690
+ "fragment"
691
+ ]
692
+ },
693
+ {
694
+ "id": "nav.profile",
695
+ "title": "nav.profile",
696
+ "slotId": "nav.profile",
697
+ "renderModes": [
698
+ "fragment"
699
+ ]
700
+ }
701
+ ]
702
+ }
703
+ }
704
+ },
705
+ "auth": {
706
+ "required": false,
707
+ "callers": [
708
+ "user"
709
+ ],
710
+ "permissions": []
711
+ },
712
+ "sitemap": {
713
+ "kind": "default"
714
+ },
715
+ "robots": [],
716
+ "role": "auth.login",
717
+ "dependencies": [
718
+ {
719
+ "operationId": "auth.login",
720
+ "method": "POST"
721
+ },
722
+ {
723
+ "operationId": "auth.logout.view",
724
+ "method": "GET"
725
+ },
726
+ {
727
+ "operationId": "auth.refresh",
728
+ "method": "POST"
729
+ },
730
+ {
731
+ "operationId": "auth.register.view",
732
+ "method": "GET"
733
+ },
734
+ {
735
+ "operationId": "auth.account.view",
736
+ "method": "GET"
737
+ },
738
+ {
739
+ "operationId": "auth.social.view",
740
+ "method": "GET"
741
+ }
742
+ ],
743
+ "chrome": {
744
+ "fullScreen": true
745
+ },
746
+ "apiContracts": [],
747
+ "demoScenarios": [],
748
+ "cacheHints": {
749
+ "ttlSeconds": 0,
750
+ "varyBy": []
751
+ }
752
+ },
753
+ {
754
+ "operationId": "auth.login",
755
+ "method": "POST",
756
+ "title": "Login",
757
+ "description": "Authenticate with username and password to receive a JWT.",
758
+ "querySchema": {
759
+ "anyvaliVersion": "1.0",
760
+ "schemaVersion": "1.1",
761
+ "root": {
762
+ "kind": "object",
763
+ "properties": {
764
+ "action": {
765
+ "kind": "optional",
766
+ "inner": {
767
+ "kind": "string"
768
+ },
769
+ "metadata": {
770
+ "description": "Optional login route action, currently supports logout."
771
+ }
772
+ },
773
+ "next": {
774
+ "kind": "optional",
775
+ "inner": {
776
+ "kind": "string"
777
+ },
778
+ "metadata": {
779
+ "description": "The view path that redirected to the login page and should be redirected back to after a successful login."
780
+ }
781
+ }
782
+ },
783
+ "required": [],
784
+ "unknownKeys": "strip"
785
+ },
786
+ "definitions": {},
787
+ "extensions": {}
788
+ },
789
+ "headersSchema": {},
790
+ "bodySchema": {
791
+ "anyvaliVersion": "1.0",
792
+ "schemaVersion": "1.1",
793
+ "root": {
794
+ "kind": "object",
795
+ "properties": {
796
+ "username": {
797
+ "kind": "string",
798
+ "minLength": 1,
799
+ "metadata": {
800
+ "description": "Username for the account signing in."
801
+ }
802
+ },
803
+ "password": {
804
+ "kind": "string",
805
+ "minLength": 1,
806
+ "metadata": {
807
+ "description": "Password for the account signing in."
808
+ }
809
+ },
810
+ "next": {
811
+ "kind": "optional",
812
+ "inner": {
813
+ "kind": "string"
814
+ },
815
+ "metadata": {
816
+ "description": "The view path to soft-navigate to after a successful login."
817
+ }
818
+ }
819
+ },
820
+ "required": [
821
+ "username",
822
+ "password"
823
+ ],
824
+ "unknownKeys": "strip"
825
+ },
826
+ "definitions": {},
827
+ "extensions": {}
828
+ },
829
+ "jsonResponseSchema": {
830
+ "anyvaliVersion": "1.0",
831
+ "schemaVersion": "1.1",
832
+ "root": {
833
+ "kind": "object",
834
+ "properties": {
835
+ "challenge": {
836
+ "kind": "optional",
837
+ "inner": {
838
+ "kind": "record",
839
+ "valueSchema": {
840
+ "kind": "ref",
841
+ "ref": "#/definitions/BetterPortalJsonValue"
842
+ }
843
+ }
844
+ },
845
+ "accountUrl": {
846
+ "kind": "optional",
847
+ "inner": {
848
+ "kind": "string"
849
+ }
850
+ },
851
+ "socialUrl": {
852
+ "kind": "optional",
853
+ "inner": {
854
+ "kind": "string"
855
+ }
856
+ },
857
+ "status": {
858
+ "kind": "enum",
859
+ "values": [
860
+ "ok",
861
+ "error"
862
+ ],
863
+ "metadata": {
864
+ "description": "Login request outcome."
865
+ }
866
+ },
867
+ "message": {
868
+ "kind": "optional",
869
+ "inner": {
870
+ "kind": "string"
871
+ },
872
+ "metadata": {
873
+ "description": "Human-readable status or error message for the renderer."
874
+ }
875
+ },
876
+ "accessToken": {
877
+ "kind": "optional",
878
+ "inner": {
879
+ "kind": "string"
880
+ },
881
+ "metadata": {
882
+ "description": "Signed JWT access token returned on successful login."
883
+ }
884
+ },
885
+ "refreshToken": {
886
+ "kind": "optional",
887
+ "inner": {
888
+ "kind": "string"
889
+ },
890
+ "metadata": {
891
+ "description": "Signed JWT refresh token returned on successful login."
892
+ }
893
+ },
894
+ "expiresInSeconds": {
895
+ "kind": "optional",
896
+ "inner": {
897
+ "kind": "int",
898
+ "min": 1
899
+ },
900
+ "metadata": {
901
+ "description": "Access token lifetime in seconds."
902
+ }
903
+ },
904
+ "user": {
905
+ "kind": "optional",
906
+ "inner": {
907
+ "kind": "object",
908
+ "properties": {
909
+ "id": {
910
+ "kind": "string",
911
+ "metadata": {
912
+ "description": "Stable UUIDv7 user id."
913
+ }
914
+ },
915
+ "username": {
916
+ "kind": "string",
917
+ "metadata": {
918
+ "description": "Account username."
919
+ }
920
+ },
921
+ "email": {
922
+ "kind": "optional",
923
+ "inner": {
924
+ "kind": "string"
925
+ },
926
+ "metadata": {
927
+ "description": "User email address, when set."
928
+ }
929
+ },
930
+ "name": {
931
+ "kind": "optional",
932
+ "inner": {
933
+ "kind": "string"
934
+ },
935
+ "metadata": {
936
+ "description": "Display name, when set."
937
+ }
938
+ }
939
+ },
940
+ "required": [
941
+ "id",
942
+ "username"
943
+ ],
944
+ "unknownKeys": "strip",
945
+ "metadata": {
946
+ "description": "Authenticated user summary."
947
+ }
948
+ }
949
+ },
950
+ "requiresFirstAdmin": {
951
+ "kind": "optional",
952
+ "inner": {
953
+ "kind": "bool"
954
+ },
955
+ "metadata": {
956
+ "description": "True while management bootstrap is incomplete; the theme renderer should redirect to first-admin registration instead of showing the login form."
957
+ }
958
+ },
959
+ "firstAdminUrl": {
960
+ "kind": "optional",
961
+ "inner": {
962
+ "kind": "string"
963
+ },
964
+ "metadata": {
965
+ "description": "Absolute self-origin URL of this auth service's register view so the theme can load it in-shell without knowing the auth origin."
966
+ }
967
+ },
968
+ "alreadyLoggedIn": {
969
+ "kind": "optional",
970
+ "inner": {
971
+ "kind": "bool"
972
+ },
973
+ "metadata": {
974
+ "description": "True when the GET request already carried a valid access token; the theme renderer should show a signed-in state instead of the login form."
975
+ }
976
+ },
977
+ "loggedOut": {
978
+ "kind": "optional",
979
+ "inner": {
980
+ "kind": "bool"
981
+ },
982
+ "metadata": {
983
+ "description": "True after the login route handled ?action=logout."
984
+ }
985
+ },
986
+ "logoutUrl": {
987
+ "kind": "optional",
988
+ "inner": {
989
+ "kind": "string"
990
+ },
991
+ "metadata": {
992
+ "description": "Tenant-app path of the logout view from app auth config."
993
+ }
994
+ },
995
+ "nextUrl": {
996
+ "kind": "optional",
997
+ "inner": {
998
+ "kind": "string"
999
+ },
1000
+ "metadata": {
1001
+ "description": "Echo of the next path when already signed in; the theme renderer should redirect there immediately."
1002
+ }
1003
+ }
1004
+ },
1005
+ "required": [
1006
+ "status"
1007
+ ],
1008
+ "unknownKeys": "strip"
1009
+ },
1010
+ "definitions": {
1011
+ "BetterPortalJsonValue": {
1012
+ "kind": "union",
1013
+ "variants": [
1014
+ {
1015
+ "kind": "null"
1016
+ },
1017
+ {
1018
+ "kind": "bool"
1019
+ },
1020
+ {
1021
+ "kind": "string"
1022
+ },
1023
+ {
1024
+ "kind": "number"
1025
+ },
1026
+ {
1027
+ "kind": "array",
1028
+ "items": {
1029
+ "kind": "ref",
1030
+ "ref": "#/definitions/BetterPortalJsonValue"
1031
+ }
1032
+ },
1033
+ {
1034
+ "kind": "record",
1035
+ "valueSchema": {
1036
+ "kind": "ref",
1037
+ "ref": "#/definitions/BetterPortalJsonValue"
1038
+ }
1039
+ }
1040
+ ]
1041
+ }
1042
+ },
1043
+ "extensions": {}
1044
+ },
1045
+ "metadataResponseSchema": {},
1046
+ "renderable": true,
1047
+ "html": {
1048
+ "renderers": {
1049
+ "bootstrap5": {
1050
+ "defaultRenderer": "default",
1051
+ "renderModes": [
1052
+ "page"
1053
+ ],
1054
+ "slots": [
1055
+ "main"
1056
+ ],
1057
+ "renderers": [
1058
+ {
1059
+ "id": "default",
1060
+ "title": "Default Content",
1061
+ "slotId": "main",
1062
+ "renderModes": [
1063
+ "page",
1064
+ "fragment"
1065
+ ]
1066
+ }
1067
+ ]
1068
+ }
1069
+ }
1070
+ },
1071
+ "auth": {
1072
+ "required": false,
1073
+ "callers": [
1074
+ "user"
1075
+ ],
1076
+ "permissions": []
1077
+ },
1078
+ "sitemap": {
1079
+ "kind": "default"
1080
+ },
1081
+ "robots": [],
1082
+ "role": "auth.login",
1083
+ "dependencies": [],
1084
+ "chrome": {
1085
+ "fullScreen": true
1086
+ },
1087
+ "apiContracts": [],
1088
+ "demoScenarios": [],
1089
+ "cacheHints": {
1090
+ "ttlSeconds": 0,
1091
+ "varyBy": []
1092
+ }
1093
+ }
1094
+ ]
1095
+ },
1096
+ {
1097
+ "viewId": "logout.index",
1098
+ "title": "Logout",
1099
+ "description": "Clear the authentication token from the client.",
1100
+ "path": "/logout",
1101
+ "pathVariants": [],
1102
+ "paramsSchema": {},
1103
+ "operations": [
1104
+ {
1105
+ "operationId": "auth.logout.view",
1106
+ "method": "GET",
1107
+ "title": "Logout",
1108
+ "description": "Clear the authentication token from the client.",
1109
+ "querySchema": {},
1110
+ "headersSchema": {
1111
+ "anyvaliVersion": "1.0",
1112
+ "schemaVersion": "1.1",
1113
+ "root": {
1114
+ "kind": "object",
1115
+ "properties": {
1116
+ "x-bp-refresh": {
1117
+ "kind": "optional",
1118
+ "inner": {
1119
+ "kind": "string"
1120
+ }
1121
+ }
1122
+ },
1123
+ "required": [],
1124
+ "unknownKeys": "strip"
1125
+ },
1126
+ "definitions": {},
1127
+ "extensions": {}
1128
+ },
1129
+ "bodySchema": {},
1130
+ "jsonResponseSchema": {
1131
+ "anyvaliVersion": "1.0",
1132
+ "schemaVersion": "1.1",
1133
+ "root": {
1134
+ "kind": "object",
1135
+ "properties": {
1136
+ "status": {
1137
+ "kind": "enum",
1138
+ "values": [
1139
+ "ok"
1140
+ ],
1141
+ "metadata": {
1142
+ "description": "Logout request outcome."
1143
+ }
1144
+ },
1145
+ "message": {
1146
+ "kind": "string",
1147
+ "metadata": {
1148
+ "description": "Human-readable logout status for the renderer."
1149
+ }
1150
+ }
1151
+ },
1152
+ "required": [
1153
+ "status",
1154
+ "message"
1155
+ ],
1156
+ "unknownKeys": "strip"
1157
+ },
1158
+ "definitions": {},
1159
+ "extensions": {}
1160
+ },
1161
+ "metadataResponseSchema": {},
1162
+ "renderable": true,
1163
+ "html": {
1164
+ "renderers": {
1165
+ "bootstrap5": {
1166
+ "defaultRenderer": "default",
1167
+ "renderModes": [
1168
+ "page"
1169
+ ],
1170
+ "slots": [
1171
+ "main"
1172
+ ],
1173
+ "renderers": [
1174
+ {
1175
+ "id": "default",
1176
+ "title": "Default Content",
1177
+ "slotId": "main",
1178
+ "renderModes": [
1179
+ "page",
1180
+ "fragment"
1181
+ ]
1182
+ }
1183
+ ]
1184
+ }
1185
+ }
1186
+ },
1187
+ "auth": {
1188
+ "required": false,
1189
+ "callers": [
1190
+ "user"
1191
+ ],
1192
+ "permissions": []
1193
+ },
1194
+ "sitemap": {
1195
+ "kind": "default"
1196
+ },
1197
+ "robots": [],
1198
+ "role": "auth.logout",
1199
+ "dependencies": [
1200
+ {
1201
+ "operationId": "auth.logout",
1202
+ "method": "POST"
1203
+ }
1204
+ ],
1205
+ "apiContracts": [],
1206
+ "demoScenarios": [],
1207
+ "cacheHints": {
1208
+ "ttlSeconds": 0,
1209
+ "varyBy": []
1210
+ }
1211
+ },
1212
+ {
1213
+ "operationId": "auth.logout",
1214
+ "method": "POST",
1215
+ "title": "Logout",
1216
+ "description": "Clear the authentication token from the client.",
1217
+ "querySchema": {},
1218
+ "headersSchema": {
1219
+ "anyvaliVersion": "1.0",
1220
+ "schemaVersion": "1.1",
1221
+ "root": {
1222
+ "kind": "object",
1223
+ "properties": {
1224
+ "x-bp-refresh": {
1225
+ "kind": "optional",
1226
+ "inner": {
1227
+ "kind": "string"
1228
+ }
1229
+ }
1230
+ },
1231
+ "required": [],
1232
+ "unknownKeys": "strip"
1233
+ },
1234
+ "definitions": {},
1235
+ "extensions": {}
1236
+ },
1237
+ "bodySchema": {},
1238
+ "jsonResponseSchema": {
1239
+ "anyvaliVersion": "1.0",
1240
+ "schemaVersion": "1.1",
1241
+ "root": {
1242
+ "kind": "object",
1243
+ "properties": {
1244
+ "status": {
1245
+ "kind": "enum",
1246
+ "values": [
1247
+ "ok"
1248
+ ],
1249
+ "metadata": {
1250
+ "description": "Logout request outcome."
1251
+ }
1252
+ },
1253
+ "message": {
1254
+ "kind": "string",
1255
+ "metadata": {
1256
+ "description": "Human-readable logout status for the renderer."
1257
+ }
1258
+ }
1259
+ },
1260
+ "required": [
1261
+ "status",
1262
+ "message"
1263
+ ],
1264
+ "unknownKeys": "strip"
1265
+ },
1266
+ "definitions": {},
1267
+ "extensions": {}
1268
+ },
1269
+ "metadataResponseSchema": {},
1270
+ "renderable": true,
1271
+ "html": {
1272
+ "renderers": {
1273
+ "bootstrap5": {
1274
+ "defaultRenderer": "default",
1275
+ "renderModes": [
1276
+ "page"
1277
+ ],
1278
+ "slots": [
1279
+ "main"
1280
+ ],
1281
+ "renderers": [
1282
+ {
1283
+ "id": "default",
1284
+ "title": "Default Content",
1285
+ "slotId": "main",
1286
+ "renderModes": [
1287
+ "page",
1288
+ "fragment"
1289
+ ]
1290
+ }
1291
+ ]
1292
+ }
1293
+ }
1294
+ },
1295
+ "auth": {
1296
+ "required": false,
1297
+ "callers": [
1298
+ "user"
1299
+ ],
1300
+ "permissions": []
1301
+ },
1302
+ "sitemap": {
1303
+ "kind": "default"
1304
+ },
1305
+ "robots": [],
1306
+ "role": "auth.logout",
1307
+ "dependencies": [],
1308
+ "apiContracts": [],
1309
+ "demoScenarios": [],
1310
+ "cacheHints": {
1311
+ "ttlSeconds": 0,
1312
+ "varyBy": []
1313
+ }
1314
+ }
1315
+ ]
1316
+ },
1317
+ {
1318
+ "viewId": "refresh.index",
1319
+ "title": "Refresh Token",
1320
+ "description": "Exchange a refresh token for a new access token.",
1321
+ "path": "/refresh",
1322
+ "pathVariants": [],
1323
+ "paramsSchema": {},
1324
+ "operations": [
1325
+ {
1326
+ "operationId": "auth.refresh",
1327
+ "method": "POST",
1328
+ "title": "Refresh Token",
1329
+ "description": "Exchange a refresh token for a new access token.",
1330
+ "querySchema": {
1331
+ "anyvaliVersion": "1.0",
1332
+ "schemaVersion": "1.1",
1333
+ "root": {
1334
+ "kind": "object",
1335
+ "properties": {},
1336
+ "required": [],
1337
+ "unknownKeys": "strip"
1338
+ },
1339
+ "definitions": {},
1340
+ "extensions": {}
1341
+ },
1342
+ "headersSchema": {
1343
+ "anyvaliVersion": "1.0",
1344
+ "schemaVersion": "1.1",
1345
+ "root": {
1346
+ "kind": "object",
1347
+ "properties": {
1348
+ "x-bp-refresh": {
1349
+ "kind": "optional",
1350
+ "inner": {
1351
+ "kind": "string",
1352
+ "minLength": 1
1353
+ }
1354
+ }
1355
+ },
1356
+ "required": [],
1357
+ "unknownKeys": "strip"
1358
+ },
1359
+ "definitions": {},
1360
+ "extensions": {}
1361
+ },
1362
+ "bodySchema": {
1363
+ "anyvaliVersion": "1.0",
1364
+ "schemaVersion": "1.1",
1365
+ "root": {
1366
+ "kind": "object",
1367
+ "properties": {
1368
+ "refreshToken": {
1369
+ "kind": "optional",
1370
+ "inner": {
1371
+ "kind": "string",
1372
+ "minLength": 1,
1373
+ "metadata": {
1374
+ "description": "Signed refresh token issued by the auth service."
1375
+ }
1376
+ }
1377
+ }
1378
+ },
1379
+ "required": [],
1380
+ "unknownKeys": "strip"
1381
+ },
1382
+ "definitions": {},
1383
+ "extensions": {}
1384
+ },
1385
+ "jsonResponseSchema": {
1386
+ "anyvaliVersion": "1.0",
1387
+ "schemaVersion": "1.1",
1388
+ "root": {
1389
+ "kind": "object",
1390
+ "properties": {
1391
+ "status": {
1392
+ "kind": "enum",
1393
+ "values": [
1394
+ "ok",
1395
+ "error"
1396
+ ],
1397
+ "metadata": {
1398
+ "description": "Refresh request outcome."
1399
+ }
1400
+ },
1401
+ "message": {
1402
+ "kind": "optional",
1403
+ "inner": {
1404
+ "kind": "string"
1405
+ },
1406
+ "metadata": {
1407
+ "description": "Human-readable status or error message for the renderer."
1408
+ }
1409
+ },
1410
+ "refreshToken": {
1411
+ "kind": "optional",
1412
+ "inner": {
1413
+ "kind": "string"
1414
+ }
1415
+ },
1416
+ "accessToken": {
47
1417
  "kind": "optional",
48
1418
  "inner": {
49
1419
  "kind": "string"
50
1420
  },
51
1421
  "metadata": {
52
- "description": "Optional login route action, currently supports logout."
1422
+ "description": "New signed JWT access token returned when refresh succeeds."
53
1423
  }
54
1424
  },
55
- "next": {
1425
+ "expiresInSeconds": {
56
1426
  "kind": "optional",
57
1427
  "inner": {
58
- "kind": "string"
1428
+ "kind": "int",
1429
+ "min": 1
59
1430
  },
60
1431
  "metadata": {
61
- "description": "The view path that redirected to the login page and should be redirected back to after a successful login."
1432
+ "description": "New access token lifetime in seconds."
62
1433
  }
63
1434
  }
64
1435
  },
65
- "required": [],
1436
+ "required": [
1437
+ "status"
1438
+ ],
66
1439
  "unknownKeys": "strip"
67
1440
  },
68
1441
  "definitions": {},
69
1442
  "extensions": {}
70
1443
  },
71
- "headersSchema": {
1444
+ "metadataResponseSchema": {},
1445
+ "renderable": false,
1446
+ "html": {
1447
+ "renderers": {}
1448
+ },
1449
+ "auth": {
1450
+ "required": false,
1451
+ "callers": [
1452
+ "user"
1453
+ ],
1454
+ "permissions": []
1455
+ },
1456
+ "sitemap": {
1457
+ "kind": "default"
1458
+ },
1459
+ "robots": [],
1460
+ "role": "auth.refresh",
1461
+ "dependencies": [],
1462
+ "apiContracts": [],
1463
+ "demoScenarios": [],
1464
+ "cacheHints": {
1465
+ "ttlSeconds": 0,
1466
+ "varyBy": []
1467
+ }
1468
+ }
1469
+ ]
1470
+ },
1471
+ {
1472
+ "viewId": "register.index",
1473
+ "title": "Register First Admin",
1474
+ "description": "Open registration for the very first user. Once any user exists, this endpoint requires admin auth.",
1475
+ "path": "/register",
1476
+ "pathVariants": [],
1477
+ "paramsSchema": {},
1478
+ "operations": [
1479
+ {
1480
+ "operationId": "auth.register.view",
1481
+ "method": "GET",
1482
+ "title": "Register First Admin",
1483
+ "description": "Open registration for the very first user. Once any user exists, this endpoint requires admin auth.",
1484
+ "querySchema": {
72
1485
  "anyvaliVersion": "1.0",
73
1486
  "schemaVersion": "1.1",
74
1487
  "root": {
75
1488
  "kind": "object",
76
1489
  "properties": {
77
- "x-bp-refresh": {
1490
+ "next": {
78
1491
  "kind": "optional",
79
1492
  "inner": {
80
1493
  "kind": "string"
1494
+ },
1495
+ "metadata": {
1496
+ "description": "The view path to pass through to login after first-admin registration."
81
1497
  }
82
1498
  }
83
1499
  },
@@ -87,6 +1503,7 @@
87
1503
  "definitions": {},
88
1504
  "extensions": {}
89
1505
  },
1506
+ "headersSchema": {},
90
1507
  "bodySchema": {},
91
1508
  "jsonResponseSchema": {
92
1509
  "anyvaliVersion": "1.0",
@@ -101,7 +1518,7 @@
101
1518
  "error"
102
1519
  ],
103
1520
  "metadata": {
104
- "description": "Login request outcome."
1521
+ "description": "Registration request outcome."
105
1522
  }
106
1523
  },
107
1524
  "message": {
@@ -113,34 +1530,6 @@
113
1530
  "description": "Human-readable status or error message for the renderer."
114
1531
  }
115
1532
  },
116
- "accessToken": {
117
- "kind": "optional",
118
- "inner": {
119
- "kind": "string"
120
- },
121
- "metadata": {
122
- "description": "Signed JWT access token returned on successful login."
123
- }
124
- },
125
- "refreshToken": {
126
- "kind": "optional",
127
- "inner": {
128
- "kind": "string"
129
- },
130
- "metadata": {
131
- "description": "Signed JWT refresh token returned on successful login."
132
- }
133
- },
134
- "expiresInSeconds": {
135
- "kind": "optional",
136
- "inner": {
137
- "kind": "int",
138
- "min": 1
139
- },
140
- "metadata": {
141
- "description": "Access token lifetime in seconds."
142
- }
143
- },
144
1533
  "user": {
145
1534
  "kind": "optional",
146
1535
  "inner": {
@@ -155,90 +1544,43 @@
155
1544
  "username": {
156
1545
  "kind": "string",
157
1546
  "metadata": {
158
- "description": "Account username."
159
- }
160
- },
161
- "email": {
162
- "kind": "optional",
163
- "inner": {
164
- "kind": "string"
165
- },
166
- "metadata": {
167
- "description": "User email address, when set."
1547
+ "description": "Created account username."
168
1548
  }
169
1549
  },
170
- "name": {
171
- "kind": "optional",
172
- "inner": {
173
- "kind": "string"
174
- },
1550
+ "isFirstAdmin": {
1551
+ "kind": "bool",
175
1552
  "metadata": {
176
- "description": "Display name, when set."
1553
+ "description": "True when this account is the deployment's first admin."
177
1554
  }
178
1555
  }
179
1556
  },
180
1557
  "required": [
181
1558
  "id",
182
- "username"
1559
+ "username",
1560
+ "isFirstAdmin"
183
1561
  ],
184
1562
  "unknownKeys": "strip",
185
1563
  "metadata": {
186
- "description": "Authenticated user summary."
1564
+ "description": "Created first-admin user summary."
187
1565
  }
188
1566
  }
189
1567
  },
190
- "requiresFirstAdmin": {
191
- "kind": "optional",
192
- "inner": {
193
- "kind": "bool"
194
- },
195
- "metadata": {
196
- "description": "True while the auth service has zero users; the theme renderer should redirect to first-admin registration instead of showing the login form."
197
- }
198
- },
199
- "firstAdminUrl": {
200
- "kind": "optional",
201
- "inner": {
202
- "kind": "string"
203
- },
204
- "metadata": {
205
- "description": "Absolute self-origin URL of this auth service's register view so the theme can load it in-shell without knowing the auth origin."
206
- }
207
- },
208
- "alreadyLoggedIn": {
209
- "kind": "optional",
210
- "inner": {
211
- "kind": "bool"
212
- },
213
- "metadata": {
214
- "description": "True when the GET request already carried a valid access token; the theme renderer should show a signed-in state instead of the login form."
215
- }
216
- },
217
- "loggedOut": {
1568
+ "registrationOpen": {
218
1569
  "kind": "optional",
219
1570
  "inner": {
220
1571
  "kind": "bool"
221
1572
  },
222
1573
  "metadata": {
223
- "description": "True after the login route handled ?action=logout."
224
- }
225
- },
226
- "logoutUrl": {
227
- "kind": "optional",
228
- "inner": {
229
- "kind": "string"
230
- },
231
- "metadata": {
232
- "description": "Tenant-app path of the logout view from app auth config."
1574
+ "description": "True while management bootstrap is incomplete; once false, the renderer should send the browser to login."
233
1575
  }
234
1576
  },
235
- "nextUrl": {
1577
+ "loginUrl": {
236
1578
  "kind": "optional",
237
1579
  "inner": {
238
1580
  "kind": "string"
239
1581
  },
240
1582
  "metadata": {
241
- "description": "Echo of the next path when already signed in; the theme renderer should redirect there immediately."
1583
+ "description": "Absolute self-origin URL of this auth service's login view, used when registration is closed and after successful first-admin creation."
242
1584
  }
243
1585
  }
244
1586
  },
@@ -257,12 +1599,10 @@
257
1599
  "bootstrap5": {
258
1600
  "defaultRenderer": "default",
259
1601
  "renderModes": [
260
- "page",
261
- "fragment"
1602
+ "page"
262
1603
  ],
263
1604
  "slots": [
264
- "main",
265
- "nav.profile"
1605
+ "main"
266
1606
  ],
267
1607
  "renderers": [
268
1608
  {
@@ -273,14 +1613,6 @@
273
1613
  "page",
274
1614
  "fragment"
275
1615
  ]
276
- },
277
- {
278
- "id": "nav.profile",
279
- "title": "nav.profile",
280
- "slotId": "nav.profile",
281
- "renderModes": [
282
- "fragment"
283
- ]
284
1616
  }
285
1617
  ]
286
1618
  }
@@ -297,22 +1629,14 @@
297
1629
  "kind": "default"
298
1630
  },
299
1631
  "robots": [],
300
- "role": "auth.login",
1632
+ "role": "auth.register",
301
1633
  "dependencies": [
302
1634
  {
303
- "operationId": "auth.login",
304
- "method": "POST"
305
- },
306
- {
307
- "operationId": "auth.logout.view",
308
- "method": "GET"
309
- },
310
- {
311
- "operationId": "auth.refresh",
1635
+ "operationId": "auth.register",
312
1636
  "method": "POST"
313
1637
  },
314
1638
  {
315
- "operationId": "auth.register.view",
1639
+ "operationId": "auth.login.view",
316
1640
  "method": "GET"
317
1641
  }
318
1642
  ],
@@ -327,32 +1651,23 @@
327
1651
  }
328
1652
  },
329
1653
  {
330
- "operationId": "auth.login",
1654
+ "operationId": "auth.register",
331
1655
  "method": "POST",
332
- "title": "Login",
333
- "description": "Authenticate with username and password to receive a JWT.",
1656
+ "title": "Register First Admin",
1657
+ "description": "Open registration for the very first user. Once any user exists, this endpoint requires admin auth.",
334
1658
  "querySchema": {
335
1659
  "anyvaliVersion": "1.0",
336
1660
  "schemaVersion": "1.1",
337
1661
  "root": {
338
1662
  "kind": "object",
339
1663
  "properties": {
340
- "action": {
341
- "kind": "optional",
342
- "inner": {
343
- "kind": "string"
344
- },
345
- "metadata": {
346
- "description": "Optional login route action, currently supports logout."
347
- }
348
- },
349
1664
  "next": {
350
1665
  "kind": "optional",
351
1666
  "inner": {
352
1667
  "kind": "string"
353
1668
  },
354
1669
  "metadata": {
355
- "description": "The view path that redirected to the login page and should be redirected back to after a successful login."
1670
+ "description": "The view path to pass through to login after first-admin registration."
356
1671
  }
357
1672
  }
358
1673
  },
@@ -369,27 +1684,42 @@
369
1684
  "root": {
370
1685
  "kind": "object",
371
1686
  "properties": {
1687
+ "setupToken": {
1688
+ "kind": "optional",
1689
+ "inner": {
1690
+ "kind": "string"
1691
+ }
1692
+ },
372
1693
  "username": {
373
1694
  "kind": "string",
374
1695
  "minLength": 1,
375
1696
  "metadata": {
376
- "description": "Username for the account signing in."
1697
+ "description": "Username for the account."
377
1698
  }
378
1699
  },
379
1700
  "password": {
380
1701
  "kind": "string",
381
- "minLength": 1,
1702
+ "minLength": 12,
382
1703
  "metadata": {
383
- "description": "Password for the account signing in."
1704
+ "description": "Password for the first admin account."
384
1705
  }
385
1706
  },
386
- "next": {
1707
+ "email": {
387
1708
  "kind": "optional",
388
1709
  "inner": {
389
1710
  "kind": "string"
390
1711
  },
391
1712
  "metadata": {
392
- "description": "The view path to soft-navigate to after a successful login."
1713
+ "description": "Email address for the first admin account."
1714
+ }
1715
+ },
1716
+ "name": {
1717
+ "kind": "optional",
1718
+ "inner": {
1719
+ "kind": "string"
1720
+ },
1721
+ "metadata": {
1722
+ "description": "Display name for the first admin account."
393
1723
  }
394
1724
  }
395
1725
  },
@@ -415,44 +1745,16 @@
415
1745
  "error"
416
1746
  ],
417
1747
  "metadata": {
418
- "description": "Login request outcome."
1748
+ "description": "Registration request outcome."
419
1749
  }
420
1750
  },
421
1751
  "message": {
422
1752
  "kind": "optional",
423
1753
  "inner": {
424
- "kind": "string"
425
- },
426
- "metadata": {
427
- "description": "Human-readable status or error message for the renderer."
428
- }
429
- },
430
- "accessToken": {
431
- "kind": "optional",
432
- "inner": {
433
- "kind": "string"
434
- },
435
- "metadata": {
436
- "description": "Signed JWT access token returned on successful login."
437
- }
438
- },
439
- "refreshToken": {
440
- "kind": "optional",
441
- "inner": {
442
- "kind": "string"
443
- },
444
- "metadata": {
445
- "description": "Signed JWT refresh token returned on successful login."
446
- }
447
- },
448
- "expiresInSeconds": {
449
- "kind": "optional",
450
- "inner": {
451
- "kind": "int",
452
- "min": 1
1754
+ "kind": "string"
453
1755
  },
454
1756
  "metadata": {
455
- "description": "Access token lifetime in seconds."
1757
+ "description": "Human-readable status or error message for the renderer."
456
1758
  }
457
1759
  },
458
1760
  "user": {
@@ -469,90 +1771,43 @@
469
1771
  "username": {
470
1772
  "kind": "string",
471
1773
  "metadata": {
472
- "description": "Account username."
473
- }
474
- },
475
- "email": {
476
- "kind": "optional",
477
- "inner": {
478
- "kind": "string"
479
- },
480
- "metadata": {
481
- "description": "User email address, when set."
1774
+ "description": "Created account username."
482
1775
  }
483
1776
  },
484
- "name": {
485
- "kind": "optional",
486
- "inner": {
487
- "kind": "string"
488
- },
1777
+ "isFirstAdmin": {
1778
+ "kind": "bool",
489
1779
  "metadata": {
490
- "description": "Display name, when set."
1780
+ "description": "True when this account is the deployment's first admin."
491
1781
  }
492
1782
  }
493
1783
  },
494
1784
  "required": [
495
1785
  "id",
496
- "username"
1786
+ "username",
1787
+ "isFirstAdmin"
497
1788
  ],
498
1789
  "unknownKeys": "strip",
499
1790
  "metadata": {
500
- "description": "Authenticated user summary."
1791
+ "description": "Created first-admin user summary."
501
1792
  }
502
1793
  }
503
1794
  },
504
- "requiresFirstAdmin": {
505
- "kind": "optional",
506
- "inner": {
507
- "kind": "bool"
508
- },
509
- "metadata": {
510
- "description": "True while the auth service has zero users; the theme renderer should redirect to first-admin registration instead of showing the login form."
511
- }
512
- },
513
- "firstAdminUrl": {
514
- "kind": "optional",
515
- "inner": {
516
- "kind": "string"
517
- },
518
- "metadata": {
519
- "description": "Absolute self-origin URL of this auth service's register view so the theme can load it in-shell without knowing the auth origin."
520
- }
521
- },
522
- "alreadyLoggedIn": {
523
- "kind": "optional",
524
- "inner": {
525
- "kind": "bool"
526
- },
527
- "metadata": {
528
- "description": "True when the GET request already carried a valid access token; the theme renderer should show a signed-in state instead of the login form."
529
- }
530
- },
531
- "loggedOut": {
1795
+ "registrationOpen": {
532
1796
  "kind": "optional",
533
1797
  "inner": {
534
1798
  "kind": "bool"
535
1799
  },
536
1800
  "metadata": {
537
- "description": "True after the login route handled ?action=logout."
538
- }
539
- },
540
- "logoutUrl": {
541
- "kind": "optional",
542
- "inner": {
543
- "kind": "string"
544
- },
545
- "metadata": {
546
- "description": "Tenant-app path of the logout view from app auth config."
1801
+ "description": "True while management bootstrap is incomplete; once false, the renderer should send the browser to login."
547
1802
  }
548
1803
  },
549
- "nextUrl": {
1804
+ "loginUrl": {
550
1805
  "kind": "optional",
551
1806
  "inner": {
552
1807
  "kind": "string"
553
1808
  },
554
1809
  "metadata": {
555
- "description": "Echo of the next path when already signed in; the theme renderer should redirect there immediately."
1810
+ "description": "Absolute self-origin URL of this auth service's login view, used when registration is closed and after successful first-admin creation."
556
1811
  }
557
1812
  }
558
1813
  },
@@ -601,7 +1856,7 @@
601
1856
  "kind": "default"
602
1857
  },
603
1858
  "robots": [],
604
- "role": "auth.login",
1859
+ "role": "auth.register",
605
1860
  "dependencies": [],
606
1861
  "chrome": {
607
1862
  "fullScreen": true
@@ -616,134 +1871,37 @@
616
1871
  ]
617
1872
  },
618
1873
  {
619
- "viewId": "logout.index",
620
- "title": "Logout",
621
- "description": "Clear the authentication token from the client.",
622
- "path": "/logout",
1874
+ "viewId": "social.index",
1875
+ "title": "Social sign-in",
1876
+ "description": "Sign in with Google, Microsoft or GitHub, or link a provider to your account.",
1877
+ "path": "/social",
623
1878
  "pathVariants": [],
624
1879
  "paramsSchema": {},
625
1880
  "operations": [
626
1881
  {
627
- "operationId": "auth.logout.view",
1882
+ "operationId": "auth.social.view",
628
1883
  "method": "GET",
629
- "title": "Logout",
630
- "description": "Clear the authentication token from the client.",
631
- "querySchema": {},
632
- "headersSchema": {
1884
+ "title": "Social sign-in",
1885
+ "description": "Sign in with Google, Microsoft or GitHub, or link a provider to your account.",
1886
+ "querySchema": {
633
1887
  "anyvaliVersion": "1.0",
634
1888
  "schemaVersion": "1.1",
635
1889
  "root": {
636
1890
  "kind": "object",
637
1891
  "properties": {
638
- "x-bp-refresh": {
1892
+ "code": {
639
1893
  "kind": "optional",
640
1894
  "inner": {
641
1895
  "kind": "string"
642
1896
  }
643
- }
644
- },
645
- "required": [],
646
- "unknownKeys": "strip"
647
- },
648
- "definitions": {},
649
- "extensions": {}
650
- },
651
- "bodySchema": {},
652
- "jsonResponseSchema": {
653
- "anyvaliVersion": "1.0",
654
- "schemaVersion": "1.1",
655
- "root": {
656
- "kind": "object",
657
- "properties": {
658
- "status": {
659
- "kind": "enum",
660
- "values": [
661
- "ok"
662
- ],
663
- "metadata": {
664
- "description": "Logout request outcome."
665
- }
666
1897
  },
667
- "message": {
668
- "kind": "string",
669
- "metadata": {
670
- "description": "Human-readable logout status for the renderer."
671
- }
672
- }
673
- },
674
- "required": [
675
- "status",
676
- "message"
677
- ],
678
- "unknownKeys": "strip"
679
- },
680
- "definitions": {},
681
- "extensions": {}
682
- },
683
- "metadataResponseSchema": {},
684
- "renderable": true,
685
- "html": {
686
- "renderers": {
687
- "bootstrap5": {
688
- "defaultRenderer": "default",
689
- "renderModes": [
690
- "page"
691
- ],
692
- "slots": [
693
- "main"
694
- ],
695
- "renderers": [
696
- {
697
- "id": "default",
698
- "title": "Default Content",
699
- "slotId": "main",
700
- "renderModes": [
701
- "page",
702
- "fragment"
703
- ]
1898
+ "state": {
1899
+ "kind": "optional",
1900
+ "inner": {
1901
+ "kind": "string"
704
1902
  }
705
- ]
706
- }
707
- }
708
- },
709
- "auth": {
710
- "required": false,
711
- "callers": [
712
- "user"
713
- ],
714
- "permissions": []
715
- },
716
- "sitemap": {
717
- "kind": "default"
718
- },
719
- "robots": [],
720
- "role": "auth.logout",
721
- "dependencies": [
722
- {
723
- "operationId": "auth.logout",
724
- "method": "POST"
725
- }
726
- ],
727
- "apiContracts": [],
728
- "demoScenarios": [],
729
- "cacheHints": {
730
- "ttlSeconds": 0,
731
- "varyBy": []
732
- }
733
- },
734
- {
735
- "operationId": "auth.logout",
736
- "method": "POST",
737
- "title": "Logout",
738
- "description": "Clear the authentication token from the client.",
739
- "querySchema": {},
740
- "headersSchema": {
741
- "anyvaliVersion": "1.0",
742
- "schemaVersion": "1.1",
743
- "root": {
744
- "kind": "object",
745
- "properties": {
746
- "x-bp-refresh": {
1903
+ },
1904
+ "error": {
747
1905
  "kind": "optional",
748
1906
  "inner": {
749
1907
  "kind": "string"
@@ -756,36 +1914,51 @@
756
1914
  "definitions": {},
757
1915
  "extensions": {}
758
1916
  },
1917
+ "headersSchema": {},
759
1918
  "bodySchema": {},
760
1919
  "jsonResponseSchema": {
761
1920
  "anyvaliVersion": "1.0",
762
1921
  "schemaVersion": "1.1",
763
1922
  "root": {
764
- "kind": "object",
765
- "properties": {
766
- "status": {
767
- "kind": "enum",
768
- "values": [
769
- "ok"
770
- ],
771
- "metadata": {
772
- "description": "Logout request outcome."
773
- }
774
- },
775
- "message": {
776
- "kind": "string",
777
- "metadata": {
778
- "description": "Human-readable logout status for the renderer."
1923
+ "kind": "record",
1924
+ "valueSchema": {
1925
+ "kind": "ref",
1926
+ "ref": "#/definitions/BetterPortalJsonValue"
1927
+ }
1928
+ },
1929
+ "definitions": {
1930
+ "BetterPortalJsonValue": {
1931
+ "kind": "union",
1932
+ "variants": [
1933
+ {
1934
+ "kind": "null"
1935
+ },
1936
+ {
1937
+ "kind": "bool"
1938
+ },
1939
+ {
1940
+ "kind": "string"
1941
+ },
1942
+ {
1943
+ "kind": "number"
1944
+ },
1945
+ {
1946
+ "kind": "array",
1947
+ "items": {
1948
+ "kind": "ref",
1949
+ "ref": "#/definitions/BetterPortalJsonValue"
1950
+ }
1951
+ },
1952
+ {
1953
+ "kind": "record",
1954
+ "valueSchema": {
1955
+ "kind": "ref",
1956
+ "ref": "#/definitions/BetterPortalJsonValue"
1957
+ }
779
1958
  }
780
- }
781
- },
782
- "required": [
783
- "status",
784
- "message"
785
- ],
786
- "unknownKeys": "strip"
1959
+ ]
1960
+ }
787
1961
  },
788
- "definitions": {},
789
1962
  "extensions": {}
790
1963
  },
791
1964
  "metadataResponseSchema": {},
@@ -825,138 +1998,117 @@
825
1998
  "kind": "default"
826
1999
  },
827
2000
  "robots": [],
828
- "role": "auth.logout",
829
- "dependencies": [],
2001
+ "dependencies": [
2002
+ {
2003
+ "operationId": "auth.social",
2004
+ "method": "POST"
2005
+ },
2006
+ {
2007
+ "operationId": "auth.account",
2008
+ "method": "POST"
2009
+ }
2010
+ ],
830
2011
  "apiContracts": [],
831
2012
  "demoScenarios": [],
832
2013
  "cacheHints": {
833
2014
  "ttlSeconds": 0,
834
2015
  "varyBy": []
835
2016
  }
836
- }
837
- ]
838
- },
839
- {
840
- "viewId": "refresh.index",
841
- "title": "Refresh Token",
842
- "description": "Exchange a refresh token for a new access token.",
843
- "path": "/refresh",
844
- "pathVariants": [],
845
- "paramsSchema": {},
846
- "operations": [
2017
+ },
847
2018
  {
848
- "operationId": "auth.refresh",
2019
+ "operationId": "auth.social",
849
2020
  "method": "POST",
850
- "title": "Refresh Token",
851
- "description": "Exchange a refresh token for a new access token.",
852
- "querySchema": {
853
- "anyvaliVersion": "1.0",
854
- "schemaVersion": "1.1",
855
- "root": {
856
- "kind": "object",
857
- "properties": {},
858
- "required": [],
859
- "unknownKeys": "strip"
860
- },
861
- "definitions": {},
862
- "extensions": {}
863
- },
864
- "headersSchema": {
865
- "anyvaliVersion": "1.0",
866
- "schemaVersion": "1.1",
867
- "root": {
868
- "kind": "object",
869
- "properties": {
870
- "x-bp-refresh": {
871
- "kind": "optional",
872
- "inner": {
873
- "kind": "string",
874
- "minLength": 1
875
- }
876
- }
877
- },
878
- "required": [],
879
- "unknownKeys": "strip"
880
- },
881
- "definitions": {},
882
- "extensions": {}
883
- },
2021
+ "title": "Social sign-in",
2022
+ "description": "Sign in with Google, Microsoft or GitHub, or link a provider to your account.",
2023
+ "querySchema": {},
2024
+ "headersSchema": {},
884
2025
  "bodySchema": {
885
2026
  "anyvaliVersion": "1.0",
886
2027
  "schemaVersion": "1.1",
887
2028
  "root": {
888
2029
  "kind": "object",
889
2030
  "properties": {
890
- "refreshToken": {
2031
+ "action": {
2032
+ "kind": "string"
2033
+ },
2034
+ "connection": {
891
2035
  "kind": "optional",
892
2036
  "inner": {
893
- "kind": "string",
894
- "minLength": 1,
895
- "metadata": {
896
- "description": "Signed refresh token issued by the auth service."
897
- }
898
- }
899
- }
900
- },
901
- "required": [],
902
- "unknownKeys": "strip"
903
- },
904
- "definitions": {},
905
- "extensions": {}
906
- },
907
- "jsonResponseSchema": {
908
- "anyvaliVersion": "1.0",
909
- "schemaVersion": "1.1",
910
- "root": {
911
- "kind": "object",
912
- "properties": {
913
- "status": {
914
- "kind": "enum",
915
- "values": [
916
- "ok",
917
- "error"
918
- ],
919
- "metadata": {
920
- "description": "Refresh request outcome."
2037
+ "kind": "string"
921
2038
  }
922
2039
  },
923
- "message": {
2040
+ "id": {
924
2041
  "kind": "optional",
925
2042
  "inner": {
926
2043
  "kind": "string"
927
- },
928
- "metadata": {
929
- "description": "Human-readable status or error message for the renderer."
930
2044
  }
931
2045
  },
932
- "accessToken": {
2046
+ "secret": {
933
2047
  "kind": "optional",
934
2048
  "inner": {
935
2049
  "kind": "string"
936
- },
937
- "metadata": {
938
- "description": "New signed JWT access token returned when refresh succeeds."
939
2050
  }
940
2051
  },
941
- "expiresInSeconds": {
2052
+ "code": {
942
2053
  "kind": "optional",
943
2054
  "inner": {
944
- "kind": "int",
945
- "min": 1
946
- },
947
- "metadata": {
948
- "description": "New access token lifetime in seconds."
2055
+ "kind": "string"
949
2056
  }
950
2057
  }
951
2058
  },
952
2059
  "required": [
953
- "status"
2060
+ "action"
954
2061
  ],
955
2062
  "unknownKeys": "strip"
956
2063
  },
957
2064
  "definitions": {},
958
2065
  "extensions": {}
959
2066
  },
2067
+ "jsonResponseSchema": {
2068
+ "anyvaliVersion": "1.0",
2069
+ "schemaVersion": "1.1",
2070
+ "root": {
2071
+ "kind": "record",
2072
+ "valueSchema": {
2073
+ "kind": "ref",
2074
+ "ref": "#/definitions/BetterPortalJsonValue"
2075
+ }
2076
+ },
2077
+ "definitions": {
2078
+ "BetterPortalJsonValue": {
2079
+ "kind": "union",
2080
+ "variants": [
2081
+ {
2082
+ "kind": "null"
2083
+ },
2084
+ {
2085
+ "kind": "bool"
2086
+ },
2087
+ {
2088
+ "kind": "string"
2089
+ },
2090
+ {
2091
+ "kind": "number"
2092
+ },
2093
+ {
2094
+ "kind": "array",
2095
+ "items": {
2096
+ "kind": "ref",
2097
+ "ref": "#/definitions/BetterPortalJsonValue"
2098
+ }
2099
+ },
2100
+ {
2101
+ "kind": "record",
2102
+ "valueSchema": {
2103
+ "kind": "ref",
2104
+ "ref": "#/definitions/BetterPortalJsonValue"
2105
+ }
2106
+ }
2107
+ ]
2108
+ }
2109
+ },
2110
+ "extensions": {}
2111
+ },
960
2112
  "metadataResponseSchema": {},
961
2113
  "renderable": false,
962
2114
  "html": {
@@ -973,7 +2125,6 @@
973
2125
  "kind": "default"
974
2126
  },
975
2127
  "robots": [],
976
- "role": "auth.refresh",
977
2128
  "dependencies": [],
978
2129
  "apiContracts": [],
979
2130
  "demoScenarios": [],
@@ -985,31 +2136,34 @@
985
2136
  ]
986
2137
  },
987
2138
  {
988
- "viewId": "register.index",
989
- "title": "Register First Admin",
990
- "description": "Open registration for the very first user. Once any user exists, this endpoint requires admin auth.",
991
- "path": "/register",
2139
+ "viewId": "users.index",
2140
+ "title": "Users and groups",
2141
+ "description": "Manage users, group membership, invitations and app roles.",
2142
+ "path": "/users",
992
2143
  "pathVariants": [],
993
2144
  "paramsSchema": {},
994
2145
  "operations": [
995
2146
  {
996
- "operationId": "auth.register.view",
2147
+ "operationId": "auth.users.view",
997
2148
  "method": "GET",
998
- "title": "Register First Admin",
999
- "description": "Open registration for the very first user. Once any user exists, this endpoint requires admin auth.",
2149
+ "title": "Users and groups",
2150
+ "description": "Manage users, group membership, invitations and app roles.",
1000
2151
  "querySchema": {
1001
2152
  "anyvaliVersion": "1.0",
1002
2153
  "schemaVersion": "1.1",
1003
2154
  "root": {
1004
2155
  "kind": "object",
1005
2156
  "properties": {
1006
- "next": {
2157
+ "after": {
2158
+ "kind": "optional",
2159
+ "inner": {
2160
+ "kind": "string"
2161
+ }
2162
+ },
2163
+ "mailAfter": {
1007
2164
  "kind": "optional",
1008
2165
  "inner": {
1009
2166
  "kind": "string"
1010
- },
1011
- "metadata": {
1012
- "description": "The view path to pass through to login after first-admin registration."
1013
2167
  }
1014
2168
  }
1015
2169
  },
@@ -1025,87 +2179,45 @@
1025
2179
  "anyvaliVersion": "1.0",
1026
2180
  "schemaVersion": "1.1",
1027
2181
  "root": {
1028
- "kind": "object",
1029
- "properties": {
1030
- "status": {
1031
- "kind": "enum",
1032
- "values": [
1033
- "ok",
1034
- "error"
1035
- ],
1036
- "metadata": {
1037
- "description": "Registration request outcome."
1038
- }
1039
- },
1040
- "message": {
1041
- "kind": "optional",
1042
- "inner": {
1043
- "kind": "string"
2182
+ "kind": "record",
2183
+ "valueSchema": {
2184
+ "kind": "ref",
2185
+ "ref": "#/definitions/BetterPortalJsonValue"
2186
+ }
2187
+ },
2188
+ "definitions": {
2189
+ "BetterPortalJsonValue": {
2190
+ "kind": "union",
2191
+ "variants": [
2192
+ {
2193
+ "kind": "null"
1044
2194
  },
1045
- "metadata": {
1046
- "description": "Human-readable status or error message for the renderer."
1047
- }
1048
- },
1049
- "user": {
1050
- "kind": "optional",
1051
- "inner": {
1052
- "kind": "object",
1053
- "properties": {
1054
- "id": {
1055
- "kind": "string",
1056
- "metadata": {
1057
- "description": "Stable UUIDv7 user id."
1058
- }
1059
- },
1060
- "username": {
1061
- "kind": "string",
1062
- "metadata": {
1063
- "description": "Created account username."
1064
- }
1065
- },
1066
- "isFirstAdmin": {
1067
- "kind": "bool",
1068
- "metadata": {
1069
- "description": "True when this account is the deployment's first admin."
1070
- }
1071
- }
1072
- },
1073
- "required": [
1074
- "id",
1075
- "username",
1076
- "isFirstAdmin"
1077
- ],
1078
- "unknownKeys": "strip",
1079
- "metadata": {
1080
- "description": "Created first-admin user summary."
1081
- }
1082
- }
1083
- },
1084
- "registrationOpen": {
1085
- "kind": "optional",
1086
- "inner": {
2195
+ {
1087
2196
  "kind": "bool"
1088
2197
  },
1089
- "metadata": {
1090
- "description": "True while the auth service has zero users; once false, the renderer should send the browser to login."
1091
- }
1092
- },
1093
- "loginUrl": {
1094
- "kind": "optional",
1095
- "inner": {
2198
+ {
1096
2199
  "kind": "string"
1097
2200
  },
1098
- "metadata": {
1099
- "description": "Absolute self-origin URL of this auth service's login view, used when registration is closed and after successful first-admin creation."
2201
+ {
2202
+ "kind": "number"
2203
+ },
2204
+ {
2205
+ "kind": "array",
2206
+ "items": {
2207
+ "kind": "ref",
2208
+ "ref": "#/definitions/BetterPortalJsonValue"
2209
+ }
2210
+ },
2211
+ {
2212
+ "kind": "record",
2213
+ "valueSchema": {
2214
+ "kind": "ref",
2215
+ "ref": "#/definitions/BetterPortalJsonValue"
2216
+ }
1100
2217
  }
1101
- }
1102
- },
1103
- "required": [
1104
- "status"
1105
- ],
1106
- "unknownKeys": "strip"
2218
+ ]
2219
+ }
1107
2220
  },
1108
- "definitions": {},
1109
2221
  "extensions": {}
1110
2222
  },
1111
2223
  "metadataResponseSchema": {},
@@ -1135,30 +2247,30 @@
1135
2247
  }
1136
2248
  },
1137
2249
  "auth": {
1138
- "required": false,
2250
+ "required": true,
1139
2251
  "callers": [
1140
2252
  "user"
1141
2253
  ],
1142
- "permissions": []
2254
+ "permissions": [
2255
+ {
2256
+ "serviceId": "org.betterportal.auth.default",
2257
+ "viewId": "users.index",
2258
+ "permissions": [
2259
+ "read"
2260
+ ]
2261
+ }
2262
+ ]
1143
2263
  },
1144
2264
  "sitemap": {
1145
2265
  "kind": "default"
1146
2266
  },
1147
2267
  "robots": [],
1148
- "role": "auth.register",
1149
2268
  "dependencies": [
1150
2269
  {
1151
- "operationId": "auth.register",
2270
+ "operationId": "auth.users.manage",
1152
2271
  "method": "POST"
1153
- },
1154
- {
1155
- "operationId": "auth.login.view",
1156
- "method": "GET"
1157
2272
  }
1158
2273
  ],
1159
- "chrome": {
1160
- "fullScreen": true
1161
- },
1162
2274
  "apiContracts": [],
1163
2275
  "demoScenarios": [],
1164
2276
  "cacheHints": {
@@ -1166,33 +2278,12 @@
1166
2278
  "varyBy": []
1167
2279
  }
1168
2280
  },
1169
- {
1170
- "operationId": "auth.register",
1171
- "method": "POST",
1172
- "title": "Register First Admin",
1173
- "description": "Open registration for the very first user. Once any user exists, this endpoint requires admin auth.",
1174
- "querySchema": {
1175
- "anyvaliVersion": "1.0",
1176
- "schemaVersion": "1.1",
1177
- "root": {
1178
- "kind": "object",
1179
- "properties": {
1180
- "next": {
1181
- "kind": "optional",
1182
- "inner": {
1183
- "kind": "string"
1184
- },
1185
- "metadata": {
1186
- "description": "The view path to pass through to login after first-admin registration."
1187
- }
1188
- }
1189
- },
1190
- "required": [],
1191
- "unknownKeys": "strip"
1192
- },
1193
- "definitions": {},
1194
- "extensions": {}
1195
- },
2281
+ {
2282
+ "operationId": "auth.users.manage",
2283
+ "method": "POST",
2284
+ "title": "Users and groups",
2285
+ "description": "Manage users, group membership, invitations and app roles.",
2286
+ "querySchema": {},
1196
2287
  "headersSchema": {},
1197
2288
  "bodySchema": {
1198
2289
  "anyvaliVersion": "1.0",
@@ -1200,177 +2291,133 @@
1200
2291
  "root": {
1201
2292
  "kind": "object",
1202
2293
  "properties": {
1203
- "username": {
1204
- "kind": "string",
1205
- "minLength": 1,
1206
- "metadata": {
1207
- "description": "Username for the first admin account."
1208
- }
1209
- },
1210
- "password": {
1211
- "kind": "string",
1212
- "minLength": 8,
1213
- "metadata": {
1214
- "description": "Password for the first admin account."
1215
- }
2294
+ "action": {
2295
+ "kind": "string"
1216
2296
  },
1217
- "email": {
2297
+ "id": {
1218
2298
  "kind": "optional",
1219
2299
  "inner": {
1220
2300
  "kind": "string"
1221
- },
1222
- "metadata": {
1223
- "description": "Email address for the first admin account."
1224
2301
  }
1225
2302
  },
1226
- "name": {
2303
+ "email": {
1227
2304
  "kind": "optional",
1228
2305
  "inner": {
1229
2306
  "kind": "string"
1230
- },
1231
- "metadata": {
1232
- "description": "Display name for the first admin account."
1233
- }
1234
- }
1235
- },
1236
- "required": [
1237
- "username",
1238
- "password"
1239
- ],
1240
- "unknownKeys": "strip"
1241
- },
1242
- "definitions": {},
1243
- "extensions": {}
1244
- },
1245
- "jsonResponseSchema": {
1246
- "anyvaliVersion": "1.0",
1247
- "schemaVersion": "1.1",
1248
- "root": {
1249
- "kind": "object",
1250
- "properties": {
1251
- "status": {
1252
- "kind": "enum",
1253
- "values": [
1254
- "ok",
1255
- "error"
1256
- ],
1257
- "metadata": {
1258
- "description": "Registration request outcome."
1259
2307
  }
1260
2308
  },
1261
- "message": {
2309
+ "name": {
1262
2310
  "kind": "optional",
1263
2311
  "inner": {
1264
2312
  "kind": "string"
1265
- },
1266
- "metadata": {
1267
- "description": "Human-readable status or error message for the renderer."
1268
2313
  }
1269
2314
  },
1270
- "user": {
2315
+ "enabled": {
1271
2316
  "kind": "optional",
1272
2317
  "inner": {
1273
- "kind": "object",
1274
- "properties": {
1275
- "id": {
1276
- "kind": "string",
1277
- "metadata": {
1278
- "description": "Stable UUIDv7 user id."
1279
- }
1280
- },
1281
- "username": {
1282
- "kind": "string",
1283
- "metadata": {
1284
- "description": "Created account username."
1285
- }
1286
- },
1287
- "isFirstAdmin": {
1288
- "kind": "bool",
1289
- "metadata": {
1290
- "description": "True when this account is the deployment's first admin."
1291
- }
1292
- }
1293
- },
1294
- "required": [
1295
- "id",
1296
- "username",
1297
- "isFirstAdmin"
1298
- ],
1299
- "unknownKeys": "strip",
1300
- "metadata": {
1301
- "description": "Created first-admin user summary."
1302
- }
2318
+ "kind": "bool"
1303
2319
  }
1304
2320
  },
1305
- "registrationOpen": {
2321
+ "roles": {
1306
2322
  "kind": "optional",
1307
2323
  "inner": {
1308
- "kind": "bool"
1309
- },
1310
- "metadata": {
1311
- "description": "True while the auth service has zero users; once false, the renderer should send the browser to login."
2324
+ "kind": "array",
2325
+ "items": {
2326
+ "kind": "string"
2327
+ }
1312
2328
  }
1313
2329
  },
1314
- "loginUrl": {
2330
+ "members": {
1315
2331
  "kind": "optional",
1316
2332
  "inner": {
1317
- "kind": "string"
1318
- },
1319
- "metadata": {
1320
- "description": "Absolute self-origin URL of this auth service's login view, used when registration is closed and after successful first-admin creation."
2333
+ "kind": "array",
2334
+ "items": {
2335
+ "kind": "string"
2336
+ }
1321
2337
  }
1322
2338
  }
1323
2339
  },
1324
2340
  "required": [
1325
- "status"
2341
+ "action"
1326
2342
  ],
1327
2343
  "unknownKeys": "strip"
1328
2344
  },
1329
2345
  "definitions": {},
1330
2346
  "extensions": {}
1331
2347
  },
1332
- "metadataResponseSchema": {},
1333
- "renderable": true,
1334
- "html": {
1335
- "renderers": {
1336
- "bootstrap5": {
1337
- "defaultRenderer": "default",
1338
- "renderModes": [
1339
- "page"
1340
- ],
1341
- "slots": [
1342
- "main"
1343
- ],
1344
- "renderers": [
2348
+ "jsonResponseSchema": {
2349
+ "anyvaliVersion": "1.0",
2350
+ "schemaVersion": "1.1",
2351
+ "root": {
2352
+ "kind": "record",
2353
+ "valueSchema": {
2354
+ "kind": "ref",
2355
+ "ref": "#/definitions/BetterPortalJsonValue"
2356
+ }
2357
+ },
2358
+ "definitions": {
2359
+ "BetterPortalJsonValue": {
2360
+ "kind": "union",
2361
+ "variants": [
1345
2362
  {
1346
- "id": "default",
1347
- "title": "Default Content",
1348
- "slotId": "main",
1349
- "renderModes": [
1350
- "page",
1351
- "fragment"
1352
- ]
2363
+ "kind": "null"
2364
+ },
2365
+ {
2366
+ "kind": "bool"
2367
+ },
2368
+ {
2369
+ "kind": "string"
2370
+ },
2371
+ {
2372
+ "kind": "number"
2373
+ },
2374
+ {
2375
+ "kind": "array",
2376
+ "items": {
2377
+ "kind": "ref",
2378
+ "ref": "#/definitions/BetterPortalJsonValue"
2379
+ }
2380
+ },
2381
+ {
2382
+ "kind": "record",
2383
+ "valueSchema": {
2384
+ "kind": "ref",
2385
+ "ref": "#/definitions/BetterPortalJsonValue"
2386
+ }
1353
2387
  }
1354
2388
  ]
1355
2389
  }
1356
- }
2390
+ },
2391
+ "extensions": {}
2392
+ },
2393
+ "metadataResponseSchema": {},
2394
+ "renderable": false,
2395
+ "html": {
2396
+ "renderers": {}
1357
2397
  },
1358
2398
  "auth": {
1359
- "required": false,
2399
+ "required": true,
2400
+ "elevation": {
2401
+ "minimum": "mfa"
2402
+ },
1360
2403
  "callers": [
1361
2404
  "user"
1362
2405
  ],
1363
- "permissions": []
2406
+ "permissions": [
2407
+ {
2408
+ "serviceId": "org.betterportal.auth.default",
2409
+ "viewId": "users.index",
2410
+ "permissions": [
2411
+ "update"
2412
+ ]
2413
+ }
2414
+ ]
1364
2415
  },
1365
2416
  "sitemap": {
1366
2417
  "kind": "default"
1367
2418
  },
1368
2419
  "robots": [],
1369
- "role": "auth.register",
1370
2420
  "dependencies": [],
1371
- "chrome": {
1372
- "fullScreen": true
1373
- },
1374
2421
  "apiContracts": [],
1375
2422
  "demoScenarios": [],
1376
2423
  "cacheHints": {
@@ -1381,9 +2428,220 @@
1381
2428
  ]
1382
2429
  }
1383
2430
  ],
1384
- "configSchemas": [],
2431
+ "configSchemas": [
2432
+ {
2433
+ "id": "default-auth.tenant",
2434
+ "title": "Account isolation",
2435
+ "description": "Account directory boundaries. Locked permanently when the first user is created.",
2436
+ "scope": "tenant",
2437
+ "jsonSchema": {
2438
+ "userIsolation": "string",
2439
+ "directoryAdminAppId": "string"
2440
+ },
2441
+ "fields": [
2442
+ {
2443
+ "key": "userIsolation",
2444
+ "title": "User isolation",
2445
+ "description": "Account directory boundary; cannot change after user creation.",
2446
+ "scope": "tenant",
2447
+ "visibility": "protected",
2448
+ "ownership": "bp",
2449
+ "sourceOfTruth": "bp",
2450
+ "defaultValue": "app",
2451
+ "ui": {
2452
+ "control": "select",
2453
+ "options": [
2454
+ {
2455
+ "value": "app",
2456
+ "label": "Separate accounts per app"
2457
+ },
2458
+ {
2459
+ "value": "tenant",
2460
+ "label": "Shared accounts in this tenant"
2461
+ }
2462
+ ]
2463
+ },
2464
+ "required": false
2465
+ },
2466
+ {
2467
+ "key": "directoryAdminAppId",
2468
+ "title": "Directory administration app",
2469
+ "description": "For shared tenant accounts, the app whose authorized administrators may disable accounts, revoke all sessions and change shared groups. Must be an app in this tenant.",
2470
+ "scope": "tenant",
2471
+ "visibility": "protected",
2472
+ "ownership": "bp",
2473
+ "sourceOfTruth": "bp",
2474
+ "required": false
2475
+ }
2476
+ ]
2477
+ },
2478
+ {
2479
+ "id": "default-auth.app",
2480
+ "title": "Default authentication",
2481
+ "description": "Registration, first-login roles, MFA, email delivery and social connections for this app.",
2482
+ "scope": "app",
2483
+ "jsonSchema": {
2484
+ "registration": "string",
2485
+ "defaultRoleIds": "string",
2486
+ "requireMfa": "boolean",
2487
+ "mailTransport": "string",
2488
+ "mailUrl": "string",
2489
+ "mailFrom": "string",
2490
+ "mailApiKey": "string",
2491
+ "mailHeaders": "string",
2492
+ "socialConnections": "string"
2493
+ },
2494
+ "fields": [
2495
+ {
2496
+ "key": "registration",
2497
+ "title": "Registration",
2498
+ "description": "Registration",
2499
+ "scope": "app",
2500
+ "visibility": "protected",
2501
+ "ownership": "bp",
2502
+ "sourceOfTruth": "bp",
2503
+ "defaultValue": "invite-only",
2504
+ "ui": {
2505
+ "control": "select",
2506
+ "options": [
2507
+ {
2508
+ "value": "invite-only",
2509
+ "label": "Invitations only"
2510
+ },
2511
+ {
2512
+ "value": "public",
2513
+ "label": "Public registration"
2514
+ },
2515
+ {
2516
+ "value": "closed",
2517
+ "label": "Closed"
2518
+ }
2519
+ ]
2520
+ },
2521
+ "required": false
2522
+ },
2523
+ {
2524
+ "key": "defaultRoleIds",
2525
+ "title": "Default role IDs",
2526
+ "description": "JSON array of existing app role IDs. Applied once at first completed login. Empty by default.",
2527
+ "scope": "app",
2528
+ "visibility": "protected",
2529
+ "ownership": "bp",
2530
+ "sourceOfTruth": "bp",
2531
+ "defaultValue": "[]",
2532
+ "required": false
2533
+ },
2534
+ {
2535
+ "key": "requireMfa",
2536
+ "title": "Require multi-factor authentication",
2537
+ "description": "Require multi-factor authentication",
2538
+ "scope": "app",
2539
+ "visibility": "protected",
2540
+ "ownership": "bp",
2541
+ "sourceOfTruth": "bp",
2542
+ "defaultValue": false,
2543
+ "required": false
2544
+ },
2545
+ {
2546
+ "key": "mailTransport",
2547
+ "title": "Email delivery",
2548
+ "description": "Email delivery",
2549
+ "scope": "app",
2550
+ "visibility": "protected",
2551
+ "ownership": "bp",
2552
+ "sourceOfTruth": "bp",
2553
+ "ui": {
2554
+ "control": "select",
2555
+ "options": [
2556
+ {
2557
+ "value": "postal",
2558
+ "label": "Postal HTTP API"
2559
+ },
2560
+ {
2561
+ "value": "http",
2562
+ "label": "Custom HTTP API"
2563
+ }
2564
+ ]
2565
+ },
2566
+ "required": false
2567
+ },
2568
+ {
2569
+ "key": "mailUrl",
2570
+ "title": "Email API URL",
2571
+ "description": "Email API URL",
2572
+ "scope": "app",
2573
+ "visibility": "protected",
2574
+ "ownership": "bp",
2575
+ "sourceOfTruth": "bp",
2576
+ "required": false
2577
+ },
2578
+ {
2579
+ "key": "mailFrom",
2580
+ "title": "Sender email",
2581
+ "description": "Sender email",
2582
+ "scope": "app",
2583
+ "visibility": "protected",
2584
+ "ownership": "bp",
2585
+ "sourceOfTruth": "bp",
2586
+ "required": false
2587
+ },
2588
+ {
2589
+ "key": "mailApiKey",
2590
+ "title": "Postal API key",
2591
+ "description": "Postal API key",
2592
+ "scope": "app",
2593
+ "visibility": "secret",
2594
+ "ownership": "bp",
2595
+ "sourceOfTruth": "bp",
2596
+ "required": false
2597
+ },
2598
+ {
2599
+ "key": "mailHeaders",
2600
+ "title": "Custom HTTP headers",
2601
+ "description": "JSON object of server-side headers.",
2602
+ "scope": "app",
2603
+ "visibility": "secret",
2604
+ "ownership": "bp",
2605
+ "sourceOfTruth": "bp",
2606
+ "required": false
2607
+ },
2608
+ {
2609
+ "key": "socialConnections",
2610
+ "title": "Social connections",
2611
+ "description": "JSON array of Google, Microsoft or GitHub connections. Each app requires its own registered redirect URL.",
2612
+ "scope": "app",
2613
+ "visibility": "secret",
2614
+ "ownership": "bp",
2615
+ "sourceOfTruth": "bp",
2616
+ "required": false
2617
+ }
2618
+ ]
2619
+ }
2620
+ ],
1385
2621
  "permissions": [],
1386
- "adminApis": [],
2622
+ "adminApis": [
2623
+ {
2624
+ "id": "config.schema",
2625
+ "title": "Config Schema",
2626
+ "description": "BetterPortal-managed config schemas for this service.",
2627
+ "path": "/.well-known/bp/config/schema",
2628
+ "methods": [
2629
+ "GET"
2630
+ ],
2631
+ "supportsCustomUi": false
2632
+ },
2633
+ {
2634
+ "id": "config.values",
2635
+ "title": "Config Values",
2636
+ "description": "Read and write BetterPortal-managed config values.",
2637
+ "path": "/.well-known/bp/config",
2638
+ "methods": [
2639
+ "GET",
2640
+ "POST"
2641
+ ],
2642
+ "supportsCustomUi": false
2643
+ }
2644
+ ],
1387
2645
  "webhooks": [],
1388
2646
  "apiContracts": [],
1389
2647
  "m2mRequests": [],
@@ -1393,6 +2651,28 @@
1393
2651
  }
1394
2652
  },
1395
2653
  "routes": [
2654
+ {
2655
+ "viewId": "account.index",
2656
+ "path": "/account",
2657
+ "pathVariants": [],
2658
+ "operations": [
2659
+ {
2660
+ "operationId": "auth.account.view",
2661
+ "method": "GET"
2662
+ },
2663
+ {
2664
+ "operationId": "auth.account",
2665
+ "method": "POST"
2666
+ }
2667
+ ],
2668
+ "paramNames": [],
2669
+ "renderers": [
2670
+ "bootstrap5"
2671
+ ],
2672
+ "hasFragments": false,
2673
+ "fragments": [],
2674
+ "components": []
2675
+ },
1396
2676
  {
1397
2677
  "viewId": "login.index",
1398
2678
  "path": "/login",
@@ -1484,6 +2764,50 @@
1484
2764
  "hasFragments": false,
1485
2765
  "fragments": [],
1486
2766
  "components": []
2767
+ },
2768
+ {
2769
+ "viewId": "social.index",
2770
+ "path": "/social",
2771
+ "pathVariants": [],
2772
+ "operations": [
2773
+ {
2774
+ "operationId": "auth.social.view",
2775
+ "method": "GET"
2776
+ },
2777
+ {
2778
+ "operationId": "auth.social",
2779
+ "method": "POST"
2780
+ }
2781
+ ],
2782
+ "paramNames": [],
2783
+ "renderers": [
2784
+ "bootstrap5"
2785
+ ],
2786
+ "hasFragments": false,
2787
+ "fragments": [],
2788
+ "components": []
2789
+ },
2790
+ {
2791
+ "viewId": "users.index",
2792
+ "path": "/users",
2793
+ "pathVariants": [],
2794
+ "operations": [
2795
+ {
2796
+ "operationId": "auth.users.view",
2797
+ "method": "GET"
2798
+ },
2799
+ {
2800
+ "operationId": "auth.users.manage",
2801
+ "method": "POST"
2802
+ }
2803
+ ],
2804
+ "paramNames": [],
2805
+ "renderers": [
2806
+ "bootstrap5"
2807
+ ],
2808
+ "hasFragments": false,
2809
+ "fragments": [],
2810
+ "components": []
1487
2811
  }
1488
2812
  ]
1489
2813
  }