@adonis-agora/durable 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 (180) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/dist/assets/spa/assets/index-B2kIfzsc.css +1 -0
  3. package/dist/assets/spa/assets/index-Bgf_8IJ0.js +16 -0
  4. package/dist/assets/spa/assets/index-Bgf_8IJ0.js.map +1 -0
  5. package/dist/assets/spa/index.html +2 -2
  6. package/dist/commands/durable_worker.d.ts +3 -3
  7. package/dist/commands/durable_worker.js +7 -7
  8. package/dist/commands/durable_worker.js.map +1 -1
  9. package/dist/commands/runs.d.ts.map +1 -1
  10. package/dist/commands/runs.js +4 -2
  11. package/dist/commands/runs.js.map +1 -1
  12. package/dist/providers/dashboard_provider.d.ts +20 -54
  13. package/dist/providers/dashboard_provider.d.ts.map +1 -1
  14. package/dist/providers/dashboard_provider.js +87 -262
  15. package/dist/providers/dashboard_provider.js.map +1 -1
  16. package/dist/providers/durable_provider.d.ts.map +1 -1
  17. package/dist/providers/durable_provider.js +38 -33
  18. package/dist/providers/durable_provider.js.map +1 -1
  19. package/dist/src/commands/runs.js +1 -1
  20. package/dist/src/commands/runs.js.map +1 -1
  21. package/dist/src/concurrency.d.ts.map +1 -1
  22. package/dist/src/concurrency.js +1 -0
  23. package/dist/src/concurrency.js.map +1 -1
  24. package/dist/src/config_types.d.ts +12 -12
  25. package/dist/src/config_types.d.ts.map +1 -1
  26. package/dist/src/control-flow-signal.d.ts +5 -4
  27. package/dist/src/control-flow-signal.d.ts.map +1 -1
  28. package/dist/src/control-flow-signal.js +5 -4
  29. package/dist/src/control-flow-signal.js.map +1 -1
  30. package/dist/src/dashboard/access_denied_page.d.ts +5 -7
  31. package/dist/src/dashboard/access_denied_page.d.ts.map +1 -1
  32. package/dist/src/dashboard/access_denied_page.js +2 -6
  33. package/dist/src/dashboard/access_denied_page.js.map +1 -1
  34. package/dist/src/dashboard/console_authorize.d.ts +76 -0
  35. package/dist/src/dashboard/console_authorize.d.ts.map +1 -0
  36. package/dist/src/dashboard/console_authorize.js +101 -0
  37. package/dist/src/dashboard/console_authorize.js.map +1 -0
  38. package/dist/src/dashboard/define_config.d.ts +44 -81
  39. package/dist/src/dashboard/define_config.d.ts.map +1 -1
  40. package/dist/src/dashboard/define_config.js +16 -112
  41. package/dist/src/dashboard/define_config.js.map +1 -1
  42. package/dist/src/dashboard/diagnostics-recorder.d.ts +1 -1
  43. package/dist/src/dashboard/diagnostics-recorder.js +1 -1
  44. package/dist/src/dashboard/gateway-adapter.d.ts +6 -6
  45. package/dist/src/dashboard/gateway-adapter.d.ts.map +1 -1
  46. package/dist/src/dashboard/gateway-adapter.js +5 -5
  47. package/dist/src/dashboard/gateway-adapter.js.map +1 -1
  48. package/dist/src/dashboard/handlers.d.ts +4 -4
  49. package/dist/src/dashboard/handlers.d.ts.map +1 -1
  50. package/dist/src/dashboard/handlers.js +11 -7
  51. package/dist/src/dashboard/handlers.js.map +1 -1
  52. package/dist/src/dashboard/index.d.ts +6 -9
  53. package/dist/src/dashboard/index.d.ts.map +1 -1
  54. package/dist/src/dashboard/index.js +5 -7
  55. package/dist/src/dashboard/index.js.map +1 -1
  56. package/dist/src/dashboard/openapi.d.ts.map +1 -1
  57. package/dist/src/dashboard/openapi.js +12 -2
  58. package/dist/src/dashboard/openapi.js.map +1 -1
  59. package/dist/src/dashboard/run-filter.d.ts.map +1 -1
  60. package/dist/src/dashboard/run-filter.js +1 -0
  61. package/dist/src/dashboard/run-filter.js.map +1 -1
  62. package/dist/src/define_config.d.ts +10 -12
  63. package/dist/src/define_config.d.ts.map +1 -1
  64. package/dist/src/define_config.js +9 -4
  65. package/dist/src/define_config.js.map +1 -1
  66. package/dist/src/diagnostics/index.d.ts +11 -0
  67. package/dist/src/diagnostics/index.d.ts.map +1 -0
  68. package/dist/src/diagnostics/index.js +6 -0
  69. package/dist/src/diagnostics/index.js.map +1 -0
  70. package/dist/src/diagnostics/transport.d.ts +71 -0
  71. package/dist/src/diagnostics/transport.d.ts.map +1 -0
  72. package/dist/src/diagnostics/transport.js +188 -0
  73. package/dist/src/diagnostics/transport.js.map +1 -0
  74. package/dist/src/diagnostics-bridge.d.ts +2 -1
  75. package/dist/src/diagnostics-bridge.d.ts.map +1 -1
  76. package/dist/src/diagnostics-bridge.js +7 -1
  77. package/dist/src/diagnostics-bridge.js.map +1 -1
  78. package/dist/src/engine.d.ts +14 -9
  79. package/dist/src/engine.d.ts.map +1 -1
  80. package/dist/src/engine.js +137 -52
  81. package/dist/src/engine.js.map +1 -1
  82. package/dist/src/errors.d.ts +9 -0
  83. package/dist/src/errors.d.ts.map +1 -1
  84. package/dist/src/errors.js +13 -0
  85. package/dist/src/errors.js.map +1 -1
  86. package/dist/src/event-trigger-bridge.d.ts +5 -14
  87. package/dist/src/event-trigger-bridge.d.ts.map +1 -1
  88. package/dist/src/event-trigger-bridge.js +11 -99
  89. package/dist/src/event-trigger-bridge.js.map +1 -1
  90. package/dist/src/index.d.ts +1 -1
  91. package/dist/src/index.d.ts.map +1 -1
  92. package/dist/src/index.js +1 -1
  93. package/dist/src/index.js.map +1 -1
  94. package/dist/src/interfaces.d.ts +24 -8
  95. package/dist/src/interfaces.d.ts.map +1 -1
  96. package/dist/src/interfaces.js +8 -0
  97. package/dist/src/interfaces.js.map +1 -1
  98. package/dist/src/origin.js +3 -3
  99. package/dist/src/role_bindings.d.ts +8 -8
  100. package/dist/src/role_bindings.js +8 -8
  101. package/dist/src/run-gateway/interface.d.ts +4 -3
  102. package/dist/src/run-gateway/interface.d.ts.map +1 -1
  103. package/dist/src/run-gateway/proxy-run-gateway.d.ts +1 -1
  104. package/dist/src/run-gateway/proxy-run-gateway.js +1 -1
  105. package/dist/src/run-gateway/run-request-responder.d.ts +1 -1
  106. package/dist/src/run-gateway/store-run-gateway.d.ts +4 -4
  107. package/dist/src/run-gateway/store-run-gateway.d.ts.map +1 -1
  108. package/dist/src/run-gateway/store-run-gateway.js +4 -4
  109. package/dist/src/run-gateway/store-run-gateway.js.map +1 -1
  110. package/dist/src/scheduler.d.ts.map +1 -1
  111. package/dist/src/scheduler.js +2 -1
  112. package/dist/src/scheduler.js.map +1 -1
  113. package/dist/src/services/main.d.ts +3 -3
  114. package/dist/src/services/main.js +6 -6
  115. package/dist/src/services/main.js.map +1 -1
  116. package/dist/src/singleton-admission.d.ts.map +1 -1
  117. package/dist/src/singleton-admission.js +2 -0
  118. package/dist/src/singleton-admission.js.map +1 -1
  119. package/dist/src/singleton-gate.d.ts +1 -1
  120. package/dist/src/singleton-gate.d.ts.map +1 -1
  121. package/dist/src/singleton-gate.js +4 -3
  122. package/dist/src/singleton-gate.js.map +1 -1
  123. package/dist/src/stores/lucid-pg-hot-path.d.ts +6 -2
  124. package/dist/src/stores/lucid-pg-hot-path.d.ts.map +1 -1
  125. package/dist/src/stores/lucid-pg-hot-path.js +7 -3
  126. package/dist/src/stores/lucid-pg-hot-path.js.map +1 -1
  127. package/dist/src/stores/lucid.d.ts +15 -2
  128. package/dist/src/stores/lucid.d.ts.map +1 -1
  129. package/dist/src/stores/lucid.js +191 -49
  130. package/dist/src/stores/lucid.js.map +1 -1
  131. package/dist/src/testing/in-memory-state-store.js +3 -3
  132. package/dist/src/testing/in-memory-state-store.js.map +1 -1
  133. package/dist/src/testing-kit/state-store-conformance.d.ts.map +1 -1
  134. package/dist/src/testing-kit/state-store-conformance.js +13 -0
  135. package/dist/src/testing-kit/state-store-conformance.js.map +1 -1
  136. package/dist/src/testing-kit/transport-conformance.d.ts.map +1 -1
  137. package/dist/src/testing-kit/transport-conformance.js +5 -1
  138. package/dist/src/testing-kit/transport-conformance.js.map +1 -1
  139. package/dist/src/transports/bullmq/bullmq-transport.d.ts +1 -1
  140. package/dist/src/transports/bullmq/bullmq-transport.d.ts.map +1 -1
  141. package/dist/src/transports/bullmq/bullmq-transport.js +14 -3
  142. package/dist/src/transports/bullmq/bullmq-transport.js.map +1 -1
  143. package/dist/src/transports/db.d.ts.map +1 -1
  144. package/dist/src/transports/db.js +42 -3
  145. package/dist/src/transports/db.js.map +1 -1
  146. package/dist/src/transports/queue.d.ts +2 -2
  147. package/dist/src/transports/queue.d.ts.map +1 -1
  148. package/dist/src/transports/queue.js +49 -8
  149. package/dist/src/transports/queue.js.map +1 -1
  150. package/dist/src/workflow-discovery.d.ts +1 -1
  151. package/dist/src/workflow-discovery.d.ts.map +1 -1
  152. package/dist/src/workflow-discovery.js +4 -7
  153. package/dist/src/workflow-discovery.js.map +1 -1
  154. package/dist/src/workflow-events.d.ts +20 -51
  155. package/dist/src/workflow-events.d.ts.map +1 -1
  156. package/dist/src/workflow-events.js +12 -30
  157. package/dist/src/workflow-events.js.map +1 -1
  158. package/dist/src/workflow-ref.d.ts +1 -1
  159. package/dist/src/workflow-turn.d.ts.map +1 -1
  160. package/dist/src/workflow-turn.js +18 -1
  161. package/dist/src/workflow-turn.js.map +1 -1
  162. package/dist/stubs/config/durable_dashboard.stub +9 -29
  163. package/package.json +12 -2
  164. package/skills/durable-cluster/SKILL.md +34 -22
  165. package/skills/durable-reliability/SKILL.md +2 -2
  166. package/dist/assets/spa/assets/index-70hGzOnT.css +0 -1
  167. package/dist/assets/spa/assets/index-CJjMAUau.js +0 -16
  168. package/dist/assets/spa/assets/index-CJjMAUau.js.map +0 -1
  169. package/dist/src/dashboard/auth.d.ts +0 -134
  170. package/dist/src/dashboard/auth.d.ts.map +0 -1
  171. package/dist/src/dashboard/auth.js +0 -156
  172. package/dist/src/dashboard/auth.js.map +0 -1
  173. package/dist/src/dashboard/login_page.d.ts +0 -36
  174. package/dist/src/dashboard/login_page.d.ts.map +0 -1
  175. package/dist/src/dashboard/login_page.js +0 -158
  176. package/dist/src/dashboard/login_page.js.map +0 -1
  177. package/dist/src/dashboard/session_cookie.d.ts +0 -45
  178. package/dist/src/dashboard/session_cookie.d.ts.map +0 -1
  179. package/dist/src/dashboard/session_cookie.js +0 -97
  180. package/dist/src/dashboard/session_cookie.js.map +0 -1
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * The built-in "access denied" page a BROWSER sees when the dashboard guard refuses a page
3
- * navigation — the SPA shell, its assets, or (Mode A only) a session-less visit. Before this page
3
+ * navigation — the SPA shell or its assets. Before this page
4
4
  * existed the guard answered every denial with the JSON it answers the API with
