@teamscala/service-boot 0.23.432 → 0.23.434

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 (32) hide show
  1. package/package.json +1 -1
  2. package/src/auth-gate.ts +0 -9
  3. package/src/bind-page-handler.ts +0 -3
  4. package/src/build-client-assets/hydrate-bundle.ts +0 -9
  5. package/src/build-client-assets/input-fingerprint.ts +0 -9
  6. package/src/build-client-assets/sourcemaps-upload.ts +0 -3
  7. package/src/build-client-assets/styles-build.ts +5 -2
  8. package/src/build-client-assets.ts +0 -3
  9. package/src/content-gate/catalog.ts +0 -6
  10. package/src/content-gate/gate.ts +0 -3
  11. package/src/fn-routers/agreement-sign-side-effects.ts +0 -3
  12. package/src/fn-routers/index.ts +16 -0
  13. package/src/fn-routers/panel-data-router.ts +104 -0
  14. package/src/fn-routers/work-items-router.ts +0 -3
  15. package/src/handlers/platform-fault-escalation/orpc-client.ts +0 -3
  16. package/src/handlers/scala-tools-currency-watch.ts +0 -3
  17. package/src/handlers/singleton-tools-currency-watch.ts +0 -6
  18. package/src/mount-server-packages.ts +0 -3
  19. package/src/register-page-server-client.ts +0 -3
  20. package/src/register-registry-page-route/ai-chat-prefetch.ts +0 -3
  21. package/src/register-registry-page-route/apply-page-branding.ts +0 -9
  22. package/src/register-registry-page-route/graph-cache.ts +0 -3
  23. package/src/register-registry-page-route/meta-title.ts +0 -3
  24. package/src/register-registry-page-route/prefetch-org-id.ts +0 -3
  25. package/src/register-registry-page-route/proposal-approval-email-token.ts +0 -3
  26. package/src/resolvers/portal-route-paths.ts +0 -3
  27. package/src/resource-chat-inject.ts +0 -9
  28. package/src/resource-not-found.ts +0 -3
  29. package/src/two-phase-full-app.ts +0 -9
  30. package/src/two-phase-minimal-app.ts +0 -6
  31. package/src/two-phase-readiness.ts +0 -9
  32. package/src/ui-service.ts +0 -9
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "name": "@teamscala/service-boot",
8
8
  "type": "module",
9
- "version": "0.23.432",
9
+ "version": "0.23.434",
10
10
  "sideEffects": false,
