@teamscala/service-boot 0.23.522 → 0.23.524

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 (119) hide show
  1. package/package.json +1 -1
  2. package/src/agreement-gate/agreement-lookup.ts +0 -7
  3. package/src/agreement-gate/authorized-emails.ts +0 -7
  4. package/src/agreement-gate/placeholder-strip.ts +0 -8
  5. package/src/agreement-gate/resolution-caches.ts +0 -5
  6. package/src/agreement-gate/settings.ts +0 -7
  7. package/src/agreement-gate/signing-session.ts +0 -8
  8. package/src/agreement-gate/signing-shell.ts +0 -9
  9. package/src/agreement-gate.ts +0 -18
  10. package/src/apply-logger-config.ts +1 -9
  11. package/src/asset-cache-key.ts +1 -5
  12. package/src/asset-optimize.ts +1 -7
  13. package/src/asset-proxy.ts +15 -9
  14. package/src/asset-social-card.ts +1 -9
  15. package/src/attach-agreement-magic.ts +0 -14
  16. package/src/attach-portal-members.ts +0 -17
  17. package/src/attach-proposal-accept.ts +0 -20
  18. package/src/attach-proposal-magic.ts +0 -12
  19. package/src/attach-transfers-upload.ts +0 -21
  20. package/src/auth/sign-out.ts +1 -42
  21. package/src/auth-gate/public-paths.ts +1 -10
  22. package/src/auth-gate.ts +1 -22
  23. package/src/bind-page-handler.ts +1 -7
  24. package/src/build-client-assets/build-lock.ts +1 -11
  25. package/src/build-client-assets/hashed-output.ts +1 -11
  26. package/src/build-client-assets/hydrate-bundle.ts +1 -11
  27. package/src/build-client-assets/manifest.ts +1 -12
  28. package/src/build-client-assets/source-candidates.ts +0 -17
  29. package/src/build-client-assets/sourcemaps-upload.ts +1 -10
  30. package/src/build-client-assets/styles-build.ts +1 -21
  31. package/src/build-client-assets.ts +1 -30
  32. package/src/capability-slug.ts +1 -35
  33. package/src/compose-page-title.ts +1 -25
  34. package/src/content-gate/access.ts +0 -8
  35. package/src/content-gate/catalog.ts +0 -23
  36. package/src/content-gate/config-types.ts +0 -6
  37. package/src/content-gate/gate-entry-clears.ts +0 -18
  38. package/src/content-gate/gate.ts +0 -7
  39. package/src/content-gate/parse-cookie.ts +0 -4
  40. package/src/content-gate/token.ts +0 -22
  41. package/src/content-page-floor.ts +0 -17
  42. package/src/csrf-protection.ts +1 -28
  43. package/src/error-page-logo.ts +0 -23
  44. package/src/expand-roster.ts +1 -16
  45. package/src/gate-ttls.ts +0 -12
  46. package/src/gpt-gate.ts +0 -18
  47. package/src/hono-error-handler.ts +0 -15
  48. package/src/install-harness.ts +1 -12
  49. package/src/install-logging.ts +1 -15
  50. package/src/is-react-element-type.ts +1 -11
  51. package/src/load-page-manifest.ts +1 -23
  52. package/src/load-service-install-row.ts +1 -6
  53. package/src/module-not-found.ts +0 -6
  54. package/src/mount-orpc-router.ts +0 -6
  55. package/src/mount-server-packages.ts +1 -8
  56. package/src/mount.ts +1 -4
  57. package/src/mutable-app-ref.ts +0 -10
  58. package/src/orpc-openapi-document.ts +1 -13
  59. package/src/orpc-openapi-gate.ts +1 -13
  60. package/src/page-route-shell-types.ts +1 -8
  61. package/src/page-server-loader-graph.ts +0 -10
  62. package/src/page-server-orpc/hub-mcp-client.ts +1 -7
  63. package/src/page-server-orpc/server-client.ts +1 -23
  64. package/src/pg-boss-handler-registry.ts +1 -12
  65. package/src/pg-boss-mount.ts +1 -8
  66. package/src/proposal-authorized-emails.ts +0 -32
  67. package/src/proposal-gate.ts +0 -11
  68. package/src/quiz-gate.ts +0 -22
  69. package/src/read-html-template.ts +1 -49
  70. package/src/readiness-gate.ts +0 -8
  71. package/src/register-api-routes.ts +1 -11
  72. package/src/register-crash-handlers.ts +1 -6
  73. package/src/register-page-routes.ts +1 -12
  74. package/src/register-page-server-client.ts +1 -13
  75. package/src/register-registry-page-route/ai-chat-prefetch.ts +1 -6
  76. package/src/register-registry-page-route/apply-page-branding.ts +1 -10
  77. package/src/register-registry-page-route/captured-loader-config.ts +1 -11
  78. package/src/register-registry-page-route/graph-cache.ts +1 -21
  79. package/src/register-registry-page-route/live-loader-config.ts +1 -22
  80. package/src/register-registry-page-route/meta-title.ts +1 -12
  81. package/src/register-registry-page-route/page-data-shared.ts +1 -12
  82. package/src/register-registry-page-route/prefetch-org-id.ts +1 -7
  83. package/src/register-registry-page-route/proposal-approval-email-token.ts +1 -11
  84. package/src/register-registry-page-route/proposal-brand-stamping.ts +1 -11
  85. package/src/register-registry-page-route/public-shell-page-data.ts +1 -8
  86. package/src/register-registry-page-route/region-slots-page-data.ts +1 -8
  87. package/src/register-registry-page-route/resolve-page-data.ts +1 -10
  88. package/src/register-registry-page-route/resolve-panel-page.ts +1 -10
  89. package/src/register-registry-page-route/resolve-request-graph.ts +1 -11
  90. package/src/register-registry-page-route/run-content-gates.ts +1 -10
  91. package/src/register-registry-page-route/single-page-data.ts +1 -9
  92. package/src/register-registry-page-route/stamp-session-context.ts +1 -10
  93. package/src/register-registry-page-route/warn-uncovered-blocks.ts +1 -8
  94. package/src/register-registry-page-route.ts +1 -18
  95. package/src/register-static-assets.ts +1 -8
  96. package/src/register-ws-routes.ts +1 -21
  97. package/src/resolve-brand-favicon.ts +0 -13
  98. package/src/resolve-service-port.ts +1 -50
  99. package/src/resolve-theme-mode.ts +1 -22
  100. package/src/resolvers/app-header.ts +1 -19
  101. package/src/resolvers/fetch-org-brand.ts +1 -10
  102. package/src/resolvers/portal-route-paths.ts +1 -12
  103. package/src/resolvers/website-by-host-map.ts +1 -7
  104. package/src/resource-chat-inject.ts +0 -17
  105. package/src/resource-not-found.ts +0 -24
  106. package/src/run-boot-hook-list.ts +1 -13
  107. package/src/run-boot-hooks.ts +1 -19
  108. package/src/scala-tools-currency-watchdog.ts +1 -7
  109. package/src/security-headers.ts +1 -7
  110. package/src/select-service-routes.ts +1 -17
  111. package/src/server-error-page.ts +0 -18
  112. package/src/theme-fonts-link.ts +1 -16
  113. package/src/transfers/presigned-upload.ts +1 -27
  114. package/src/two-phase-full-app.ts +0 -6
  115. package/src/two-phase-minimal-app.ts +0 -6
  116. package/src/two-phase-readiness.ts +0 -6
  117. package/src/types.ts +0 -3
  118. package/src/ui-service.ts +1 -6
  119. package/src/ws-boot-self-test.ts +1 -14
