@teamscala/service-boot 0.23.503 → 0.23.505

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 (62) hide show
  1. package/package.json +1 -1
  2. package/src/agreement-gate/signing-shell.test.ts +9 -15
  3. package/src/agreement-gate.test.ts +8 -15
  4. package/src/asset-proxy.test.ts +9 -9
  5. package/src/attach-portal-members.test.ts +9 -13
  6. package/src/attach-transfers-upload.test.ts +9 -10
  7. package/src/auth-gate.test.ts +8 -7
  8. package/src/build-client-assets/manifest.test.ts +8 -14
  9. package/src/build-client-assets/source-candidates.test.ts +9 -11
  10. package/src/build-client-assets/sourcemaps-upload.test.ts +8 -15
  11. package/src/build-client-assets/styles-build.test.ts +9 -15
  12. package/src/build-client-assets.test.ts +8 -12
  13. package/src/capability-slug.test.ts +9 -0
  14. package/src/compose-page-title.test.ts +8 -9
  15. package/src/content-gate/catalog.test.ts +8 -8
  16. package/src/content-gate/token.test.ts +8 -13
  17. package/src/content-page-floor.test.ts +9 -11
  18. package/src/csrf-body-limit.test.ts +9 -15
  19. package/src/handlers/messaging-send-reconcile-logic.test.ts +9 -11
  20. package/src/handlers/messaging-send-recording-logic.test.ts +9 -9
  21. package/src/handlers/messaging-send-recording-watch.test.ts +9 -11
  22. package/src/handlers/messaging-send-sweep-selection.test.ts +9 -7
  23. package/src/handlers/platform-fault-escalation/probe.test.ts +9 -10
  24. package/src/handlers/platform-fault-escalation-refresh.test.ts +9 -22
  25. package/src/handlers/platform-fault-escalation.test.ts +9 -10
  26. package/src/handlers/scala-tools-currency-watch.test.ts +9 -0
  27. package/src/handlers/singleton-tools-currency-watch.test.ts +9 -0
  28. package/src/handlers/whatsapp-liveness-handler.test.ts +9 -12
  29. package/src/handlers/whatsapp-liveness.test.ts +9 -9
  30. package/src/interpolate-meta.ts +123 -0
  31. package/src/is-react-element-type.test.ts +8 -9
  32. package/src/loader-errors.ts +41 -0
  33. package/src/module-not-found.test.ts +8 -12
  34. package/src/mount-orpc-router.test.ts +8 -9
  35. package/src/page-server-orpc/server-client.test.ts +8 -17
  36. package/src/read-html-template.test.ts +8 -12
  37. package/src/register-registry-page-route/apply-page-branding.test.ts +8 -19
  38. package/src/register-registry-page-route/captured-loader-config.test.ts +9 -13
  39. package/src/register-registry-page-route/graph-cache.test.ts +9 -12
  40. package/src/register-registry-page-route/live-loader-config.test.ts +8 -24
  41. package/src/register-registry-page-route/meta-title.ts +1 -1
  42. package/src/register-registry-page-route/page-data-shared.test.ts +9 -12
  43. package/src/register-registry-page-route/public-shell-page-data.test.ts +8 -19
  44. package/src/register-registry-page-route/resolve-entity-title.test.ts +8 -7
  45. package/src/register-registry-page-route/resolve-page-data.test.ts +9 -13
  46. package/src/register-registry-page-route/resolve-request-graph.test.ts +9 -13
  47. package/src/resolve-from-loader-config.test.ts +10 -14
  48. package/src/resolve-from-loader-config.ts +28 -115
  49. package/src/resolve-service-port.test.ts +8 -12
  50. package/src/resolvers/app-header.test.ts +9 -5
  51. package/src/resolvers/fetch-org-brand.ts +18 -2
  52. package/src/resolvers/portal-route-paths.test.ts +8 -13
  53. package/src/resource-chat-inject.page-assistant.test.ts +8 -28
  54. package/src/resource-chat-inject.test.ts +8 -25
  55. package/src/resource-not-found.test.ts +9 -8
  56. package/src/security-headers.test.ts +9 -12
  57. package/src/select-service-routes.test.ts +9 -0
  58. package/src/server-error-page.test.ts +8 -10
  59. package/src/theme-fonts-link.test.ts +8 -10
  60. package/src/two-phase-full-app.test.ts +8 -16
  61. package/src/two-phase-health-gate-client-only.test.ts +8 -28
  62. package/src/two-phase-health-gate.test.ts +8 -28