11
11
  "imports": {
12
12
  "#service-boot/*": "./src/*",
package/src/auth-gate.ts CHANGED
@@ -44,9 +44,6 @@
44
44
  * registry refused a path exemption for it, correctly — `guard-exemptions-to-zero`.
45
45
  */
46
46
 
47
- // Why: Point the event-log primitive at the process's Prisma single…
48
- // (full note hoisted to this file's leading header — kept out of the body per
49
- // no-inline-prose-blocks / prose-stays-in-docs)
50
47
  // Eager-warm the local BetterAuth runtime at boot whenever a request path
51
48
  // will build it: the session-READ path (getSession, better-auth-cookie mode)
52
49
  // always uses the local instance — even when /api/auth/* forwards to
@@ -61,9 +58,6 @@
61
58
  // (e.g. mid-install) the first successful request rebuilds and caches — the
62
59
  // service is never left wedged, and never boot-loops on a transient.
63
60
 
64
- // Why: Eager-warm the local BetterAuth runtime at boot whenever a r…
65
- // (full note hoisted to this file's leading header — kept out of the body per
66
- // no-inline-prose-blocks / prose-stays-in-docs)
67
61
  // NO localhost bypass: a 127.0.0.1 page request is gated EXACTLY like a
68
62
  // tunnel request (no session → redirect to /sign-in). The old
69
63
  // `if (isLocalhost) return next()` let any tool — and the agent's own
@@ -76,9 +70,6 @@
76
70
  // service-to-service auth still flows through the cookie/secret on the
77
71
  // request, never the source IP.
78
72
 
79
- // Why: NO localhost bypass: a 127.0.0.1 page request is gated EXACT…
80
- // (full note hoisted to this file's leading header — kept out of the body per
81
- // no-inline-prose-blocks / prose-stays-in-docs)
82
73
  import type { ServiceInstallConfig } from "@teamscala/db/registry/loader/load-service-install-row";
83
74
  import { getPrisma } from "@teamscala/db/prisma-registry";
84
75
  import { loadRegistryConfig } from "@teamscala/db/registry/load-config";
@@ -21,9 +21,6 @@
21
21
  // and was REMOVED by operator ruling the same day ("the origin should be so fast we don't care") — the origin-speed work (SWR caches,
22
22
  // wave-parallel loader, brotli) is the sanctioned path; re-adding shared-cache headers needs a fresh operator ruling.
23
23
 
24
- // Why: Per-page root.props.maxWidth (the canonical mechanism) cente…
25
- // (full note hoisted to this file's leading header — kept out of the body per
26
- // no-inline-prose-blocks / prose-stays-in-docs)
27
24
  import { getAppLogger } from "@teamscala/logger/app-loggers";
28
25
  import type { Context } from "hono";
29
26
  import { readHtmlTemplate } from "./read-html-template.ts";
@@ -27,9 +27,6 @@
27
27
  // tombstone (no-dead-block-imports-in-manifest) — never silent. Entry-point imports are excluded — those must fail loudly (silently
28
28
  // externalizing a core import turns a build error into a mystery runtime crash; containment must not become a swallow).
29
29
 
30
- // Why: Externalize an unresolvable @teamscala/* block import (a dea…
31
- // (full note hoisted to this file's leading header — kept out of the body per
32
- // no-inline-prose-blocks / prose-stays-in-docs)
33
30
  // minifyIdentifiers is DISABLED (whitespace + syntax/dead-code minify
34
31
  // kept): under code-splitting, identifier mangling interacting with a
35
32
  // shared sideEffects:false package (@tanstack/react-query) trips Bun's
@@ -42,9 +39,6 @@
42
39
  // gate below fails the build LOUD if this or any future regression slips
43
40
  // a fatal facade through on any UI service.
44
41
 
45
- // Why: minifyIdentifiers is DISABLED (whitespace + syntax/dead-code…
46
- // (full note hoisted to this file's leading header — kept out of the body per
47
- // no-inline-prose-blocks / prose-stays-in-docs)
48
42
  // dead-facade prevention gate (agents.scala.business 2026-07-22): a Bun
49
43
  // splitter+tree-shake bug (stable 1.3.14 + canary 1.4.0) can emit a "dead
50
44
  // facade" chunk — `export { ... }` with NO `from` clause and NO local binding
@@ -61,9 +55,6 @@
61
55
  // be silently bypassed; a valid local-export chunk carries a
62
56
  // class/function/const/var/let/import, a valid re-export carries `from`).
63
57
 
64
- // Why: dead-facade prevention gate (agents.scala.business 2026-07-2…
65
- // (full note hoisted to this file's leading header — kept out of the body per
66
- // no-inline-prose-blocks / prose-stays-in-docs)
67
58
  import { mkdir, readdir, rename, rm } from "node:fs/promises";
68
59
  import { join } from "node:path";
69
60
  import { getAppLogger } from "@teamscala/logger/app-loggers";
@@ -31,9 +31,6 @@
31
31
  // @teamscala/* version (backend packages included), so it invalidates on every publish — the false-invalidation source that made every UI service rebuild
32
32
  // on a backend publish. The closure inputs above are a strict improvement: they catch every change that affects THIS bundle AND nothing that doesn't.
33
33
 
34
- // Why: Content fingerprint of the client-bundle dependency CLOSURE …
35
- // (full note hoisted to this file's leading header — kept out of the body per
36
- // no-inline-prose-blocks / prose-stays-in-docs)
37
34
  // Keyed on each input's RELATIVE label + CONTENT only — never the absolute
38
35
  // path (that would make the fingerprint cwd-dependent and defeat the skip
39
36
  // across two checkouts of the same service). bun.lock is DELIBERATELY
@@ -46,9 +43,6 @@
46
43
  // so a non-closure publish changes nothing here → zero rebuild. Rebuild
47
44
  // iff this fingerprint differs from the one stored in the manifest.
48
45
 
49
- // Why: Keyed on each input's RELATIVE label + CONTENT only — never …
50
- // (full note hoisted to this file's leading header — kept out of the body per
51
- // no-inline-prose-blocks / prose-stays-in-docs)
52
46
  // Fold in the resolved CONTENT of every @teamscala/* JS/TS module reachable
53
47
  // from the client entrypoints (hashTeamgbgJsGraph). bun.lock pins versions;
54
48
  // the build reads BYTES — and a boot can build MID-INSTALL (the package-
@@ -64,9 +58,6 @@
64
58
  // which already closes this exact race for CSS). A stale bake then hashes
65
59
  // differently from the freshly-installed bytes → rebuild → self-heals.
66
60
 
67
- // Why: Fold in the resolved CONTENT of every @teamscala/* JS/TS mod…
68
- // (full note hoisted to this file's leading header — kept out of the body per
69
- // no-inline-prose-blocks / prose-stays-in-docs)
70
61
  import { join } from "node:path";
71
62
  import {
72
63
  hashResolvedPackageStylesheets,
@@ -23,9 +23,6 @@
23
23
  * ships publicly; the debug IDs in the served bundles are all the SDK needs.
24
24
  */
25
25
 
26
- // Why: Upload source maps to GlitchTip via the official `glitchtip-…
27
- // (full note hoisted to this file's leading header — kept out of the body per
28
- // no-inline-prose-blocks / prose-stays-in-docs)
29
26
  import { readdir, rm } from "node:fs/promises";
30
27
  import { join } from "node:path";
31
28
  import { getAppLogger } from "@teamscala/logger/app-loggers";
@@ -35,7 +35,7 @@ async function resolveStylesheetRaw(
35
35
  const r = await Bun.resolve(id, base);
36
36
  return { path: r, base: dirname(r), content: await Bun.file(r).text() };
37
37
  } catch (error) {
38
- log.warn("style import resolve failed — trying package fallback", error);
38
+ getAppLogger().warn("style import resolve failed — trying package fallback", error);
39
39
  }
40
40
  if (!id.startsWith(".")) {
41
41
  try {
@@ -48,7 +48,10 @@ async function resolveStylesheetRaw(
48
48
  return { path: r, base: dirname(r), content: await Bun.file(r).text() };
49
49
  }
50
50
  } catch (error) {
51
- log.warn("package style entry resolve failed — falling back to bare resolve", error);
51
+ getAppLogger().warn(
52
+ "package style entry resolve failed — falling back to bare resolve",
53
+ error,
54
+ );
52
55
  }
53
56
  }
54
57
  const r = resolve(base, id);
@@ -52,9 +52,6 @@
52
52
  // kept serving the old bytes across restarts while node_modules was mid-install — invisible until the operator hit the white-on-white
53
53
  // toolbar regression the fix was supposed to close).
54
54
 
55
- // Why: Each build is wrapped in its own catch so a JS bundle failur…
56
- // (full note hoisted to this file's leading header — kept out of the body per
57
- // no-inline-prose-blocks / prose-stays-in-docs)
58
55
  import { mkdir } from "node:fs/promises";
59
56
  import { join } from "node:path";
60
57
  import { withFileLock } from "@teamscala/file-lock/with-lock";
@@ -39,9 +39,6 @@
39
39
  * govern.
40
40
  */
41
41
 
42
- // Why: Registered gates, in evaluation order.
43
- // (full note hoisted to this file's leading header — kept out of the body per
44
- // no-inline-prose-blocks / prose-stays-in-docs)
45
42
  /**
46
43
  * Does this gate WITHHOLD content, or only identify the visitor?
47
44
  *
@@ -57,9 +54,6 @@
57
54
  * read as an unauthorized viewer and lose an assistant they are entitled to.
58
55
  */
59
56
 
60
- // Why: Does this gate WITHHOLD content, or only identify the visito…
61
- // (full note hoisted to this file's leading header — kept out of the body per
62
- // no-inline-prose-blocks / prose-stays-in-docs)
63
57
  import type { AccessConfig, ContentGateConfig } from "./config-types.ts";
64
58
  import { agreementAccessConfig, agreementGateConfig } from "../agreement-gate.ts";
65
59
  import { gptAccessConfig, gptGateConfig } from "../gpt-gate.ts";
@@ -25,9 +25,6 @@
25
25
  * confused with one.
26
26
  */
27
27
 
28
- // Why: What a gate decided, so a caller can act on it without re-de…
29
- // (full note hoisted to this file's leading header — kept out of the body per
30
- // no-inline-prose-blocks / prose-stays-in-docs)
31
28
  import type { ContentGateConfig } from "./config-types.ts";
32
29
  import { parseCookie } from "./parse-cookie.ts";
33
30
 
@@ -32,9 +32,6 @@
32
32
  * payUrl) before this runs; only the stored record is reset.
33
33
  */
34
34
 
35
- // Why: Self-resetting demo harness. If the signed agreement's `prop…
36
- // (full note hoisted to this file's leading header — kept out of the body per
37
- // no-inline-prose-blocks / prose-stays-in-docs)
38
35
  import { getAppLogger } from "@teamscala/logger/app-loggers";
39
36
  import { queryRows } from "@teamscala/db/query-rows";
40
37
  import type { PrismaClient } from "@teamscala/db/client";
@@ -13,10 +13,24 @@
13
13
  * RegionPageSwap can fetch a region's Puck page on demand and render it into a
14
14
  * slot — the no-reload half of `region-views-are-pages` (every region is a Puck
15
15
  * page; switching a view loads a different page's content).
16
+ *
17
+ * `resolvePanelData` WAS RESTORED 2026-08-31. `72ac1a7` ("Retire unoffered page
18
+ * ORPC procedures") deleted it three weeks earlier as unoffered, but its
19
+ * consumer is live and in ANOTHER REPO: `use-region-page.ts` in
20
+ * @teamscala/ui-foundation calls `regions.resolvePanelData` on every panel
21
+ * open. Only the comment describing it was left behind — the shape
22
+ * `a-deleted-producer-leaves-its-consumers-executing` names, where deleting a
23
+ * producer leaves its consumers demanding something that can no longer exist.
24
+ *
25
+ * It failed SILENTLY for three weeks because the client treats a failure as
26
+ * best-effort and maps it to null, so the 404 rendered an empty panel with no
27
+ * error anywhere. Observed live as `POST /api/rpc/regions/resolvePanelData 404`
28
+ * on every panel open on projects-dev.
16
29
  */
17
30
 
18
31
  import { registerCustomRouter } from "@teamscala/orpc/app-router";
19
32
  import { puckPagesRouter } from "../page-server-orpc/puck-pages-router";
33
+ import { resolvePanelDataHandler } from "./panel-data-router.ts";
20
34
  import { watchDataChange } from "@teamscala/realtime-utils/data-change-procedure";
21
35
  import { watchPresence } from "@teamscala/realtime-utils/presence-procedure";
22
36
  import { agreementSendRouter } from "./agreement-send-router.ts";
@@ -51,6 +65,8 @@ export function registerFnRouters(): void {
51
65
  loadPage: puckPagesRouter.loadFromWebsite,
52
66
  // Resolve a page-kind panel's OWN loaderData (panel_view.loader_slug) so a
53
67
  // panel region renders against the panel page's data, not the host's.
68
+ //
69
+ resolvePanelData: resolvePanelDataHandler,
54
70
  });
55
71
  registerCustomRouter("realtime", {
56
72
  watchDataChange,
@@ -0,0 +1,104 @@
1
+ /**
2
+ * @system service-boot
3
+ * @status handwritten
4
+ * @edit edit directly
5
+ *
6
+ * `regions.resolvePanelData` — resolves a page-kind panel's OWN loaderData so a
7
+ * panel region renders blocks against the panel page's data, not the host
8
+ * page's. RegionPageSwap calls this on panel-open + injects the result via
9
+ * LiveDataProvider("page-data"), making panel-embedded data blocks (e.g. the
10
+ * workload Chart) self-sufficient: each panel carries its own data, no host
11
+ * coupling + no preloading the host route.
12
+ *
13
+ * Flow (registry reads via the loadRegistryConfig helper — registry-via-helper):
14
+ * panel_view.content.loader_slug → resource_loader config → orgId derived from
15
+ * the serving website (builda_websites.organisation_id) → resolveFromLoaderConfig
16
+ * → the loader's resolved sources. Panels without a loader_slug (e.g. the AI
17
+ * panel, whose block self-loads) return null — no extra round-trip, no behavior
18
+ * change.
19
+ */
20
+ import { os } from "@orpc/server";
21
+ import * as v from "valibot";
22
+ import { loadRegistryConfig } from "@teamscala/db/registry/load-config";
23
+ import type { PanelViewKey } from "@teamscala/db/registry/generated/panel-view";
24
+ import type { ResourceLoaderKey } from "@teamscala/db/registry/generated/resource-loader";
25
+ import { resolveFromLoaderConfig } from "../resolve-from-loader-config.ts";
26
+
27
+ interface Context {
28
+ prisma: {
29
+ builda_websites: {
30
+ findFirst: (args: unknown) => Promise<{
31
+ organisation_id?: string | null;
32
+ } | null>;
33
+ };
34
+ };
35
+ }
36
+
37
+ const panelViewSchema = v.looseObject({
38
+ content: v.looseObject({ loader_slug: v.optional(v.string()) }),
39
+ });
40
+
41
+ export const resolvePanelDataHandler = os
42
+ .$context<Context>()
43
+ .input(
44
+ v.object({
45
+ panelSlug: v.string(),
46
+ websiteSlug: v.string(),
47
+ /** Tenant orgId (preferred over the website's organisation_id, which is
48
+ * the platform org on a multi-tenant portal — not the tenant). The
49
+ * caller (RegionPageSwap) threads this from __PAGE_DATA__.orgId. */
50
+ orgId: v.optional(v.string()),
51
+ }),
52
+ )
53
+ .handler(async ({ input, context }) => {
54
+ // panel_view → loader_slug (null when missing or the panel has no loader).
55
+ let loaderSlug: string | undefined;
56
+ try {
57
+ // THE SLUG IS RUNTIME-SUPPLIED, so it cannot be statically a
58
+ // PanelViewKey: it arrives from the browser as the opened panel's
59
+ // name. The lookup itself is the validation — loadRegistryConfig
60
+ // throws when no such row exists, and the catch below turns that into
61
+ // the documented null. Narrowing here states that contract rather
62
+ // than asserting the value is known good.
63
+ const pv = await loadRegistryConfig(
64
+ "panel_view",
65
+ input.panelSlug as PanelViewKey,
66
+ panelViewSchema,
67
+ );
68
+ loaderSlug = pv.content?.loader_slug;
69
+ } catch {
70
+ return null;
71
+ }
72
+ if (!loaderSlug) return null;
73
+ // resource_loader → its config (loose schema; resolveFromLoaderConfig owns
74
+ // the typed LoaderConfig contract).
75
+ let loader: unknown;
76
+ try {
77
+ loader = await loadRegistryConfig(
78
+ "resource_loader",
79
+ // Same contract: loader_slug is read from the panel row's loose
80
+ // content schema as a plain string, and a missing row throws into
81
+ // the catch below.
82
+ loaderSlug as ResourceLoaderKey,
83
+ v.unknown(),
84
+ );
85
+ } catch {
86
+ return null;
87
+ }
88
+ // Tenant orgId: prefer the caller-provided value (the route's tenant org,
89
+ // threaded from __PAGE_DATA__.orgId); fall back to the website's
90
+ // organisation_id (the platform org — wrong for multi-tenant portals, but
91
+ // the only derivable value when the caller omits it).
92
+ let orgId = input.orgId;
93
+ if (!orgId) {
94
+ const site = await context.prisma.builda_websites.findFirst({
95
+ where: { OR: [{ slug: input.websiteSlug }, { id: input.websiteSlug }] },
96
+ select: { organisation_id: true },
97
+ });
98
+ orgId = site?.organisation_id ?? undefined;
99
+ }
100
+ return await resolveFromLoaderConfig(
101
+ loader as Parameters<typeof resolveFromLoaderConfig>[0],
102
+ { orgId },
103
+ );
104
+ });
@@ -33,9 +33,6 @@
33
33
  * dependent client-side round-trip chain).
34
34
  */
35
35
 
36
- // Why: Org-scoped member list for the task-comments panel — @mentio…
37
- // (full note hoisted to this file's leading header — kept out of the body per
38
- // no-inline-prose-blocks / prose-stays-in-docs)
39
36
  import { createEmailClient } from "@teamscala/email-client/client";
40
37
  import { getAppLogger } from "@teamscala/logger/app-loggers";
41
38
  import { authed, type Context } from "./auth-router.ts";
@@ -27,9 +27,6 @@
27
27
  * never Date instances (the generated valibot schemas require it).
28
28
  */
29
29
 
30
- // Why: The system-authed in-process ORPC client, built LAZILY on fi…
31
- // (full note hoisted to this file's leading header — kept out of the body per
32
- // no-inline-prose-blocks / prose-stays-in-docs)
33
30
  import { loadRegistryConfig } from "@teamscala/db/registry/load-config";
34
31
  import * as v from "valibot";
35
32
  import { createCache } from "@teamscala/cache/create-cache";
@@ -45,9 +45,6 @@
45
45
  // If a future package genuinely needs a restart to take effect, it does not belong here: add it to dep-sync's PM2_CACHED map, which already owns
46
46
  // install-plus-restart and coalesces them.
47
47
 
48
- // Why: NO RESTART. The reinstall alone is sufficient, and restartin…
49
- // (full note hoisted to this file's leading header — kept out of the body per
50
- // no-inline-prose-blocks / prose-stays-in-docs)
51
48
  import type { ScheduledJobConfig } from "@teamscala/db-validation/registry-schemas/scheduled-job";
52
49
  import { recordEvent } from "@teamscala/event-log/record-event";
53
50
  import { getAppLogger } from "@teamscala/logger/app-loggers";
@@ -40,9 +40,6 @@
40
40
  * tracking, never placement.
41
41
  */
42
42
 
43
- // Why: Where a tool's "latest" comes from.
44
- // (full note hoisted to this file's leading header — kept out of the body per
45
- // no-inline-prose-blocks / prose-stays-in-docs)
46
43
  // A GitHub-released binary is NOT installed by a package manager, so there
47
44
  // is no "reinstall" verb to call — it would have to be downloaded, verified,
48
45
  // made executable and swapped atomically over a file that may be RUNNING.
@@ -55,9 +52,6 @@
55
52
  // watcher cannot actually install is honest — silently claiming currency
56
53
  // would not be.
57
54
 
58
- // Why: A GitHub-released binary is NOT installed by a package manag…
59
- // (full note hoisted to this file's leading header — kept out of the body per
60
- // no-inline-prose-blocks / prose-stays-in-docs)
61
55
  import type { ScheduledJobConfig } from "@teamscala/db-validation/registry-schemas/scheduled-job";
62
56
  import { loadRegistryConfig } from "@teamscala/db/registry/load-config";
63
57
  import { recordEvent } from "@teamscala/event-log/record-event";
@@ -24,9 +24,6 @@
24
24
  * only warms the cache, never gates boot.
25
25
  */
26
26
 
27
- // Why: Speculatively import every server_package's mount module so …
28
- // (full note hoisted to this file's leading header — kept out of the body per
29
- // no-inline-prose-blocks / prose-stays-in-docs)
30
27
  import type { ServiceInstallConfig } from "@teamscala/db/registry/loader/load-service-install-row";
31
28
  import { getAppLogger } from "@teamscala/logger/app-loggers";
32
29
  import { BootFatalError } from "@teamscala/os/errors/boot-error";
@@ -21,9 +21,6 @@
21
21
  // rather than reporting a state it has not verified (`a-component-may-not-report-a-state-it-has-not-verified`). A service
22
22
  // that declares no models (daemon/portal shells owning no DB schema) still passes through cleanly.
23
23
 
24
- // Why: REFUSE, DO NOT SKIP. `existsSync(routerPath)` being false us…
25
- // (full note hoisted to this file's leading header — kept out of the body per
26
- // no-inline-prose-blocks / prose-stays-in-docs)
27
24
  import { join } from "node:path";
28
25
  import { getAppLogger } from "@teamscala/logger/app-loggers";
29
26
 
@@ -20,9 +20,6 @@
20
20
  * createOrRestore fallback, never an error page.
21
21
  */
22
22
 
23
- // Why: SSR-prefetch the signed-in user's AI-chat conversation so a …
24
- // (full note hoisted to this file's leading header — kept out of the body per
25
- // no-inline-prose-blocks / prose-stays-in-docs)
26
23
  import { getServerClient } from "../page-server-orpc/server-client.ts";
27
24
 
28
25
  /**
@@ -28,9 +28,6 @@
28
28
  * Shared helper so this and bind-page-handler cannot drift on the answer.
29
29
  */
30
30
 
31
- // Why: /sign-in brand override: a shared org-scoped link 302→/sign-…
32
- // (full note hoisted to this file's leading header — kept out of the body per
33
- // no-inline-prose-blocks / prose-stays-in-docs)
34
31
  /**
35
32
  * brand-is-org-owned-full-scheme, reconciled with page-org-first
36
33
  * (portal-branding-resolves-page-org-first): the session override now
@@ -53,9 +50,6 @@
53
50
  * got the wrong page.
54
51
  */
55
52
 
56
- // Why: brand-is-org-owned-full-scheme, reconciled with page-org-fir…
57
- // (full note hoisted to this file's leading header — kept out of the body per
58
- // no-inline-prose-blocks / prose-stays-in-docs)
59
53
  /**
60
54
  * BRAND FROM THE ORG THAT OWNS THE RESOURCE, not the website's owner.
61
55
  * A public resource page (an assessment report, a shared document) is
@@ -77,9 +71,6 @@
77
71
  * more specific owner, never blank it.
78
72
  */
79
73
 
80
- // Why: BRAND FROM THE ORG THAT OWNS THE RESOURCE, not the website's…
81
- // (full note hoisted to this file's leading header — kept out of the body per
82
- // no-inline-prose-blocks / prose-stays-in-docs)
83
74
  import { fetchOrganisationPageBranding } from "@teamscala/db/fetch-organisation-page-branding";
84
75
  import { getPlatformOrgId } from "@teamscala/db/registry/platform";
85
76
  import { getAppLogger } from "@teamscala/logger/app-loggers";
@@ -40,9 +40,6 @@
40
40
  * (an observable dead-link signal, not a hard error).
41
41
  */
42
42
 
43
- // Why: Stale-while-revalidate read of a cached loader graph.
44
- // (full note hoisted to this file's leading header — kept out of the body per
45
- // no-inline-prose-blocks / prose-stays-in-docs)
46
43
  import { createCache } from "@teamscala/cache/create-cache";
47
44
 
48
45
  // The structural surface readCachedGraph touches (getWithMeta + refreshInBackground).
@@ -33,9 +33,6 @@
33
33
  * edit here rather than a fourth branch in three files.
34
34
  */
35
35
 
36
- // Why: THE ONE SUBJECT DERIVATION. What a page is ABOUT — the entit…
37
- // (full note hoisted to this file's leading header — kept out of the body per
38
- // no-inline-prose-blocks / prose-stays-in-docs)
39
36
  import { interpolateMeta } from "../resolve-from-loader-config.ts";
40
37
 
41
38
  export function buildMetaFromContext(
@@ -27,9 +27,6 @@
27
27
  * (found 2026-07-21).
28
28
  */
29
29
 
30
- // Why: Prefer segment 1; fall back to segment 0 only when segment 1…
31
- // (full note hoisted to this file's leading header — kept out of the body per
32
- // no-inline-prose-blocks / prose-stays-in-docs)
33
30
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
34
31
 
35
32
  export function resolveAiOrgId(pathname: string): string | undefined {
@@ -24,9 +24,6 @@
24
24
  * pages; other registry pages are untouched.
25
25
  */
26
26
 
27
- // Why: Resolve the `{{approvalEmail}}` placeholder in a proposal pa…
28
- // (full note hoisted to this file's leading header — kept out of the body per
29
- // no-inline-prose-blocks / prose-stays-in-docs)
30
27
  import { getServerClient } from "../page-server-orpc/server-client.ts";
31
28
 
32
29
  export async function applyApprovalEmailToken(
@@ -31,9 +31,6 @@
31
31
  * neither leading segment is a UUID.
32
32
  */
33
33
 
34
- // Why: Extract the organisation id from a portal-shaped callback/pa…
35
- // (full note hoisted to this file's leading header — kept out of the body per
36
- // no-inline-prose-blocks / prose-stays-in-docs)
37
34
  export interface ResolverArgs {
38
35
  input: Record<string, unknown>;
39
36
  client: unknown;
@@ -36,9 +36,6 @@
36
36
  * column holds them yet.
37
37
  */
38
38
 
39
- // Why: THE ASSISTANT'S WORDS BELONG TO THE AGENT ROW, NOT TO THIS F…
40
- // (full note hoisted to this file's leading header — kept out of the body per
41
- // no-inline-prose-blocks / prose-stays-in-docs)
42
39
  /**
43
40
  * The rendered content tree to append the launcher to.
44
41
  *
@@ -67,9 +64,6 @@
67
64
  * caller. One shared convention, not a per-resource list.
68
65
  */
69
66
 
70
- // Why: The rendered content tree to append the launcher to.
71
- // (full note hoisted to this file's leading header — kept out of the body per
72
- // no-inline-prose-blocks / prose-stays-in-docs)
73
67
  /**
74
68
  * Serialise EVERYTHING THIS VIEWER MAY SEE as text for the assistant.
75
69
  *
@@ -101,9 +95,6 @@
101
95
  * safe rather than reckless.
102
96
  */
103
97
 
104
- // Why: Serialise EVERYTHING THIS VIEWER MAY SEE as text for the ass…
105
- // (full note hoisted to this file's leading header — kept out of the body per
106
- // no-inline-prose-blocks / prose-stays-in-docs)
107
98
  import { getAppLogger } from "@teamscala/logger/app-loggers";
108
99
  import { loadRegistryConfig } from "@teamscala/db/registry/load-config";
109
100
  import { getServerClient } from "./page-server-orpc/server-client.ts";
@@ -47,9 +47,6 @@
47
47
  * HTML; the page renders logo-less, never broken.
48
48
  */
49
49
 
50
- // Why: The host org's LOGO (wordmark) for the dark error page — the…
51
- // (full note hoisted to this file's leading header — kept out of the body per
52
- // no-inline-prose-blocks / prose-stays-in-docs)
53
50
  import { getClient } from "@teamscala/object-storage/create/client/get-client";
54
51
  import { createCache } from "@teamscala/cache/create-cache";
55
52
  import { registerCacheInvalidation } from "@teamscala/db/notify-listener/index";
@@ -22,9 +22,6 @@
22
22
  * so we don't need to modify the app here. The app reference stays the same.
23
23
  */
24
24
 
25
- // Why: Build the full app with hydration. This adds the expensive o…
26
- // (full note hoisted to this file's leading header — kept out of the body per
27
- // no-inline-prose-blocks / prose-stays-in-docs)
28
25
  // Client asset building (expensive: Vite build).
29
26
  //
30
27
  // ISOLATED, because a PRESENTATION failure must not take out BACKGROUND WORK.
@@ -45,9 +42,6 @@
45
42
  // registry and the DB, not a bundle. Ordering it behind a Vite build was
46
43
  // incidental, so the coupling was never intended.
47
44
 
48
- // Why: Client asset building (expensive: Vite build).
49
- // (full note hoisted to this file's leading header — kept out of the body per
50
- // no-inline-prose-blocks / prose-stays-in-docs)
51
45
  // pg-boss (mount for UI services - wasn't mounted in minimal app)
52
46
  //
53
47
  // Wrapped for the SAME reason buildClientAssets above is, in the other
@@ -62,9 +56,6 @@
62
56
  // migration threw, and an outage of every page followed from a scheduled-job
63
57
  // dependency. Jobs are the degradable half; pages are not.
64
58
 
65
- // Why: pg-boss (mount for UI services - wasn't mounted in minimal a…
66
- // (full note hoisted to this file's leading header — kept out of the body per
67
- // no-inline-prose-blocks / prose-stays-in-docs)
68
59
  import { getAppLogger } from "@teamscala/logger/app-loggers";
69
60
  import type { Hono } from "hono";
70
61
  import { buildClientAssets } from "./build-client-assets.ts";
@@ -29,9 +29,6 @@
29
29
  * - ORPC router, API routes, WS routes, data routes, page routes
30
30
  */
31
31
 
32
- // Why: Build the minimal tool-only app. This excludes the expensive…
33
- // (full note hoisted to this file's leading header — kept out of the body per
34
- // no-inline-prose-blocks / prose-stays-in-docs)
35
32
  // Fire independent I/O + compilation NOW, overlapping with the gate chain
36
33
  // below. These three touch NO app route and have no ordering dependency on
37
34
  // the gate/mount sequence, so they run concurrently with it:
@@ -45,9 +42,6 @@
45
42
  // - discoverBlocks: loads the page-manifest (no app mutation, no gate
46
43
  // dependency). Its result is consumed by registerPageRoutes much later.
47
44
 
48
- // Why: Fire independent I/O + compilation NOW, overlapping with the…
49
- // (full note hoisted to this file's leading header — kept out of the body per
50
- // no-inline-prose-blocks / prose-stays-in-docs)
51
45
  import { getAppLogger } from "@teamscala/logger/app-loggers";
52
46
  import { BootFatalError } from "@teamscala/os/errors/boot-error";
53
47
  import { createTimer } from "@teamscala/timing/create-timer";
@@ -30,9 +30,6 @@
30
30
  * still reported starting — while three untouched UI services reported ok.
31
31
  */
32
32
 
33
- // Why: Flip readiness once phase 2 has built the full app.
34
- // (full note hoisted to this file's leading header — kept out of the body per
35
- // no-inline-prose-blocks / prose-stays-in-docs)
36
33
  /**
37
34
  * Reset both phase-2 flags. TEST-ONLY.
38
35
  *
@@ -48,9 +45,6 @@
48
45
  * the only writers on the boot path.
49
46
  */
50
47
 
51
- // Why: Reset both phase-2 flags. TEST-ONLY.
52
- // (full note hoisted to this file's leading header — kept out of the body per
53
- // no-inline-prose-blocks / prose-stays-in-docs)
54
48
  /**
55
49
  * `/health` for a UI service — 200 ONLY once the full app can actually render
56
50
  * a page, 503 before that.
@@ -94,9 +88,6 @@
94
88
  * one consumer contract is "can you serve me a page", is moved to phase 2.
95
89
  */
96
90
 
97
- // Why: `/health` for a UI service — 200 ONLY once the full app can …
98
- // (full note hoisted to this file's leading header — kept out of the body per
99
- // no-inline-prose-blocks / prose-stays-in-docs)
100
91
  import { buildWakingPageHtml } from "@teamscala/os/brand/waking-page-html";
101
92
  import { WAKING_RETRY_SECONDS } from "@teamscala/os/brand/waking-page-budget.generated";
102
93
  import type { Context } from "hono";
package/src/ui-service.ts CHANGED
@@ -22,9 +22,6 @@
22
22
  * place and is NOT undone.
23
23
  */
24
24
 
25
- // Why: Boots a UI service using two-phase boot for fast availabilit…
26
- // (full note hoisted to this file's leading header — kept out of the body per
27
- // no-inline-prose-blocks / prose-stays-in-docs)
28
25
  // Resolve the listen port through the SHARED resolver (`resolveServicePort`),
29
26
  // the same one the backend branch uses. The registry wins wherever it has an
30
27
  // opinion and a contradicting PORT env is reported, never silently obeyed —
@@ -39,9 +36,6 @@
39
36
  // makes the healthcheck probe a dead port and the deploy fails (`isRailway`
40
37
  // path in the resolver).
41
38
 
42
- // Why: Resolve the listen port through the SHARED resolver (`resolv…
43
- // (full note hoisted to this file's leading header — kept out of the body per
44
- // no-inline-prose-blocks / prose-stays-in-docs)
45
39
  // NO-SILENT-REVERTS — surface the failed client build to OBSERVABILITY
46
40
  // (event-log → GlitchTip, per event-log-is-the-only-durable-event-log).
47
41
  // The minimal-app fallback keeps serving SSR from the LAST-successful
@@ -55,9 +49,6 @@
55
49
  // event-log's 7-day retention → surfaces in GlitchTip as an incident
56
50
  // trail the operator actually watches.
57
51
 
58
- // Why: NO-SILENT-REVERTS — surface the failed client build to OBSER…
59
- // (full note hoisted to this file's leading header — kept out of the body per
60
- // no-inline-prose-blocks / prose-stays-in-docs)
61
52
  import { recordEvent } from "@teamscala/event-log/record-event";
62
53
  import { getAppLogger } from "@teamscala/logger/app-loggers";
63
54
  import { BootFatalError } from "@teamscala/os/errors/boot-error";