@@ -1,18 +1,6 @@
1
1
  /**
2
2
  * @system service-boot
3
- * @status handwritten — none derivable: the gate is a REJECTION RULE over four request facts, and no row states a rule — searched the service-boot auth surfaces (auth-gate.ts, auth/, content-gate/, gpt-gate.ts, bind-page-handler.ts) for an existing static-key check to call, and public-paths.ts names exempted PATHS, never a verifier
4
- * @edit edit directly
5
- *
6
- * THE OpenAPI CONTRACT GATE: who may read the document.
7
- *
8
- * It refuses a PROXIED request even when the key is right. The guard
9
- * `auth-helpers-fail-closed` holds a static key internal-only and never a
10
- * public sole-gate, and names the remedy: also reject on proxy-header
11
- * presence. Here the two are one fact from both sides — public ingress
12
- * crosses the tunnel and injects those headers, an internal fetch carries
13
- * neither, and the MCP gateway is the internal fetch.
14
- *
15
- * EVERY REFUSAL IS A REFUSAL: no key, no header, wrong key, proxied.
3
+ * @status handwritten
16
4
  */
17
5
 
18
6
  /**
@@ -1,13 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Render mode literal shared across page route registration. The old
7
- * shell-variant types (LegacyShell, PageSlugShell, RegionsShell,
8
- * PublicShell, ConfigPageRoute) were removed when the Phase 2 deploy-time
9
- * `service_install.page_routes[]` path was eliminated — all routing is
10
- * now registry-driven `page_route` rows (Phase 1).
11
4
  */