@@ -1,13 +1,12 @@
1
- /**
2
- * @system server-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Unit tests for the pure decision core of the platform-fault escalation
7
- * sweep (`platform-fault-escalation` handler). The handler's DB/WhatsApp I/O
8
- * is runtime-verified by the scheduled_job firing; this locks the threshold,
9
- * dedup and episode semantics from the 2026-08-15 incident brief.
10
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
9
+
11
10
  import { describe, expect, test } from "bun:test";
12
11
  import {
13
12
  composeEscalationMessage,
@@ -1,3 +1,12 @@
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
9
+
1
10
  import { describe, expect, test } from "bun:test";
2
11
  import { join } from "node:path";
3
12
 
@@ -1,3 +1,12 @@
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
9
+
1
10
  import { describe, expect, test } from "bun:test";
2
11
  import { join } from "node:path";
3
12
 
@@ -1,15 +1,12 @@
1
- /**
2
- * @system server-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Handler-level integration test for `pollWhatsAppLiveness`: mocks the central
7
- * /mcp forwarder (`forwardToolToCentralMcp`) + recordEvent, drives a
8
- * connected→disconnected transition across two polls, and asserts the
9
- * `messaging.whatsapp.device.disconnected` recordEvent fires — the "simulated
10
- * disconnect emitting recordEvent" of `whatsapp-remote-logout-monitor`, without
11
- * touching the real device or the real /mcp.
12
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
9
+
13
10
  import { beforeEach, expect, mock, test } from "bun:test";
14
11
 
15
12
  const recordEventCalls: Array<{ kind: string; payload: Record<string, unknown> }> = [];
@@ -1,12 +1,12 @@
1
- /**
2
- * @system server-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Unit tests for the pure `detectLivenessTransitions` core of the
7
- * `whatsapp-liveness` monitor. The handler's GOWA poll + recordEvent emission is
8
- * runtime-verified by the scheduled_job firing; this locks the transition logic.
9
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
9
+
10
10
  import { expect, test } from "bun:test";
11
11
  import { detectLivenessTransitions } from "./whatsapp-liveness-logic.ts";
12
12
 
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @system ui-service-boot
3
+ * @status handwritten
4
+ * @edit edit directly
5
+ *
6
+ * Template interpolation against URL params and resolved loader data:
7
+ * resolveParamRef, interpolateTemplate, and the meta-context filler.
8
+ *
9
+ * interpolateTemplate moved here from resolve-from-loader-config.ts
10
+ * (file-size-budget): interpolation is its own canonical unit and the meta
11
+ * filler already consumed it, so the import direction now points at the
12
+ * family home instead of the wave resolver.
13
+ *
14
+ * An unresolved ref keeps its literal template rather than becoming
15
+ * undefined — a page whose brand failed should show a raw `:brand.companyName`
16
+ * somewhere visible rather than silently dropping its title.
17
+ */
18
+
19
+ export function resolveParamRef(
20
+ ref: string,
21
+ params: Record<string, unknown>,
22
+ resolved: Record<string, unknown>,
23
+ ): unknown {
24
+ const parts = ref.split(".");
25
+ // A bare (no-dot) ref can name either a resolved source key (e.g. `:response`
26
+ // passes the whole resolved source object to a resolver_fn) or a URL param
27
+ // (e.g. `:id`). Prefer the resolved source key, then fall back to the param.
28
+ // Dotted refs (`:response.total_score`) always read from `resolved`.
29
+ if (parts.length === 1) {
30
+ if (resolved != null && typeof resolved === "object" && ref in resolved) {
31
+ return (resolved as Record<string, unknown>)[ref];
32
+ }
33
+ if (params != null && typeof params === "object" && ref in params) {
34
+ return (params as Record<string, unknown>)[ref];
35
+ }
36
+ return undefined;
37
+ }
38
+ let current: unknown = resolved;
39
+ for (const part of parts) {
40
+ if (current == null || typeof current !== "object") return undefined;
41
+ current = readField(current as Record<string, unknown>, part);
42
+ }
43
+ return current;
44
+ }
45
+
46
+ /**
47
+ * A resource_loader row spells DATABASE COLUMN NAMES — `page_id`,
48
+ * `organisation_id`, `prepared_for` — because that is what the schema calls
49
+ * them. The ORM hands back CAMELCASE keys — `pageId`, `organisationId`,
50
+ * `preparedFor`. Nothing reconciled the two, so a `:proposal.page_id` ref read
51
+ * a key the object does not have and returned undefined.
52
+ *
53
+ * MEASURED 2026-09-03, and the consequence is far worse than a missing value.
54
+ * `interpolateTemplate` DROPS a key whose value is undefined, so a dependent
55
+ * source declared `where: { id: ":proposal.page_id" }` was issued as
56
+ * `where: {}` — and findFirst with an empty filter returns AN ARBITRARY FIRST
57
+ * ROW. A client proposal page therefore loaded an unrelated builda_page,
58
+ * rendered a stranger's content under the correct brand chrome, and answered
59
+ * 200 throughout. Instrumenting the live resolver showed every dependent
60
+ * source doing it: page, website, contact, partnerOrg and clientOrg all with
61
+ * `where={}`; only `proposal` was correct, because its ref is the URL param
62
+ * `:id` rather than a sibling source.
63
+ *
64
+ * Read the spelled key first, then its camelCase equivalent. Column names stay
65
+ * the authoring vocabulary and a row never has to know what the ORM did to its
66
+ * keys.
67
+ */
68
+ function readField(source: Record<string, unknown>, key: string): unknown {
69
+ if (key in source) return source[key];
70
+ const camel = key.replace(/_([a-z0-9])/g, (_m, c: string) => c.toUpperCase());
71
+ return camel === key ? undefined : source[camel];
72
+ }
73
+
74
+ export function interpolateTemplate(
75
+ template: unknown,
76
+ params: Record<string, unknown>,
77
+ resolved: Record<string, unknown>,
78
+ ): unknown {
79
+ if (typeof template === "string") {
80
+ const exactMatch = template.match(/^:([a-zA-Z0-9_.]+)$/);
81
+ if (exactMatch) {
82
+ return resolveParamRef(exactMatch[1], params, resolved);
83
+ }
84
+ if (template.includes(":")) {
85
+ return template.replace(
86
+ /:([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*)/g,
87
+ (_match, ref: string) => {
88
+ const value = resolveParamRef(ref, params, resolved);
89
+ return value != null ? String(value) : _match;
90
+ },
91
+ );
92
+ }
93
+ return template;
94
+ }
95
+ if (Array.isArray(template)) {
96
+ return template.map((v) => interpolateTemplate(v, params, resolved));
97
+ }
98
+ if (template != null && typeof template === "object") {
99
+ const out: Record<string, unknown> = {};
100
+ for (const [k, v] of Object.entries(template)) {
101
+ const result = interpolateTemplate(v, params, resolved);
102
+ if (result !== undefined) out[k] = result;
103
+ }
104
+ return out;
105
+ }
106
+ return template;
107
+ }
108
+
109
+ export function interpolateMeta(
110
+ template: Record<string, unknown>,
111
+ data: Record<string, unknown>,
112
+ ): Record<string, unknown> {
113
+ const out: Record<string, unknown> = {};
114
+ for (const [k, v] of Object.entries(template)) {
115
+ if (v != null && typeof v === "object" && !Array.isArray(v)) {
116
+ out[k] = interpolateMeta(v as Record<string, unknown>, data);
117
+ } else {
118
+ const result = interpolateTemplate(v, {}, data);
119
+ out[k] = result ?? v;
120
+ }
121
+ }
122
+ return out;
123
+ }
@@ -1,12 +1,11 @@
1
- /**
2
- * @system ui-service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Pins the three React idioms a `typeof === "function"` check silently rejects.
7
- * The memo case is the measured one: PresenceAvatars rendered blank on every
8
- * scala-projects page carrying it, because memo() returns an object.
9
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
10
9
 
11
10
  import { expect, test } from "bun:test";
12
11
  import { forwardRef, lazy, memo } from "react";
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @system ui-service-boot
3
+ * @status handwritten
4
+ * @edit edit directly
5
+ *
6
+ * Error vocabulary for resource_loader source resolution. Split out of
7
+ * resolve-from-loader-config (file-size-budget): the classes are the
8
+ * name-matched contract other layers key on, and they belong where they
9
+ * can be imported without dragging the wave resolver with them.
10
+ */
11
+
12
+ export class MissingLoaderModelCapabilityError extends Error {
13
+ constructor(model: string, sourceKey: string) {
14
+ super(
15
+ `[resource_loader] source "${sourceKey}" requires model "${model}", but the generated server client does not expose findFirst for it — regenerate the service schema from its page loaders`,
16
+ );
17
+ this.name = "MissingLoaderModelCapabilityError";
18
+ }
19
+ }
20
+
21
+ /**
22
+ * A Prisma/pg query rejected an interpolated URL param as not a valid uuid
23
+ * (pg 22P02 surfaced as the generated client's SqlQueryError). The value came
24
+ * from the URL, so the URL names no row — the same state as a deleted row,
25
+ * not a renderer failure. Deliberately a tight name+message match: a
26
+ * genuinely malformed query is a config fault and must keep failing loudly.
27
+ *
28
+ * Measured 2026-09-12 on scala-quiz prod: scanner paths (/.env, /robots.txt,
29
+ * *.php) and slug links each threw `invalid input syntax for type uuid` as a
30
+ * 500 after a ~2.5s DB round trip, and the page-server:render-budget breaker
31
+ * counted them as CONSECUTIVE render failures — 53 in a row on 2026-09-11 —
32
+ * so the layer sat DEGRADED fail-closed and every real quiz page 503'd for
33
+ * hours while the only successful render in the window was a crawler.
34
+ */
35
+ export function isUrlRefNotUuidError(err: unknown): boolean {
36
+ return (
37
+ err instanceof Error &&
38
+ err.name === "SqlQueryError" &&
39
+ err.message.includes("invalid input syntax for type uuid")
40
+ );
41
+ }
@@ -1,15 +1,11 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Locks the mount candidate-chain regression (2026-08-24): scala-agents-ui
7
- * crash-looped at boot because @teamscala/cli-session exports ./boot/mount.ts
8
- * and not ./mount.ts. The chain already listed boot/mount.ts as a fallback,
9
- * but Bun names an unexported subpath by its BARE package, so the first
10
- * candidate's miss was classified as a real error and boot died before the
11
- * fallback ran. The whole value of the chain is that candidate 1 may be absent.
12
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
13
9
 
14
10
  import { describe, expect, it } from "bun:test";
15
11
  import { barePackageOf, isModuleNotFound } from "./module-not-found";
@@ -1,12 +1,11 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Regression coverage for the generated-router boot seam. A service schema
7
- * without its generated router is a codegen failure, not a daemon-only
8
- * service, so production boot must fail before it can report healthy.
9
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
10
9
 
11
10
  import { mkdir, mkdtemp, rm } from "node:fs/promises";
12
11
  import { afterEach, describe, expect, mock, test } from "bun:test";
@@ -1,20 +1,11 @@
1
- /**
2
- * @system page-server
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * The empty-router substitute that hid a total outage.
7
- *
8
- * MEASURED 2026-08-20: scala-quiz and scala-forms served 500s on every
9
- * data-backed page for hours. /health returned 200 and boot logged "ORPC
10
- * serverClient registered", because an unregistered read was answered with
11
- * `createRouterClient({}, …)` — a client that looks registered and carries no
12
- * models. The fault only surfaced later and elsewhere, as
13
- * MissingLoaderModelCapabilityError during page render.
14
- *
15
- * These pin the contract: a missing client is an error at the point of the
16
- * fault, never a fabricated stand-in.
17
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
18
9
 
19
10
  import { afterEach, describe, expect, test } from "bun:test";
20
11
  import {
@@ -1,15 +1,11 @@
1
- /**
2
- * @system ui-service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Regression guard for the runtime-owned Puck document and manifest-keyed
7
- * HTML cache. The lifetime-pinned
8
- * cache served a deleted bundle hash after a post-boot rebuild (scala-docs
9
- * 2026-06-13): build-client-assets rewrites asset-manifest.json + deletes the
10
- * old hashed bundle, but the cached HTML kept the old hash → 404 → no
11
- * hydration. These tests pin that a manifest change re-substitutes the HTML.
12
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
13
9
 
14
10
  import { mkdir, mkdtemp, rm } from "node:fs/promises";
15
11
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
@@ -1,22 +1,11 @@
1
- /**
2
- * @system ui-service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * applySessionOrgBranding must never repaint a TENANT document in the
7
- * VIEWER's brand.
8
- *
9
- * A public document belongs to the org that PUBLISHED it and must look
10
- * identical to every reader. Personalising to the reader's org is right for a
11
- * portal (you are looking at your own workspace) and wrong for a document.
12
- *
13
- * The regression this locks: sign.scala.business's website is owned by the
14
- * PLATFORM org, so the website-level test passed and the session override
15
- * fired on agreements owned by tenants. Every signed-in staff viewer saw a
16
- * GMG APAC agreement in their own org's brand while an anonymous client saw
17
- * it correctly — so the only people who could not see what the client sees
18
- * were the people reviewing it before sending.
19
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
20
9
 
21
10
  import { describe, expect, mock, test } from "bun:test";
22
11
 
@@ -1,16 +1,12 @@
1
- /**
2
- * @system ui-service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * The boot log is the ONLY observable statement of what a running service
7
- * captured from its resource_loader row (the 2026-08-18 evening-long bisect:
8
- * a footer region added to the row never reached the booted process, and
9
- * nothing anywhere said so). These tests pin the contract the line states —
10
- * the captured source keys, the captured region slots, and the restart
11
- * requirement — so the observability cannot silently regress to the old bare
12
- * "registered route" line.
13
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
9
+
14
10
  import { describe, expect, test } from "bun:test";
15
11
  import { describeCapturedLoaderConfig } from "./captured-loader-config.ts";
16
12
 
@@ -1,15 +1,12 @@
1
- /**
2
- * @system ui-service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Regression guard for readCachedGraph's stale-while-revalidate decision
7
- * (capability-harvest-on-split / what-must-have-a-test). The fold onto
8
- * @teamscala/cache's getWithMeta + refreshInBackground must keep firing the
9
- * background refresh past the fresh window — if it ever stops, the page-route
10
- * graph cache silently degrades to fresh-or-miss (the measured 3.8s
11
- * cache-expired in-request regression the SWR exists to prevent).
12
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
9
+
13
10
  import { describe, expect, test } from "bun:test";
14
11
  import { createCache } from "@teamscala/cache/create-cache";
15
12
  import { readCachedGraph } from "./graph-cache.ts";
@@ -1,27 +1,11 @@
1
- /**
2
- * @system ui-service-boot
3
- * @status handwritten
4
- * @edit extend the regression set for the live loader-config contract
5
- *
6
- * Behavioural tests for the per-request resource_loader read (the fix for the
7
- * boot-baked-loader defect): resource_loader is NOT on the deploy-time bake
8
- * list, so a registry row edit must reach the running service WITHOUT a
9
- * restart. The registration loop's boot read is warm/validate only.
10
- *
11
- * 1. Two requests to the same route with the row edited between them — the
12
- * SECOND request's graph resolution receives the NEW source set, and the
13
- * live read ran once per request (not once per boot).
14
- * 2. A row that vanishes (or stops validating) between requests — the second
15
- * request FAILS CLOSED (the read throws into the branded error path;
16
- * the boot snapshot never silently outlives its row).
17
- * 3. The graphKey fingerprint changes when the config changes — a row edit
18
- * invalidates the per-route SWR graph cache immediately instead of
19
- * serving the old graph until the fresh window lapses.
20
- *
21
- * Only the registry reader and the heavy graph collaborators are mocked; the
22
- * real registrar, real Hono app, real loadData pipeline and the real
23
- * live-loader-config unit are under test.
24
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
25
9
 
26
10
  import { GlobalRegistrator } from "@happy-dom/global-registrator";
27
11
  import { afterEach, describe, expect, mock, test } from "bun:test";
@@ -33,7 +33,7 @@
33
33
  * edit here rather than a fourth branch in three files.
34
34
  */
35
35
 
36
- import { interpolateMeta } from "../resolve-from-loader-config.ts";
36
+ import { interpolateMeta } from "../interpolate-meta.ts";
37
37
 
38
38
  export function buildMetaFromContext(
39
39
  metaContext: Record<string, Record<string, string>> | undefined,
@@ -1,15 +1,12 @@
1
- /**
2
- * @system ui-service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Behavioural pins for the shared page-data helpers. The load-bearing cases:
7
- * layout defaults FILL missing root props and never clobber existing values
8
- * (a theme row must not overwrite page-authored props), pickRootProp takes
9
- * the FIRST region carrying a usable value, brand tokens degrade to nulls —
10
- * never throw — on a missing brand row, and the unresolved-region-slot warn
11
- * fires ONCE per slot per process (the hot-path throttle).
12
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
9
+
13
10
  import { describe, expect, mock, test } from "bun:test";
14
11
 
15
12
  const warns: string[] = [];
@@ -1,22 +1,11 @@
1
- /**
2
- * @system service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Regression cover for two defects the operator reported on the launcha quiz,
7
- * both of which lived in publicShellPageData and were invisible to every other
8
- * check because the page rendered 200 with a clean log either way.
9
- *
10
- * 1. screenMode was never threaded, so a page declaring "full-screen" fell back
11
- * to build-page-tree's card-wrapper default and the site header rendered
12
- * INSIDE the card instead of across the top of the page.
13
- * 2. the page title used the LEGAL entity name (companyName) rather than the
14
- * trading name (companyFriendlyName), putting "GMG APAC" on every launcha
15
- * page.
16
- *
17
- * Both assert the OUTCOME (the emitted flag, the composed title text), not the
18
- * presence of a key — a shape assertion would have passed throughout the bug.
19
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
20
9
 
21
10
  import { describe, expect, test } from "bun:test";
22
11
  import { publicShellPageData } from "./public-shell-page-data.ts";
@@ -1,10 +1,11 @@
1
- /**
2
- * @system ui-service-boot
3
- * @status handwritten
4
- * @edit edit directly
5
- *
6
- * Locks the single subject derivation that replaced three divergent copies.
7
- */
1
+ // ! @system codegen
2
+ // ! @status generated
3
+ // ! @edit change the suite in the owned-suites band, then re-run codegen. Hand-edits are overwritten.
4
+ // !
5
+ // ! This suite's assertions are OWNED by the codegen band: the band module
6
+ // ! carries them verbatim, this file is the emission, and hand edits here are
7
+ // ! overwritten on the next run. The rationale each assertion carries moved
8
+ // ! with it into the band.
8
9
 
9
10
  import { describe, expect, test } from "bun:test";
10
11
  import { resolveEntityTitle } from "./meta-title.ts";