5
5
  * (`{ "error": "forbidden" }`), which is the right thing for the SPA's `fetch` calls and the wrong
6
6
  * thing for a human staring at a browser tab.
7
7
  *
8
- * Deliberately a small, dependency-free, hand-authored HTML page (like `login_page.ts`) — NOT part
8
+ * Deliberately a small, dependency-free, hand-authored HTML page — NOT part
9
9
  * of the bundled SPA, so a denial never needs the SPA to load first. It carries NO `<script>` at all,
10
10
  * so a host running a nonce'd `script-src` CSP (the `@adonisjs/shield` default) cannot break it; the
11
11
  * one inline `<style>` takes the request's CSP nonce when the provider hands one over.
@@ -36,10 +36,6 @@ const DEFAULT_COPY = {
36
36
  title: 'Access denied',
37
37
  message: 'Your account is not allowed to open this console. If that looks wrong, ask an administrator to grant you access.',
38
38
  },
39
- 'session-required': {
40
- title: 'Open this console from your app',
41
- message: 'This console only accepts a session minted by your application. Go back to the app and open the console from there.',
42
- },
43
39
  };
44
40
  /** Escape the five characters that matter inside HTML text and double-quoted attributes. */
45
41
  export function escapeHtml(value) {
@@ -1 +1 @@
1
- {"version":3,"file":"access_denied_page.js","sourceRoot":"","sources":["../../../src/dashboard/access_denied_page.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"access_denied_page.js","sourceRoot":"","sources":["../../../src/dashboard/access_denied_page.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type { HttpContext } from '@adonisjs/core/http';
2
+ /**
3
+ * What a console `authorize` returns. The same shape every `@adonis-agora` console accepts:
4
+ *
5
+ * - `true` / `{ allowed: true }` → the request proceeds;
6
+ * - `false` / `{ allowed: false }` / `{ allowed: false, reason: 'forbidden' }` → `403`;
7
+ * - `{ allowed: false, reason: 'unauthenticated' }` → `401`;
8
+ * - `{ redirectTo: '/login' }` → `302` to that path for a page navigation, `401` JSON for an API call.
9
+ */
10
+ export type ConsoleAuthorizeResult = boolean | {
11
+ allowed: true;
12
+ } | {
13
+ allowed: false;
14
+ reason?: 'unauthenticated' | 'forbidden';
15
+ } | {
16
+ redirectTo: string;
17
+ };
18
+ /** A class form, for an authorizer in its own file (`@inject()` works). */
19
+ export interface ConsoleAuthorizer {
20
+ authorize(ctx: HttpContext): ConsoleAuthorizeResult | Promise<ConsoleAuthorizeResult>;
21
+ }
22
+ export type ConsoleAuthorizerClass = new (...args: any[]) => ConsoleAuthorizer;
23
+ /**
24
+ * The console `authorize` option, in three forms: an inline function, an authorizer class, or a
25
+ * lazy import of a module whose default export is an authorizer class.
26
+ */
27
+ export type ConsoleAuthorize = ((ctx: HttpContext) => ConsoleAuthorizeResult | Promise<ConsoleAuthorizeResult>) | ConsoleAuthorizerClass | (() => Promise<{
28
+ default: ConsoleAuthorizerClass;
29
+ }>);
30
+ /** A normalized console decision. A denial always carries a reason (`401` vs `403`). */
31
+ export type ConsoleDecision = {
32
+ allowed: true;
33
+ } | {
34
+ allowed: false;
35
+ reason: 'unauthenticated' | 'forbidden';
36
+ /** Set when `authorize` asked for a redirect: page navigations go there (`302`). */
37
+ redirectTo?: string;
38
+ /** Set when `authorize` threw: the denial is a `403`, the error is for logging only. */
39
+ error?: unknown;
40
+ };
41
+ /** A resolved `authorize`: one call per request, never throws. */
42
+ export type ConsoleAuthorizeGate = (ctx: HttpContext) => Promise<ConsoleDecision>;
43
+ /**
44
+ * Collapse an `authorize` result into a {@link ConsoleDecision}. Only `true` or an object with
45
+ * `allowed === true` allows; `{ redirectTo }` is an unauthenticated denial with a redirect target;
46
+ * anything else — `false`, `{ allowed: false }`, a truthy non-boolean, a missing value — is a `403`.
47
+ */
48
+ export declare function normalizeConsoleDecision(result: unknown): ConsoleDecision;
49
+ /**
50
+ * Turn any {@link ConsoleAuthorize} form into a per-request gate:
51
+ *
52
+ * - a class is instantiated through the request's container resolver (so `@inject()` works) and its
53
+ * `authorize(ctx)` is called;
54
+ * - a function is called with `ctx`; when it resolves to a module whose `default` is an authorizer
55
+ * class it was a lazy import — the class is remembered (the import runs once) and used from then on;
56
+ * - a thrown error is a `403`, never an allow.
57
+ */
58
+ export declare function resolveConsoleAuthorize(authorize: unknown): ConsoleAuthorizeGate;
59
+ /** Options for {@link authorizeByToken}. */
60
+ export interface AuthorizeByTokenOptions {
61
+ /** The shared secret callers send as `Authorization: Bearer <token>`. */
62
+ token: string | undefined;
63
+ }
64
+ /**
65
+ * An `authorize` for machine access (scripts, a Prometheus scrape): allows a request whose
66
+ * `Authorization` header is `Bearer <token>`, and answers `{ allowed: false, reason: 'unauthenticated' }`
67
+ * (`401`) otherwise. Only the header is read.
68
+ *
69
+ * ```ts
70
+ * authorize: authorizeByToken({ token: env.get('CONSOLE_TOKEN') }),
71
+ * ```
72
+ *
73
+ * Throws at config time when `token` is empty or undefined.
74
+ */
75
+ export declare function authorizeByToken(options: AuthorizeByTokenOptions): (ctx: HttpContext) => ConsoleAuthorizeResult;
76
+ //# sourceMappingURL=console_authorize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console_authorize.d.ts","sourceRoot":"","sources":["../../../src/dashboard/console_authorize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,MAAM,sBAAsB,GAC9B,OAAO,GACP;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,WAAW,CAAA;CAAE,GAC5D;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3B,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,GAAG,EAAE,WAAW,GAAG,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACvF;AAGD,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,iBAAiB,CAAC;AAE/E;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GACxB,CAAC,CAAC,GAAG,EAAE,WAAW,KAAK,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAChF,sBAAsB,GACtB,CAAC,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,sBAAsB,CAAA;CAAE,CAAC,CAAC,CAAC;AAEzD,wFAAwF;AACxF,MAAM,MAAM,eAAe,GACvB;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IACE,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAAC;IACxC,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEN,kEAAkE;AAClE,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAelF;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CAYzE;AAUD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,GAAG,oBAAoB,CA2BhF;AAED,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,uBAAuB,GAC/B,CAAC,GAAG,EAAE,WAAW,KAAK,sBAAsB,CAa9C"}
@@ -0,0 +1,101 @@
1
+ import { createHash, timingSafeEqual } from 'node:crypto';
2
+ function isAuthorizerClass(value) {
3
+ return (typeof value === 'function' &&
4
+ typeof value.prototype?.authorize === 'function');
5
+ }
6
+ function lazyModuleClass(value) {
7
+ if (typeof value !== 'object' || value === null)
8
+ return undefined;
9
+ const candidate = value.default;
10
+ return isAuthorizerClass(candidate) ? candidate : undefined;
11
+ }
12
+ /**
13
+ * Collapse an `authorize` result into a {@link ConsoleDecision}. Only `true` or an object with
14
+ * `allowed === true` allows; `{ redirectTo }` is an unauthenticated denial with a redirect target;
15
+ * anything else — `false`, `{ allowed: false }`, a truthy non-boolean, a missing value — is a `403`.
16
+ */
17
+ export function normalizeConsoleDecision(result) {
18
+ if (result === true)
19
+ return { allowed: true };
20
+ if (typeof result !== 'object' || result === null)
21
+ return { allowed: false, reason: 'forbidden' };
22
+ const record = result;
23
+ if (record.allowed === true)
24
+ return { allowed: true };
25
+ if (typeof record.redirectTo === 'string' && record.redirectTo !== '') {
26
+ return { allowed: false, reason: 'unauthenticated', redirectTo: record.redirectTo };
27
+ }
28
+ return {
29
+ allowed: false,
30
+ reason: record.reason === 'unauthenticated' ? 'unauthenticated' : 'forbidden',
31
+ };
32
+ }
33
+ async function runAuthorizer(Authorizer, ctx) {
34
+ const instance = await ctx.containerResolver.make(Authorizer);
35
+ return instance.authorize(ctx);
36
+ }
37
+ /**
38
+ * Turn any {@link ConsoleAuthorize} form into a per-request gate:
39
+ *
40
+ * - a class is instantiated through the request's container resolver (so `@inject()` works) and its
41
+ * `authorize(ctx)` is called;
42
+ * - a function is called with `ctx`; when it resolves to a module whose `default` is an authorizer
43
+ * class it was a lazy import — the class is remembered (the import runs once) and used from then on;
44
+ * - a thrown error is a `403`, never an allow.
45
+ */
46
+ export function resolveConsoleAuthorize(authorize) {
47
+ let Authorizer = isAuthorizerClass(authorize)
48
+ ? authorize
49
+ : undefined;
50
+ if (Authorizer === undefined && typeof authorize !== 'function') {
51
+ throw new TypeError('[console] `authorize` must be a function, an authorizer class, or a lazy import of one.');
52
+ }
53
+ const fn = authorize;
54
+ return async (ctx) => {
55
+ try {
56
+ if (Authorizer !== undefined) {
57
+ return normalizeConsoleDecision(await runAuthorizer(Authorizer, ctx));
58
+ }
59
+ const result = await fn(ctx);
60
+ const lazy = lazyModuleClass(result);
61
+ if (lazy !== undefined) {
62
+ Authorizer = lazy;
63
+ return normalizeConsoleDecision(await runAuthorizer(lazy, ctx));
64
+ }
65
+ return normalizeConsoleDecision(result);
66
+ }
67
+ catch (error) {
68
+ return { allowed: false, reason: 'forbidden', error };
69
+ }
70
+ };
71
+ }
72
+ function digest(value) {
73
+ return createHash('sha256').update(value).digest();
74
+ }
75
+ /**
76
+ * An `authorize` for machine access (scripts, a Prometheus scrape): allows a request whose
77
+ * `Authorization` header is `Bearer <token>`, and answers `{ allowed: false, reason: 'unauthenticated' }`
78
+ * (`401`) otherwise. Only the header is read.
79
+ *
80
+ * ```ts
81
+ * authorize: authorizeByToken({ token: env.get('CONSOLE_TOKEN') }),
82
+ * ```
83
+ *
84
+ * Throws at config time when `token` is empty or undefined.
85
+ */
86
+ export function authorizeByToken(options) {
87
+ const token = options?.token;
88
+ if (typeof token !== 'string' || token === '') {
89
+ throw new Error('authorizeByToken: `token` must be a non-empty string');
90
+ }
91
+ // Compare digests: equal length always, so the check leaks neither a match nor the token length.
92
+ const expected = digest(token);
93
+ return (ctx) => {
94
+ const header = ctx.request.header('authorization');
95
+ const match = typeof header === 'string' ? /^Bearer\s+(.+)$/i.exec(header.trim()) : null;
96
+ if (match?.[1] && timingSafeEqual(digest(match[1]), expected))
97
+ return { allowed: true };
98
+ return { allowed: false, reason: 'unauthenticated' };
99
+ };
100
+ }
101
+ //# sourceMappingURL=console_authorize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console_authorize.js","sourceRoot":"","sources":["../../../src/dashboard/console_authorize.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { HttpContext } from '@adonisjs/core/http';
2
2
  import type { AccessDeniedOption as GenericAccessDeniedOption, AccessDeniedRenderer as GenericAccessDeniedRenderer } from './access_denied_page.js';
3
- import { type DashboardAuthOptions, type ResolvedDashboardAuth } from './auth.js';
3
+ import { type ConsoleAuthorize, type ConsoleAuthorizeGate, type ConsoleAuthorizeResult, type ConsoleDecision } from './console_authorize.js';
4
4
  /**
5
5
  * The function form of {@link DurableDashboardConfig.accessDenied}: render (or answer) a refused
6
6
  * page navigation yourself. Receives the refusal ({@link AccessDeniedInfo}) and the AdonisJS
@@ -15,41 +15,28 @@ export type AccessDeniedOption = GenericAccessDeniedOption<HttpContext>;
15
15
  * A structured answer from an {@link AuthorizeHook}: whether the request may proceed and, when it may
16
16
  * not, why. The `reason` picks the status: `'unauthenticated'` (nobody is signed in) → `401`,
17
17
  * `'forbidden'` (signed in, not allowed) → `403`. No reason → `403` (fail closed).
18
- *
19
- * This is the shared Agora dashboard-gate contract — the same shape every `@adonis-agora` console
20
- * accepts, so one hook (e.g. `@adonis-agora/authz`'s `authorizeByRoles`) can gate them all.
21
18
  */
22
19
  export interface AuthorizeDecision {
23
20
  allowed: boolean;
24
21
  reason?: 'unauthenticated' | 'forbidden';
25
22
  }
26
- /** What an {@link AuthorizeHook} may return: a bare boolean or an {@link AuthorizeDecision}. */
27
- export type AuthorizeResult = boolean | AuthorizeDecision;
28
23
  /**
29
- * Authorization guard for the dashboard. Runs before every dashboard route (API + HTML). May be
30
- * async (e.g. an auth lookup). Return:
31
- *
32
- * - `true` or `{ allowed: true }` → the request proceeds;
33
- * - `{ allowed: false, reason: 'unauthenticated' }` → `401` (the access-denied page with the
34
- * "sign in" story for a page navigation, `{ error: 'unauthorized' }` for an API request);
35
- * - `{ allowed: false, reason: 'forbidden' }`, `{ allowed: false }` or `false` → `403` (the
36
- * access-denied page, or `{ error: 'forbidden' }`).
37
- *
38
- * A hook that THROWS is a denial (`403`), never a pass. A hook that answers the request itself — a
39
- * redirect to the host's login page, most commonly — keeps its answer: the provider writes nothing
40
- * over it.
41
- *
42
- * It receives the AdonisJS {@link HttpContext}, so it can read the session,
43
- * a bearer token, an IP allow-list, etc.
24
+ * What an {@link AuthorizeHook} may return: the shared {@link ConsoleAuthorizeResult} (a boolean,
25
+ * a decision, or `{ redirectTo }`) or an {@link AuthorizeDecision}.
26
+ */
27
+ export type AuthorizeResult = ConsoleAuthorizeResult | AuthorizeDecision;
28
+ /**
29
+ * The function form of `authorize`. It receives the AdonisJS {@link HttpContext}, so it can read the
30
+ * session, a bearer token, an IP allow-list, etc. May be async.
44
31
  */
45
32
  export type AuthorizeHook = (ctx: HttpContext) => AuthorizeResult | Promise<AuthorizeResult>;
46
33
  /**
47
34
  * Collapse an {@link AuthorizeResult} into a decision. Only `true` or an object with
48
- * `allowed === true` allows: anything else — `false`, `{ allowed: false }`, a truthy non-boolean, a
49
- * missing value — denies. (A decision OBJECT is truthy, so a `!result` check would wave
50
- * `{ allowed: false }` through; this is why the guard never tests the raw value.)
35
+ * `allowed === true` allows; `{ redirectTo }` is an unauthenticated denial carrying the redirect
36
+ * target; anything else — `false`, `{ allowed: false }`, a truthy non-boolean, a missing value —
37
+ * denies with `403`.
51
38
  */
52
- export declare function normalizeAuthorizeResult(result: unknown): AuthorizeDecision;
39
+ export declare function normalizeAuthorizeResult(result: unknown): ConsoleDecision;
53
40
  /** Shape of `config/durable_dashboard.ts`. */
54
41
  export interface DurableDashboardConfig {
55
42
  /**
@@ -64,39 +51,17 @@ export interface DurableDashboardConfig {
64
51
  */
65
52
  path?: string;
66
53
  /**
67
- * Per-request authorization guard — see {@link AuthorizeHook} for what it may return
68
- * (`boolean` or an {@link AuthorizeDecision}; `reason: 'unauthenticated'` → `401`, otherwise a
69
- * denial is `403`). Defaults to {@link defaultAuthorize}, which FAILS CLOSED in
70
- * EVERY environment: it requires a bearer token matching `DURABLE_DASHBOARD_TOKEN` (denying
71
- * everything when that env var is unset) — unless {@link dashboardAuth} is configured (the
72
- * session guard is then the gate) or {@link allowUnauthenticated} explicitly opts out.
73
- *
74
- * (Before 0.37 the default was open outside `NODE_ENV=production` — which left every dev/staging
75
- * deployment, and any box where NODE_ENV was unset or spelled differently, with an unauthenticated
76
- * console whose destructive endpoints a malicious web page could drive via cross-site POSTs.)
77
- */
78
- authorize?: AuthorizeHook;
79
- /**
80
- * Explicitly serve the dashboard WITHOUT any authentication. This is the loaded footgun the old
81
- * "open outside production" default was — now it at least has to be spelled out in config, so a
82
- * deploy can grep for it. Only for local development / networks you fully trust. Ignored when
83
- * `authorize` or `dashboardAuth` is configured.
84
- */
85
- allowUnauthenticated?: boolean;
86
- /**
87
- * Optional built-in login screen. When set, the provider mounts a
88
- * server-rendered `GET <path>/login` page plus `POST <path>/login` /
89
- * `GET <path>/logout`, and stamps a session guard on the dashboard: an
90
- * unauthenticated page navigation is redirected (`302`) to the login page and
91
- * an unauthenticated API request gets `401`. The signed session cookie is
92
- * minted only by the host's {@link DashboardAuthOptions.login} hook.
54
+ * Who may reach the console. Runs before every dashboard route (API + HTML). Takes the shared
55
+ * {@link ConsoleAuthorize} contract — an inline function, an authorizer class (resolved through the
56
+ * container, so `@inject()` works), or a lazy import of one (`() => import('#policies/console_access')`).
57
+ * It returns a boolean, `{ allowed, reason? }` (`reason: 'unauthenticated'` → `401`, any other
58
+ * denial `403`) or `{ redirectTo }` (`302` for a page, `401` for an API call). A throw is a `403`.
93
59
  *
94
- * This is ADDITIVE and composes WITH {@link authorize} (both must pass) — it
95
- * does not replace it. Omit it entirely to keep today's behavior byte-for-byte
96
- * (no login/logout routes, no session guard). Missing `secret`/`login` fails
97
- * closed at boot.
60
+ * Omitted, the console is open when the app is not in production and answers `403` to every
61
+ * request in production (a warning is logged once at boot). For machine access use
62
+ * `authorizeByToken({ token })`.
98
63
  */
99
- dashboardAuth?: DashboardAuthOptions;
64
+ authorize?: ConsoleAuthorize | AuthorizeHook;
100
65
  /**
101
66
  * Audit sink for MUTATING console actions (retry, cancel, bulk, fix-and-replay, signal, update,
102
67
  * task completion, schedule control): called once per attempt with who did what, before the
@@ -117,13 +82,12 @@ export interface DurableDashboardConfig {
117
82
  };
118
83
  /**
119
84
  * What a BROWSER sees when the guard refuses a page navigation (the SPA shell, its assets, or —
120
- * Mode A only — a session-less visit). API requests are unaffected:
85
+ * nothing else). API requests are unaffected:
121
86
  * they keep getting the JSON the SPA relies on (`403 { error: 'forbidden' }` /
122
- * `401 { error: 'unauthorized', auth }`).
87
+ * `401 { error: 'unauthenticated' }`).
123
88
  *
124
89
  * Omit it for the built-in page — a dark card in the console's own visual language, with the
125
- * status, a sentence explaining the refusal, a "Back to app" link and, when `dashboardAuth.login`
126
- * exists, a "Sign in" button. Pass an object to tweak that page (`brand`, `title`, `message`,
90
+ * status, a sentence explaining the refusal and a "Back to app" link. Pass an object to tweak that page (`brand`, `title`, `message`,
127
91
  * `homeHref`, `loginHref`, `accent`, …), or a function to render/answer it yourself — see
128
92
  * {@link AccessDeniedRenderer}. Either way, an `authorize` hook that already wrote a redirect
129
93
  * still wins: the provider never overwrites a `location` header.
@@ -134,9 +98,10 @@ export interface DurableDashboardConfig {
134
98
  export interface ResolvedDurableDashboardConfig {
135
99
  enabled: boolean;
136
100
  path: string;
137
- authorize: AuthorizeHook;
138
- /** Resolved built-in login config, or `null` when `dashboardAuth` is unconfigured. */
139
- dashboardAuth: ResolvedDashboardAuth | null;
101
+ /** The resolved `authorize` gate (or the default): one call per request, never throws. */
102
+ authorize: ConsoleAuthorizeGate;
103
+ /** Whether the host set `authorize` (`false` means the dev-open / production-deny default). */
104
+ authorizeConfigured: boolean;
140
105
  /** The host's `accessDenied` option as given, or `null` for the built-in page with defaults. */
141
106
  accessDenied: AccessDeniedOption | null;
142
107
  /** The host's audit sink, or `null` for the default logger line. */
@@ -150,29 +115,27 @@ export interface ResolvedDurableDashboardConfig {
150
115
  /** One audited mutating console action — who (actor), what (method + path), when. */
151
116
  export interface DashboardAuditEntry {
152
117
  at: Date;
153
- /** The session user's name/id, `'token'` for a bearer-token caller, else `'anonymous'`. */
118
+ /**
119
+ * The signed-in user (`ctx.auth.user`'s `email`, `name` or `id`), `'bearer'` for a caller with an
120
+ * `Authorization` header and no user, else `'anonymous'`.
121
+ */
154
122
  actor: string;
155
123
  method: string;
156
- /** The request path (no query string — a `?token=` must never reach an audit log). */
124
+ /** The request path (no query string). */
157
125
  path: string;
158
126
  }
159
- /**
160
- * Whether the process is running in production. Mirrors how AdonisJS reads the
161
- * environment without taking a hard dependency on its env service. No longer an
162
- * AUTH decision input (the guard fails closed everywhere) — used only for
163
- * cookie hardening defaults.
164
- */
165
- export declare function isProduction(): boolean;
166
- /**
167
- * The default guard: FAIL CLOSED in every environment — require a bearer token equal to
168
- * `DURABLE_DASHBOARD_TOKEN`, denying everything when that env var is unset. There is no
169
- * NODE_ENV branch anymore: "not production" is exactly the set of deployments (dev boxes,
170
- * staging, misspelled envs) that used to ship an open console. Opt out explicitly with
171
- * `allowUnauthenticated: true`, or configure `dashboardAuth`/your own `authorize`.
172
- */
173
- export declare function defaultAuthorize(ctx: HttpContext): boolean;
127
+ /** The warning logged once at boot when `authorize` is omitted. */
128
+ export declare const NO_AUTHORIZE_WARNING = "[@adonis-agora/durable] console has no `authorize` configured: it is open outside production and denies every request in production. Set `authorize` in config/durable_dashboard.ts.";
129
+ /** Options for {@link resolveConfig}. */
130
+ export interface ResolveConfigOptions {
131
+ /**
132
+ * Whether the app runs in production (`app.inProduction`). Only `false` opens a console without
133
+ * `authorize`; anything else denies it.
134
+ */
135
+ inProduction?: boolean;
136
+ }
174
137
  /** Apply defaults to a partial config, producing a fully-resolved one. */
175
- export declare function resolveConfig(config?: DurableDashboardConfig): ResolvedDurableDashboardConfig;
138
+ export declare function resolveConfig(config?: DurableDashboardConfig, options?: ResolveConfigOptions): ResolvedDurableDashboardConfig;
176
139
  /** Identity helper giving `config/durable_dashboard.ts` full type-checking. */
177
140
  export declare function defineConfig(config?: DurableDashboardConfig): DurableDashboardConfig;
178
141
  //# sourceMappingURL=define_config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../../src/dashboard/define_config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../../src/dashboard/define_config.ts"],"names":[],"mappings":"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"}
@@ -1,129 +1,33 @@
1
- import { timingSafeEqual } from 'node:crypto';
2
- import { resolveDashboardAuth, } from './auth.js';
1
+ import { normalizeConsoleDecision, resolveConsoleAuthorize, } from './console_authorize.js';
3
2
  /**
4
3
  * Collapse an {@link AuthorizeResult} into a decision. Only `true` or an object with
5
- * `allowed === true` allows: anything else — `false`, `{ allowed: false }`, a truthy non-boolean, a
6
- * missing value — denies. (A decision OBJECT is truthy, so a `!result` check would wave
7
- * `{ allowed: false }` through; this is why the guard never tests the raw value.)
4
+ * `allowed === true` allows; `{ redirectTo }` is an unauthenticated denial carrying the redirect
5
+ * target; anything else — `false`, `{ allowed: false }`, a truthy non-boolean, a missing value —
6
+ * denies with `403`.
8
7
  */
9
8
  export function normalizeAuthorizeResult(result) {
10
- if (result === true)
11
- return { allowed: true };
12
- if (typeof result === 'object' &&
13
- result !== null &&
14
- result.allowed === true) {
15
- return { allowed: true };
16
- }
17
- const reason = typeof result === 'object' && result !== null
18
- ? result.reason
19
- : undefined;
20
- return { allowed: false, reason: reason === 'unauthenticated' ? 'unauthenticated' : 'forbidden' };
9
+ return normalizeConsoleDecision(result);
21
10
  }
22
- /**
23
- * Whether the process is running in production. Mirrors how AdonisJS reads the
24
- * environment without taking a hard dependency on its env service. No longer an
25
- * AUTH decision input (the guard fails closed everywhere) — used only for
26
- * cookie hardening defaults.
27
- */
28
- export function isProduction() {
29
- return (process.env.NODE_ENV ?? '').toLowerCase() === 'production';
30
- }
31
- /**
32
- * Extract a bearer token from an `Authorization: Bearer <token>` header, a
33
- * `token` query-string param, or an `x-durable-token` header — whichever is
34
- * present. Returns `undefined` when none is supplied.
35
- */
36
- function readToken(ctx) {
37
- const header = ctx.request.header('authorization');
38
- if (header) {
39
- const match = /^Bearer\s+(.+)$/i.exec(header);
40
- if (match?.[1])
41
- return match[1].trim();
42
- }
43
- const xHeader = ctx.request.header('x-durable-token');
44
- if (xHeader)
45
- return xHeader.trim();
46
- // The query-string channel exists ONLY because EventSource (the SSE live-tail) cannot set
47
- // headers. Restricted to read methods: a `?token=` that authorized POSTs turned any leaked/logged
48
- // URL (access logs, Referer, browser history) into a destructive-capable magic link.
49
- const method = ctx.request.method().toUpperCase();
50
- if (method === 'GET' || method === 'HEAD') {
51
- const qs = ctx.request.qs().token;
52
- if (typeof qs === 'string' && qs.length > 0)
53
- return qs;
54
- }
55
- return undefined;
56
- }
57
- /**
58
- * Compare two secrets in constant time (guarding for equal byte-length first,
59
- * since {@link timingSafeEqual} throws on a length mismatch). Returns `false`
60
- * for any length difference, otherwise the timing-safe equality — so the token
61
- * check leaks neither a match nor the token's length via response time.
62
- */
63
- function secretsMatch(a, b) {
64
- const bufA = Buffer.from(a);
65
- const bufB = Buffer.from(b);
66
- if (bufA.length !== bufB.length)
67
- return false;
68
- return timingSafeEqual(bufA, bufB);
69
- }
70
- /**
71
- * The default guard: FAIL CLOSED in every environment — require a bearer token equal to
72
- * `DURABLE_DASHBOARD_TOKEN`, denying everything when that env var is unset. There is no
73
- * NODE_ENV branch anymore: "not production" is exactly the set of deployments (dev boxes,
74
- * staging, misspelled envs) that used to ship an open console. Opt out explicitly with
75
- * `allowUnauthenticated: true`, or configure `dashboardAuth`/your own `authorize`.
76
- */
77
- export function defaultAuthorize(ctx) {
78
- const expected = process.env.DURABLE_DASHBOARD_TOKEN;
79
- if (!expected)
80
- return false;
81
- const provided = readToken(ctx);
82
- if (provided === undefined)
83
- return false;
84
- // Constant-time compare to remove the timing side-channel from the token check.
85
- return secretsMatch(provided, expected);
86
- }
87
- /** The explicit `allowUnauthenticated: true` guard — allow everything, by conscious opt-in only. */
88
- const allowAll = () => true;
89
- let warnedOpenDashboard = false;
11
+ /** The warning logged once at boot when `authorize` is omitted. */
12
+ export const NO_AUTHORIZE_WARNING = '[@adonis-agora/durable] console has no `authorize` configured: it is open outside production and denies every request in production. Set `authorize` in config/durable_dashboard.ts.';
13
+ const allowAll = async () => ({ allowed: true });
14
+ const denyAll = async () => ({ allowed: false, reason: 'forbidden' });
90
15
  /** Apply defaults to a partial config, producing a fully-resolved one. */
91
- export function resolveConfig(config = {}) {
16
+ export function resolveConfig(config = {}, options = {}) {
92
17
  const rawPath = config.path ?? '/durable';
93
18
  // Normalize: ensure a single leading slash and no trailing slash (root stays '/').
94
19
  const trimmed = `/${rawPath.replace(/^\/+/, '').replace(/\/+$/, '')}`;
95
- // Default guard resolution, in order:
96
- // 1. a host `authorize` hook wins;
97
- // 2. `dashboardAuth` configured -> the session guard IS the gate (the default token guard would
98
- // otherwise 403 every login flow that never set DURABLE_DASHBOARD_TOKEN);
99
- // 3. `allowUnauthenticated: true` -> consciously open (warned once at resolve time);
100
- // 4. else the fail-closed token guard.
101
- const hasDashboardAuth = config.dashboardAuth !== undefined;
20
+ const authorizeConfigured = config.authorize !== undefined;
102
21
  let authorize;
103
- if (config.authorize) {
104
- authorize = config.authorize;
105
- }
106
- else if (hasDashboardAuth) {
107
- authorize = allowAll;
108
- }
109
- else if (config.allowUnauthenticated === true) {
110
- if (!warnedOpenDashboard) {
111
- warnedOpenDashboard = true;
112
- console.warn('[durable_dashboard] allowUnauthenticated: true — the console (including destructive ' +
113
- 'endpoints) is served with NO authentication. Never ship this to a reachable network.');
114
- }
115
- authorize = allowAll;
116
- }
117
- else {
118
- authorize = defaultAuthorize;
119
- }
22
+ if (config.authorize !== undefined)
23
+ authorize = resolveConsoleAuthorize(config.authorize);
24
+ else
25
+ authorize = options.inProduction === false ? allowAll : denyAll;
120
26
  return {
121
27
  enabled: config.enabled ?? true,
122
28
  path: trimmed === '/' ? '' : trimmed,
123
29
  authorize,
124
- // Validate + resolve now so a misconfigured secret/login fails closed at boot,
125
- // not on the first login attempt. `null` when `dashboardAuth` is omitted.
126
- dashboardAuth: resolveDashboardAuth(config.dashboardAuth),
30
+ authorizeConfigured,
127
31
  accessDenied: config.accessDenied ?? null,
128
32
  audit: config.audit ?? null,
129
33
  redact: config.redact ?? null,
@@ -1 +1 @@
1
- {"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../../src/dashboard/define_config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../../src/dashboard/define_config.ts"],"names":[],"mappings":"AAKA,OAAO,EAKL,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,wBAAwB,CAAC;AAoChC;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAe;IACtD,OAAO,wBAAwB,CAAC,MAAM,CAAC,CAAC;AAC1C,CAAC;AA4FD,mEAAmE;AACnE,MAAM,CAAC,MAAM,oBAAoB,GAC/B,sLAAsL,CAAC;AAEzL,MAAM,QAAQ,GAAyB,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AACvE,MAAM,OAAO,GAAyB,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;AAW5F,0EAA0E;AAC1E,MAAM,UAAU,aAAa,CAC3B,MAAM,GAA2B,EAAE,EACnC,OAAO,GAAyB,EAAE;IAElC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI,UAAU,CAAC;IAC1C,mFAAmF;IACnF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;IACtE,MAAM,mBAAmB,GAAG,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC;IAC3D,IAAI,SAA+B,CAAC;IACpC,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;QAAE,SAAS,GAAG,uBAAuB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;;QACrF,SAAS,GAAG,OAAO,CAAC,YAAY,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;IACrE,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI;QAC/B,IAAI,EAAE,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;QACpC,SAAS;QACT,mBAAmB;QACnB,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI;QACzC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;KAC9B,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,MAAM,GAA2B,EAAE;IAC9D,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -33,7 +33,7 @@ export interface RecordedBlock {
33
33
  * - `controlPlaneDescriptor()` is the CP side the events were negotiated against.
34
34
  *
35
35
  * Bounded by an LRU-ish cap on the per-run map (oldest evicted) so a long-lived control plane never
36
- * grows this without bound. Store-role only: a `tenant` pod owns no engine to subscribe to, so its
36
+ * grows this without bound. Store-topology only: a `tenant` pod owns no engine to subscribe to, so its
37
37
  * panel shows `blocked` runs (reason from `run.error.message`) without the enriched delta.
38
38
  */
39
39
  export declare class BlockedDiagnosticsRecorder {
@@ -10,7 +10,7 @@
10
10
  * - `controlPlaneDescriptor()` is the CP side the events were negotiated against.
11
11
  *
12
12
  * Bounded by an LRU-ish cap on the per-run map (oldest evicted) so a long-lived control plane never
13
- * grows this without bound. Store-role only: a `tenant` pod owns no engine to subscribe to, so its
13
+ * grows this without bound. Store-topology only: a `tenant` pod owns no engine to subscribe to, so its
14
14
  * panel shows `blocked` runs (reason from `run.error.message`) without the enriched delta.
15
15
  */
16
16
  export class BlockedDiagnosticsRecorder {