@adonis-agora/authkit-server 1.0.0-rc.1 → 1.0.0-rc.11

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 (181) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/README.md +4 -5
  3. package/build/commands/agora_doctor.d.ts +22 -0
  4. package/build/commands/agora_doctor.js +109 -0
  5. package/build/commands/clients_create.d.ts +4 -0
  6. package/build/commands/clients_create.js +97 -0
  7. package/build/commands/commands.json +78 -0
  8. package/build/commands/doctor.js +8 -74
  9. package/build/host/views/account/apps.edge +1 -5
  10. package/build/host/views/account/extension.edge +77 -0
  11. package/build/host/views/account/mfa.edge +2 -0
  12. package/build/host/views/account/partials/extension_actions.edge +14 -0
  13. package/build/host/views/account/partials/extension_block.edge +197 -0
  14. package/build/host/views/account/partials/extension_value.edge +8 -0
  15. package/build/host/views/account/partials/nav.edge +14 -0
  16. package/build/host/views/account/security.edge +1 -5
  17. package/build/host/views/account/tokens.edge +2 -2
  18. package/build/host/views/agents/consent.edge +11 -2
  19. package/build/host/views/agents/done.edge +1 -1
  20. package/build/host/views/partials/styles.edge +1 -1
  21. package/build/index.d.ts +12 -12
  22. package/build/index.js +7 -9
  23. package/build/providers/authkit_server_provider.js +29 -8
  24. package/build/src/account/extension.d.ts +10 -0
  25. package/build/src/account/extension.js +9 -0
  26. package/build/src/account/http.d.ts +77 -0
  27. package/build/src/account/http.js +381 -0
  28. package/build/src/account/mount.d.ts +40 -0
  29. package/build/src/account/mount.js +171 -0
  30. package/build/src/account/registry.d.ts +41 -0
  31. package/build/src/account/registry.js +81 -0
  32. package/build/src/account/remote.d.ts +72 -0
  33. package/build/src/account/remote.js +406 -0
  34. package/build/src/account/runtime.d.ts +289 -0
  35. package/build/src/account/runtime.js +641 -0
  36. package/build/src/accounts/account_store.d.ts +13 -7
  37. package/build/src/accounts/lucid_account_store.d.ts +3 -3
  38. package/build/src/accounts/lucid_account_store.js +42 -17
  39. package/build/src/accounts/lucid_store/mfa.js +3 -3
  40. package/build/src/accounts/lucid_store/organization_models.d.ts +14 -3
  41. package/build/src/accounts/lucid_store/organization_models.js +31 -3
  42. package/build/src/accounts/lucid_store/organizations.d.ts +2 -2
  43. package/build/src/accounts/lucid_store/organizations.js +40 -31
  44. package/build/src/accounts/lucid_store/shared.d.ts +11 -3
  45. package/build/src/accounts/lucid_store/shared.js +7 -5
  46. package/build/src/accounts/lucid_store/webauthn.js +1 -1
  47. package/build/src/adapters/factory.d.ts +13 -2
  48. package/build/src/adapters/factory.js +2 -2
  49. package/build/src/agents/config.d.ts +9 -13
  50. package/build/src/agents/config.js +17 -11
  51. package/build/src/agents/delegation_service.js +3 -3
  52. package/build/src/agents/delegation_store.d.ts +3 -2
  53. package/build/src/agents/delegation_store.js +6 -5
  54. package/build/src/agents/extension.d.ts +261 -0
  55. package/build/src/agents/extension.js +40 -0
  56. package/build/src/agents/middleware.js +1 -1
  57. package/build/src/agents/protocol.d.ts +4 -4
  58. package/build/src/agents/registry_store.d.ts +3 -2
  59. package/build/src/agents/registry_store.js +1 -1
  60. package/build/src/agents/runtime.d.ts +26 -7
  61. package/build/src/agents/runtime.js +110 -75
  62. package/build/src/audit/audit_sink.d.ts +1 -1
  63. package/build/src/audit/audit_sink.js +10 -1
  64. package/build/src/commands/expire_scan_command.js +1 -1
  65. package/build/src/commands/settings_commands.js +2 -2
  66. package/build/src/console_switcher.d.ts +132 -0
  67. package/build/src/console_switcher.js +206 -0
  68. package/build/src/define_config.d.ts +38 -13
  69. package/build/src/define_config.js +32 -10
  70. package/build/src/dev_tools/contract.d.ts +72 -0
  71. package/build/src/dev_tools/contract.js +10 -0
  72. package/build/src/dev_tools/gate.d.ts +17 -0
  73. package/build/src/dev_tools/gate.js +69 -0
  74. package/build/src/dev_tools/register.d.ts +11 -0
  75. package/build/src/dev_tools/register.js +25 -0
  76. package/build/src/dev_tools/tools.d.ts +24 -0
  77. package/build/src/dev_tools/tools.js +384 -0
  78. package/build/src/doctor/agora_checks.d.ts +15 -0
  79. package/build/src/doctor/agora_checks.js +150 -0
  80. package/build/src/doctor/agora_doctor.d.ts +115 -0
  81. package/build/src/doctor/agora_doctor.js +692 -0
  82. package/build/src/doctor/checks.js +2 -2
  83. package/build/src/doctor/doctor_input.d.ts +27 -0
  84. package/build/src/doctor/doctor_input.js +86 -0
  85. package/build/src/doctor/index.d.ts +5 -0
  86. package/build/src/doctor/index.js +4 -0
  87. package/build/src/host/access_token_verifier.js +7 -0
  88. package/build/src/host/account_api/account_api_controller.js +8 -6
  89. package/build/src/host/account_session_sign_in.d.ts +12 -0
  90. package/build/src/host/account_session_sign_in.js +19 -0
  91. package/build/src/host/admin_api/admin_users_service.d.ts +5 -2
  92. package/build/src/host/admin_api/api_clients_controller.d.ts +37 -0
  93. package/build/src/host/admin_api/api_clients_controller.js +31 -1
  94. package/build/src/host/admin_api/dto.d.ts +3 -1
  95. package/build/src/host/admin_api/dto.js +2 -0
  96. package/build/src/host/admin_authorize.d.ts +8 -0
  97. package/build/src/host/admin_authorize.js +25 -0
  98. package/build/src/host/admin_clients_service.d.ts +20 -0
  99. package/build/src/host/admin_clients_service.js +55 -0
  100. package/build/src/host/admin_console/admin_console_entry.d.ts +14 -0
  101. package/build/src/host/admin_console/admin_console_entry.js +80 -0
  102. package/build/src/host/admin_console/admin_shell_controller.js +8 -0
  103. package/build/src/host/admin_console/console_clients_controller.d.ts +41 -0
  104. package/build/src/host/admin_console/console_clients_controller.js +34 -1
  105. package/build/src/host/admin_console/console_personal_agents_controller.d.ts +1 -6
  106. package/build/src/host/admin_console/console_personal_agents_controller.js +50 -30
  107. package/build/src/host/admin_console/console_switcher_controller.d.ts +11 -0
  108. package/build/src/host/admin_console/console_switcher_controller.js +23 -0
  109. package/build/src/host/admin_sessions_service.js +8 -5
  110. package/build/src/host/admin_validators.d.ts +29 -0
  111. package/build/src/host/admin_validators.js +30 -0
  112. package/build/src/host/auth_host_config.d.ts +9 -2
  113. package/build/src/host/controllers/account_apps_controller.js +15 -11
  114. package/build/src/host/csrf.d.ts +3 -3
  115. package/build/src/host/csrf.js +3 -13
  116. package/build/src/host/default_mailer.d.ts +11 -6
  117. package/build/src/host/default_mailer.js +16 -12
  118. package/build/src/host/i18n.d.ts +41 -14
  119. package/build/src/host/i18n.js +55 -13
  120. package/build/src/host/rate_limit.d.ts +8 -0
  121. package/build/src/host/rate_limit.js +9 -0
  122. package/build/src/host/register_auth_host.d.ts +14 -0
  123. package/build/src/host/register_auth_host.js +167 -106
  124. package/build/src/host/renderers/edge_renderer.js +5 -0
  125. package/build/src/host/renderers/inertia_renderer.js +7 -1
  126. package/build/src/host/runtime_settings.d.ts +6 -6
  127. package/build/src/host/runtime_settings.js +4 -3
  128. package/build/src/host/screen_props.d.ts +39 -8
  129. package/build/src/host/ui-dist/assets/index-Dq3dJVBv.js +67 -0
  130. package/build/src/host/ui-dist/assets/{index-DTSmD4RU.css → index-WNIyCEPA.css} +1 -1
  131. package/build/src/host/ui-dist/index.html +2 -2
  132. package/build/src/provider/build_provider.js +37 -6
  133. package/build/src/provider/oidc_service.d.ts +1 -1
  134. package/build/src/provider/oidc_service.js +1 -1
  135. package/build/src/schema/ensure.d.ts +24 -1
  136. package/build/src/schema/ensure.js +44 -154
  137. package/build/src/schema/tables_location.d.ts +27 -0
  138. package/build/src/schema/tables_location.js +22 -0
  139. package/build/src/service_tenants/client_metadata.d.ts +39 -0
  140. package/build/src/service_tenants/client_metadata.js +80 -0
  141. package/build/src/service_tenants/config.d.ts +44 -0
  142. package/build/src/service_tenants/config.js +44 -0
  143. package/build/src/service_tenants/provider_hooks.d.ts +52 -0
  144. package/build/src/service_tenants/provider_hooks.js +124 -0
  145. package/build/src/service_tenants/tenant_verifier.d.ts +73 -0
  146. package/build/src/service_tenants/tenant_verifier.js +104 -0
  147. package/build/src/tenancy/tenant_labels.d.ts +30 -0
  148. package/build/src/tenancy/tenant_labels.js +64 -0
  149. package/build/types.d.ts +3 -1
  150. package/package.json +9 -6
  151. package/build/src/agents/poppy/client_registry.d.ts +0 -50
  152. package/build/src/agents/poppy/client_registry.js +0 -260
  153. package/build/src/agents/poppy/config.d.ts +0 -396
  154. package/build/src/agents/poppy/config.js +0 -228
  155. package/build/src/agents/poppy/dpop.d.ts +0 -61
  156. package/build/src/agents/poppy/dpop.js +0 -158
  157. package/build/src/agents/poppy/email_code_sign_in.d.ts +0 -27
  158. package/build/src/agents/poppy/email_code_sign_in.js +0 -140
  159. package/build/src/agents/poppy/errors.d.ts +0 -25
  160. package/build/src/agents/poppy/errors.js +0 -25
  161. package/build/src/agents/poppy/replay.d.ts +0 -25
  162. package/build/src/agents/poppy/replay.js +0 -106
  163. package/build/src/agents/poppy/resource.d.ts +0 -100
  164. package/build/src/agents/poppy/resource.js +0 -129
  165. package/build/src/agents/poppy/safe_fetch.d.ts +0 -48
  166. package/build/src/agents/poppy/safe_fetch.js +0 -262
  167. package/build/src/agents/poppy/service.d.ts +0 -293
  168. package/build/src/agents/poppy/service.js +0 -1458
  169. package/build/src/agents/poppy/session_jwt.d.ts +0 -30
  170. package/build/src/agents/poppy/session_jwt.js +0 -133
  171. package/build/src/agents/poppy/store.d.ts +0 -106
  172. package/build/src/agents/poppy/store.js +0 -261
  173. package/build/src/agents/poppy/web_session.d.ts +0 -39
  174. package/build/src/agents/poppy/web_session.js +0 -122
  175. package/build/src/host/controllers/poppy_consent_controller.d.ts +0 -19
  176. package/build/src/host/controllers/poppy_consent_controller.js +0 -199
  177. package/build/src/host/controllers/poppy_controller.d.ts +0 -33
  178. package/build/src/host/controllers/poppy_controller.js +0 -219
  179. package/build/src/host/poppy_session_key.d.ts +0 -9
  180. package/build/src/host/poppy_session_key.js +0 -9
  181. package/build/src/host/ui-dist/assets/index-D0EIeyKK.js +0 -67