12
5
 
13
6
  export type RenderModeLiteral =
@@ -1,16 +1,6 @@
1
1
  /**
2
2
  * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * page-server-loader-graph.ts — binds the ONE loader-graph resolver
7
- * (@teamscala/resolver-engine's createLoaderConfigResolver) to the page-server
8
- * SSR client. The resolver used to be duplicated here with its own algorithm;
9
- * the copies drifted (a non-UUID URL ref resolved absent on this surface and
10
- * still threw into the render breaker on the fn-router surface), so the
11
- * algorithm became one injected function and each surface binds its own
12
- * client source. This module IS that binding for the SSR surface — the single
13
- * place the page-server client and the loader-graph resolver meet.
14
4
  */
15
5
 
16
6
  import { createLoaderConfigResolver } from "@teamscala/resolver-engine/loader-config/resolve-from-loader-config";
@@ -1,12 +1,6 @@
1
1
  /**
2
- * @system page-server
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Module-level singleton for the hub MCP client. setHubMcpClient(client)
7
- * is called once at boot by the host service after creating the multi-
8
- * tenant MCP client; createPageHandler's resolve-page-state reads it via
9
- * getHubMcpClient to pass through to data loaders.
10
4
  */
11
5
 
12
6
  let _hubMcpClient: unknown | null = null;
@@ -1,28 +1,6 @@
1
1
  /**
2
- * @system page-server
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Server-side ORPC client for in-process direct invocation, per the canonical
7
- * Vite/Next/Nuxt SSR pattern documented at https://orpc.dev/docs/best-practices/optimize-ssr
8
- *
9
- * The host service (scala-install) must call `setServerClient(client)` once
10
- * at boot, after createRouterClient(appRouter, { context: { prisma } }).
11
- * Then page-server's createPageHandler reads `getServerClient()` per request
12
- * — no HTTP loopback, just a typed function call.
13
- *
14
- * NO EMPTY-ROUTER SUBSTITUTE. This used to answer an unregistered read by
15
- * fabricating `createRouterClient({}, …)` — a client with no models on it. That
16
- * turned "boot never registered a client" into "every model lookup returns
17
- * undefined", which surfaces far away as MissingLoaderModelCapabilityError on
18
- * page render rather than as a boot failure. Measured 2026-08-20: quiz and forms
19
- * served 500s on every data-backed page for hours while /health returned 200 and
20
- * boot logged "ORPC serverClient registered", because the empty router is
21
- * indistinguishable from a real one until something asks it for a model
22
- * (`a-component-may-not-report-a-state-it-has-not-verified`).
23
- *
24
- * A missing client is now a thrown error naming the boot step that should have
25
- * set it, so the failure is reported by the component that has the fault.
26
4
  */
27
5
 
28
6
  import { createRouterClient } from "@orpc/server";
@@ -1,17 +1,6 @@
1
1
  /**
2
- * @system server-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * The pg-boss scheduled-job handler registry — `handler_slug` → handler
7
- * function. Built on `@teamscala/generic-registry` `createRegistry` (the mandated
8
- * primitive per `generic-registry-is-the-only-registry-pattern`); a hand-rolled
9
- * Map or a hardcoded switch in service-boot is the prohibited alternative.
10
- *
11
- * Handlers live in packages and self-register at boot (a boot hook / package
12
- * subscriber shape) by calling `registerScheduledJobHandler`. `resolveHandler`
13
- * in `pg-boss-mount.ts` reads this registry to dispatch a firing `scheduled_job`
14
- * row to its registered function.
15
4
  */
16
5
  import type { ScheduledJobConfig } from "@teamscala/db-validation/registry-schemas/scheduled-job";
17
6
  import { createRegistry } from "@teamscala/generic-registry/create-registry";
@@ -1,13 +1,6 @@
1
1
  /**
2
- * @system server-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Mounts pg-boss for a backend service. Reads all scheduled_job registry
7
- * entries scoped to the current service from the registry cache, registers
8
- * pg-boss workers per queue_name, and schedules cron/interval jobs.
9
- * Per Constitution Rule 6: pg-boss is the single mechanism for all
10
- * application background work.
11
4
  */
12
5
 
13
6
  import type { ScheduledJobConfig } from "@teamscala/db-validation/registry-schemas/scheduled-job";
@@ -1,38 +1,6 @@
1
1
  /**
2
2
  * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Resolves the set of emails authorized to view a proposal. A proposal is
7
- * gated (proposal-access) — only these emails can unlock it:
8
- *
9
- * - the issuing-org team: every member of the proposal's organisation
10
- * (better_auth_member → user.email). Lets the agency team open any of their
11
- * own proposals AND covers existing proposals whose created_by is
12
- * "system"/null.
13
- * - the recipient: the proposal's CRM contact (client_database.primary_email),
14
- * when contact_id is set.
15
- * - the partner team: every CRM contact belonging to the proposal's partner
16
- * org (client_database.company_id = proposals.partner_id → primary_email),
17
- * when partner_id is set. Lets the co-delivery partner's team open a
18
- * co-branded proposal. The partner is still branding-first; this is the one
19
- * access edge it carries.
20
- *
21
- * The partner clause casts to ::uuid because the two sides disagree in the
22
- * database: client_database.company_id is `uuid` while proposals.partner_id is
23
- * `text`. Postgres resolves operators at PLAN time, so `uuid = text` raises
24
- * "operator does not exist" for EVERY proposal — including ones with no partner
25
- * — the catch below swallows it, and the fail-closed empty Set then denies
26
- * access to everyone. Measured 2026-09-10: no proposal could be unlocked by any
27
- * email. The cast is correct once partner_id becomes `uuid` too (a no-op then);
28
- * the column type is the real fix and is tracked separately.
29
- *
30
- * Uses $queryRaw (raw SQL) deliberately: the per-service Prisma client is scoped
31
- * to that service's own models, so the proposals service's client has no
32
- * `member`/`user` model methods — but $queryRaw runs against the shared DB
33
- * regardless of the client's model scope. Returns a lowercased Set, checked
34
- * server-side only (emails never sent to the client). Fail-closed: any error
35
- * yields an empty set (no access).
36
4
  */
37
5
 
38
6
  import { getAppLogger } from "@teamscala/logger/app-loggers";
@@ -1,17 +1,6 @@
1
1
  /**
2
2
  * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * The PROPOSAL content gate, expressed as config for the content-gate primitive
7
- * (content-gate/). No bespoke gate plumbing — just the proposal-specific bits:
8
- * which resource (resolved.proposal.id), who's authorized (issuing-org team +
9
- * recipient), what to seed (initialVisitor for the chat), and how to withhold
10
- * (replace the proposal body with an injected SignIn gate block + neutralize the
11
- * meta tags). The engine handles cookie/token/verify/orchestration.
12
- *
13
- * Universal: every proposal route exposes resolved.proposal, so this gates every
14
- * proposal (existing + new) with no per-page block or migration.
15
4
  */
16
5
 
17
6
  import type { AccessConfig, ContentGateConfig } from "./content-gate/config-types.ts";