@@ -0,0 +1,171 @@
1
+ import { getBootedApp } from '../../services/booted_app.js';
2
+ import { accountPathsMap, accountPrefix, joinAccountPath } from '../host/account_paths.js';
3
+ import { AccountExtensionRegistryImpl } from './registry.js';
4
+ import { RemoteAccountExtensions } from './remote.js';
5
+ import { accountExtensionPages, remoteAccountPageBySegment, setAccountConsoleState, } from './runtime.js';
6
+ function inProduction() {
7
+ try {
8
+ return getBootedApp().inProduction === true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ function lifecycleApp() {
15
+ try {
16
+ return getBootedApp();
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ let registry = null;
23
+ /** The process registry bound at `authkit.accountExtensions`. */
24
+ export function accountExtensionRegistry() {
25
+ registry ??= new AccountExtensionRegistryImpl({ production: inProduction });
26
+ return registry;
27
+ }
28
+ /** A fresh registry (tests). */
29
+ export function resetAccountExtensionRegistry(next) {
30
+ registry = next ?? null;
31
+ }
32
+ /** The IdP's issuer and signing keys, from the OIDC service of the booted app. */
33
+ async function signingSource() {
34
+ const service = (await getBootedApp().container.make('authkit.server'));
35
+ return { issuer: service.config.issuer, signingJwks: service.signingJwks };
36
+ }
37
+ /**
38
+ * A route matcher that only accepts the segments remote pages currently use, so the catch-all
39
+ * routes never shadow another route under the account prefix.
40
+ */
41
+ function liveSegmentMatcher() {
42
+ const matcher = /^[a-z0-9][a-z0-9-]{0,63}$/;
43
+ Object.defineProperty(matcher, 'test', {
44
+ value: (segment) => remoteAccountPageBySegment(segment) !== undefined,
45
+ });
46
+ return matcher;
47
+ }
48
+ const H = () => import('./http.js');
49
+ function builtinSegments() {
50
+ const prefix = accountPrefix() === '/' ? '' : accountPrefix();
51
+ return Object.values(accountPathsMap()).map((path) => (path.startsWith(`${prefix}/`) ? path.slice(prefix.length + 1) : path).split('/')[0] ?? '');
52
+ }
53
+ /**
54
+ * Mounts the JSON API of the extensions now, and the page routes once every provider booted
55
+ * (contributors register from their `boot()`; pages mount when the app starts), then freezes the
56
+ * registry.
57
+ */
58
+ export function mountAccountExtensions(router, options) {
59
+ const apiBase = joinAccountPath('api');
60
+ const withJsonThrottle = (route) => {
61
+ if (options.throttle)
62
+ route.use([options.throttle.json]);
63
+ return route;
64
+ };
65
+ router
66
+ .group(() => {
67
+ router.get(`${apiBase}/extensions`, async (ctx) => (await H()).apiExtensions(ctx));
68
+ router.get(`${apiBase}/x/:pageId`, async (ctx) => (await H()).apiPage(ctx));
69
+ withJsonThrottle(router.post(`${apiBase}/x/:pageId/actions/:action`, async (ctx) => (await H()).apiAction(ctx)));
70
+ })
71
+ .use([options.guard]);
72
+ const remote = options.remote && options.remote.length > 0
73
+ ? new RemoteAccountExtensions(options.remote, {
74
+ signing: signingSource,
75
+ pathOf: (segment) => joinAccountPath(segment),
76
+ production: inProduction(),
77
+ ...(options.actionTimeoutMs !== undefined
78
+ ? { actionTimeoutMs: options.actionTimeoutMs }
79
+ : {}),
80
+ })
81
+ : null;
82
+ const pushEntries = (pages) => {
83
+ for (const page of pages) {
84
+ if (page.page.nav === false)
85
+ continue;
86
+ if (options.entries.some((entry) => entry.id === page.page.id))
87
+ continue;
88
+ const label = page.page.nav?.label ?? page.page.title;
89
+ options.entries.push({
90
+ id: page.page.id,
91
+ href: joinAccountPath(page.segment),
92
+ label: typeof label === 'string' ? label : label.key,
93
+ order: page.order,
94
+ });
95
+ }
96
+ };
97
+ const mountRemote = () => {
98
+ if (!remote)
99
+ return;
100
+ const segment = { xsegment: { match: liveSegmentMatcher() } };
101
+ const page = (ctx) => remoteAccountPageBySegment(String(ctx.params.xsegment));
102
+ router
103
+ .group(() => {
104
+ router
105
+ .get(joinAccountPath(':xsegment'), async (ctx) => (await H()).showRemotePage(ctx, page(ctx)))
106
+ .where('xsegment', segment.xsegment);
107
+ router
108
+ .get(joinAccountPath(':xsegment/actions/:action/confirm'), async (ctx) => (await H()).showRemoteActionStep(ctx, page(ctx)))
109
+ .where('xsegment', segment.xsegment);
110
+ const post = router
111
+ .post(joinAccountPath(':xsegment/actions/:action'), async (ctx) => (await H()).postRemoteAction(ctx, page(ctx)))
112
+ .where('xsegment', segment.xsegment);
113
+ if (options.throttle)
114
+ post.use([options.throttle.html]);
115
+ })
116
+ .use([options.guard]);
117
+ };
118
+ const mountPages = () => {
119
+ const reg = accountExtensionRegistry();
120
+ const pages = reg.freeze({
121
+ overrides: options.overrides,
122
+ builtinSegments: builtinSegments(),
123
+ production: inProduction(),
124
+ });
125
+ setAccountConsoleState({
126
+ pages,
127
+ builtins: options.builtins,
128
+ registry: reg,
129
+ remote,
130
+ builtinSegments: builtinSegments(),
131
+ ...(options.overrides ? { overrides: options.overrides } : {}),
132
+ });
133
+ mountRemote();
134
+ if (pages.length === 0)
135
+ return;
136
+ router
137
+ .group(() => {
138
+ for (const page of pages) {
139
+ const base = joinAccountPath(page.segment);
140
+ router.get(base, async (ctx) => (await H()).showPage(ctx, page));
141
+ router.get(`${base}/actions/:action/confirm`, async (ctx) => (await H()).showActionStep(ctx, page));
142
+ const post = router.post(`${base}/actions/:action`, async (ctx) => (await H()).postAction(ctx, page));
143
+ if (options.throttle)
144
+ post.use([options.throttle.html]);
145
+ }
146
+ })
147
+ .use([options.guard]);
148
+ pushEntries(pages);
149
+ };
150
+ // Remote manifests: fetched when the app starts (bounded), refreshed in the background after.
151
+ const startRemote = async () => {
152
+ if (!remote)
153
+ return;
154
+ await remote.start();
155
+ pushEntries(accountExtensionPages().filter((page) => page.remote !== undefined));
156
+ };
157
+ setAccountConsoleState({ builtins: options.builtins, registry: accountExtensionRegistry() });
158
+ // During the providers' boot (auto-mount from `config.routes`) contributors may not have
159
+ // registered yet: mount the pages when the app starts, before the preloads and the router commit.
160
+ const app = lifecycleApp();
161
+ if (app && app.isBooted === false && typeof app.starting === 'function') {
162
+ app.starting(mountPages);
163
+ if (remote)
164
+ app.starting(startRemote);
165
+ }
166
+ else {
167
+ mountPages();
168
+ if (remote)
169
+ void startRemote();
170
+ }
171
+ }
@@ -0,0 +1,41 @@
1
+ import { AccountExtensionError, BaseAccountExtensionRegistry, validateAccountExtension } from '@adonis-agora/authkit-core';
2
+ import type { AccountExtensionOverride, AccountPage } from './extension.js';
3
+ export { AccountExtensionError, validateAccountExtension };
4
+ /** A page as the console serves it, after host overrides. */
5
+ export interface RegisteredAccountPage {
6
+ extensionId: string;
7
+ page: AccountPage;
8
+ segment: string;
9
+ order: number;
10
+ scriptOrigins: readonly string[];
11
+ /** Client id of the app serving it, for a remote page. */
12
+ remote?: string;
13
+ }
14
+ /** Thrown for an invalid extension; the message names it. */
15
+ export interface FreezeOptions {
16
+ /** `accountConsole.extensions` from `config/authkit.ts`. */
17
+ overrides?: Readonly<Record<string, AccountExtensionOverride>>;
18
+ /** Segments of the mounted built-in screens (after `accountRoutes` renames). */
19
+ builtinSegments?: readonly string[];
20
+ /** `true` → an invalid extension is skipped and logged instead of thrown. */
21
+ production: boolean;
22
+ log?: (message: string) => void;
23
+ }
24
+ /**
25
+ * The registry bound at `authkit.accountExtensions`. Contributors call `register()` from their
26
+ * provider's `boot()`; authkit freezes it when it mounts the console routes.
27
+ */
28
+ export declare class AccountExtensionRegistryImpl extends BaseAccountExtensionRegistry {
29
+ #private;
30
+ protected beforeRegister(extension: {
31
+ id?: unknown;
32
+ }): void;
33
+ get frozen(): boolean;
34
+ /**
35
+ * Applies the host overrides, checks the segments against the mounted screens and freezes the
36
+ * registry. Returns the pages to serve. Idempotent.
37
+ */
38
+ freeze(options: FreezeOptions): RegisteredAccountPage[];
39
+ /** The served pages (empty until frozen). */
40
+ pages(): readonly RegisteredAccountPage[];
41
+ }
@@ -0,0 +1,81 @@
1
+ import { ACCOUNT_RESERVED_SEGMENTS, ACCOUNT_SEGMENT, AccountExtensionError, BaseAccountExtensionRegistry, failAccountExtension as fail, validateAccountExtension, } from '@adonis-agora/authkit-core';
2
+ export { AccountExtensionError, validateAccountExtension };
3
+ /**
4
+ * The registry bound at `authkit.accountExtensions`. Contributors call `register()` from their
5
+ * provider's `boot()`; authkit freezes it when it mounts the console routes.
6
+ */
7
+ export class AccountExtensionRegistryImpl extends BaseAccountExtensionRegistry {
8
+ #pages = null;
9
+ beforeRegister(extension) {
10
+ if (this.#pages !== null) {
11
+ throw new AccountExtensionError(`authkit: account extension "${String(extension?.id)}" registered after the account console routes were mounted. Register it from your provider's boot(), not from a preload.`);
12
+ }
13
+ }
14
+ get frozen() {
15
+ return this.#pages !== null;
16
+ }
17
+ /**
18
+ * Applies the host overrides, checks the segments against the mounted screens and freezes the
19
+ * registry. Returns the pages to serve. Idempotent.
20
+ */
21
+ freeze(options) {
22
+ if (this.#pages !== null)
23
+ return this.#pages;
24
+ const log = options.log ?? this.log;
25
+ const builtin = new Set(options.builtinSegments ?? []);
26
+ const used = new Map();
27
+ const out = [];
28
+ for (const extension of this.registered) {
29
+ const override = options.overrides?.[extension.id];
30
+ if (override === false)
31
+ continue;
32
+ const pages = [];
33
+ try {
34
+ for (const page of extension.pages) {
35
+ const pageOverride = override ? override.pages?.[page.id] : undefined;
36
+ if (pageOverride === false)
37
+ continue;
38
+ const segment = pageOverride?.segment ?? page.segment;
39
+ if (!ACCOUNT_SEGMENT.test(segment) || ACCOUNT_RESERVED_SEGMENTS.has(segment)) {
40
+ fail(extension.id, `accountConsole.extensions renames "${page.id}" to an invalid segment "${segment}".`);
41
+ }
42
+ if (builtin.has(segment)) {
43
+ fail(extension.id, `segment "${segment}" of "${page.id}" collides with a built-in screen.`);
44
+ }
45
+ const owner = used.get(segment);
46
+ if (owner)
47
+ fail(extension.id, `segment "${segment}" of "${page.id}" is already used by "${owner}".`);
48
+ used.set(segment, page.id);
49
+ const nav = page.nav === false ? undefined : page.nav;
50
+ pages.push({
51
+ extensionId: extension.id,
52
+ page,
53
+ segment,
54
+ order: pageOverride?.order ?? nav?.order ?? 100,
55
+ scriptOrigins: extension.scriptOrigins ?? [],
56
+ });
57
+ }
58
+ }
59
+ catch (error) {
60
+ for (const page of pages)
61
+ used.delete(page.segment);
62
+ if (!options.production)
63
+ throw error;
64
+ log(`${error.message} The extension is skipped.`);
65
+ continue;
66
+ }
67
+ out.push(...pages);
68
+ }
69
+ for (const id of Object.keys(options.overrides ?? {})) {
70
+ if (!this.registered.some((e) => e.id === id)) {
71
+ log(`authkit: accountConsole.extensions names "${id}", which no installed package registered.`);
72
+ }
73
+ }
74
+ this.#pages = out;
75
+ return out;
76
+ }
77
+ /** The served pages (empty until frozen). */
78
+ pages() {
79
+ return this.#pages ?? [];
80
+ }
81
+ }
@@ -0,0 +1,72 @@
1
+ import { type AccountExtension, type AccountExtensionOverride } from '@adonis-agora/authkit-core';
2
+ import type { RegisteredAccountPage } from './registry.js';
3
+ /**
4
+ * One app that signs in through this IdP and contributes account console pages
5
+ * (`accountConsole.remote` in `config/authkit.ts`).
6
+ */
7
+ export interface RemoteAccountExtensionSource {
8
+ /** The app's OIDC client id: the `aud` of every token this IdP sends it. */
9
+ clientId: string;
10
+ /** Base URL the app serves `/.well-known/agora-account-extensions` under (`https://app.example.com`). */
11
+ url: string;
12
+ /** How long a fetched manifest is reused, in ms. Default 300 000 (5 min). */
13
+ ttlMs?: number;
14
+ /** Budget of one call to the app, in ms. Default 5000 (actions: `actionTimeoutMs`). */
15
+ timeoutMs?: number;
16
+ }
17
+ /** Where the IdP's issuer and signing keys come from (the OIDC service; read on every call). */
18
+ export interface RemoteSigningSource {
19
+ issuer: string;
20
+ signingJwks: {
21
+ keys: Record<string, any>[];
22
+ };
23
+ }
24
+ export interface RemoteAccountExtensionsDeps {
25
+ signing: () => RemoteSigningSource | Promise<RemoteSigningSource>;
26
+ fetch?: typeof fetch;
27
+ now?: () => number;
28
+ log?: (message: string) => void;
29
+ /** Same-origin path of a page segment (`billing` → `/account/billing`). */
30
+ pathOf: (segment: string) => string;
31
+ actionTimeoutMs?: number;
32
+ }
33
+ /** Signs a remote-extension token with the IdP's current signing key. */
34
+ export declare function signRemoteExtensionToken(signing: RemoteSigningSource, claims: {
35
+ audience: string;
36
+ subject: string;
37
+ bodyHash?: string;
38
+ ttlSec?: number;
39
+ now?: number;
40
+ }): Promise<string>;
41
+ /** Thrown when an app answers a call with an error or cannot be reached. */
42
+ export declare class RemoteAccountExtensionError extends Error {
43
+ readonly status: number;
44
+ constructor(message: string, status: number);
45
+ }
46
+ /**
47
+ * The remote account extensions of this IdP: fetches each app's manifest (cached for `ttlMs`,
48
+ * refreshed in the background), turns it into extensions whose `visible`, `load` and actions call
49
+ * the app, and serves their pages next to the in-process ones. An app that is down keeps its last
50
+ * manifest (its pages then show the load-failure notice) or, never reached, contributes nothing.
51
+ */
52
+ export declare class RemoteAccountExtensions {
53
+ #private;
54
+ constructor(sources: readonly RemoteAccountExtensionSource[], deps: RemoteAccountExtensionsDeps & {
55
+ production?: boolean;
56
+ });
57
+ get size(): number;
58
+ /** Fetches every manifest now; resolves when all settled or after `timeoutMs`. */
59
+ start(timeoutMs?: number): Promise<void>;
60
+ /** Every remote extension currently known (for the message catalogs). */
61
+ extensions(): AccountExtension[];
62
+ /**
63
+ * The remote pages to serve now, after host overrides, minus any whose segment collides with a
64
+ * built-in screen, an in-process page or an earlier app (skipped and logged once).
65
+ */
66
+ pages(context: {
67
+ taken: ReadonlySet<string>;
68
+ /** Ids of the in-process extensions. */
69
+ takenIds: ReadonlySet<string>;
70
+ overrides?: Readonly<Record<string, AccountExtensionOverride>>;
71
+ }): readonly RegisteredAccountPage[];
72
+ }