package/src/quiz-gate.ts CHANGED
@@ -1,28 +1,6 @@
1
1
  /**
2
2
  * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * The PUBLIC QUIZ identity gate, expressed as config for the content-gate
7
- * primitive. Like the GPT gate this is lead capture, not access control: every
8
- * email is a valid visitor. Its job is to make the visitor KNOWN AT SSR so the
9
- * page's identity blocks hide themselves and the quiz blocks reveal themselves
10
- * — by block condition on `initialVisitor`, never by a component deciding which
11
- * screen to render.
12
- *
13
- * That is the whole point of this file existing. The quiz identity form used to
14
- * be a composite React component that hand-assembled a logo, a heading, three
15
- * inputs and a button, and then branched in TypeScript on whether a visitor was
16
- * known. Every one of those pieces is already a Puck block, and the branch is
17
- * already expressible as a block condition — what was missing was only the
18
- * server half: something to turn a submitted email into a visitor the next
19
- * render can see. This is that half, and it is 60 lines of config because the
20
- * engine (content-gate/gate.ts + access.ts) already does the work.
21
- *
22
- * Flow: the composed form POSTs {quizId, name, email, phone} to
23
- * /api/quiz-access (openCapture → any email matches); the access endpoint signs
24
- * a `quiz_token` cookie and redirects back. On the next request runContentGate
25
- * verifies it for this assessment and seeds resolved.initialVisitor.
26
4
  */
27
5
 
28
6
  import type { AccessConfig, ContentGateConfig } from "./content-gate/config-types.ts";
@@ -1,54 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Builds the shared React/Puck document envelope and substitutes the current
7
- * content-hashed asset URLs from `dist/client/asset-manifest.json`.
8
- *
9
- * The envelope is runtime-owned. UI services are Puck compositions and must
10
- * not carry or generate a per-service `src/index.html`; requiring that file
11
- * creates a second rendering surface that can disappear independently of the
12
- * Hono + React/Puck runtime.
13
- *
14
- * Build-time produces hashed filenames (e.g. `styles-abc123.css`); the
15
- * static-asset handler serves them with `cache-control: immutable`. New
16
- * deployments emit new hashes → new URLs → browsers refetch without ever
17
- * holding a stale copy. Without the substitution, a fixed
18
- * `/assets/styles.css` paired with `immutable` would pin every visitor to
19
- * whatever version they first downloaded.
20
- *
21
- * Cached per service process, keyed on the manifest's mtime. The cache MUST
22
- * invalidate when `asset-manifest.json` changes: `buildClientAssets` can
23
- * rebuild the bundle AFTER the first request — producing a new content hash,
24
- * rewriting the manifest, AND deleting the old hashed bundle
25
- * (`removeStaleHashedFiles`). A lifetime-pinned HTML cache then keeps serving
26
- * the OLD hash, which now 404s → hydration never runs → the page renders SSR
27
- * HTML but is dead client-side (the doc-editor overlay never mounts; scala-docs
28
- * 2026-06-13, exposed by the ui-foundation publish-storm's repeated rebuilds).
29
- * Re-stat'ing the tiny manifest per request is negligible (OS-cached, no
30
- * network); the substituted HTML is reused while the mtime is unchanged.
31
- *
32
- * NO SERVED HTML WITHOUT A VERIFIED MANIFEST: when the manifest is absent,
33
- * unreadable, or names files that do not exist, this module THROWS rather
34
- * than emitting HTML — the fixed-name fallback (`/assets/styles.css`,
35
- * `/assets/hydrate.js`) it once served names files NOTHING builds, so a
36
- * 200 page with those URLs was a stylesheet 404 wearing a working page's
37
- * clothes. Measured 2026-09-01: proposals.scala.business served a
38
- * client-facing proposal unstyled while Railway reported the deploy
39
- * SUCCESS. The readiness flip now gates on `verifyClientBuildAssets`
40
- * (build-client-assets/manifest.ts), so this throw is defence in depth for
41
- * a manifest that vanishes mid-process; the page-server render catch turns
42
- * it into the branded error page, never a 200 with dead URLs.
43
- *
44
- * NO-SILENT-REVERTS: when the manifest is a TOMBSTONE (the last client build
45
- * failed), the served HTML is stamped with a `<meta name="x-client-build-status"
46
- * content="failed">` tag in <head> so any operator / chrome-devtools / theme
47
- * probe inspecting the page can see the served bundle is STALE (a published fix
48
- * that reached node_modules but failed to bundle is silently served from the
49
- * prior bundle otherwise — scala-agents 2026-07-18, the white-on-white toolbar
50
- * regression that looked "not fixed" while the bundle kept serving pre-fix
51
- * bytes across restarts).
52
4
  */
53
5
 
54
6
  import { createCache } from "@teamscala/cache/create-cache";
@@ -1,14 +1,6 @@
1
1
  /**
2
2
  * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Readiness gate — returns 503 + Retry-After: 1 until the boot pipeline
7
- * flips the ready flag true as its last step. Registered as the FIRST
8
- * middleware in both UI and backend boot paths per readiness-gated-boot.
9
- *
10
- * The gate fails open: if it ever throws, the request passes through to
11
- * the normal handler rather than producing a hard 500.
12
4
  */
13
5
 
14
6
  import { getAppLogger } from "@teamscala/logger/app-loggers";
@@ -1,16 +1,6 @@
1
1
  /**
2
- * @system server-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Walks `service_install.api_routes[]` and binds each entry to its
7
- * registered handler (via mountRegistry.handlers, populated by server_packages
8
- * during their mount phase). Unresolved handler_slug values are fatal — the
9
- * service cannot boot with declared routes pointing at nothing.
10
- *
11
- * Injects x-remote-port header from Bun's getConnInfo so downstream
12
- * handlers (MCP route) can resolve caller identity via process-tree
13
- * walking when explicit caller headers are absent.
14
4
  */
15
5
 
16
6
  import type { ServiceInstallConfig } from "./load-service-install-row";
@@ -1,11 +1,6 @@
1
1
  /**
2
- * @system server-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Registers process-level crash handlers (unhandledRejection, uncaughtException)
7
- * for a given service. Each handler logs the error with the service slug for
8
- * identification. Per constitution crash-isolation.
9
4
  */
10
5
 
11
6
  import { getAppLogger } from "@teamscala/logger/app-loggers";
@@ -1,17 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit directly
5
- *
6
- * Page route registration — reads `page_route` registry rows for the
7
- * current service and delegates to `registerRegistryPageRoute`.
8
- *
9
- * All routes are registry-driven (Phase 1): each `page_route` row pairs
10
- * a URL pattern with a `resource_loader` graph that resolves data in
11
- * wave-parallel via `resolveFromLoaderConfig`. No deploy-time shell
12
- * variant routes — the old `service_install.page_routes[]` Phase 2 path
13
- * was removed when every active service migrated to registry-driven
14
- * `page_route` rows (all 9 services carry empty arrays).
15
4
  */
16
5
 
17
6
  import { BootFatalError } from "@teamscala/os/errors/boot-error";
@@ -1,18 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Registers the system server-client for page-server SSR rendering. Composes
7
- * the platform-owned routers into the service's generated `appRouter` and
8
- * stashes the resulting client via setServerClient. Called once at boot before
9
- * any page route handler fires.
10
- *
11
- * Handwritten because no machine-readable contract generates it: this is the
12
- * EXECUTOR half of a rows+executor pair (`business-logic-is-rows-plus-executors`),
13
- * whose declared half is the `service_install`/`service_schema` rows read at
14
- * boot. There is no supplier spec, CLI or registry row that could emit this
15
- * boot-time wiring, so it stays hand-written; the row half remains the source.
16
4
  */
17
5
 
18
6
  // REFUSE, DO NOT SKIP. `existsSync(routerPath)` being false used to fall straight through with appRouter=null and still register a client + log
@@ -1,11 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * SSR-prefetch the signed-in user's AI-chat conversation so a click-opened AI
7
- * panel renders the real conversation on first paint. Extracted from
8
- * register-registry-page-route.ts (single-purpose-file split).
9
4
  */
10
5
  /**
11
6
  * SSR-prefetch the signed-in user's AI-chat conversation so a CLICK-opened AI
@@ -1,15 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * The three brand-override paths of a registered page route: the /sign-in
7
- * callback-org override, the signed-in session-org personalisation
8
- * (platform pages only), and the brand_org_path resource-owner override.
9
- *
10
- * Split out of register-registry-page-route.ts (924 lines) — the loadData
11
- * closure segments moved byte-identical; only the closure variables became
12
- * explicit parameters.
13
4
  */
14
5
 
15
6
  /**
@@ -1,16 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Summarises the resource_loader config a route captured at boot, for the
7
- * route-registration log line. Registration reads the loader row ONCE into
8
- * the route closure, so an edit to the row silently does not reach the
9
- * running service (measured 2026-08-18: a footer region added to a report
10
- * produced no footer and no diagnostic until a cold wake). Naming the
11
- * captured shape in the boot log makes the row-vs-running-service gap a
12
- * one-glance check in the service logs, and the restart contract is stated
13
- * where the operator will be looking when the edit "doesn't work".
14
4
  */
15
5
 
16
6
  /** Structural slice of the ResourceLoaderConfigSchema output this unit reads. */
@@ -1,26 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * The two SWR loader-graph caches (static-shell + parameterised routes) for the
7
- * registry page registrar, plus readCachedGraph — the testable stale-while-
8
- * revalidate read. Extracted from register-registry-page-route.ts so the SWR
9
- * decision is unit-testable independent of the Hono/DB/graph machinery.
10
- *
11
- * The SWR contract rides @teamscala/cache directly (the hand-rolled `at` timestamp,
12
- * FRESH_MS window, and graphRefreshInflight single-flight Set are gone): each
13
- * cache is configured ttlMs = the fresh window (serve, no refresh) + staleTtlMs =
14
- * the rest (serve stale + fire ONE background refresh). readCachedGraph uses
15
- * getWithMeta for the fresh/stale/miss decision and cache.refreshInBackground
16
- * for the fire-and-forget refresh — deduped against the cache's own in-flight map
17
- * (so delete/clear/disable drop its flights, and a refresh in flight across an
18
- * invalidation can no longer resurrect the dropped entry).
19
- *
20
- * Graphs deep-clone on BOTH set and get at the caller (registerRegistryPageRoute):
21
- * gateAgreementContent + downstream block resolution MUTATE the object in place,
22
- * so handing a cached tree out twice would ship request A's resolved data to
23
- * request B (ssr-first-tick-parity). Clone-on-get stays local to the caller.
24
4
  */
25
5
  /**
26
6
  * Stale-while-revalidate read of a cached loader graph.
@@ -1,27 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * live-loader-config.ts — the per-request resource_loader read.
7
- *
8
- * The constitution's deploy-time bake list (installer-and-runtime) names
9
- * service_install, service_manifest, block_schema, page_route, api_route and
10
- * scheduled_job — resource_loader is NOT among it, so a loader row is runtime
11
- * data: a registry edit must reach the running service on a subsequent request
12
- * without a restart. This module is that contract: `readLiveLoaderConfig`
13
- * re-reads the row through `loadRegistryConfig` on EVERY request (its SWR
14
- * cache makes the fresh-window hit a memory read, not a DB round trip) and
15
- * FAILS CLOSED — a row that vanished or stopped validating mid-flight throws
16
- * into the branded error path rather than silently serving the boot-time
17
- * snapshot of a row that no longer exists.
18
- *
19
- * `fingerprintLoaderConfig` gives the per-request graph cache a key component
20
- * derived from the LIVE config, so a row edit invalidates cached graphs for
21
- * that route immediately (the graph cache keys on route+host+path alone would
22
- * otherwise serve a stale graph until its SWR window lapsed — right cache,
23
- * wrong key: the graph is a function of the config, so the config belongs in
24
- * the key).
25
4
  */
26
5
 
27
6
  import { loadRegistryConfig } from "@teamscala/db/registry/load-config";
@@ -1,17 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Meta/title helpers for the route registrar: interpolate the route's
7
- * meta_context against the resolved graph. Extracted from
8
- * register-registry-page-route.ts.
9
- *
10
- * resolveTemplateTitle (the page_meta_template title reader) was DELETED
11
- * 2026-08-17: it only ever applied when NO resource entity resolved, and on a
12
- * resource page an entity ALWAYS resolves — the curated template was discarded
13
- * by construction, dead on exactly the pages the type exists for (Valencia's
14
- * finding). composePageTitle (+ the org-prefix flag) owns titles end to end.
15
4
  */
16
5
  /**
17
6
  * THE ONE SUBJECT DERIVATION. What a page is ABOUT — the entity whose name the
@@ -1,17 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Shared Puck-page-data helpers for the resolved-graph → pageData conversion:
7
- * the PuckData alias of the canonical boundary Data, JSON extraction with an
8
- * honest null on
9
- * malformed input, layout-default application, region root-prop picking, the
10
- * RegionEntry shape, and the unresolved-region-slot warn. Plus the brand-token
11
- * prologue shared by all three render branches.
12
- *
13
- * Split out of resolve-page-data.ts (547 lines) — byte-for-byte moves; only
14
- * closure variables became explicit parameters.
15
4
  */
16
5
 
17
6
  import { getAppLogger } from "@teamscala/logger/app-loggers";
@@ -1,12 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Resolves the organisation id for the background AI-chat session prefetch
7
- * from the request path. A canonical portal URL is /<websiteId>/<orgId>/
8
- * <path> — the org is segment 1, NOT segment 0. Moved from
9
- * register-registry-page-route.ts.
10
4
  */
11
5
 
12
6
  /**
@@ -1,16 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Resolve the `{{approvalEmail}}` token on a proposal page, after pageData is
7
- * built.
8
- *
9
- * Split from proposal-post-processors.ts, which single-purpose-file correctly
10
- * flagged as two unrelated export groups. This unit is an async ORPC lookup
11
- * that rewrites button props; its former co-tenants are synchronous brand
12
- * stamping that touch no network. Sharing a file made an I/O-bound resolver
13
- * look like a pure formatter.
14
4
  */
15
5
  /**
16
6
  * Resolve the `{{approvalEmail}}` placeholder in a proposal page's button props
@@ -1,16 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Stamp partner and client brand assets onto a proposal page's pageData, after
7
- * it is built.
8
- * Split from proposal-post-processors.ts (single-purpose-file: two unrelated
9
- * export groups). Both helpers here are synchronous, take an already-resolved
10
- * loader-graph org, and only map a logo/colour onto pageData — no network, no
11
- * ORPC. The approval-email token resolver they used to share a file with is an
12
- * async ORPC lookup, which is the distinction that was invisible while they sat
13
- * together.
14
4
  */
15
5
 
16
6
  /**
@@ -1,13 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Branch 2 of the resolved-graph → pageData conversion: the public shell
7
- * (header/body/footer regions from header/footer sources).
8
- *
9
- * Split out of resolve-page-data.ts (547 lines) — byte-identical body; only
10
- * the closure variables became explicit parameters.
11
4
  */
12
5
 
13
6
  import { resolveThemeMode } from "../resolve-theme-mode.ts";
@@ -1,13 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Branch 1 of the resolved-graph → pageData conversion: arbitrary region-slots
7
- * (portal/agents/docs) driven by resource_loader.region_slots.
8
- *
9
- * Split out of resolve-page-data.ts (547 lines) — byte-identical body; only
10
- * the closure variables became explicit parameters.
11
4
  */
12
5
 
13
6
  import { resolveThemeMode } from "../resolve-theme-mode.ts";
@@ -1,15 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Converts the resolved loader-graph into the pageData shape the renderer
7
- * consumes — three branches: arbitrary region-slots (portal/utility), the
8
- * header/body/footer public shell, and the single-page fallback. Extracted
9
- * from register-registry-page-route.ts (single-purpose-file split); the three
10
- * branches + shared helpers were split out of THIS file at 547 lines
11
- * (region-slots-page-data.ts, public-shell-page-data.ts, single-page-data.ts,
12
- * page-data-shared.ts).
13
4
  */
14
5
 
15
6
  import { regionSlotsPageData } from "./region-slots-page-data.ts";
@@ -1,15 +1,6 @@
1
1
  /**
2
- * @system ui-service-boot
2
+ * @system service-boot
3
3
  * @status handwritten
4
- * @edit edit directly
5
- *
6
- * ?panel=<slug> resolution: reads the panel_view row, follows its
7
- * content.page_slug to the builda_pages row, and stashes the panel page
8
- * data + active panel slug on pageData.
9
- *
10
- * Split out of register-registry-page-route.ts (924 lines) — the loadData
11
- * closure segment moved byte-identical; only the closure variables became
12
- * explicit parameters.
13
4
  */
14
5
 
15
6
  import { getServerClient } from "../page-server-orpc/server-client.ts";