@teamscala/service-boot 0.23.525 → 0.23.527

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.
@@ -1,126 +1,11 @@
1
1
  {
2
2
  "suite": {
3
- "target": "src/orpc-contract-rows.json"
3
+ "target": "src/orpc-contract-rows.test.ts",
4
+ "package": "@teamscala/service-boot",
5
+ "rows_module": "./orpc-contract-rows.json",
6
+ "describe_label": "@teamscala/service-boot function_call contracts"
4
7
  },
5
8
  "rows": [
6
- {
7
- "args": [
8
- {
9
- "key": "row-fixture-key",
10
- "authorization": "Bearer row-fixture-key"
11
- },
12
- ""
13
- ],
14
- "note": "THE ONE CALLER THAT GETS THROUGH. The internal service-to-service fetch the MCP gateway makes at boot: the configured key presented as a Bearer token, on a request carrying no forwarding header. The second arg position is a placeholder the one-parameter subject ignores, because the registry writer collapses an argument array shorter than two elements (measured 2026-09-30 while filing the @teamscala/orpc rows) so a one-argument row cannot be spelled. The key value is a fixture, not a credential: no secret row holds it and the production key arrives from the SCALA_DEV_KEY environment.",
15
- "expect": true,
16
- "export": "openApiContractAuthorised",
17
- "module": "src/orpc-openapi-gate.ts",
18
- "package": "@teamscala/service-boot",
19
- "suite_type": "function_call",
20
- "slug": "boot:openapi-contract-authorises-the-internal-key-holder"
21
- },
22
- {
23
- "args": [
24
- "scala-quiz",
25
- "",
26
- ""
27
- ],
28
- "note": "THE FALLBACKS, PINNED SO A MISSING HEADER CANNOT PRODUCE A MALFORMED URL. A request that names no Host and carries no forwarding header still gets a well-formed server entry (localhost, http) rather than an undefined host interpolated into the document as the string null. The title comes from the slug regardless - the service always names itself. The empty-string arg positions stand for absent headers: a JSON argument cannot spell undefined, and the subject reads absence through the same falsy branch an empty string takes.",
29
- "expect": {
30
- "member_equals": {
31
- "title": "scala-quiz oRPC procedures",
32
- "servers.0.url": "http://localhost/api/rpc"
33
- }
34
- },
35
- "export": "openApiContractOptions",
36
- "module": "src/orpc-openapi-document.ts",
37
- "package": "@teamscala/service-boot",
38
- "suite_type": "function_call",
39
- "slug": "boot:openapi-contract-falls-back-when-the-request-names-no-host"
40
- },
41
- {
42
- "args": [
43
- "scala-portal",
44
- "scala-portal.internal:5200",
45
- "http"
46
- ],
47
- "note": "THE DOCUMENT NAMES ITS SERVICE AND THE PREFIX IT SERVES. The title is the slug the mount was handed and the server URL is the host this request arrived on, with the /api/rpc prefix appended because that is the prefix the POST handler serves under - a client that reads the document can therefore call what the document describes. Deriving both rather than configuring them is what makes ONE document correct for the internal address the MCP gateway fetches and for a public host at the same time; the values are asserted exactly, so a change in either is a visible diff rather than a silently wrong server URL.",
48
- "expect": {
49
- "member_equals": {
50
- "title": "scala-portal oRPC procedures",
51
- "servers.0.url": "http://scala-portal.internal:5200/api/rpc"
52
- }
53
- },
54
- "export": "openApiContractOptions",
55
- "module": "src/orpc-openapi-document.ts",
56
- "package": "@teamscala/service-boot",
57
- "suite_type": "function_call",
58
- "slug": "boot:openapi-contract-names-the-service-and-the-prefix-it-serves"
59
- },
60
- {
61
- "args": [
62
- {
63
- "key": "row-fixture-key",
64
- "forwardedFor": "203.0.113.7",
65
- "authorization": "Bearer row-fixture-key",
66
- "forwardedProto": "https"
67
- },
68
- ""
69
- ],
70
- "note": "THE STATIC KEY IS NEVER A PUBLIC SOLE-GATE. Guard auth-helpers-fail-closed holds that a shared key is internal-only and names the remedy for a legitimate internal bearer check: also reject on proxy-header presence. This row is that remedy. The caller holds the right key and is still refused, because x-forwarded-proto and x-forwarded-for prove the request crossed a proxy, and on this platform only public ingress puts them there - an internal fetch, which is what the MCP gateway makes at boot, carries neither. Without this refusal the key alone would open the procedure surface to the public internet.",
71
- "expect": false,
72
- "export": "openApiContractAuthorised",
73
- "module": "src/orpc-openapi-gate.ts",
74
- "package": "@teamscala/service-boot",
75
- "suite_type": "function_call",
76
- "slug": "boot:openapi-contract-refuses-a-proxied-request"
77
- },
78
- {
79
- "args": [
80
- {
81
- "key": "row-fixture-key"
82
- },
83
- ""
84
- ],
85
- "note": "NO CREDENTIAL, NO DOCUMENT. A caller presenting no Authorization header is refused even though the service HAS a key configured, so the gate is not merely comparing a header to a value. The trailing empty-string arg position is a placeholder the one-parameter subject ignores: the registry writer collapses an argument array shorter than two elements (measured 2026-09-30 while filing the @teamscala/orpc rows), so a one-argument row cannot be spelled.",
86
- "expect": false,
87
- "export": "openApiContractAuthorised",
88
- "module": "src/orpc-openapi-gate.ts",
89
- "package": "@teamscala/service-boot",
90
- "suite_type": "function_call",
91
- "slug": "boot:openapi-contract-refuses-a-request-with-no-authorization"
92
- },
93
- {
94
- "args": [
95
- {
96
- "key": "row-fixture-key",
97
- "authorization": "Bearer not-the-configured-key"
98
- },
99
- ""
100
- ],
101
- "note": "THE NEAR-MISS. A Bearer token of the right shape carrying the wrong value is refused, which is the case a prefix check alone would wave through. Trailing arg position is a placeholder (see the no-authorization row for why).",
102
- "expect": false,
103
- "export": "openApiContractAuthorised",
104
- "module": "src/orpc-openapi-gate.ts",
105
- "package": "@teamscala/service-boot",
106
- "suite_type": "function_call",
107
- "slug": "boot:openapi-contract-refuses-a-wrong-key"
108
- },
109
- {
110
- "args": [
111
- {
112
- "authorization": "Bearer anything-at-all"
113
- },
114
- ""
115
- ],
116
- "note": "FAIL CLOSED WHEN THE SERVICE CANNOT GATE. No SCALA_DEV_KEY configured means there is no key to match, and a missing signal must DENY rather than admit every caller: a service that cannot authenticate must not serve the internal procedure surface. The key member is absent from the argument, which is exactly how an unconfigured environment reaches this subject. Trailing arg position is a placeholder.",
117
- "expect": false,
118
- "export": "openApiContractAuthorised",
119
- "module": "src/orpc-openapi-gate.ts",
120
- "package": "@teamscala/service-boot",
121
- "suite_type": "function_call",
122
- "slug": "boot:openapi-contract-refuses-when-no-key-is-configured"
123
- },
124
9
  {
125
10
  "args": [
126
11
  {},
@@ -409,6 +294,3873 @@
409
294
  "package": "@teamscala/service-boot",
410
295
  "suite_type": "function_call",
411
296
  "slug": "quiz-gate:gate-declares-the-one-view-entry-marker"
297
+ },
298
+ {
299
+ "args": [
300
+ "@teamscala/cli-session"
301
+ ],
302
+ "label": "keeps the scope for scoped packages",
303
+ "expect": "@teamscala/cli-session",
304
+ "export": "barePackageOf",
305
+ "module": "src/module-not-found.ts",
306
+ "package": "@teamscala/service-boot",
307
+ "suite_type": "function_call",
308
+ "slug": "service-boot:bare-package-of-keeps-the-scope-for-scoped-packages-bare"
309
+ },
310
+ {
311
+ "args": [
312
+ "@teamscala/cli-session/mount.ts"
313
+ ],
314
+ "label": "keeps the scope for scoped packages",
315
+ "expect": "@teamscala/cli-session",
316
+ "export": "barePackageOf",
317
+ "module": "src/module-not-found.ts",
318
+ "package": "@teamscala/service-boot",
319
+ "suite_type": "function_call",
320
+ "slug": "service-boot:bare-package-of-keeps-the-scope-for-scoped-packages-with-subpath"
321
+ },
322
+ {
323
+ "args": [
324
+ "hono"
325
+ ],
326
+ "label": "takes the first segment for unscoped packages",
327
+ "expect": "hono",
328
+ "export": "barePackageOf",
329
+ "module": "src/module-not-found.ts",
330
+ "package": "@teamscala/service-boot",
331
+ "suite_type": "function_call",
332
+ "slug": "service-boot:bare-package-of-takes-the-first-segment-for-unscoped-packages-bare"
333
+ },
334
+ {
335
+ "args": [
336
+ "hono/mount.ts"
337
+ ],
338
+ "label": "takes the first segment for unscoped packages",
339
+ "expect": "hono",
340
+ "export": "barePackageOf",
341
+ "module": "src/module-not-found.ts",
342
+ "package": "@teamscala/service-boot",
343
+ "suite_type": "function_call",
344
+ "slug": "service-boot:bare-package-of-takes-the-first-segment-for-unscoped-packages-with-subpath"
345
+ },
346
+ {
347
+ "args": [
348
+ "u",
349
+ "",
350
+ {
351
+ "title": "DB title",
352
+ "subtitle": "Sign to continue",
353
+ "requireOtp": true,
354
+ "submitLabel": "Sign now"
355
+ }
356
+ ],
357
+ "label": "a blank per-agreement title falls back to the DB-driven default",
358
+ "expect": {
359
+ "type": "SignIn",
360
+ "props": {
361
+ "id": "agreement-gate-u",
362
+ "mode": "gate",
363
+ "title": "DB title",
364
+ "subtitle": "Sign to continue",
365
+ "gateAction": "/api/agreement-access",
366
+ "gateRequireOtp": "true",
367
+ "showBackToHome": true,
368
+ "gateSubmitLabel": "Sign now",
369
+ "gateContextField": "agreementId",
370
+ "gateContextValue": "u"
371
+ }
372
+ },
373
+ "export": "buildGateBlock",
374
+ "module": "src/agreement-gate/signing-shell.ts",
375
+ "package": "@teamscala/service-boot",
376
+ "suite_type": "function_call",
377
+ "slug": "service-boot:build-gate-block-a-blank-per-agreement-title-falls-back-to-the-db-driven-default"
378
+ },
379
+ {
380
+ "args": [
381
+ "agreement-uuid-1",
382
+ "Custom title",
383
+ {
384
+ "title": "DB title",
385
+ "subtitle": "Sign to continue",
386
+ "requireOtp": true,
387
+ "submitLabel": "Sign now"
388
+ }
389
+ ],
390
+ "note": "gateRequireOtp is the STRING the renderer validates, never a boolean: a boolean is stripped before reaching the component (the same coercion that bit the pre-placed gate block).",
391
+ "label": "carries the agreement uuid as the gate context (and the requireOtp string form true)",
392
+ "expect": {
393
+ "type": "SignIn",
394
+ "props": {
395
+ "id": "agreement-gate-agreement-uuid-1",
396
+ "mode": "gate",
397
+ "title": "Custom title",
398
+ "subtitle": "Sign to continue",
399
+ "gateAction": "/api/agreement-access",
400
+ "gateRequireOtp": "true",
401
+ "showBackToHome": true,
402
+ "gateSubmitLabel": "Sign now",
403
+ "gateContextField": "agreementId",
404
+ "gateContextValue": "agreement-uuid-1"
405
+ }
406
+ },
407
+ "export": "buildGateBlock",
408
+ "module": "src/agreement-gate/signing-shell.ts",
409
+ "package": "@teamscala/service-boot",
410
+ "suite_type": "function_call",
411
+ "slug": "service-boot:build-gate-block-carries-the-agreement-uuid-as-the-gate-context"
412
+ },
413
+ {
414
+ "args": [
415
+ "u",
416
+ "t",
417
+ {
418
+ "title": "DB title",
419
+ "subtitle": "Sign to continue",
420
+ "requireOtp": false,
421
+ "submitLabel": "Sign now"
422
+ }
423
+ ],
424
+ "label": "requireOtp is the STRING the renderer validates, never a boolean (false spelling)",
425
+ "expect": {
426
+ "type": "SignIn",
427
+ "props": {
428
+ "id": "agreement-gate-u",
429
+ "mode": "gate",
430
+ "title": "t",
431
+ "subtitle": "Sign to continue",
432
+ "gateAction": "/api/agreement-access",
433
+ "gateRequireOtp": "false",
434
+ "showBackToHome": true,
435
+ "gateSubmitLabel": "Sign now",
436
+ "gateContextField": "agreementId",
437
+ "gateContextValue": "u"
438
+ }
439
+ },
440
+ "export": "buildGateBlock",
441
+ "module": "src/agreement-gate/signing-shell.ts",
442
+ "package": "@teamscala/service-boot",
443
+ "suite_type": "function_call",
444
+ "slug": "service-boot:build-gate-block-require-otp-false-spells-the-string-false"
445
+ },
446
+ {
447
+ "args": [
448
+ "page",
449
+ null,
450
+ 200
451
+ ],
452
+ "note": "The html text claims (absent Take me home, present no-page-at-this-link) stay hand-written: then-step expects carry structural verbs only.",
453
+ "then": [
454
+ {
455
+ "call": "text"
456
+ }
457
+ ],
458
+ "label": "floor render: bare-root landing → no Take-me-home (it IS home)",
459
+ "expect": {
460
+ "instance_of": "Response",
461
+ "member_equals": {
462
+ "status": 200
463
+ }
464
+ },
465
+ "export": "buildResourceNotFoundResponse",
466
+ "module": "src/resource-not-found.ts",
467
+ "package": "@teamscala/service-boot",
468
+ "suite_type": "function_call",
469
+ "slug": "service-boot:build-resource-not-found-response-bare-root-landing-renders-200-without-take-me-home"
470
+ },
471
+ {
472
+ "args": [
473
+ "page",
474
+ null,
475
+ 404,
476
+ {
477
+ "homeUrl": "/"
478
+ }
479
+ ],
480
+ "note": "The html text claims (Take me home, doesn't exist, href, noindex) stay hand-written: the text lives behind the async Response.text() member call, and then-step expects carry the structural verbs only, so no row can read the body. The then step here proves text() resolves.",
481
+ "then": [
482
+ {
483
+ "call": "text"
484
+ }
485
+ ],
486
+ "label": "floor render: dead link → 404 with Take-me-home copy",
487
+ "expect": {
488
+ "instance_of": "Response",
489
+ "member_equals": {
490
+ "status": 404
491
+ }
492
+ },
493
+ "export": "buildResourceNotFoundResponse",
494
+ "module": "src/resource-not-found.ts",
495
+ "package": "@teamscala/service-boot",
496
+ "suite_type": "function_call",
497
+ "slug": "service-boot:build-resource-not-found-response-dead-link-renders-404"
498
+ },
499
+ {
500
+ "args": [
501
+ "page",
502
+ null,
503
+ 200,
504
+ {
505
+ "empty": true,
506
+ "homeUrl": "/"
507
+ }
508
+ ],
509
+ "note": "The html text claims stay hand-written: then-step expects carry structural verbs only (no contains_text), so no row can read the async body.",
510
+ "then": [
511
+ {
512
+ "call": "text"
513
+ }
514
+ ],
515
+ "label": "floor render: empty page → 200 with This-page-is-empty copy",
516
+ "expect": {
517
+ "instance_of": "Response",
518
+ "member_equals": {
519
+ "status": 200
520
+ }
521
+ },
522
+ "export": "buildResourceNotFoundResponse",
523
+ "module": "src/resource-not-found.ts",
524
+ "package": "@teamscala/service-boot",
525
+ "suite_type": "function_call",
526
+ "slug": "service-boot:build-resource-not-found-response-empty-page-renders-200"
527
+ },
528
+ {
529
+ "args": [
530
+ "project",
531
+ null,
532
+ 200,
533
+ {
534
+ "empty": true
535
+ }
536
+ ],
537
+ "note": "The html copy claims stay hand-written: async body, structural then-steps only.",
538
+ "then": [
539
+ {
540
+ "call": "text"
541
+ }
542
+ ],
543
+ "label": "renders the empty-page surface when opts.empty",
544
+ "expect": {
545
+ "instance_of": "Response",
546
+ "member_equals": {
547
+ "status": 200
548
+ }
549
+ },
550
+ "export": "buildResourceNotFoundResponse",
551
+ "module": "src/resource-not-found.ts",
552
+ "package": "@teamscala/service-boot",
553
+ "suite_type": "function_call",
554
+ "slug": "service-boot:build-resource-not-found-response-renders-the-empty-page-surface-when-opts-empty"
555
+ },
556
+ {
557
+ "args": [
558
+ "project",
559
+ null,
560
+ 200
561
+ ],
562
+ "note": "The html copy claims stay hand-written: async body, structural then-steps only.",
563
+ "then": [
564
+ {
565
+ "call": "text"
566
+ }
567
+ ],
568
+ "label": "returns a 200 Response for the bare root (no resource selected)",
569
+ "expect": {
570
+ "instance_of": "Response",
571
+ "member_equals": {
572
+ "status": 200
573
+ }
574
+ },
575
+ "export": "buildResourceNotFoundResponse",
576
+ "module": "src/resource-not-found.ts",
577
+ "package": "@teamscala/service-boot",
578
+ "suite_type": "function_call",
579
+ "slug": "service-boot:build-resource-not-found-response-returns-a-200-response-for-the-bare-root"
580
+ },
581
+ {
582
+ "args": [
583
+ "project"
584
+ ],
585
+ "note": "The html copy claims stay hand-written: async body, structural then-steps only.",
586
+ "then": [
587
+ {
588
+ "call": "text"
589
+ }
590
+ ],
591
+ "label": "returns a 404 Response for a dead link",
592
+ "expect": {
593
+ "instance_of": "Response",
594
+ "member_equals": {
595
+ "status": 404
596
+ }
597
+ },
598
+ "export": "buildResourceNotFoundResponse",
599
+ "module": "src/resource-not-found.ts",
600
+ "package": "@teamscala/service-boot",
601
+ "suite_type": "function_call",
602
+ "slug": "service-boot:build-resource-not-found-response-returns-a-404-response-for-a-dead-link-project"
603
+ },
604
+ {
605
+ "args": [
606
+ {
607
+ "code": "UNKNOWN",
608
+ "http": {
609
+ "body": {},
610
+ "status": 500,
611
+ "headers": {}
612
+ },
613
+ "name": "TypeError",
614
+ "errorId": "xyz-789",
615
+ "message": "cannot read properties of undefined",
616
+ "stackHead": "",
617
+ "transient": false
618
+ }
619
+ ],
620
+ "note": "The html text claims (load-this-page wording, the real message shown so the operator has an explanation, errorId) stay hand-written: async body, structural then-steps only.",
621
+ "then": [
622
+ {
623
+ "args": [
624
+ "retry-after"
625
+ ],
626
+ "call": "headers.get",
627
+ "expect": null
628
+ },
629
+ {
630
+ "call": "text"
631
+ }
632
+ ],
633
+ "label": "hard error report → 500 HTML page, no Retry-After, error heading",
634
+ "expect": {
635
+ "instance_of": "Response",
636
+ "member_equals": {
637
+ "status": 500
638
+ }
639
+ },
640
+ "export": "buildServerErrorPageResponse",
641
+ "module": "src/server-error-page.ts",
642
+ "package": "@teamscala/service-boot",
643
+ "suite_type": "function_call",
644
+ "slug": "service-boot:build-server-error-page-response-hard-error-report-renders-500-without-retry-after"
645
+ },
646
+ {
647
+ "args": [
648
+ {
649
+ "code": "RENDER_TIMEOUT",
650
+ "http": {
651
+ "body": {},
652
+ "status": 503,
653
+ "headers": {}
654
+ },
655
+ "name": "SafeFallbackTimeoutError",
656
+ "reason": "render timed out under load",
657
+ "errorId": "abc-123",
658
+ "message": "safe-fallback exceeded 45000ms",
659
+ "stackHead": "",
660
+ "transient": true,
661
+ "retryAfter": 5
662
+ }
663
+ ],
664
+ "note": "The html text claims (taking-longer wording, absent load-this-page wording, errorId present) stay hand-written: the body lives behind the async Response.text() call and then-step expects carry the structural verbs only. errorId is present for browser-GlitchTip correlation.",
665
+ "then": [
666
+ {
667
+ "args": [
668
+ "content-type"
669
+ ],
670
+ "call": "headers.get",
671
+ "expect": "text/html; charset=utf-8"
672
+ },
673
+ {
674
+ "args": [
675
+ "retry-after"
676
+ ],
677
+ "call": "headers.get",
678
+ "expect": "5"
679
+ },
680
+ {
681
+ "args": [
682
+ "cache-control"
683
+ ],
684
+ "call": "headers.get",
685
+ "expect": "no-store, no-transform"
686
+ },
687
+ {
688
+ "call": "text"
689
+ }
690
+ ],
691
+ "label": "transient report → 503 HTML page with Retry-After + transient heading + errorId",
692
+ "expect": {
693
+ "instance_of": "Response",
694
+ "member_equals": {
695
+ "status": 503
696
+ }
697
+ },
698
+ "export": "buildServerErrorPageResponse",
699
+ "module": "src/server-error-page.ts",
700
+ "package": "@teamscala/service-boot",
701
+ "suite_type": "function_call",
702
+ "slug": "service-boot:build-server-error-page-response-transient-report-renders-503-with-retry-after"
703
+ },
704
+ {
705
+ "args": [],
706
+ "label": "an EMPTY registry block list falls back to the default shell",
707
+ "expect": [
708
+ {
709
+ "type": "Text",
710
+ "props": {
711
+ "id": "agreement-title",
712
+ "size": "xl",
713
+ "text": "{{agreement.name}}",
714
+ "align": "left",
715
+ "weight": "bold",
716
+ "element": "h1"
717
+ }
718
+ },
719
+ {
720
+ "type": "Text",
721
+ "props": {
722
+ "id": "agreement-execution",
723
+ "size": "sm",
724
+ "text": "IN WITNESS WHEREOF, the parties have executed this Agreement as of the date(s) of signature below.",
725
+ "align": "left",
726
+ "weight": "normal",
727
+ "element": "p"
728
+ }
729
+ },
730
+ {
731
+ "type": "Container",
732
+ "props": {
733
+ "id": "agreement-signature-panel",
734
+ "gap": "md",
735
+ "layout": "grid",
736
+ "columns": 2,
737
+ "content": [
738
+ {
739
+ "type": "SignatureField",
740
+ "props": {
741
+ "id": "agreement-signature-field",
742
+ "label": ""
743
+ }
744
+ }
745
+ ],
746
+ "padding": "md",
747
+ "direction": "column",
748
+ "mobileBehavior": "stack"
749
+ }
750
+ },
751
+ {
752
+ "type": "Button",
753
+ "props": {
754
+ "id": "agreement-print",
755
+ "href": "",
756
+ "icon": "lucide:printer",
757
+ "size": "default",
758
+ "label": "Print",
759
+ "preset": "action-primary",
760
+ "target": "_self",
761
+ "fullWidth": false,
762
+ "pushRight": false,
763
+ "actionType": "print",
764
+ "borderColor": "var(--border-color-default)",
765
+ "borderWidth": "var(--border-width-default)",
766
+ "borderRadius": "var(--radius-md)"
767
+ }
768
+ },
769
+ {
770
+ "type": "Text",
771
+ "props": {
772
+ "id": "agreement-audit",
773
+ "size": "xs",
774
+ "text": "Secured electronic signature · {{agreement.org}}",
775
+ "align": "center",
776
+ "element": "p"
777
+ }
778
+ }
779
+ ],
780
+ "export": "buildSigningShellBlocks",
781
+ "module": "src/agreement-gate/signing-shell.ts",
782
+ "package": "@teamscala/service-boot",
783
+ "fixtures": {
784
+ "stubs": [
785
+ {
786
+ "export": "loadRegistryConfig",
787
+ "module": "@teamscala/db/registry/load-config",
788
+ "returns": {
789
+ "blocks": []
790
+ }
791
+ }
792
+ ]
793
+ },
794
+ "suite_type": "function_call",
795
+ "slug": "service-boot:build-signing-shell-blocks-an-empty-registry-block-list-falls-back-to-the-default-shell"
796
+ },
797
+ {
798
+ "args": [],
799
+ "label": "an unreadable registry row still renders — the hardcoded shell is the fallback",
800
+ "expect": [
801
+ {
802
+ "type": "Text",
803
+ "props": {
804
+ "id": "agreement-title",
805
+ "size": "xl",
806
+ "text": "{{agreement.name}}",
807
+ "align": "left",
808
+ "weight": "bold",
809
+ "element": "h1"
810
+ }
811
+ },
812
+ {
813
+ "type": "Text",
814
+ "props": {
815
+ "id": "agreement-execution",
816
+ "size": "sm",
817
+ "text": "IN WITNESS WHEREOF, the parties have executed this Agreement as of the date(s) of signature below.",
818
+ "align": "left",
819
+ "weight": "normal",
820
+ "element": "p"
821
+ }
822
+ },
823
+ {
824
+ "type": "Container",
825
+ "props": {
826
+ "id": "agreement-signature-panel",
827
+ "gap": "md",
828
+ "layout": "grid",
829
+ "columns": 2,
830
+ "content": [
831
+ {
832
+ "type": "SignatureField",
833
+ "props": {
834
+ "id": "agreement-signature-field",
835
+ "label": ""
836
+ }
837
+ }
838
+ ],
839
+ "padding": "md",
840
+ "direction": "column",
841
+ "mobileBehavior": "stack"
842
+ }
843
+ },
844
+ {
845
+ "type": "Button",
846
+ "props": {
847
+ "id": "agreement-print",
848
+ "href": "",
849
+ "icon": "lucide:printer",
850
+ "size": "default",
851
+ "label": "Print",
852
+ "preset": "action-primary",
853
+ "target": "_self",
854
+ "fullWidth": false,
855
+ "pushRight": false,
856
+ "actionType": "print",
857
+ "borderColor": "var(--border-color-default)",
858
+ "borderWidth": "var(--border-width-default)",
859
+ "borderRadius": "var(--radius-md)"
860
+ }
861
+ },
862
+ {
863
+ "type": "Text",
864
+ "props": {
865
+ "id": "agreement-audit",
866
+ "size": "xs",
867
+ "text": "Secured electronic signature · {{agreement.org}}",
868
+ "align": "center",
869
+ "element": "p"
870
+ }
871
+ }
872
+ ],
873
+ "export": "buildSigningShellBlocks",
874
+ "module": "src/agreement-gate/signing-shell.ts",
875
+ "package": "@teamscala/service-boot",
876
+ "fixtures": {
877
+ "stubs": [
878
+ {
879
+ "error": {
880
+ "$error": {
881
+ "args": [
882
+ "missing"
883
+ ],
884
+ "class": "Error"
885
+ }
886
+ },
887
+ "export": "loadRegistryConfig",
888
+ "module": "@teamscala/db/registry/load-config"
889
+ }
890
+ ]
891
+ },
892
+ "suite_type": "function_call",
893
+ "slug": "service-boot:build-signing-shell-blocks-an-unreadable-registry-row-still-renders-the-default-shell"
894
+ },
895
+ {
896
+ "args": [],
897
+ "note": "The mutation-isolation half (the band mutates the first call's tree and reads the second) stays hand-written: it needs an in-test mutation between two calls, which no row expresses.",
898
+ "label": "registry-configured blocks replace the default, deep-cloned per call",
899
+ "expect": [
900
+ {
901
+ "type": "Text",
902
+ "props": {
903
+ "id": "custom-clause",
904
+ "text": "Custom clause"
905
+ }
906
+ }
907
+ ],
908
+ "export": "buildSigningShellBlocks",
909
+ "module": "src/agreement-gate/signing-shell.ts",
910
+ "package": "@teamscala/service-boot",
911
+ "fixtures": {
912
+ "stubs": [
913
+ {
914
+ "export": "loadRegistryConfig",
915
+ "module": "@teamscala/db/registry/load-config",
916
+ "returns": {
917
+ "blocks": [
918
+ {
919
+ "type": "Text",
920
+ "props": {
921
+ "id": "custom-clause",
922
+ "text": "Custom clause"
923
+ }
924
+ }
925
+ ]
926
+ }
927
+ }
928
+ ]
929
+ },
930
+ "suite_type": "function_call",
931
+ "slug": "service-boot:build-signing-shell-blocks-registry-configured-blocks-replace-the-default"
932
+ },
933
+ {
934
+ "args": [
935
+ {
936
+ "websiteName": "scala Roadmap"
937
+ }
938
+ ],
939
+ "label": "app root with no subject renders the website name alone",
940
+ "expect": "scala Roadmap",
941
+ "export": "composePageTitle",
942
+ "module": "src/compose-page-title.ts",
943
+ "package": "@teamscala/service-boot",
944
+ "suite_type": "function_call",
945
+ "slug": "service-boot:compose-page-title-app-root-with-no-subject-renders-the-website-name-alone"
946
+ },
947
+ {
948
+ "args": [
949
+ {
950
+ "pageName": "chat",
951
+ "websiteName": "scala GPT",
952
+ "templateTitle": "Sales Agent — GBG Indo"
953
+ }
954
+ ],
955
+ "label": "curated resource template beats the default derivation",
956
+ "expect": "Sales Agent — GBG Indo",
957
+ "export": "composePageTitle",
958
+ "module": "src/compose-page-title.ts",
959
+ "package": "@teamscala/service-boot",
960
+ "suite_type": "function_call",
961
+ "slug": "service-boot:compose-page-title-curated-resource-template-beats-the-default-derivation"
962
+ },
963
+ {
964
+ "args": [
965
+ {
966
+ "pageName": "P",
967
+ "templateTitle": "T",
968
+ "organisationName": "GBG Indo"
969
+ },
970
+ {
971
+ "orgPrefix": true
972
+ }
973
+ ],
974
+ "label": "per-page override and curated template still win over the org prefix",
975
+ "expect": "T",
976
+ "export": "composePageTitle",
977
+ "module": "src/compose-page-title.ts",
978
+ "package": "@teamscala/service-boot",
979
+ "suite_type": "function_call",
980
+ "slug": "service-boot:compose-page-title-curated-template-still-wins-over-the-org-prefix"
981
+ },
982
+ {
983
+ "args": [
984
+ {
985
+ "pageName": "Dashboard",
986
+ "websiteName": "creata Portal"
987
+ }
988
+ ],
989
+ "label": "default derivation: '<website>: <subject>' (portal spec)",
990
+ "expect": "creata Portal: Dashboard",
991
+ "export": "composePageTitle",
992
+ "module": "src/compose-page-title.ts",
993
+ "package": "@teamscala/service-boot",
994
+ "suite_type": "function_call",
995
+ "slug": "service-boot:compose-page-title-default-derivation-website-colon-subject"
996
+ },
997
+ {
998
+ "args": [
999
+ {
1000
+ "pageName": "view",
1001
+ "entityTitle": "Q3 Proposal",
1002
+ "websiteName": "scala Portal"
1003
+ }
1004
+ ],
1005
+ "label": "entity title is the preferred subject over page name",
1006
+ "expect": "scala Portal: Q3 Proposal",
1007
+ "export": "composePageTitle",
1008
+ "module": "src/compose-page-title.ts",
1009
+ "package": "@teamscala/service-boot",
1010
+ "suite_type": "function_call",
1011
+ "slug": "service-boot:compose-page-title-entity-title-is-the-preferred-subject-over-page-name"
1012
+ },
1013
+ {
1014
+ "args": [
1015
+ {
1016
+ "pageName": "Dashboard",
1017
+ "websiteName": "Public Pages",
1018
+ "organisationName": "GBG Indo"
1019
+ }
1020
+ ],
1021
+ "label": "flag off keeps the legacy website-name derivation",
1022
+ "expect": "Public Pages: Dashboard",
1023
+ "export": "composePageTitle",
1024
+ "module": "src/compose-page-title.ts",
1025
+ "package": "@teamscala/service-boot",
1026
+ "suite_type": "function_call",
1027
+ "slug": "service-boot:compose-page-title-flag-absent-keeps-the-legacy-website-name-derivation"
1028
+ },
1029
+ {
1030
+ "args": [
1031
+ {
1032
+ "pageName": "Dashboard",
1033
+ "websiteName": "Public Pages",
1034
+ "organisationName": "GBG Indo"
1035
+ },
1036
+ {
1037
+ "orgPrefix": false
1038
+ }
1039
+ ],
1040
+ "label": "flag off keeps the legacy website-name derivation",
1041
+ "expect": "Public Pages: Dashboard",
1042
+ "export": "composePageTitle",
1043
+ "module": "src/compose-page-title.ts",
1044
+ "package": "@teamscala/service-boot",
1045
+ "suite_type": "function_call",
1046
+ "slug": "service-boot:compose-page-title-flag-off-keeps-the-legacy-website-name-derivation"
1047
+ },
1048
+ {
1049
+ "args": [
1050
+ {
1051
+ "organisationName": "GBG Indo"
1052
+ },
1053
+ {
1054
+ "orgPrefix": true
1055
+ }
1056
+ ],
1057
+ "label": "no subject renders the org name alone; nothing at all is 'Untitled'",
1058
+ "expect": "GBG Indo",
1059
+ "export": "composePageTitle",
1060
+ "module": "src/compose-page-title.ts",
1061
+ "package": "@teamscala/service-boot",
1062
+ "suite_type": "function_call",
1063
+ "slug": "service-boot:compose-page-title-no-subject-renders-the-org-name-alone"
1064
+ },
1065
+ {
1066
+ "args": [
1067
+ {
1068
+ "websiteName": ""
1069
+ }
1070
+ ],
1071
+ "note": "The regression: a default titleTemplate of {org.name} produced GBG Indo with no context. The composer structurally cannot.",
1072
+ "label": "never degrades to a bare org name — no website + no subject is 'Untitled'",
1073
+ "expect": "Untitled",
1074
+ "export": "composePageTitle",
1075
+ "module": "src/compose-page-title.ts",
1076
+ "package": "@teamscala/service-boot",
1077
+ "suite_type": "function_call",
1078
+ "slug": "service-boot:compose-page-title-no-website-and-no-subject-is-untitled-blank-website-name"
1079
+ },
1080
+ {
1081
+ "args": [
1082
+ {}
1083
+ ],
1084
+ "note": "The regression: a default titleTemplate of {org.name} produced GBG Indo with no context. The composer structurally cannot.",
1085
+ "label": "never degrades to a bare org name — no website + no subject is 'Untitled'",
1086
+ "expect": "Untitled",
1087
+ "export": "composePageTitle",
1088
+ "module": "src/compose-page-title.ts",
1089
+ "package": "@teamscala/service-boot",
1090
+ "suite_type": "function_call",
1091
+ "slug": "service-boot:compose-page-title-no-website-and-no-subject-is-untitled-empty-context"
1092
+ },
1093
+ {
1094
+ "args": [
1095
+ {}
1096
+ ],
1097
+ "label": "no subject renders the org name alone; nothing at all is 'Untitled'",
1098
+ "expect": "Untitled",
1099
+ "export": "composePageTitle",
1100
+ "module": "src/compose-page-title.ts",
1101
+ "package": "@teamscala/service-boot",
1102
+ "suite_type": "function_call",
1103
+ "slug": "service-boot:compose-page-title-nothing-at-all-with-org-prefix-is-untitled"
1104
+ },
1105
+ {
1106
+ "args": [
1107
+ {
1108
+ "entityTitle": "Launcha Blueprint",
1109
+ "websiteName": "Public Pages",
1110
+ "organisationName": "GBG Indo"
1111
+ },
1112
+ {
1113
+ "orgPrefix": true
1114
+ }
1115
+ ],
1116
+ "note": "The defect: client-facing document tabs read Public Pages: <subject>. The orgPrefix flag exists to remove it.",
1117
+ "label": "prefix is the owning org's name, never the internal website label",
1118
+ "expect": "GBG Indo: Launcha Blueprint",
1119
+ "export": "composePageTitle",
1120
+ "module": "src/compose-page-title.ts",
1121
+ "package": "@teamscala/service-boot",
1122
+ "suite_type": "function_call",
1123
+ "slug": "service-boot:compose-page-title-org-prefix-is-the-owning-orgs-name-never-the-internal-website-label"
1124
+ },
1125
+ {
1126
+ "args": [
1127
+ {
1128
+ "entityTitle": "Launcha Blueprint",
1129
+ "websiteName": "Public Pages",
1130
+ "organisationName": ""
1131
+ },
1132
+ {
1133
+ "orgPrefix": true
1134
+ }
1135
+ ],
1136
+ "label": "org with no display name gets NO prefix — never the website name",
1137
+ "expect": "Launcha Blueprint",
1138
+ "export": "composePageTitle",
1139
+ "module": "src/compose-page-title.ts",
1140
+ "package": "@teamscala/service-boot",
1141
+ "suite_type": "function_call",
1142
+ "slug": "service-boot:compose-page-title-org-with-no-display-name-gets-no-prefix-blank-organisation-name"
1143
+ },
1144
+ {
1145
+ "args": [
1146
+ {
1147
+ "entityTitle": "Launcha Blueprint",
1148
+ "websiteName": "Public Pages"
1149
+ },
1150
+ {
1151
+ "orgPrefix": true
1152
+ }
1153
+ ],
1154
+ "label": "org with no display name gets NO prefix — never the website name",
1155
+ "expect": "Launcha Blueprint",
1156
+ "export": "composePageTitle",
1157
+ "module": "src/compose-page-title.ts",
1158
+ "package": "@teamscala/service-boot",
1159
+ "suite_type": "function_call",
1160
+ "slug": "service-boot:compose-page-title-org-with-no-display-name-gets-no-prefix-organisation-name-absent"
1161
+ },
1162
+ {
1163
+ "args": [
1164
+ {
1165
+ "pageName": "P",
1166
+ "websiteName": "W",
1167
+ "pageMetaTitle": "Override",
1168
+ "templateTitle": "Template"
1169
+ }
1170
+ ],
1171
+ "label": "override beats template",
1172
+ "expect": "Override",
1173
+ "export": "composePageTitle",
1174
+ "module": "src/compose-page-title.ts",
1175
+ "package": "@teamscala/service-boot",
1176
+ "suite_type": "function_call",
1177
+ "slug": "service-boot:compose-page-title-override-beats-template"
1178
+ },
1179
+ {
1180
+ "args": [
1181
+ {
1182
+ "pageName": "Dashboard",
1183
+ "websiteName": "creata Portal",
1184
+ "pageMetaTitle": "Custom SEO Title"
1185
+ }
1186
+ ],
1187
+ "label": "per-page meta_title override wins outright",
1188
+ "expect": "Custom SEO Title",
1189
+ "export": "composePageTitle",
1190
+ "module": "src/compose-page-title.ts",
1191
+ "package": "@teamscala/service-boot",
1192
+ "suite_type": "function_call",
1193
+ "slug": "service-boot:compose-page-title-per-page-meta-title-override-wins-outright"
1194
+ },
1195
+ {
1196
+ "args": [
1197
+ {
1198
+ "pageName": "P",
1199
+ "pageMetaTitle": "Override",
1200
+ "organisationName": "GBG Indo"
1201
+ },
1202
+ {
1203
+ "orgPrefix": true
1204
+ }
1205
+ ],
1206
+ "label": "per-page override and curated template still win over the org prefix",
1207
+ "expect": "Override",
1208
+ "export": "composePageTitle",
1209
+ "module": "src/compose-page-title.ts",
1210
+ "package": "@teamscala/service-boot",
1211
+ "suite_type": "function_call",
1212
+ "slug": "service-boot:compose-page-title-per-page-override-still-wins-over-the-org-prefix"
1213
+ },
1214
+ {
1215
+ "args": [
1216
+ {
1217
+ "pageName": "Dashboard"
1218
+ }
1219
+ ],
1220
+ "label": "subject without a website name renders the subject alone",
1221
+ "expect": "Dashboard",
1222
+ "export": "composePageTitle",
1223
+ "module": "src/compose-page-title.ts",
1224
+ "package": "@teamscala/service-boot",
1225
+ "suite_type": "function_call",
1226
+ "slug": "service-boot:compose-page-title-subject-without-a-website-name-renders-the-subject-alone"
1227
+ },
1228
+ {
1229
+ "args": [
1230
+ {
1231
+ "pageName": "Dashboard",
1232
+ "websiteName": "creata Portal",
1233
+ "pageMetaTitle": " "
1234
+ }
1235
+ ],
1236
+ "label": "whitespace-only meta_title is not treated as an override",
1237
+ "expect": "creata Portal: Dashboard",
1238
+ "export": "composePageTitle",
1239
+ "module": "src/compose-page-title.ts",
1240
+ "package": "@teamscala/service-boot",
1241
+ "suite_type": "function_call",
1242
+ "slug": "service-boot:compose-page-title-whitespace-only-meta-title-is-not-treated-as-an-override"
1243
+ },
1244
+ {
1245
+ "args": [],
1246
+ "note": "Carries the band's order test (proposals evaluate before agreements), the open-capture test (gpt withholds nothing, so it is absent from this list) and the allow-list test (proposal and agreement withhold). The slug-uniqueness and access-cookie-pairing invariants over the catalog stay hand-written: they are call-free claims over module state, not a call's return.",
1247
+ "label": "exposes only the withholding gates as the assistant's authority",
1248
+ "expect": {
1249
+ "member_equals": {
1250
+ "0.slug": "proposal",
1251
+ "1.slug": "agreement",
1252
+ "length": 2
1253
+ }
1254
+ },
1255
+ "export": "contentWithholdingGates",
1256
+ "module": "src/content-gate/catalog.ts",
1257
+ "package": "@teamscala/service-boot",
1258
+ "suite_type": "function_call",
1259
+ "slug": "service-boot:content-withholding-gates-resolves-the-withholding-gates-in-order"
1260
+ },
1261
+ {
1262
+ "args": [
1263
+ {
1264
+ "page": null,
1265
+ "hasResourceType": false,
1266
+ "hasPageContentSource": true
1267
+ }
1268
+ ],
1269
+ "note": "The call returns a PrimaryResourceMissingError; the class identity is carried by its own member triple (resourceType/httpStatus/empty) because instance_of names globalThis constructors only.",
1270
+ "label": "decideContentPageFloor: no page row → dead-link 404 floor (the /roadmap case)",
1271
+ "expect": {
1272
+ "member_equals": {
1273
+ "empty": false,
1274
+ "httpStatus": 404,
1275
+ "resourceType": "page"
1276
+ }
1277
+ },
1278
+ "export": "decideContentPageFloor",
1279
+ "module": "src/content-page-floor.ts",
1280
+ "package": "@teamscala/service-boot",
1281
+ "suite_type": "function_call",
1282
+ "slug": "service-boot:decide-content-page-floor-no-page-row-is-the-dead-link-404-floor"
1283
+ },
1284
+ {
1285
+ "args": [
1286
+ {
1287
+ "page": null,
1288
+ "hasResourceType": false,
1289
+ "hasPageContentSource": false
1290
+ }
1291
+ ],
1292
+ "label": "decideContentPageFloor: no page source (region-slot shell) → null (untouched)",
1293
+ "expect": null,
1294
+ "export": "decideContentPageFloor",
1295
+ "module": "src/content-page-floor.ts",
1296
+ "package": "@teamscala/service-boot",
1297
+ "suite_type": "function_call",
1298
+ "slug": "service-boot:decide-content-page-floor-no-page-source-region-slot-shell-is-null"
1299
+ },
1300
+ {
1301
+ "args": [
1302
+ {
1303
+ "page": {
1304
+ "id": "p1",
1305
+ "puck_data": {
1306
+ "content": [
1307
+ {
1308
+ "type": "Text",
1309
+ "props": {}
1310
+ }
1311
+ ]
1312
+ }
1313
+ },
1314
+ "hasResourceType": false,
1315
+ "hasPageContentSource": true
1316
+ }
1317
+ ],
1318
+ "label": "decideContentPageFloor: page row with blocks → null (renders normally)",
1319
+ "expect": null,
1320
+ "export": "decideContentPageFloor",
1321
+ "module": "src/content-page-floor.ts",
1322
+ "package": "@teamscala/service-boot",
1323
+ "suite_type": "function_call",
1324
+ "slug": "service-boot:decide-content-page-floor-page-row-with-blocks-renders-normally"
1325
+ },
1326
+ {
1327
+ "args": [
1328
+ {
1329
+ "page": {
1330
+ "id": "p1",
1331
+ "puck_data": {
1332
+ "root": {
1333
+ "props": {}
1334
+ },
1335
+ "content": []
1336
+ }
1337
+ },
1338
+ "hasResourceType": false,
1339
+ "hasPageContentSource": true
1340
+ }
1341
+ ],
1342
+ "label": "decideContentPageFloor: page row with zero blocks → empty-page 200 floor",
1343
+ "expect": {
1344
+ "member_equals": {
1345
+ "empty": true,
1346
+ "httpStatus": 200,
1347
+ "resourceType": "page"
1348
+ }
1349
+ },
1350
+ "export": "decideContentPageFloor",
1351
+ "module": "src/content-page-floor.ts",
1352
+ "package": "@teamscala/service-boot",
1353
+ "suite_type": "function_call",
1354
+ "slug": "service-boot:decide-content-page-floor-page-row-with-zero-blocks-is-the-empty-page-200-floor"
1355
+ },
1356
+ {
1357
+ "args": [
1358
+ {
1359
+ "page": null,
1360
+ "hasResourceType": true,
1361
+ "hasPageContentSource": true
1362
+ }
1363
+ ],
1364
+ "label": "decideContentPageFloor: resource_type route → null (handled by the resource-type check)",
1365
+ "expect": null,
1366
+ "export": "decideContentPageFloor",
1367
+ "module": "src/content-page-floor.ts",
1368
+ "package": "@teamscala/service-boot",
1369
+ "suite_type": "function_call",
1370
+ "slug": "service-boot:decide-content-page-floor-resource-type-route-is-null"
1371
+ },
1372
+ {
1373
+ "args": [
1374
+ {
1375
+ "sources": [
1376
+ {
1377
+ "key": "page"
1378
+ }
1379
+ ]
1380
+ }
1381
+ ],
1382
+ "label": "an absent list renders as none, never an empty bracket pair",
1383
+ "expect": "captured at boot: sources [page], region_slots [none] — resource_loader edits reach this service only after a restart",
1384
+ "export": "describeCapturedLoaderConfig",
1385
+ "module": "src/register-registry-page-route/captured-loader-config.ts",
1386
+ "package": "@teamscala/service-boot",
1387
+ "suite_type": "function_call",
1388
+ "slug": "service-boot:describe-captured-loader-config-an-absent-list-renders-as-none"
1389
+ },
1390
+ {
1391
+ "args": [
1392
+ {
1393
+ "sources": [
1394
+ {
1395
+ "key": "brand"
1396
+ },
1397
+ {
1398
+ "key": "website"
1399
+ },
1400
+ {
1401
+ "key": "footer"
1402
+ }
1403
+ ],
1404
+ "region_slots": [
1405
+ "header",
1406
+ "center",
1407
+ "footer"
1408
+ ]
1409
+ }
1410
+ ],
1411
+ "label": "names every captured source key and region slot, and states the restart contract",
1412
+ "expect": "captured at boot: sources [brand, website, footer], region_slots [header, center, footer] — resource_loader edits reach this service only after a restart",
1413
+ "export": "describeCapturedLoaderConfig",
1414
+ "module": "src/register-registry-page-route/captured-loader-config.ts",
1415
+ "package": "@teamscala/service-boot",
1416
+ "suite_type": "function_call",
1417
+ "slug": "service-boot:describe-captured-loader-config-names-every-source-key-and-region-slot-and-states-the-restart-contract"
1418
+ },
1419
+ {
1420
+ "args": [
1421
+ "/"
1422
+ ],
1423
+ "label": "empty / malformed → undefined",
1424
+ "expect": {
1425
+ "is_undefined": true
1426
+ },
1427
+ "export": "extractOrgIdFromCallbackPath",
1428
+ "module": "src/resolvers/portal-route-paths.ts",
1429
+ "package": "@teamscala/service-boot",
1430
+ "suite_type": "function_call",
1431
+ "slug": "service-boot:extract-org-id-from-callback-path-bare-slash-is-undefined"
1432
+ },
1433
+ {
1434
+ "args": [
1435
+ "/a9a28515-4ad5-405c-a74d-bb83fed079d0/5b742740-0f37-494c-a059-d8399ae4b350/dashboard"
1436
+ ],
1437
+ "note": "The violating behaviour this locks out returned the WEBSITE id (segment 0) → brand resolved no org → fell back to super-admin.",
1438
+ "label": "canonical portal shape /<websiteId>/<orgId>/<path> → ORG at segment 1 (not the website id at segment 0)",
1439
+ "expect": "5b742740-0f37-494c-a059-d8399ae4b350",
1440
+ "export": "extractOrgIdFromCallbackPath",
1441
+ "module": "src/resolvers/portal-route-paths.ts",
1442
+ "package": "@teamscala/service-boot",
1443
+ "suite_type": "function_call",
1444
+ "slug": "service-boot:extract-org-id-from-callback-path-canonical-portal-shape-resolves-the-org-at-segment-1"
1445
+ },
1446
+ {
1447
+ "args": [
1448
+ ""
1449
+ ],
1450
+ "label": "empty / malformed → undefined",
1451
+ "expect": {
1452
+ "is_undefined": true
1453
+ },
1454
+ "export": "extractOrgIdFromCallbackPath",
1455
+ "module": "src/resolvers/portal-route-paths.ts",
1456
+ "package": "@teamscala/service-boot",
1457
+ "suite_type": "function_call",
1458
+ "slug": "service-boot:extract-org-id-from-callback-path-empty-string-is-undefined"
1459
+ },
1460
+ {
1461
+ "args": [
1462
+ "/dashboard"
1463
+ ],
1464
+ "label": "non-UUID path → undefined (no brand override, falls back as before)",
1465
+ "expect": {
1466
+ "is_undefined": true
1467
+ },
1468
+ "export": "extractOrgIdFromCallbackPath",
1469
+ "module": "src/resolvers/portal-route-paths.ts",
1470
+ "package": "@teamscala/service-boot",
1471
+ "suite_type": "function_call",
1472
+ "slug": "service-boot:extract-org-id-from-callback-path-non-uuid-path-dashboard-is-undefined"
1473
+ },
1474
+ {
1475
+ "args": [
1476
+ "/sign-in"
1477
+ ],
1478
+ "label": "non-UUID path → undefined (no brand override, falls back as before)",
1479
+ "expect": {
1480
+ "is_undefined": true
1481
+ },
1482
+ "export": "extractOrgIdFromCallbackPath",
1483
+ "module": "src/resolvers/portal-route-paths.ts",
1484
+ "package": "@teamscala/service-boot",
1485
+ "suite_type": "function_call",
1486
+ "slug": "service-boot:extract-org-id-from-callback-path-non-uuid-path-sign-in-is-undefined"
1487
+ },
1488
+ {
1489
+ "args": [
1490
+ "/a9a28515-4ad5-405c-a74d-bb83fed079d0/5b742740-0f37-494c-a059-d8399ae4b350/dashboard?right=chat"
1491
+ ],
1492
+ "label": "query string is ignored",
1493
+ "expect": "5b742740-0f37-494c-a059-d8399ae4b350",
1494
+ "export": "extractOrgIdFromCallbackPath",
1495
+ "module": "src/resolvers/portal-route-paths.ts",
1496
+ "package": "@teamscala/service-boot",
1497
+ "suite_type": "function_call",
1498
+ "slug": "service-boot:extract-org-id-from-callback-path-query-string-is-ignored"
1499
+ },
1500
+ {
1501
+ "args": [
1502
+ "/019e9124-af4c-7000-bfaf-2ae97fb64772"
1503
+ ],
1504
+ "label": "proposal/form/quiz resource host /<resourceId> → segment 0 (non-org, resolves no brand, falls back)",
1505
+ "expect": "019e9124-af4c-7000-bfaf-2ae97fb64772",
1506
+ "export": "extractOrgIdFromCallbackPath",
1507
+ "module": "src/resolvers/portal-route-paths.ts",
1508
+ "package": "@teamscala/service-boot",
1509
+ "suite_type": "function_call",
1510
+ "slug": "service-boot:extract-org-id-from-callback-path-resource-host-single-uuid-segment-0"
1511
+ },
1512
+ {
1513
+ "args": [
1514
+ "/5b742740-0f37-494c-a059-d8399ae4b350/projects"
1515
+ ],
1516
+ "label": "scala-projects single-UUID shape /<orgId>/<path> → segment 0 (unchanged)",
1517
+ "expect": "5b742740-0f37-494c-a059-d8399ae4b350",
1518
+ "export": "extractOrgIdFromCallbackPath",
1519
+ "module": "src/resolvers/portal-route-paths.ts",
1520
+ "package": "@teamscala/service-boot",
1521
+ "suite_type": "function_call",
1522
+ "slug": "service-boot:extract-org-id-from-callback-path-scala-projects-single-uuid-shape-segment-0"
1523
+ },
1524
+ {
1525
+ "note": "The generated router shape is what matters, not mere key presence.",
1526
+ "hoist": [
1527
+ {
1528
+ "args": [
1529
+ {
1530
+ "assessments": {}
1531
+ }
1532
+ ],
1533
+ "export": "setServerClient"
1534
+ },
1535
+ {
1536
+ "args": [
1537
+ [
1538
+ "assessments"
1539
+ ]
1540
+ ],
1541
+ "export": "recordServerClientCapability"
1542
+ }
1543
+ ],
1544
+ "label": "a model present without findFirst still counts as missing",
1545
+ "expect": {
1546
+ "contains_text": [
1547
+ "assessments"
1548
+ ]
1549
+ },
1550
+ "export": "getServerClientCapabilityFault",
1551
+ "module": "src/page-server-orpc/server-client.ts",
1552
+ "package": "@teamscala/service-boot",
1553
+ "suite_type": "function_call",
1554
+ "slug": "service-boot:get-server-client-capability-fault-a-model-present-without-findfirst-still-counts-as-missing"
1555
+ },
1556
+ {
1557
+ "note": "Daemon/portal shells own no DB schema and are healthy with an empty client.",
1558
+ "hoist": [
1559
+ {
1560
+ "args": [
1561
+ {
1562
+ "puckPages": {}
1563
+ }
1564
+ ],
1565
+ "export": "setServerClient"
1566
+ },
1567
+ {
1568
+ "args": [
1569
+ []
1570
+ ],
1571
+ "export": "recordServerClientCapability"
1572
+ }
1573
+ ],
1574
+ "label": "a service declaring no models is never faulted",
1575
+ "expect": null,
1576
+ "export": "getServerClientCapabilityFault",
1577
+ "module": "src/page-server-orpc/server-client.ts",
1578
+ "package": "@teamscala/service-boot",
1579
+ "suite_type": "function_call",
1580
+ "slug": "service-boot:get-server-client-capability-fault-a-service-declaring-no-models-is-never-faulted"
1581
+ },
1582
+ {
1583
+ "hoist": [
1584
+ {
1585
+ "args": [
1586
+ null
1587
+ ],
1588
+ "export": "setServerClient"
1589
+ },
1590
+ {
1591
+ "args": [
1592
+ [
1593
+ "assessments"
1594
+ ]
1595
+ ],
1596
+ "export": "recordServerClientCapability"
1597
+ }
1598
+ ],
1599
+ "label": "an unregistered client is itself the fault",
1600
+ "expect": {
1601
+ "contains_text": [
1602
+ "no ORPC server client registered"
1603
+ ]
1604
+ },
1605
+ "export": "getServerClientCapabilityFault",
1606
+ "module": "src/page-server-orpc/server-client.ts",
1607
+ "package": "@teamscala/service-boot",
1608
+ "suite_type": "function_call",
1609
+ "slug": "service-boot:get-server-client-capability-fault-an-unregistered-client-is-itself-the-fault"
1610
+ },
1611
+ {
1612
+ "note": "THE OUTAGE, AS A HEALTH ANSWER. A client was registered and carried only the platform routers, so every process-existence signal was green while every data-backed page 500d. /health must be able to say this.",
1613
+ "hoist": [
1614
+ {
1615
+ "args": [
1616
+ {
1617
+ "puckPages": {},
1618
+ "userPreferences": {}
1619
+ }
1620
+ ],
1621
+ "export": "setServerClient"
1622
+ },
1623
+ {
1624
+ "args": [
1625
+ [
1626
+ "assessments",
1627
+ "assessment_responses"
1628
+ ]
1629
+ ],
1630
+ "export": "recordServerClientCapability"
1631
+ }
1632
+ ],
1633
+ "label": "names the models the client cannot serve",
1634
+ "expect": {
1635
+ "contains_text": [
1636
+ "assessments",
1637
+ "assessment_responses"
1638
+ ]
1639
+ },
1640
+ "export": "getServerClientCapabilityFault",
1641
+ "module": "src/page-server-orpc/server-client.ts",
1642
+ "package": "@teamscala/service-boot",
1643
+ "suite_type": "function_call",
1644
+ "slug": "service-boot:get-server-client-capability-fault-names-the-models-the-client-cannot-serve"
1645
+ },
1646
+ {
1647
+ "hoist": [
1648
+ {
1649
+ "args": [
1650
+ {
1651
+ "assessments": {
1652
+ "findFirst": {
1653
+ "$fn": {
1654
+ "returns": null
1655
+ }
1656
+ }
1657
+ },
1658
+ "assessment_responses": {
1659
+ "findFirst": {
1660
+ "$fn": {
1661
+ "returns": null
1662
+ }
1663
+ }
1664
+ }
1665
+ }
1666
+ ],
1667
+ "export": "setServerClient"
1668
+ },
1669
+ {
1670
+ "args": [
1671
+ [
1672
+ "assessments",
1673
+ "assessment_responses"
1674
+ ]
1675
+ ],
1676
+ "export": "recordServerClientCapability"
1677
+ }
1678
+ ],
1679
+ "label": "no fault when every declared model is servable",
1680
+ "expect": null,
1681
+ "export": "getServerClientCapabilityFault",
1682
+ "module": "src/page-server-orpc/server-client.ts",
1683
+ "package": "@teamscala/service-boot",
1684
+ "suite_type": "function_call",
1685
+ "slug": "service-boot:get-server-client-capability-fault-no-fault-when-every-declared-model-is-servable"
1686
+ },
1687
+ {
1688
+ "note": "The band asserts reference identity (toBe) across two calls; the row spells the shape that comes back, since the runner names no cross-call reference. The single module slot is the mechanism that makes them the same object.",
1689
+ "hoist": [
1690
+ {
1691
+ "args": [
1692
+ {
1693
+ "assessments": {
1694
+ "findFirst": {
1695
+ "$fn": {
1696
+ "returns": null
1697
+ }
1698
+ }
1699
+ }
1700
+ }
1701
+ ],
1702
+ "export": "setServerClient"
1703
+ }
1704
+ ],
1705
+ "label": "returns the registered client once boot sets one",
1706
+ "expect": {
1707
+ "member_is": {
1708
+ "assessments.findFirst": "function"
1709
+ }
1710
+ },
1711
+ "export": "getServerClient",
1712
+ "module": "src/page-server-orpc/server-client.ts",
1713
+ "package": "@teamscala/service-boot",
1714
+ "suite_type": "function_call",
1715
+ "slug": "service-boot:get-server-client-returns-the-registered-client-once-boot-sets-one"
1716
+ },
1717
+ {
1718
+ "note": "The old fallback returned a truthy client, so callers could not tell registration had never happened. Both band spellings (the no-registration message and the registerPageServerClient naming) are declared as the substrings the rejection must carry.",
1719
+ "hoist": [
1720
+ {
1721
+ "args": [
1722
+ null
1723
+ ],
1724
+ "export": "setServerClient"
1725
+ }
1726
+ ],
1727
+ "label": "throws rather than substituting an empty router when unregistered, and names the boot step responsible",
1728
+ "export": "getServerClient",
1729
+ "module": "src/page-server-orpc/server-client.ts",
1730
+ "package": "@teamscala/service-boot",
1731
+ "suite_type": "function_call",
1732
+ "expect_error": [
1733
+ "no ORPC server client registered",
1734
+ "registerPageServerClient"
1735
+ ],
1736
+ "slug": "service-boot:get-server-client-throws-rather-than-substituting-an-empty-router-when-unregistered"
1737
+ },
1738
+ {
1739
+ "args": [
1740
+ {
1741
+ "page": {
1742
+ "puck_data": {
1743
+ "content": [
1744
+ {
1745
+ "type": "Text",
1746
+ "props": {
1747
+ "id": "t1"
1748
+ }
1749
+ }
1750
+ ]
1751
+ }
1752
+ }
1753
+ }
1754
+ ],
1755
+ "label": "a page with no gate block reads as new-flow (no pre-placed gate)",
1756
+ "expect": false,
1757
+ "export": "hasPrePlacedGate",
1758
+ "module": "src/agreement-gate/signing-shell.ts",
1759
+ "package": "@teamscala/service-boot",
1760
+ "suite_type": "function_call",
1761
+ "slug": "service-boot:has-pre-placed-gate-a-page-with-no-gate-block-reads-as-new-flow"
1762
+ },
1763
+ {
1764
+ "args": [
1765
+ {
1766
+ "page": {
1767
+ "puck_data": {
1768
+ "content": [
1769
+ {
1770
+ "type": "SignIn",
1771
+ "props": {
1772
+ "mode": "gate",
1773
+ "gateContextField": "agreementId",
1774
+ "gateContextValue": "uuid-77"
1775
+ }
1776
+ }
1777
+ ]
1778
+ }
1779
+ }
1780
+ }
1781
+ ],
1782
+ "label": "a pre-placed SignIn gate block reads as an agreement gate",
1783
+ "expect": true,
1784
+ "export": "hasPrePlacedGate",
1785
+ "module": "src/agreement-gate/signing-shell.ts",
1786
+ "package": "@teamscala/service-boot",
1787
+ "suite_type": "function_call",
1788
+ "slug": "service-boot:has-pre-placed-gate-a-pre-placed-sign-in-gate-block-reads-as-an-agreement-gate"
1789
+ },
1790
+ {
1791
+ "args": [
1792
+ {
1793
+ "page": {
1794
+ "puck_data": {
1795
+ "content": [
1796
+ {
1797
+ "type": "SignIn",
1798
+ "props": {
1799
+ "mode": "gate",
1800
+ "gateContextField": "proposalId",
1801
+ "gateContextValue": "p1"
1802
+ }
1803
+ }
1804
+ ]
1805
+ }
1806
+ }
1807
+ }
1808
+ ],
1809
+ "label": "a PROPOSAL gate (proposalId context) is not an agreement gate",
1810
+ "expect": false,
1811
+ "export": "hasPrePlacedGate",
1812
+ "module": "src/agreement-gate/signing-shell.ts",
1813
+ "package": "@teamscala/service-boot",
1814
+ "suite_type": "function_call",
1815
+ "slug": "service-boot:has-pre-placed-gate-a-proposal-gate-is-not-an-agreement-gate"
1816
+ },
1817
+ {
1818
+ "args": [
1819
+ {
1820
+ "$error": {
1821
+ "args": [
1822
+ "Unexpected token"
1823
+ ],
1824
+ "class": "SyntaxError"
1825
+ }
1826
+ },
1827
+ "@teamscala/cli-session/mount.ts"
1828
+ ],
1829
+ "label": "does NOT swallow a syntax or runtime error",
1830
+ "expect": false,
1831
+ "export": "isModuleNotFound",
1832
+ "module": "src/module-not-found.ts",
1833
+ "package": "@teamscala/service-boot",
1834
+ "suite_type": "function_call",
1835
+ "slug": "service-boot:is-module-not-found-does-not-swallow-a-syntax-or-runtime-error"
1836
+ },
1837
+ {
1838
+ "args": [
1839
+ {
1840
+ "message": "Cannot find package '@teamscala/some-other-dep'"
1841
+ },
1842
+ "@teamscala/cli-session/mount.ts"
1843
+ ],
1844
+ "note": "A file inside the candidate failing to resolve something else must surface as a real error, or the true cause hides behind not-found.",
1845
+ "label": "does NOT swallow a transitive miss of a DIFFERENT module",
1846
+ "expect": false,
1847
+ "export": "isModuleNotFound",
1848
+ "module": "src/module-not-found.ts",
1849
+ "package": "@teamscala/service-boot",
1850
+ "suite_type": "function_call",
1851
+ "slug": "service-boot:is-module-not-found-does-not-swallow-a-transitive-miss-of-a-different-module"
1852
+ },
1853
+ {
1854
+ "args": [
1855
+ "Cannot find package '@teamscala/cli-session'",
1856
+ "@teamscala/cli-session/mount.ts"
1857
+ ],
1858
+ "label": "reads non-Error throwables defensively (Bun ResolveMessage is not an Error)",
1859
+ "expect": true,
1860
+ "export": "isModuleNotFound",
1861
+ "module": "src/module-not-found.ts",
1862
+ "package": "@teamscala/service-boot",
1863
+ "suite_type": "function_call",
1864
+ "slug": "service-boot:is-module-not-found-reads-non-error-throwables-defensively"
1865
+ },
1866
+ {
1867
+ "args": [
1868
+ {
1869
+ "message": "Cannot find module '@teamscala/x/mount.ts'"
1870
+ },
1871
+ "@teamscala/x/mount.ts"
1872
+ ],
1873
+ "label": "still matches when the error names the full specifier",
1874
+ "expect": true,
1875
+ "export": "isModuleNotFound",
1876
+ "module": "src/module-not-found.ts",
1877
+ "package": "@teamscala/service-boot",
1878
+ "suite_type": "function_call",
1879
+ "slug": "service-boot:is-module-not-found-still-matches-when-the-error-names-the-full-specifier"
1880
+ },
1881
+ {
1882
+ "args": [
1883
+ {
1884
+ "message": "Cannot find package '@teamscala/cli-session' imported from /srv/node_modules/@teamscala/service-boot/src/mount-server-packages.ts"
1885
+ },
1886
+ "@teamscala/cli-session/mount.ts"
1887
+ ],
1888
+ "note": "The exact shape Bun emits for an unexported subpath: it names the PACKAGE, never the subpath that was asked for.",
1889
+ "label": "treats an unexported subpath as not-found so the chain falls through",
1890
+ "expect": true,
1891
+ "export": "isModuleNotFound",
1892
+ "module": "src/module-not-found.ts",
1893
+ "package": "@teamscala/service-boot",
1894
+ "suite_type": "function_call",
1895
+ "slug": "service-boot:is-module-not-found-treats-an-unexported-subpath-as-not-found"
1896
+ },
1897
+ {
1898
+ "hoist": [
1899
+ {
1900
+ "args": [
1901
+ null
1902
+ ],
1903
+ "export": "setServerClient"
1904
+ }
1905
+ ],
1906
+ "label": "isServerClientRegistered tracks registration state (unregistered)",
1907
+ "expect": false,
1908
+ "export": "isServerClientRegistered",
1909
+ "module": "src/page-server-orpc/server-client.ts",
1910
+ "package": "@teamscala/service-boot",
1911
+ "suite_type": "function_call",
1912
+ "slug": "service-boot:is-server-client-registered-is-false-before-boot-registers"
1913
+ },
1914
+ {
1915
+ "hoist": [
1916
+ {
1917
+ "args": [
1918
+ {
1919
+ "x": 1
1920
+ }
1921
+ ],
1922
+ "export": "setServerClient"
1923
+ }
1924
+ ],
1925
+ "label": "isServerClientRegistered tracks registration state (registered)",
1926
+ "expect": true,
1927
+ "export": "isServerClientRegistered",
1928
+ "module": "src/page-server-orpc/server-client.ts",
1929
+ "package": "@teamscala/service-boot",
1930
+ "suite_type": "function_call",
1931
+ "slug": "service-boot:is-server-client-registered-is-true-after-a-client-is-set"
1932
+ },
1933
+ {
1934
+ "args": [
1935
+ "/assets/chunk-4efmn1eh.js"
1936
+ ],
1937
+ "label": "every asset kind a browser fetches without a session is public",
1938
+ "expect": true,
1939
+ "export": "isStaticAssetPath",
1940
+ "module": "src/auth-gate/public-paths.ts",
1941
+ "package": "@teamscala/service-boot",
1942
+ "suite_type": "function_call",
1943
+ "slug": "service-boot:is-static-asset-path-asset-kinds-a-browser-fetches-chunk-js"
1944
+ },
1945
+ {
1946
+ "args": [
1947
+ "/logos/dark.svg"
1948
+ ],
1949
+ "label": "every asset kind a browser fetches without a session is public",
1950
+ "expect": true,
1951
+ "export": "isStaticAssetPath",
1952
+ "module": "src/auth-gate/public-paths.ts",
1953
+ "package": "@teamscala/service-boot",
1954
+ "suite_type": "function_call",
1955
+ "slug": "service-boot:is-static-asset-path-asset-kinds-a-browser-fetches-dark-svg"
1956
+ },
1957
+ {
1958
+ "args": [
1959
+ "/favicon.ico"
1960
+ ],
1961
+ "label": "every asset kind a browser fetches without a session is public",
1962
+ "expect": true,
1963
+ "export": "isStaticAssetPath",
1964
+ "module": "src/auth-gate/public-paths.ts",
1965
+ "package": "@teamscala/service-boot",
1966
+ "suite_type": "function_call",
1967
+ "slug": "service-boot:is-static-asset-path-asset-kinds-a-browser-fetches-favicon-ico"
1968
+ },
1969
+ {
1970
+ "args": [
1971
+ "/img/hero.webp"
1972
+ ],
1973
+ "label": "every asset kind a browser fetches without a session is public",
1974
+ "expect": true,
1975
+ "export": "isStaticAssetPath",
1976
+ "module": "src/auth-gate/public-paths.ts",
1977
+ "package": "@teamscala/service-boot",
1978
+ "suite_type": "function_call",
1979
+ "slug": "service-boot:is-static-asset-path-asset-kinds-a-browser-fetches-hero-webp"
1980
+ },
1981
+ {
1982
+ "args": [
1983
+ "/fonts/inter.woff2"
1984
+ ],
1985
+ "label": "every asset kind a browser fetches without a session is public",
1986
+ "expect": true,
1987
+ "export": "isStaticAssetPath",
1988
+ "module": "src/auth-gate/public-paths.ts",
1989
+ "package": "@teamscala/service-boot",
1990
+ "suite_type": "function_call",
1991
+ "slug": "service-boot:is-static-asset-path-asset-kinds-a-browser-fetches-inter-woff2"
1992
+ },
1993
+ {
1994
+ "args": [
1995
+ "/styles/main.css"
1996
+ ],
1997
+ "label": "every asset kind a browser fetches without a session is public",
1998
+ "expect": true,
1999
+ "export": "isStaticAssetPath",
2000
+ "module": "src/auth-gate/public-paths.ts",
2001
+ "package": "@teamscala/service-boot",
2002
+ "suite_type": "function_call",
2003
+ "slug": "service-boot:is-static-asset-path-asset-kinds-a-browser-fetches-main-css"
2004
+ },
2005
+ {
2006
+ "args": [
2007
+ "/brand/mark.avif"
2008
+ ],
2009
+ "label": "every asset kind a browser fetches without a session is public",
2010
+ "expect": true,
2011
+ "export": "isStaticAssetPath",
2012
+ "module": "src/auth-gate/public-paths.ts",
2013
+ "package": "@teamscala/service-boot",
2014
+ "suite_type": "function_call",
2015
+ "slug": "service-boot:is-static-asset-path-asset-kinds-a-browser-fetches-mark-avif"
2016
+ },
2017
+ {
2018
+ "args": [
2019
+ "/logos/Company.PNG"
2020
+ ],
2021
+ "label": "case does not decide whether an image is reachable",
2022
+ "expect": true,
2023
+ "export": "isStaticAssetPath",
2024
+ "module": "src/auth-gate/public-paths.ts",
2025
+ "package": "@teamscala/service-boot",
2026
+ "suite_type": "function_call",
2027
+ "slug": "service-boot:is-static-asset-path-case-does-not-decide-reachability-png"
2028
+ },
2029
+ {
2030
+ "args": [
2031
+ "/logos/Mark.SVG"
2032
+ ],
2033
+ "label": "case does not decide whether an image is reachable",
2034
+ "expect": true,
2035
+ "export": "isStaticAssetPath",
2036
+ "module": "src/auth-gate/public-paths.ts",
2037
+ "package": "@teamscala/service-boot",
2038
+ "suite_type": "function_call",
2039
+ "slug": "service-boot:is-static-asset-path-case-does-not-decide-reachability-svg"
2040
+ },
2041
+ {
2042
+ "args": [
2043
+ "/dashboard"
2044
+ ],
2045
+ "label": "pages and APIs are still gated",
2046
+ "expect": false,
2047
+ "export": "isStaticAssetPath",
2048
+ "module": "src/auth-gate/public-paths.ts",
2049
+ "package": "@teamscala/service-boot",
2050
+ "suite_type": "function_call",
2051
+ "slug": "service-boot:is-static-asset-path-pages-and-apis-are-still-gated-dashboard"
2052
+ },
2053
+ {
2054
+ "args": [
2055
+ "/logos"
2056
+ ],
2057
+ "label": "pages and APIs are still gated",
2058
+ "expect": false,
2059
+ "export": "isStaticAssetPath",
2060
+ "module": "src/auth-gate/public-paths.ts",
2061
+ "package": "@teamscala/service-boot",
2062
+ "suite_type": "function_call",
2063
+ "slug": "service-boot:is-static-asset-path-pages-and-apis-are-still-gated-logos"
2064
+ },
2065
+ {
2066
+ "args": [
2067
+ "/png"
2068
+ ],
2069
+ "label": "pages and APIs are still gated",
2070
+ "expect": false,
2071
+ "export": "isStaticAssetPath",
2072
+ "module": "src/auth-gate/public-paths.ts",
2073
+ "package": "@teamscala/service-boot",
2074
+ "suite_type": "function_call",
2075
+ "slug": "service-boot:is-static-asset-path-pages-and-apis-are-still-gated-png"
2076
+ },
2077
+ {
2078
+ "args": [
2079
+ "/reports/quarterly.pdf"
2080
+ ],
2081
+ "label": "pages and APIs are still gated",
2082
+ "expect": false,
2083
+ "export": "isStaticAssetPath",
2084
+ "module": "src/auth-gate/public-paths.ts",
2085
+ "package": "@teamscala/service-boot",
2086
+ "suite_type": "function_call",
2087
+ "slug": "service-boot:is-static-asset-path-pages-and-apis-are-still-gated-quarterly-pdf"
2088
+ },
2089
+ {
2090
+ "args": [
2091
+ "/"
2092
+ ],
2093
+ "note": "The predicate widens what is PUBLIC, so its limit is the security-relevant half: pages and APIs must keep failing closed. A path is an asset because of its EXTENSION, never because it merely contains an asset-looking word.",
2094
+ "label": "pages and APIs are still gated",
2095
+ "expect": false,
2096
+ "export": "isStaticAssetPath",
2097
+ "module": "src/auth-gate/public-paths.ts",
2098
+ "package": "@teamscala/service-boot",
2099
+ "suite_type": "function_call",
2100
+ "slug": "service-boot:is-static-asset-path-pages-and-apis-are-still-gated-root"
2101
+ },
2102
+ {
2103
+ "args": [
2104
+ "/api/rpc/fn/workItems/list"
2105
+ ],
2106
+ "label": "pages and APIs are still gated",
2107
+ "expect": false,
2108
+ "export": "isStaticAssetPath",
2109
+ "module": "src/auth-gate/public-paths.ts",
2110
+ "package": "@teamscala/service-boot",
2111
+ "suite_type": "function_call",
2112
+ "slug": "service-boot:is-static-asset-path-pages-and-apis-are-still-gated-rpc-workitems"
2113
+ },
2114
+ {
2115
+ "args": [
2116
+ "/settings/logos"
2117
+ ],
2118
+ "label": "pages and APIs are still gated",
2119
+ "expect": false,
2120
+ "export": "isStaticAssetPath",
2121
+ "module": "src/auth-gate/public-paths.ts",
2122
+ "package": "@teamscala/service-boot",
2123
+ "suite_type": "function_call",
2124
+ "slug": "service-boot:is-static-asset-path-pages-and-apis-are-still-gated-settings-logos"
2125
+ },
2126
+ {
2127
+ "args": [
2128
+ "/logos/companyLogo.png"
2129
+ ],
2130
+ "label": "the logo that broke the signed-out screen is public",
2131
+ "expect": true,
2132
+ "export": "isStaticAssetPath",
2133
+ "module": "src/auth-gate/public-paths.ts",
2134
+ "package": "@teamscala/service-boot",
2135
+ "suite_type": "function_call",
2136
+ "slug": "service-boot:is-static-asset-path-the-logo-that-broke-the-signed-out-screen-companylogo-png"
2137
+ },
2138
+ {
2139
+ "args": [
2140
+ "/logos/cropped.png"
2141
+ ],
2142
+ "note": "Public paths were an ENUMERATED allowlist: /assets/ was on it, /logos/ never was, so /logos/cropped.png fell through to the session gate and answered 302 to /sign-in. A browser cannot act on a redirect it received for an <img>, so it painted nothing. Enumerating what is public makes every new asset private by default; a predicate makes that unrepresentable.",
2143
+ "label": "the logo that broke the signed-out screen is public",
2144
+ "expect": true,
2145
+ "export": "isStaticAssetPath",
2146
+ "module": "src/auth-gate/public-paths.ts",
2147
+ "package": "@teamscala/service-boot",
2148
+ "suite_type": "function_call",
2149
+ "slug": "service-boot:is-static-asset-path-the-logo-that-broke-the-signed-out-screen-cropped-png"
2150
+ },
2151
+ {
2152
+ "args": [
2153
+ {
2154
+ "key": "row-fixture-key",
2155
+ "authorization": "Bearer row-fixture-key"
2156
+ },
2157
+ ""
2158
+ ],
2159
+ "note": "THE ONE CALLER THAT GETS THROUGH. The internal service-to-service fetch the MCP gateway makes at boot: the configured key presented as a Bearer token, on a request carrying no forwarding header. The second arg position is a placeholder the one-parameter subject ignores, because the registry writer collapses an argument array shorter than two elements (measured 2026-09-30 while filing the @teamscala/orpc rows) so a one-argument row cannot be spelled. The key value is a fixture, not a credential: no secret row holds it and the production key arrives from the SCALA_DEV_KEY environment.",
2160
+ "expect": true,
2161
+ "export": "openApiContractAuthorised",
2162
+ "module": "src/orpc-openapi-gate.ts",
2163
+ "package": "@teamscala/service-boot",
2164
+ "suite_type": "function_call",
2165
+ "slug": "service-boot:openapi-contract-authorises-the-internal-key-holder"
2166
+ },
2167
+ {
2168
+ "args": [
2169
+ "scala-quiz",
2170
+ "",
2171
+ ""
2172
+ ],
2173
+ "note": "THE FALLBACKS, PINNED SO A MISSING HEADER CANNOT PRODUCE A MALFORMED URL. A request that names no Host and carries no forwarding header still gets a well-formed server entry (localhost, http) rather than an undefined host interpolated into the document as the string null. The title comes from the slug regardless - the service always names itself. The empty-string arg positions stand for absent headers: a JSON argument cannot spell undefined, and the subject reads absence through the same falsy branch an empty string takes.",
2174
+ "expect": {
2175
+ "member_equals": {
2176
+ "title": "scala-quiz oRPC procedures",
2177
+ "servers.0.url": "http://localhost/api/rpc"
2178
+ }
2179
+ },
2180
+ "export": "openApiContractOptions",
2181
+ "module": "src/orpc-openapi-document.ts",
2182
+ "package": "@teamscala/service-boot",
2183
+ "suite_type": "function_call",
2184
+ "slug": "service-boot:openapi-contract-falls-back-when-the-request-names-no-host"
2185
+ },
2186
+ {
2187
+ "args": [
2188
+ "scala-portal",
2189
+ "scala-portal.internal:5200",
2190
+ "http"
2191
+ ],
2192
+ "note": "THE DOCUMENT NAMES ITS SERVICE AND THE PREFIX IT SERVES. The title is the slug the mount was handed and the server URL is the host this request arrived on, with the /api/rpc prefix appended because that is the prefix the POST handler serves under - a client that reads the document can therefore call what the document describes. Deriving both rather than configuring them is what makes ONE document correct for the internal address the MCP gateway fetches and for a public host at the same time; the values are asserted exactly, so a change in either is a visible diff rather than a silently wrong server URL.",
2193
+ "expect": {
2194
+ "member_equals": {
2195
+ "title": "scala-portal oRPC procedures",
2196
+ "servers.0.url": "http://scala-portal.internal:5200/api/rpc"
2197
+ }
2198
+ },
2199
+ "export": "openApiContractOptions",
2200
+ "module": "src/orpc-openapi-document.ts",
2201
+ "package": "@teamscala/service-boot",
2202
+ "suite_type": "function_call",
2203
+ "slug": "service-boot:openapi-contract-names-the-service-and-the-prefix-it-serves"
2204
+ },
2205
+ {
2206
+ "args": [
2207
+ {
2208
+ "key": "row-fixture-key",
2209
+ "forwardedFor": "203.0.113.7",
2210
+ "authorization": "Bearer row-fixture-key",
2211
+ "forwardedProto": "https"
2212
+ },
2213
+ ""
2214
+ ],
2215
+ "note": "THE STATIC KEY IS NEVER A PUBLIC SOLE-GATE. Guard auth-helpers-fail-closed holds that a shared key is internal-only and names the remedy for a legitimate internal bearer check: also reject on proxy-header presence. This row is that remedy. The caller holds the right key and is still refused, because x-forwarded-proto and x-forwarded-for prove the request crossed a proxy, and on this platform only public ingress puts them there - an internal fetch, which is what the MCP gateway makes at boot, carries neither. Without this refusal the key alone would open the procedure surface to the public internet.",
2216
+ "expect": false,
2217
+ "export": "openApiContractAuthorised",
2218
+ "module": "src/orpc-openapi-gate.ts",
2219
+ "package": "@teamscala/service-boot",
2220
+ "suite_type": "function_call",
2221
+ "slug": "service-boot:openapi-contract-refuses-a-proxied-request"
2222
+ },
2223
+ {
2224
+ "args": [
2225
+ {
2226
+ "key": "row-fixture-key"
2227
+ },
2228
+ ""
2229
+ ],
2230
+ "note": "NO CREDENTIAL, NO DOCUMENT. A caller presenting no Authorization header is refused even though the service HAS a key configured, so the gate is not merely comparing a header to a value. The trailing empty-string arg position is a placeholder the one-parameter subject ignores: the registry writer collapses an argument array shorter than two elements (measured 2026-09-30 while filing the @teamscala/orpc rows), so a one-argument row cannot be spelled.",
2231
+ "expect": false,
2232
+ "export": "openApiContractAuthorised",
2233
+ "module": "src/orpc-openapi-gate.ts",
2234
+ "package": "@teamscala/service-boot",
2235
+ "suite_type": "function_call",
2236
+ "slug": "service-boot:openapi-contract-refuses-a-request-with-no-authorization"
2237
+ },
2238
+ {
2239
+ "args": [
2240
+ {
2241
+ "key": "row-fixture-key",
2242
+ "authorization": "Bearer not-the-configured-key"
2243
+ },
2244
+ ""
2245
+ ],
2246
+ "note": "THE NEAR-MISS. A Bearer token of the right shape carrying the wrong value is refused, which is the case a prefix check alone would wave through. Trailing arg position is a placeholder (see the no-authorization row for why).",
2247
+ "expect": false,
2248
+ "export": "openApiContractAuthorised",
2249
+ "module": "src/orpc-openapi-gate.ts",
2250
+ "package": "@teamscala/service-boot",
2251
+ "suite_type": "function_call",
2252
+ "slug": "service-boot:openapi-contract-refuses-a-wrong-key"
2253
+ },
2254
+ {
2255
+ "args": [
2256
+ {
2257
+ "authorization": "Bearer anything-at-all"
2258
+ },
2259
+ ""
2260
+ ],
2261
+ "note": "FAIL CLOSED WHEN THE SERVICE CANNOT GATE. No SCALA_DEV_KEY configured means there is no key to match, and a missing signal must DENY rather than admit every caller: a service that cannot authenticate must not serve the internal procedure surface. The key member is absent from the argument, which is exactly how an unconfigured environment reaches this subject. Trailing arg position is a placeholder.",
2262
+ "expect": false,
2263
+ "export": "openApiContractAuthorised",
2264
+ "module": "src/orpc-openapi-gate.ts",
2265
+ "package": "@teamscala/service-boot",
2266
+ "suite_type": "function_call",
2267
+ "slug": "service-boot:openapi-contract-refuses-when-no-key-is-configured"
2268
+ },
2269
+ {
2270
+ "args": [
2271
+ null
2272
+ ],
2273
+ "note": "The band calls pageBodyIsEmpty(null) and pageBodyIsEmpty(undefined); the runner spells an absent argument as null, which decodes to undefined, and the function treats both alike (!page).",
2274
+ "label": "pageBodyIsEmpty: absent page → false (not the empty-page case)",
2275
+ "expect": false,
2276
+ "export": "pageBodyIsEmpty",
2277
+ "module": "src/content-page-floor.ts",
2278
+ "package": "@teamscala/service-boot",
2279
+ "suite_type": "function_call",
2280
+ "slug": "service-boot:page-body-is-empty-absent-page-is-false"
2281
+ },
2282
+ {
2283
+ "args": [
2284
+ {
2285
+ "id": "p1",
2286
+ "puck_data": "{\"content\":[]}"
2287
+ }
2288
+ ],
2289
+ "label": "pageBodyIsEmpty: row with string puck_data (raw) — empty",
2290
+ "expect": true,
2291
+ "export": "pageBodyIsEmpty",
2292
+ "module": "src/content-page-floor.ts",
2293
+ "package": "@teamscala/service-boot",
2294
+ "suite_type": "function_call",
2295
+ "slug": "service-boot:page-body-is-empty-raw-string-puck-data-empty-content-is-empty"
2296
+ },
2297
+ {
2298
+ "args": [
2299
+ {
2300
+ "id": "p1",
2301
+ "puck_data": "{\"content\":[{\"type\":\"Text\"}]}"
2302
+ }
2303
+ ],
2304
+ "label": "pageBodyIsEmpty: row with string puck_data (raw) — non-empty",
2305
+ "expect": false,
2306
+ "export": "pageBodyIsEmpty",
2307
+ "module": "src/content-page-floor.ts",
2308
+ "package": "@teamscala/service-boot",
2309
+ "suite_type": "function_call",
2310
+ "slug": "service-boot:page-body-is-empty-raw-string-puck-data-with-blocks-is-not-empty"
2311
+ },
2312
+ {
2313
+ "args": [
2314
+ {
2315
+ "id": "p1",
2316
+ "puck_data": {
2317
+ "content": [
2318
+ {
2319
+ "type": "Hero"
2320
+ }
2321
+ ]
2322
+ }
2323
+ }
2324
+ ],
2325
+ "label": "pageBodyIsEmpty: row with content blocks → not empty",
2326
+ "expect": false,
2327
+ "export": "pageBodyIsEmpty",
2328
+ "module": "src/content-page-floor.ts",
2329
+ "package": "@teamscala/service-boot",
2330
+ "suite_type": "function_call",
2331
+ "slug": "service-boot:page-body-is-empty-row-with-content-blocks-is-not-empty"
2332
+ },
2333
+ {
2334
+ "args": [
2335
+ {
2336
+ "id": "p1",
2337
+ "puck_data": {
2338
+ "content": []
2339
+ }
2340
+ }
2341
+ ],
2342
+ "label": "pageBodyIsEmpty: row with empty content array → empty",
2343
+ "expect": true,
2344
+ "export": "pageBodyIsEmpty",
2345
+ "module": "src/content-page-floor.ts",
2346
+ "package": "@teamscala/service-boot",
2347
+ "suite_type": "function_call",
2348
+ "slug": "service-boot:page-body-is-empty-row-with-empty-content-array-is-empty"
2349
+ },
2350
+ {
2351
+ "args": [
2352
+ {
2353
+ "id": "p1"
2354
+ }
2355
+ ],
2356
+ "label": "pageBodyIsEmpty: row with no puck_data → empty",
2357
+ "expect": true,
2358
+ "export": "pageBodyIsEmpty",
2359
+ "module": "src/content-page-floor.ts",
2360
+ "package": "@teamscala/service-boot",
2361
+ "suite_type": "function_call",
2362
+ "slug": "service-boot:page-body-is-empty-row-with-no-puck-data-is-empty"
2363
+ },
2364
+ {
2365
+ "args": [
2366
+ [
2367
+ {
2368
+ "slot": "a",
2369
+ "pageId": "a-page",
2370
+ "puckData": {
2371
+ "root": {
2372
+ "props": {
2373
+ "title": ""
2374
+ }
2375
+ },
2376
+ "content": []
2377
+ }
2378
+ },
2379
+ {
2380
+ "slot": "b",
2381
+ "pageId": "b-page",
2382
+ "puckData": {
2383
+ "root": {
2384
+ "props": {
2385
+ "title": "winner"
2386
+ }
2387
+ },
2388
+ "content": []
2389
+ }
2390
+ },
2391
+ {
2392
+ "slot": "c",
2393
+ "pageId": "c-page",
2394
+ "puckData": {
2395
+ "root": {
2396
+ "props": {
2397
+ "title": "loser"
2398
+ }
2399
+ },
2400
+ "content": []
2401
+ }
2402
+ }
2403
+ ],
2404
+ "title"
2405
+ ],
2406
+ "label": "returns the FIRST region carrying a non-empty value",
2407
+ "expect": "winner",
2408
+ "export": "pickRootProp",
2409
+ "module": "src/register-registry-page-route/page-data-shared.ts",
2410
+ "package": "@teamscala/service-boot",
2411
+ "suite_type": "function_call",
2412
+ "slug": "service-boot:pick-root-prop-returns-the-first-region-carrying-a-non-empty-value"
2413
+ },
2414
+ {
2415
+ "args": [
2416
+ [
2417
+ {
2418
+ "slot": "a",
2419
+ "pageId": "a-page",
2420
+ "puckData": {}
2421
+ },
2422
+ {
2423
+ "slot": "b",
2424
+ "pageId": "b-page",
2425
+ "puckData": {
2426
+ "content": []
2427
+ }
2428
+ },
2429
+ {
2430
+ "slot": "c",
2431
+ "pageId": "c-page",
2432
+ "puckData": {
2433
+ "root": {
2434
+ "props": {
2435
+ "other": 1
2436
+ }
2437
+ },
2438
+ "content": []
2439
+ }
2440
+ }
2441
+ ],
2442
+ "title"
2443
+ ],
2444
+ "label": "skips regions without root props and returns undefined when nothing carries the key",
2445
+ "expect": {
2446
+ "is_undefined": true
2447
+ },
2448
+ "export": "pickRootProp",
2449
+ "module": "src/register-registry-page-route/page-data-shared.ts",
2450
+ "package": "@teamscala/service-boot",
2451
+ "suite_type": "function_call",
2452
+ "slug": "service-boot:pick-root-prop-skips-regions-without-root-props-and-resolves-undefined"
2453
+ },
2454
+ {
2455
+ "args": [
2456
+ "Inter, sans-serif"
2457
+ ],
2458
+ "label": "primaryFontFamily takes the first family of a stack",
2459
+ "expect": "Inter",
2460
+ "export": "primaryFontFamily",
2461
+ "module": "src/theme-fonts-link.ts",
2462
+ "package": "@teamscala/service-boot",
2463
+ "suite_type": "function_call",
2464
+ "slug": "service-boot:primary-font-family-takes-the-first-family-of-a-stack-inter"
2465
+ },
2466
+ {
2467
+ "args": [
2468
+ "'Playfair Display'"
2469
+ ],
2470
+ "label": "primaryFontFamily takes the first family of a stack (quotes stripped)",
2471
+ "expect": "Playfair Display",
2472
+ "export": "primaryFontFamily",
2473
+ "module": "src/theme-fonts-link.ts",
2474
+ "package": "@teamscala/service-boot",
2475
+ "suite_type": "function_call",
2476
+ "slug": "service-boot:primary-font-family-takes-the-first-family-of-a-stack-quoted-playfair"
2477
+ },
2478
+ {
2479
+ "args": [
2480
+ {
2481
+ "page": {
2482
+ "id": "page-1",
2483
+ "name": "The Launcha Authority Index",
2484
+ "puck_data": {
2485
+ "root": {
2486
+ "props": {
2487
+ "screenMode": "contained"
2488
+ }
2489
+ },
2490
+ "content": []
2491
+ }
2492
+ },
2493
+ "brand": {
2494
+ "companyName": "GMG APAC",
2495
+ "primaryColor": "#FF4500",
2496
+ "companyFriendlyName": null
2497
+ },
2498
+ "website": {
2499
+ "name": "launcha Website",
2500
+ "slug": "launcha-website"
2501
+ }
2502
+ },
2503
+ {},
2504
+ null,
2505
+ null
2506
+ ],
2507
+ "label": "a page declaring a non-full-screen mode emits fullScreen false",
2508
+ "expect": {
2509
+ "member_equals": {
2510
+ "theme": "light",
2511
+ "fullScreen": false,
2512
+ "meta.title": "launcha Website: The Launcha Authority Index"
2513
+ }
2514
+ },
2515
+ "export": "publicShellPageData",
2516
+ "module": "src/register-registry-page-route/public-shell-page-data.ts",
2517
+ "package": "@teamscala/service-boot",
2518
+ "suite_type": "function_call",
2519
+ "slug": "service-boot:public-shell-page-data-a-page-declaring-a-non-full-screen-mode-emits-fullscreen-false"
2520
+ },
2521
+ {
2522
+ "args": [
2523
+ {
2524
+ "page": {
2525
+ "id": "page-1",
2526
+ "name": "The Launcha Authority Index",
2527
+ "puck_data": {
2528
+ "root": {
2529
+ "props": {
2530
+ "screenMode": "full-screen"
2531
+ }
2532
+ },
2533
+ "content": []
2534
+ }
2535
+ },
2536
+ "brand": {
2537
+ "companyName": "GMG APAC",
2538
+ "primaryColor": "#FF4500",
2539
+ "companyFriendlyName": null
2540
+ },
2541
+ "website": {
2542
+ "name": "launcha Website",
2543
+ "slug": "launcha-website"
2544
+ }
2545
+ },
2546
+ {},
2547
+ null,
2548
+ null
2549
+ ],
2550
+ "note": "The renderer branches on this exact flag. Absent, build-page-tree wraps the body in a centred card and the header goes inside it.",
2551
+ "label": "a page declaring full-screen emits fullScreen true",
2552
+ "expect": {
2553
+ "member_equals": {
2554
+ "theme": "light",
2555
+ "fullScreen": true,
2556
+ "meta.title": "launcha Website: The Launcha Authority Index",
2557
+ "brand.primaryColor": "#FF4500",
2558
+ "brand.companyFriendlyName": null
2559
+ }
2560
+ },
2561
+ "export": "publicShellPageData",
2562
+ "module": "src/register-registry-page-route/public-shell-page-data.ts",
2563
+ "package": "@teamscala/service-boot",
2564
+ "suite_type": "function_call",
2565
+ "slug": "service-boot:public-shell-page-data-a-page-declaring-full-screen-emits-fullscreen-true"
2566
+ },
2567
+ {
2568
+ "args": [
2569
+ {
2570
+ "page": {
2571
+ "id": "page-1",
2572
+ "name": "The Launcha Authority Index",
2573
+ "puck_data": {
2574
+ "root": {
2575
+ "props": {}
2576
+ },
2577
+ "content": []
2578
+ }
2579
+ },
2580
+ "brand": {
2581
+ "companyName": "GMG APAC",
2582
+ "primaryColor": "#FF4500",
2583
+ "companyFriendlyName": null
2584
+ },
2585
+ "website": {
2586
+ "name": "launcha Website",
2587
+ "slug": "launcha-website"
2588
+ }
2589
+ },
2590
+ {},
2591
+ null,
2592
+ null
2593
+ ],
2594
+ "note": "Deliberately absent rather than false: an explicit false would override the public/gpts default and regress every page that never set the prop. The whole-value compare carries the absence: fullScreen:false would fail it, and toEqual treats an undefined member and an absent member alike.",
2595
+ "label": "a page declaring nothing omits the flag so the render-mode default still applies",
2596
+ "expect": {
2597
+ "meta": {
2598
+ "title": "launcha Website: The Launcha Authority Index"
2599
+ },
2600
+ "brand": {
2601
+ "logo": {
2602
+ "dark": null,
2603
+ "brand": null,
2604
+ "light": null
2605
+ },
2606
+ "favicon": null,
2607
+ "bodyFont": null,
2608
+ "mutedColor": null,
2609
+ "accentColor": null,
2610
+ "companyName": "GMG APAC",
2611
+ "darkSurface": null,
2612
+ "headingFont": null,
2613
+ "contactEmail": null,
2614
+ "lightSurface": null,
2615
+ "primaryColor": "#FF4500",
2616
+ "secondaryColor": null,
2617
+ "backgroundColor": null,
2618
+ "companyFriendlyName": null
2619
+ },
2620
+ "orgId": null,
2621
+ "theme": "light",
2622
+ "regions": [
2623
+ {
2624
+ "slot": "body",
2625
+ "pageId": "page-1",
2626
+ "puckData": {
2627
+ "root": {
2628
+ "props": {}
2629
+ },
2630
+ "content": []
2631
+ },
2632
+ "metaTitle": null,
2633
+ "metaDescription": null
2634
+ }
2635
+ ],
2636
+ "website": {
2637
+ "name": "launcha Website",
2638
+ "slug": "launcha-website",
2639
+ "header_settings": null,
2640
+ "organisation_id": null
2641
+ },
2642
+ "puckData": {
2643
+ "root": {
2644
+ "props": {}
2645
+ },
2646
+ "content": []
2647
+ },
2648
+ "loaderData": {
2649
+ "page": {
2650
+ "id": "page-1",
2651
+ "name": "The Launcha Authority Index",
2652
+ "puck_data": {
2653
+ "root": {
2654
+ "props": {}
2655
+ },
2656
+ "content": []
2657
+ }
2658
+ },
2659
+ "brand": {
2660
+ "companyName": "GMG APAC",
2661
+ "primaryColor": "#FF4500",
2662
+ "companyFriendlyName": null
2663
+ },
2664
+ "website": {
2665
+ "name": "launcha Website",
2666
+ "slug": "launcha-website"
2667
+ }
2668
+ }
2669
+ },
2670
+ "export": "publicShellPageData",
2671
+ "module": "src/register-registry-page-route/public-shell-page-data.ts",
2672
+ "package": "@teamscala/service-boot",
2673
+ "suite_type": "function_call",
2674
+ "slug": "service-boot:public-shell-page-data-a-page-declaring-nothing-omits-the-fullscreen-flag"
2675
+ },
2676
+ {
2677
+ "args": [
2678
+ {
2679
+ "page": {
2680
+ "id": "page-1",
2681
+ "name": "The Launcha Authority Index",
2682
+ "puck_data": {
2683
+ "root": {
2684
+ "props": {}
2685
+ },
2686
+ "content": []
2687
+ }
2688
+ },
2689
+ "brand": {
2690
+ "companyName": "GMG APAC",
2691
+ "primaryColor": "#FF4500",
2692
+ "companyFriendlyName": "launcha"
2693
+ },
2694
+ "website": {
2695
+ "name": "launcha Website",
2696
+ "slug": "launcha-website"
2697
+ }
2698
+ },
2699
+ {},
2700
+ null,
2701
+ true
2702
+ ],
2703
+ "note": "orgPrefix on: the prefix is the owning org's trading name; the legal entity name must not appear in the tab title.",
2704
+ "label": "the friendly name wins over the legal entity name",
2705
+ "expect": {
2706
+ "member_equals": {
2707
+ "meta.title": "launcha: The Launcha Authority Index"
2708
+ }
2709
+ },
2710
+ "export": "publicShellPageData",
2711
+ "module": "src/register-registry-page-route/public-shell-page-data.ts",
2712
+ "package": "@teamscala/service-boot",
2713
+ "suite_type": "function_call",
2714
+ "slug": "service-boot:public-shell-page-data-the-friendly-name-wins-over-the-legal-entity-name"
2715
+ },
2716
+ {
2717
+ "args": [
2718
+ {
2719
+ "page": {
2720
+ "id": "page-1",
2721
+ "name": "The Launcha Authority Index",
2722
+ "puck_data": {
2723
+ "root": {
2724
+ "props": {}
2725
+ },
2726
+ "content": []
2727
+ }
2728
+ },
2729
+ "brand": {
2730
+ "companyName": "GMG APAC",
2731
+ "primaryColor": "#FF4500",
2732
+ "companyFriendlyName": null
2733
+ },
2734
+ "website": {
2735
+ "name": "launcha Website",
2736
+ "slug": "launcha-website"
2737
+ }
2738
+ },
2739
+ {},
2740
+ null,
2741
+ true
2742
+ ],
2743
+ "label": "the legal name is still used when no friendly name is set",
2744
+ "expect": {
2745
+ "member_equals": {
2746
+ "meta.title": "GMG APAC: The Launcha Authority Index"
2747
+ }
2748
+ },
2749
+ "export": "publicShellPageData",
2750
+ "module": "src/register-registry-page-route/public-shell-page-data.ts",
2751
+ "package": "@teamscala/service-boot",
2752
+ "suite_type": "function_call",
2753
+ "slug": "service-boot:public-shell-page-data-the-legal-name-is-still-used-when-no-friendly-name-is-set"
2754
+ },
2755
+ {
2756
+ "args": [
2757
+ {}
2758
+ ],
2759
+ "note": "brandTheme is absent from the expect because the row leaves it undefined, and a toEqual compare treats absent and undefined alike.",
2760
+ "label": "a missing brand row degrades to nulls instead of throwing",
2761
+ "expect": {
2762
+ "logo": {
2763
+ "dark": null,
2764
+ "brand": null,
2765
+ "light": null
2766
+ },
2767
+ "brand": {},
2768
+ "bodyFont": null,
2769
+ "headingFont": null,
2770
+ "primaryColor": ""
2771
+ },
2772
+ "export": "readBrandTokens",
2773
+ "module": "src/register-registry-page-route/page-data-shared.ts",
2774
+ "package": "@teamscala/service-boot",
2775
+ "suite_type": "function_call",
2776
+ "slug": "service-boot:read-brand-tokens-a-missing-brand-row-degrades-to-nulls-instead-of-throwing"
2777
+ },
2778
+ {
2779
+ "args": [
2780
+ {
2781
+ "brand": {
2782
+ "theme": 7
2783
+ }
2784
+ }
2785
+ ],
2786
+ "note": "brandTheme stays undefined (absent from the expect under toEqual).",
2787
+ "label": "a non-string theme is ignored rather than passed through",
2788
+ "expect": {
2789
+ "logo": {
2790
+ "dark": null,
2791
+ "brand": null,
2792
+ "light": null
2793
+ },
2794
+ "brand": {
2795
+ "theme": 7
2796
+ },
2797
+ "bodyFont": null,
2798
+ "headingFont": null,
2799
+ "primaryColor": ""
2800
+ },
2801
+ "export": "readBrandTokens",
2802
+ "module": "src/register-registry-page-route/page-data-shared.ts",
2803
+ "package": "@teamscala/service-boot",
2804
+ "suite_type": "function_call",
2805
+ "slug": "service-boot:read-brand-tokens-a-non-string-theme-is-ignored-rather-than-passed-through"
2806
+ },
2807
+ {
2808
+ "args": [
2809
+ {
2810
+ "brand": {
2811
+ "logo": {
2812
+ "dark": "/d.svg",
2813
+ "brand": "/b.svg",
2814
+ "light": "/l.svg"
2815
+ },
2816
+ "theme": "dark",
2817
+ "bodyFont": "Sans B",
2818
+ "headingFont": "Serif A",
2819
+ "primaryColor": "#0055ff"
2820
+ }
2821
+ }
2822
+ ],
2823
+ "label": "maps a full brand row to every token the render branches read",
2824
+ "expect": {
2825
+ "logo": {
2826
+ "dark": "/d.svg",
2827
+ "brand": "/b.svg",
2828
+ "light": "/l.svg"
2829
+ },
2830
+ "brand": {
2831
+ "logo": {
2832
+ "dark": "/d.svg",
2833
+ "brand": "/b.svg",
2834
+ "light": "/l.svg"
2835
+ },
2836
+ "theme": "dark",
2837
+ "bodyFont": "Sans B",
2838
+ "headingFont": "Serif A",
2839
+ "primaryColor": "#0055ff"
2840
+ },
2841
+ "bodyFont": "Sans B",
2842
+ "brandTheme": "dark",
2843
+ "headingFont": "Serif A",
2844
+ "primaryColor": "#0055ff"
2845
+ },
2846
+ "export": "readBrandTokens",
2847
+ "module": "src/register-registry-page-route/page-data-shared.ts",
2848
+ "package": "@teamscala/service-boot",
2849
+ "suite_type": "function_call",
2850
+ "slug": "service-boot:read-brand-tokens-maps-a-full-brand-row-to-every-token-the-render-branches-read"
2851
+ },
2852
+ {
2853
+ "args": [
2854
+ "/assets/hydrate-9df3aab732.js"
2855
+ ],
2856
+ "label": "extracts the bare content hash from a manifest hydratePath",
2857
+ "expect": "9df3aab732",
2858
+ "export": "releaseFromHydratePath",
2859
+ "module": "src/build-client-assets/sourcemaps-upload.ts",
2860
+ "package": "@teamscala/service-boot",
2861
+ "suite_type": "function_call",
2862
+ "slug": "service-boot:release-from-hydrate-path-extracts-the-bare-content-hash-from-a-manifest-hydrate-path"
2863
+ },
2864
+ {
2865
+ "args": [
2866
+ "/assets/hydrate.js"
2867
+ ],
2868
+ "label": "non-hydrate paths yield null (no proximity guess)",
2869
+ "expect": null,
2870
+ "export": "releaseFromHydratePath",
2871
+ "module": "src/build-client-assets/sourcemaps-upload.ts",
2872
+ "package": "@teamscala/service-boot",
2873
+ "suite_type": "function_call",
2874
+ "slug": "service-boot:release-from-hydrate-path-non-hydrate-path-yields-null-hydrate-js"
2875
+ },
2876
+ {
2877
+ "args": [
2878
+ "/assets/styles-abc.css"
2879
+ ],
2880
+ "label": "non-hydrate paths yield null (no proximity guess)",
2881
+ "expect": null,
2882
+ "export": "releaseFromHydratePath",
2883
+ "module": "src/build-client-assets/sourcemaps-upload.ts",
2884
+ "package": "@teamscala/service-boot",
2885
+ "suite_type": "function_call",
2886
+ "slug": "service-boot:release-from-hydrate-path-non-hydrate-path-yields-null-styles-css"
2887
+ },
2888
+ {
2889
+ "args": [
2890
+ "/assets/hydrate-9df3aab73 2.js"
2891
+ ],
2892
+ "note": "A hash with uppercase chars, spaces, or non-hash content does not match.",
2893
+ "label": "rejects paths that look like hashes but are not served hydrate bundles",
2894
+ "expect": null,
2895
+ "export": "releaseFromHydratePath",
2896
+ "module": "src/build-client-assets/sourcemaps-upload.ts",
2897
+ "package": "@teamscala/service-boot",
2898
+ "suite_type": "function_call",
2899
+ "slug": "service-boot:release-from-hydrate-path-rejects-space-broken-hash-lookalike"
2900
+ },
2901
+ {
2902
+ "args": [
2903
+ "/assets/hydrate-9DF3AAB732.js"
2904
+ ],
2905
+ "note": "A hash with uppercase chars, spaces, or non-hash content does not match.",
2906
+ "label": "rejects paths that look like hashes but are not served hydrate bundles",
2907
+ "expect": null,
2908
+ "export": "releaseFromHydratePath",
2909
+ "module": "src/build-client-assets/sourcemaps-upload.ts",
2910
+ "package": "@teamscala/service-boot",
2911
+ "suite_type": "function_call",
2912
+ "slug": "service-boot:release-from-hydrate-path-rejects-uppercase-hash-lookalike"
2913
+ },
2914
+ {
2915
+ "args": [
2916
+ {
2917
+ "input": {
2918
+ "title": "Report",
2919
+ "row3Value": {
2920
+ "$date": "2026-08-25T15:46:58.698Z"
2921
+ }
2922
+ },
2923
+ "client": null,
2924
+ "params": {}
2925
+ }
2926
+ ],
2927
+ "label": "coerces Prisma Date values to ISO strings",
2928
+ "expect": {
2929
+ "title": "Report",
2930
+ "row1Label": null,
2931
+ "row1Value": null,
2932
+ "row2Label": null,
2933
+ "row2Value": null,
2934
+ "row3Label": null,
2935
+ "row3Value": "2026-08-25T15:46:58.698Z"
2936
+ },
2937
+ "export": "resolveAppHeader",
2938
+ "module": "src/resolvers/app-header.ts",
2939
+ "package": "@teamscala/service-boot",
2940
+ "suite_type": "function_call",
2941
+ "slug": "service-boot:resolve-app-header-coerces-prisma-date-values-to-iso-strings"
2942
+ },
2943
+ {
2944
+ "args": [
2945
+ {
2946
+ "input": {
2947
+ "row3Value": "today"
2948
+ },
2949
+ "client": null,
2950
+ "params": {}
2951
+ }
2952
+ ],
2953
+ "note": "The noon-UTC suffix is the invariant half. The band's other half (the ISO date equals today's AEST calendar date) needs the live clock and stays hand-written: a row pins no date.",
2954
+ "label": "expands the today directive to a noon-UTC instant of the AEST date",
2955
+ "expect": {
2956
+ "contains_in": {
2957
+ "path": "row3Value",
2958
+ "needles": [
2959
+ "T12:00:00.000Z"
2960
+ ]
2961
+ }
2962
+ },
2963
+ "export": "resolveAppHeader",
2964
+ "module": "src/resolvers/app-header.ts",
2965
+ "package": "@teamscala/service-boot",
2966
+ "suite_type": "function_call",
2967
+ "slug": "service-boot:resolve-app-header-expands-the-today-directive-to-a-noon-utc-instant"
2968
+ },
2969
+ {
2970
+ "args": [
2971
+ {
2972
+ "input": {
2973
+ "title": "Only a title"
2974
+ },
2975
+ "client": null,
2976
+ "params": {}
2977
+ }
2978
+ ],
2979
+ "label": "maps absent fields to null (the resource-not-blank contract: null, never a stale value)",
2980
+ "expect": {
2981
+ "title": "Only a title",
2982
+ "row1Label": null,
2983
+ "row1Value": null,
2984
+ "row2Label": null,
2985
+ "row2Value": null,
2986
+ "row3Label": null,
2987
+ "row3Value": null
2988
+ },
2989
+ "export": "resolveAppHeader",
2990
+ "module": "src/resolvers/app-header.ts",
2991
+ "package": "@teamscala/service-boot",
2992
+ "suite_type": "function_call",
2993
+ "slug": "service-boot:resolve-app-header-maps-absent-fields-to-null"
2994
+ },
2995
+ {
2996
+ "args": [
2997
+ {
2998
+ "input": {
2999
+ "title": "Anna's Proposal",
3000
+ "row1Label": "Prepared for",
3001
+ "row1Value": "Joe Bellissimo",
3002
+ "row2Label": "Organisation",
3003
+ "row2Value": "GMG APAC",
3004
+ "row3Label": "Date",
3005
+ "row3Value": "2026-09-03T00:00:00.000Z"
3006
+ },
3007
+ "client": null,
3008
+ "params": {}
3009
+ }
3010
+ ],
3011
+ "label": "passes interpolated values through as strings",
3012
+ "expect": {
3013
+ "title": "Anna's Proposal",
3014
+ "row1Label": "Prepared for",
3015
+ "row1Value": "Joe Bellissimo",
3016
+ "row2Label": "Organisation",
3017
+ "row2Value": "GMG APAC",
3018
+ "row3Label": "Date",
3019
+ "row3Value": "2026-09-03T00:00:00.000Z"
3020
+ },
3021
+ "export": "resolveAppHeader",
3022
+ "module": "src/resolvers/app-header.ts",
3023
+ "package": "@teamscala/service-boot",
3024
+ "suite_type": "function_call",
3025
+ "slug": "service-boot:resolve-app-header-passes-interpolated-values-through-as-strings"
3026
+ },
3027
+ {
3028
+ "args": [
3029
+ {
3030
+ "quiz": {
3031
+ "title": "The Launcha Authority Index"
3032
+ }
3033
+ }
3034
+ ],
3035
+ "label": "a quiz with no report name falls through to its title",
3036
+ "expect": "The Launcha Authority Index",
3037
+ "export": "resolveEntityTitle",
3038
+ "module": "src/register-registry-page-route/meta-title.ts",
3039
+ "package": "@teamscala/service-boot",
3040
+ "suite_type": "function_call",
3041
+ "slug": "service-boot:resolve-entity-title-a-quiz-with-no-report-name-falls-through-to-its-title"
3042
+ },
3043
+ {
3044
+ "args": [
3045
+ {
3046
+ "quiz": {
3047
+ "title": "The Launcha Authority Index",
3048
+ "report_title": "Personalised Authority Blueprint"
3049
+ }
3050
+ }
3051
+ ],
3052
+ "note": "title names the QUIZ, report_title names the DOCUMENT the client receives. The tab must carry the document.",
3053
+ "label": "a report is named by its own document name, not the diagnostic",
3054
+ "expect": "Personalised Authority Blueprint",
3055
+ "export": "resolveEntityTitle",
3056
+ "module": "src/register-registry-page-route/meta-title.ts",
3057
+ "package": "@teamscala/service-boot",
3058
+ "suite_type": "function_call",
3059
+ "slug": "service-boot:resolve-entity-title-a-report-is-named-by-its-own-document-name-not-the-diagnostic"
3060
+ },
3061
+ {
3062
+ "args": [
3063
+ {
3064
+ "form": {
3065
+ "name": " "
3066
+ },
3067
+ "agent": {
3068
+ "name": "Agent"
3069
+ }
3070
+ }
3071
+ ],
3072
+ "label": "blank and whitespace-only names do not win",
3073
+ "expect": "Agent",
3074
+ "export": "resolveEntityTitle",
3075
+ "module": "src/register-registry-page-route/meta-title.ts",
3076
+ "package": "@teamscala/service-boot",
3077
+ "suite_type": "function_call",
3078
+ "slug": "service-boot:resolve-entity-title-blank-and-whitespace-only-names-do-not-win"
3079
+ },
3080
+ {
3081
+ "args": [
3082
+ {
3083
+ "form": {
3084
+ "name": "Form"
3085
+ },
3086
+ "quiz": {
3087
+ "report_title": "Report"
3088
+ },
3089
+ "agent": {
3090
+ "name": "Agent"
3091
+ },
3092
+ "proposal": {
3093
+ "name": "Proposal"
3094
+ }
3095
+ }
3096
+ ],
3097
+ "note": "The three former copies disagreed: two put form first, one put proposal first, so the subject depended on which render branch ran. One order now.",
3098
+ "label": "precedence is single and fixed across every caller (form first)",
3099
+ "expect": "Form",
3100
+ "export": "resolveEntityTitle",
3101
+ "module": "src/register-registry-page-route/meta-title.ts",
3102
+ "package": "@teamscala/service-boot",
3103
+ "suite_type": "function_call",
3104
+ "slug": "service-boot:resolve-entity-title-precedence-form-first"
3105
+ },
3106
+ {
3107
+ "args": [
3108
+ {
3109
+ "form": null,
3110
+ "quiz": {
3111
+ "report_title": "Report"
3112
+ },
3113
+ "agent": {
3114
+ "name": "Agent"
3115
+ },
3116
+ "proposal": {
3117
+ "name": "Proposal"
3118
+ }
3119
+ }
3120
+ ],
3121
+ "label": "precedence is single and fixed across every caller (form absent → proposal)",
3122
+ "expect": "Proposal",
3123
+ "export": "resolveEntityTitle",
3124
+ "module": "src/register-registry-page-route/meta-title.ts",
3125
+ "package": "@teamscala/service-boot",
3126
+ "suite_type": "function_call",
3127
+ "slug": "service-boot:resolve-entity-title-precedence-proposal-second"
3128
+ },
3129
+ {
3130
+ "args": [
3131
+ {
3132
+ "form": null,
3133
+ "quiz": {
3134
+ "report_title": "Report"
3135
+ },
3136
+ "agent": {
3137
+ "name": "Agent"
3138
+ },
3139
+ "proposal": null
3140
+ }
3141
+ ],
3142
+ "label": "precedence is single and fixed across every caller (form and proposal absent → report)",
3143
+ "expect": "Report",
3144
+ "export": "resolveEntityTitle",
3145
+ "module": "src/register-registry-page-route/meta-title.ts",
3146
+ "package": "@teamscala/service-boot",
3147
+ "suite_type": "function_call",
3148
+ "slug": "service-boot:resolve-entity-title-precedence-report-third"
3149
+ },
3150
+ {
3151
+ "args": [
3152
+ {}
3153
+ ],
3154
+ "label": "undefined when nothing names the page",
3155
+ "expect": {
3156
+ "is_undefined": true
3157
+ },
3158
+ "export": "resolveEntityTitle",
3159
+ "module": "src/register-registry-page-route/meta-title.ts",
3160
+ "package": "@teamscala/service-boot",
3161
+ "suite_type": "function_call",
3162
+ "slug": "service-boot:resolve-entity-title-undefined-when-nothing-names-the-page-empty"
3163
+ },
3164
+ {
3165
+ "args": [
3166
+ {
3167
+ "quiz": {}
3168
+ }
3169
+ ],
3170
+ "label": "undefined when nothing names the page (quiz present but empty)",
3171
+ "expect": {
3172
+ "is_undefined": true
3173
+ },
3174
+ "export": "resolveEntityTitle",
3175
+ "module": "src/register-registry-page-route/meta-title.ts",
3176
+ "package": "@teamscala/service-boot",
3177
+ "suite_type": "function_call",
3178
+ "slug": "service-boot:resolve-entity-title-undefined-when-nothing-names-the-page-empty-quiz"
3179
+ },
3180
+ {
3181
+ "args": [
3182
+ {
3183
+ "input": {
3184
+ "path": "/hub/portal-integrations"
3185
+ },
3186
+ "client": null,
3187
+ "params": {}
3188
+ }
3189
+ ],
3190
+ "label": "bare path (no UUID prefix) → portal_id/org_id null, path untouched",
3191
+ "expect": {
3192
+ "org_id": null,
3193
+ "portal_id": null,
3194
+ "center_path": "/hub/portal-integrations",
3195
+ "toolbar_path": "/portal-integrations-toolbar"
3196
+ },
3197
+ "export": "resolvePortalRoutePaths",
3198
+ "module": "src/resolvers/portal-route-paths.ts",
3199
+ "package": "@teamscala/service-boot",
3200
+ "suite_type": "function_call",
3201
+ "slug": "service-boot:resolve-portal-route-paths-bare-path-no-uuid-prefix-ids-null-path-untouched"
3202
+ },
3203
+ {
3204
+ "args": [
3205
+ {
3206
+ "input": {
3207
+ "path": "/a9a28515-4ad5-405c-a74d-bb83fed079d0/5b742740-0f37-494c-a059-d8399ae4b350/hub/portal-integrations"
3208
+ },
3209
+ "client": null,
3210
+ "params": {}
3211
+ }
3212
+ ],
3213
+ "label": "canonical two-UUID shape → strips portal+org, center_path is the builda path",
3214
+ "expect": {
3215
+ "org_id": "5b742740-0f37-494c-a059-d8399ae4b350",
3216
+ "portal_id": "a9a28515-4ad5-405c-a74d-bb83fed079d0",
3217
+ "center_path": "/hub/portal-integrations",
3218
+ "toolbar_path": "/portal-integrations-toolbar"
3219
+ },
3220
+ "export": "resolvePortalRoutePaths",
3221
+ "module": "src/resolvers/portal-route-paths.ts",
3222
+ "package": "@teamscala/service-boot",
3223
+ "suite_type": "function_call",
3224
+ "slug": "service-boot:resolve-portal-route-paths-canonical-two-uuid-shape-strips-portal-and-org"
3225
+ },
3226
+ {
3227
+ "args": [
3228
+ {
3229
+ "input": {
3230
+ "path": "/a9a28515-4ad5-405c-a74d-bb83fed079d0/dashboard"
3231
+ },
3232
+ "client": null,
3233
+ "params": {}
3234
+ }
3235
+ ],
3236
+ "note": "The violating behaviour this locks out left portal_id null and center_path as the literal /<websiteId>/dashboard (so it silently rendered unscoped). The org-less shape is gated upstream in resolve-page-state (portalHomeRedirect) so it never silently renders.",
3237
+ "label": "org-less portal shape /<websiteId>/<path> → portal_id populated, org_id null, center_path is the real path",
3238
+ "expect": {
3239
+ "org_id": null,
3240
+ "portal_id": "a9a28515-4ad5-405c-a74d-bb83fed079d0",
3241
+ "center_path": "/dashboard",
3242
+ "toolbar_path": "/dashboard-toolbar"
3243
+ },
3244
+ "export": "resolvePortalRoutePaths",
3245
+ "module": "src/resolvers/portal-route-paths.ts",
3246
+ "package": "@teamscala/service-boot",
3247
+ "suite_type": "function_call",
3248
+ "slug": "service-boot:resolve-portal-route-paths-org-less-portal-shape-portal-id-populated-org-id-null"
3249
+ },
3250
+ {
3251
+ "args": [
3252
+ {
3253
+ "input": {
3254
+ "path": "/a9a28515-4ad5-405c-a74d-bb83fed079d0/5b742740-0f37-494c-a059-d8399ae4b350/",
3255
+ "home_path": "/dashboard"
3256
+ },
3257
+ "client": null,
3258
+ "params": {}
3259
+ }
3260
+ ],
3261
+ "label": "/ falls back to the home path",
3262
+ "expect": {
3263
+ "org_id": "5b742740-0f37-494c-a059-d8399ae4b350",
3264
+ "portal_id": "a9a28515-4ad5-405c-a74d-bb83fed079d0",
3265
+ "center_path": "/dashboard",
3266
+ "toolbar_path": "/dashboard-toolbar"
3267
+ },
3268
+ "export": "resolvePortalRoutePaths",
3269
+ "module": "src/resolvers/portal-route-paths.ts",
3270
+ "package": "@teamscala/service-boot",
3271
+ "suite_type": "function_call",
3272
+ "slug": "service-boot:resolve-portal-route-paths-root-falls-back-to-the-home-path"
3273
+ },
3274
+ {
3275
+ "args": [
3276
+ 3021,
3277
+ 5203
3278
+ ],
3279
+ "note": "scala-quiz declares 5203; PORT=3021 leaked in from the tmux server env and it bound session-picker's port, splitting that daemon's traffic via SO_REUSEPORT. Covers the band's second test too: the conflict is reported, not swallowed.",
3280
+ "label": "the live bug: a leaked PORT cannot move a UI service off its declared port",
3281
+ "expect": {
3282
+ "port": 5203,
3283
+ "source": "service_routing",
3284
+ "conflict": {
3285
+ "envPort": 3021,
3286
+ "declaredPort": 5203
3287
+ }
3288
+ },
3289
+ "export": "resolveServicePort",
3290
+ "module": "src/resolve-service-port.ts",
3291
+ "package": "@teamscala/service-boot",
3292
+ "suite_type": "function_call",
3293
+ "slug": "service-boot:resolve-service-port-a-leaked-port-cannot-move-a-ui-service-off-its-declared-port"
3294
+ },
3295
+ {
3296
+ "args": [
3297
+ 3021,
3298
+ 8080
3299
+ ],
3300
+ "note": "The exact incident: env said 3021 (session-picker's port), the row said 8080. Obeying the env bound another service's port.",
3301
+ "label": "a PORT contradicting the routing row is REFUSED and reported",
3302
+ "expect": {
3303
+ "port": 8080,
3304
+ "source": "service_routing",
3305
+ "conflict": {
3306
+ "envPort": 3021,
3307
+ "declaredPort": 8080
3308
+ }
3309
+ },
3310
+ "export": "resolveServicePort",
3311
+ "module": "src/resolve-service-port.ts",
3312
+ "package": "@teamscala/service-boot",
3313
+ "suite_type": "function_call",
3314
+ "slug": "service-boot:resolve-service-port-a-port-contradicting-the-routing-row-is-refused-and-reported"
3315
+ },
3316
+ {
3317
+ "args": [
3318
+ 0,
3319
+ 3021
3320
+ ],
3321
+ "label": "an unparseable or out-of-range PORT never displaces a valid row (resolvedPort narrowing: 0)",
3322
+ "expect": 3021,
3323
+ "export": "resolveServicePort",
3324
+ "module": "src/resolve-service-port.ts",
3325
+ "package": "@teamscala/service-boot",
3326
+ "suite_type": "function_call",
3327
+ "slug": "service-boot:resolve-service-port-a-zero-port-never-displaces-a-valid-row"
3328
+ },
3329
+ {
3330
+ "args": [
3331
+ 5203,
3332
+ 5203
3333
+ ],
3334
+ "label": "an agreeing PORT reports no conflict (kind:ui services)",
3335
+ "expect": {
3336
+ "port": 5203,
3337
+ "source": "service_routing"
3338
+ },
3339
+ "export": "resolveServicePort",
3340
+ "module": "src/resolve-service-port.ts",
3341
+ "package": "@teamscala/service-boot",
3342
+ "suite_type": "function_call",
3343
+ "slug": "service-boot:resolve-service-port-an-agreeing-port-reports-no-conflict-for-kind-ui"
3344
+ },
3345
+ {
3346
+ "args": [
3347
+ 70000,
3348
+ 3021
3349
+ ],
3350
+ "label": "an unparseable or out-of-range PORT never displaces a valid row (resolvedPort narrowing: 70000)",
3351
+ "expect": 3021,
3352
+ "export": "resolveServicePort",
3353
+ "module": "src/resolve-service-port.ts",
3354
+ "package": "@teamscala/service-boot",
3355
+ "suite_type": "function_call",
3356
+ "slug": "service-boot:resolve-service-port-an-out-of-range-port-70000-never-displaces-a-valid-row"
3357
+ },
3358
+ {
3359
+ "args": [
3360
+ 70000,
3361
+ null
3362
+ ],
3363
+ "label": "an out-of-range PORT with no row is an error rather than a bad bind",
3364
+ "expect": {
3365
+ "error": "no-port-source"
3366
+ },
3367
+ "export": "resolveServicePort",
3368
+ "module": "src/resolve-service-port.ts",
3369
+ "package": "@teamscala/service-boot",
3370
+ "suite_type": "function_call",
3371
+ "slug": "service-boot:resolve-service-port-an-out-of-range-port-with-no-row-is-an-error-rather-than-a-bad-bind"
3372
+ },
3373
+ {
3374
+ "args": [
3375
+ null,
3376
+ null
3377
+ ],
3378
+ "label": "no routing row and no usable PORT is an error, not a guess",
3379
+ "expect": {
3380
+ "error": "no-port-source"
3381
+ },
3382
+ "export": "resolveServicePort",
3383
+ "module": "src/resolve-service-port.ts",
3384
+ "package": "@teamscala/service-boot",
3385
+ "suite_type": "function_call",
3386
+ "slug": "service-boot:resolve-service-port-no-routing-row-and-no-usable-port-is-an-error-not-a-guess"
3387
+ },
3388
+ {
3389
+ "args": [
3390
+ 8080,
3391
+ null
3392
+ ],
3393
+ "note": "A Railway-only backend legitimately has no dev routing row, and Railway healthchecks the exact port it injected.",
3394
+ "label": "no routing row: Railway's injected PORT wins",
3395
+ "expect": {
3396
+ "port": 8080,
3397
+ "source": "env"
3398
+ },
3399
+ "export": "resolveServicePort",
3400
+ "module": "src/resolve-service-port.ts",
3401
+ "package": "@teamscala/service-boot",
3402
+ "suite_type": "function_call",
3403
+ "slug": "service-boot:resolve-service-port-no-routing-row-railways-injected-port-wins"
3404
+ },
3405
+ {
3406
+ "args": [
3407
+ 8080,
3408
+ 5200
3409
+ ],
3410
+ "label": "isRailway defaults to false: off Railway the registry still wins a conflict",
3411
+ "expect": {
3412
+ "port": 5200,
3413
+ "source": "service_routing",
3414
+ "conflict": {
3415
+ "envPort": 8080,
3416
+ "declaredPort": 5200
3417
+ }
3418
+ },
3419
+ "export": "resolveServicePort",
3420
+ "module": "src/resolve-service-port.ts",
3421
+ "package": "@teamscala/service-boot",
3422
+ "suite_type": "function_call",
3423
+ "slug": "service-boot:resolve-service-port-off-railway-the-registry-still-wins-a-conflict"
3424
+ },
3425
+ {
3426
+ "args": [
3427
+ 8080,
3428
+ 5200,
3429
+ true
3430
+ ],
3431
+ "note": "The 2026-07-31 portal incident: portal declares dev port 5200 in service_install, Railway injects PORT=8080 and healthchecks 8080. The registry-wins rule made portal bind 5200 on Railway, so the healthcheck probed a dead port and the deploy failed — despite the service booting healthy. On Railway PORT must win.",
3432
+ "label": "Railway: a conflicting declared port does NOT override Railway's injected PORT",
3433
+ "expect": {
3434
+ "port": 8080,
3435
+ "source": "env"
3436
+ },
3437
+ "export": "resolveServicePort",
3438
+ "module": "src/resolve-service-port.ts",
3439
+ "package": "@teamscala/service-boot",
3440
+ "suite_type": "function_call",
3441
+ "slug": "service-boot:resolve-service-port-railway-a-conflicting-declared-port-does-not-override-the-injected-port"
3442
+ },
3443
+ {
3444
+ "args": [
3445
+ 8080,
3446
+ 8080,
3447
+ true
3448
+ ],
3449
+ "label": "Railway: an agreeing declared port still resolves to env on Railway",
3450
+ "expect": {
3451
+ "port": 8080,
3452
+ "source": "env"
3453
+ },
3454
+ "export": "resolveServicePort",
3455
+ "module": "src/resolve-service-port.ts",
3456
+ "package": "@teamscala/service-boot",
3457
+ "suite_type": "function_call",
3458
+ "slug": "service-boot:resolve-service-port-railway-an-agreeing-declared-port-still-resolves-to-env"
3459
+ },
3460
+ {
3461
+ "args": [
3462
+ null,
3463
+ 5200,
3464
+ true
3465
+ ],
3466
+ "label": "Railway with no injected PORT falls back to the declared port",
3467
+ "expect": {
3468
+ "port": 5200,
3469
+ "source": "service_routing"
3470
+ },
3471
+ "export": "resolveServicePort",
3472
+ "module": "src/resolve-service-port.ts",
3473
+ "package": "@teamscala/service-boot",
3474
+ "suite_type": "function_call",
3475
+ "slug": "service-boot:resolve-service-port-railway-no-injected-port-falls-back-to-the-declared-port"
3476
+ },
3477
+ {
3478
+ "args": [
3479
+ 3021,
3480
+ 3021
3481
+ ],
3482
+ "note": "The conflict member is absent, which a whole-value compare asserts by inequality.",
3483
+ "label": "routing row and an agreeing PORT: no conflict reported",
3484
+ "expect": {
3485
+ "port": 3021,
3486
+ "source": "service_routing"
3487
+ },
3488
+ "export": "resolveServicePort",
3489
+ "module": "src/resolve-service-port.ts",
3490
+ "package": "@teamscala/service-boot",
3491
+ "suite_type": "function_call",
3492
+ "slug": "service-boot:resolve-service-port-routing-row-and-an-agreeing-port-reports-no-conflict"
3493
+ },
3494
+ {
3495
+ "args": [
3496
+ null,
3497
+ 3021
3498
+ ],
3499
+ "label": "routing row with no PORT env: the row wins",
3500
+ "expect": {
3501
+ "port": 3021,
3502
+ "source": "service_routing"
3503
+ },
3504
+ "export": "resolveServicePort",
3505
+ "module": "src/resolve-service-port.ts",
3506
+ "package": "@teamscala/service-boot",
3507
+ "suite_type": "function_call",
3508
+ "slug": "service-boot:resolve-service-port-routing-row-with-no-port-env-the-row-wins"
3509
+ },
3510
+ {
3511
+ "args": [
3512
+ [
3513
+ {
3514
+ "config": {
3515
+ "pattern": "/:orgId",
3516
+ "service": "scala-projects"
3517
+ }
3518
+ },
3519
+ {
3520
+ "config": {
3521
+ "pattern": "/:orgId/kanban",
3522
+ "service": "scala-projects"
3523
+ }
3524
+ },
3525
+ {
3526
+ "config": {
3527
+ "pattern": "/sign-in",
3528
+ "service": "scala-projects"
3529
+ }
3530
+ },
3531
+ {
3532
+ "config": {
3533
+ "pattern": "/*",
3534
+ "service": "scala-portal"
3535
+ }
3536
+ },
3537
+ {
3538
+ "config": {
3539
+ "pattern": "/",
3540
+ "service": "scala-quiz"
3541
+ }
3542
+ }
3543
+ ],
3544
+ "scala-projects-bun-dev"
3545
+ ],
3546
+ "note": "The regression this module exists for: before the capability join, a dev lane matched ZERO rows and served 404 on every path. The whole-value compare also carries the band's never-returns-another-services-rows test: only scala-projects rows can equal this set.",
3547
+ "label": "a dev lane resolves the rows that name the capability",
3548
+ "expect": [
3549
+ {
3550
+ "config": {
3551
+ "pattern": "/sign-in",
3552
+ "service": "scala-projects"
3553
+ }
3554
+ },
3555
+ {
3556
+ "config": {
3557
+ "pattern": "/:orgId",
3558
+ "service": "scala-projects"
3559
+ }
3560
+ },
3561
+ {
3562
+ "config": {
3563
+ "pattern": "/:orgId/kanban",
3564
+ "service": "scala-projects"
3565
+ }
3566
+ }
3567
+ ],
3568
+ "export": "selectServiceRoutes",
3569
+ "module": "src/select-service-routes.ts",
3570
+ "package": "@teamscala/service-boot",
3571
+ "suite_type": "function_call",
3572
+ "slug": "service-boot:select-service-routes-a-dev-lane-resolves-the-rows-that-name-the-capability"
3573
+ },
3574
+ {
3575
+ "args": [
3576
+ [
3577
+ {
3578
+ "config": {
3579
+ "pattern": "/",
3580
+ "service": "scala-roadmap-bun-dev"
3581
+ }
3582
+ }
3583
+ ],
3584
+ "scala-roadmap"
3585
+ ],
3586
+ "label": "a row naming a deployable form still matches its lane",
3587
+ "expect": [
3588
+ {
3589
+ "config": {
3590
+ "pattern": "/",
3591
+ "service": "scala-roadmap-bun-dev"
3592
+ }
3593
+ }
3594
+ ],
3595
+ "export": "selectServiceRoutes",
3596
+ "module": "src/select-service-routes.ts",
3597
+ "package": "@teamscala/service-boot",
3598
+ "suite_type": "function_call",
3599
+ "slug": "service-boot:select-service-routes-a-row-naming-a-deployable-form-still-matches-its-lane"
3600
+ },
3601
+ {
3602
+ "args": [
3603
+ [
3604
+ {
3605
+ "config": {
3606
+ "pattern": "/:orgId",
3607
+ "service": "scala-projects"
3608
+ }
3609
+ },
3610
+ {
3611
+ "config": {
3612
+ "pattern": "/:orgId/kanban",
3613
+ "service": "scala-projects"
3614
+ }
3615
+ },
3616
+ {
3617
+ "config": {
3618
+ "pattern": "/sign-in",
3619
+ "service": "scala-projects"
3620
+ }
3621
+ },
3622
+ {
3623
+ "config": {
3624
+ "pattern": "/*",
3625
+ "service": "scala-portal"
3626
+ }
3627
+ },
3628
+ {
3629
+ "config": {
3630
+ "pattern": "/",
3631
+ "service": "scala-quiz"
3632
+ }
3633
+ }
3634
+ ],
3635
+ "scala-nonexistent-bun-dev"
3636
+ ],
3637
+ "label": "an unknown service resolves nothing",
3638
+ "expect": [],
3639
+ "export": "selectServiceRoutes",
3640
+ "module": "src/select-service-routes.ts",
3641
+ "package": "@teamscala/service-boot",
3642
+ "suite_type": "function_call",
3643
+ "slug": "service-boot:select-service-routes-an-unknown-service-resolves-nothing"
3644
+ },
3645
+ {
3646
+ "args": [
3647
+ [
3648
+ {
3649
+ "config": {
3650
+ "pattern": "/:orgId",
3651
+ "service": "scala-projects"
3652
+ }
3653
+ },
3654
+ {
3655
+ "config": {
3656
+ "pattern": "/:orgId/kanban",
3657
+ "service": "scala-projects"
3658
+ }
3659
+ },
3660
+ {
3661
+ "config": {
3662
+ "pattern": "/sign-in",
3663
+ "service": "scala-projects"
3664
+ }
3665
+ },
3666
+ {
3667
+ "config": {
3668
+ "pattern": "/*",
3669
+ "service": "scala-portal"
3670
+ }
3671
+ },
3672
+ {
3673
+ "config": {
3674
+ "pattern": "/",
3675
+ "service": "scala-quiz"
3676
+ }
3677
+ }
3678
+ ],
3679
+ "scala-projects"
3680
+ ],
3681
+ "label": "both lanes of one application resolve the same set (prod bare spelling)",
3682
+ "expect": [
3683
+ {
3684
+ "config": {
3685
+ "pattern": "/sign-in",
3686
+ "service": "scala-projects"
3687
+ }
3688
+ },
3689
+ {
3690
+ "config": {
3691
+ "pattern": "/:orgId",
3692
+ "service": "scala-projects"
3693
+ }
3694
+ },
3695
+ {
3696
+ "config": {
3697
+ "pattern": "/:orgId/kanban",
3698
+ "service": "scala-projects"
3699
+ }
3700
+ }
3701
+ ],
3702
+ "export": "selectServiceRoutes",
3703
+ "module": "src/select-service-routes.ts",
3704
+ "package": "@teamscala/service-boot",
3705
+ "suite_type": "function_call",
3706
+ "slug": "service-boot:select-service-routes-both-lanes-resolve-the-same-set-prod-bare"
3707
+ },
3708
+ {
3709
+ "args": [
3710
+ [
3711
+ {
3712
+ "config": {
3713
+ "pattern": "/:orgId",
3714
+ "service": "scala-projects"
3715
+ }
3716
+ },
3717
+ {
3718
+ "config": {
3719
+ "pattern": "/:orgId/kanban",
3720
+ "service": "scala-projects"
3721
+ }
3722
+ },
3723
+ {
3724
+ "config": {
3725
+ "pattern": "/sign-in",
3726
+ "service": "scala-projects"
3727
+ }
3728
+ },
3729
+ {
3730
+ "config": {
3731
+ "pattern": "/*",
3732
+ "service": "scala-portal"
3733
+ }
3734
+ },
3735
+ {
3736
+ "config": {
3737
+ "pattern": "/",
3738
+ "service": "scala-quiz"
3739
+ }
3740
+ }
3741
+ ],
3742
+ "scala-projects-bun-prod"
3743
+ ],
3744
+ "label": "both lanes of one application resolve the same set (prod tiered spelling)",
3745
+ "expect": [
3746
+ {
3747
+ "config": {
3748
+ "pattern": "/sign-in",
3749
+ "service": "scala-projects"
3750
+ }
3751
+ },
3752
+ {
3753
+ "config": {
3754
+ "pattern": "/:orgId",
3755
+ "service": "scala-projects"
3756
+ }
3757
+ },
3758
+ {
3759
+ "config": {
3760
+ "pattern": "/:orgId/kanban",
3761
+ "service": "scala-projects"
3762
+ }
3763
+ }
3764
+ ],
3765
+ "export": "selectServiceRoutes",
3766
+ "module": "src/select-service-routes.ts",
3767
+ "package": "@teamscala/service-boot",
3768
+ "suite_type": "function_call",
3769
+ "slug": "service-boot:select-service-routes-both-lanes-resolve-the-same-set-prod-tiered"
3770
+ },
3771
+ {
3772
+ "args": [
3773
+ [
3774
+ {
3775
+ "config": {
3776
+ "pattern": "/*",
3777
+ "service": "scala-portal"
3778
+ }
3779
+ },
3780
+ {
3781
+ "config": {
3782
+ "pattern": "/:orgId",
3783
+ "service": "scala-portal"
3784
+ }
3785
+ },
3786
+ {
3787
+ "config": {
3788
+ "pattern": "/sign-in",
3789
+ "service": "scala-portal"
3790
+ }
3791
+ }
3792
+ ],
3793
+ "scala-portal"
3794
+ ],
3795
+ "label": "orders literal before param before wildcard",
3796
+ "expect": [
3797
+ {
3798
+ "config": {
3799
+ "pattern": "/sign-in",
3800
+ "service": "scala-portal"
3801
+ }
3802
+ },
3803
+ {
3804
+ "config": {
3805
+ "pattern": "/:orgId",
3806
+ "service": "scala-portal"
3807
+ }
3808
+ },
3809
+ {
3810
+ "config": {
3811
+ "pattern": "/*",
3812
+ "service": "scala-portal"
3813
+ }
3814
+ }
3815
+ ],
3816
+ "export": "selectServiceRoutes",
3817
+ "module": "src/select-service-routes.ts",
3818
+ "package": "@teamscala/service-boot",
3819
+ "suite_type": "function_call",
3820
+ "slug": "service-boot:select-service-routes-orders-literal-before-param-before-wildcard"
3821
+ },
3822
+ {
3823
+ "args": [
3824
+ "@import \"./local.css\";\n.a{}"
3825
+ ],
3826
+ "label": "leaves local/relative @imports untouched (Tailwind inlines those)",
3827
+ "expect": "@import \"./local.css\";\n.a{}",
3828
+ "export": "stripRemoteImports",
3829
+ "module": "src/build-client-assets/styles-build.ts",
3830
+ "package": "@teamscala/service-boot",
3831
+ "suite_type": "function_call",
3832
+ "slug": "service-boot:strip-remote-imports-leaves-local-relative-imports-untouched"
3833
+ },
3834
+ {
3835
+ "args": [
3836
+ ":root{--x:1}\n.a{color:red}"
3837
+ ],
3838
+ "label": "no remote @import → unchanged",
3839
+ "expect": ":root{--x:1}\n.a{color:red}",
3840
+ "export": "stripRemoteImports",
3841
+ "module": "src/build-client-assets/styles-build.ts",
3842
+ "package": "@teamscala/service-boot",
3843
+ "suite_type": "function_call",
3844
+ "slug": "service-boot:strip-remote-imports-no-remote-import-unchanged"
3845
+ },
3846
+ {
3847
+ "args": [
3848
+ ".a { color: red; }\n@import \"https://rsms.me/inter/inter.css\";\n:root { --x: 1; }"
3849
+ ],
3850
+ "label": "removes a remote @import (Puck's rsms.me font)",
3851
+ "expect": {
3852
+ "absent": [
3853
+ "@import",
3854
+ "rsms.me"
3855
+ ],
3856
+ "contains_text": [
3857
+ ".a { color: red; }",
3858
+ "--x: 1;"
3859
+ ]
3860
+ },
3861
+ "export": "stripRemoteImports",
3862
+ "module": "src/build-client-assets/styles-build.ts",
3863
+ "package": "@teamscala/service-boot",
3864
+ "suite_type": "function_call",
3865
+ "slug": "service-boot:strip-remote-imports-removes-a-remote-import-pucks-rsms-me-font"
3866
+ },
3867
+ {
3868
+ "args": [
3869
+ "@import \"https://a.test/x.css\";\n.a{}\n@import \"https://b.test/y.css\";\n.b{}"
3870
+ ],
3871
+ "label": "removes multiple remote @imports",
3872
+ "expect": {
3873
+ "absent": [
3874
+ "@import"
3875
+ ]
3876
+ },
3877
+ "export": "stripRemoteImports",
3878
+ "module": "src/build-client-assets/styles-build.ts",
3879
+ "package": "@teamscala/service-boot",
3880
+ "suite_type": "function_call",
3881
+ "slug": "service-boot:strip-remote-imports-removes-multiple-remote-imports"
3882
+ },
3883
+ {
3884
+ "args": [
3885
+ ".a{}\n@import url(\"https://fonts.example/f.css\") screen;\n.b{}"
3886
+ ],
3887
+ "label": "removes the url() form with a media suffix",
3888
+ "expect": {
3889
+ "absent": [
3890
+ "@import"
3891
+ ],
3892
+ "contains_text": [
3893
+ ".a{}",
3894
+ ".b{}"
3895
+ ]
3896
+ },
3897
+ "export": "stripRemoteImports",
3898
+ "module": "src/build-client-assets/styles-build.ts",
3899
+ "package": "@teamscala/service-boot",
3900
+ "suite_type": "function_call",
3901
+ "slug": "service-boot:strip-remote-imports-removes-the-url-form-with-a-media-suffix"
3902
+ },
3903
+ {
3904
+ "args": [],
3905
+ "label": "families derive from the css_theme row, deduplicated",
3906
+ "expect": [
3907
+ "Inter",
3908
+ "Playfair Display"
3909
+ ],
3910
+ "export": "themeFontFamilies",
3911
+ "module": "src/theme-fonts-link.ts",
3912
+ "package": "@teamscala/service-boot",
3913
+ "fixtures": {
3914
+ "stubs": [
3915
+ {
3916
+ "export": "getEntryConfig",
3917
+ "module": "@teamscala/db/registry/accessors",
3918
+ "returns": {
3919
+ "fonts": {
3920
+ "body": "Inter, sans-serif",
3921
+ "heading": "Inter, sans-serif",
3922
+ "manuscript": "Playfair Display"
3923
+ }
3924
+ }
3925
+ }
3926
+ ]
3927
+ },
3928
+ "suite_type": "function_call",
3929
+ "slug": "service-boot:theme-font-families-derive-from-the-css-theme-row-deduplicated"
3930
+ },
3931
+ {
3932
+ "args": [],
3933
+ "label": "an absent row degrades to no fonts link — never throws",
3934
+ "expect": "",
3935
+ "export": "themeFontsLink",
3936
+ "module": "src/theme-fonts-link.ts",
3937
+ "package": "@teamscala/service-boot",
3938
+ "fixtures": {
3939
+ "stubs": [
3940
+ {
3941
+ "export": "getEntryConfig",
3942
+ "module": "@teamscala/db/registry/accessors",
3943
+ "returns": null
3944
+ }
3945
+ ]
3946
+ },
3947
+ "suite_type": "function_call",
3948
+ "slug": "service-boot:theme-fonts-link-an-absent-row-degrades-to-no-fonts-link"
3949
+ },
3950
+ {
3951
+ "args": [],
3952
+ "note": "Covers the band's served-head test at the string the template interpolates it into: the head-level contains-claims over readHtmlTemplate stay hand-written with the fs harness.",
3953
+ "label": "the fonts link carries every family the row declares",
3954
+ "expect": "<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair%20Display:wght@400;500;600;700&display=optional\" />",
3955
+ "export": "themeFontsLink",
3956
+ "module": "src/theme-fonts-link.ts",
3957
+ "package": "@teamscala/service-boot",
3958
+ "fixtures": {
3959
+ "stubs": [
3960
+ {
3961
+ "export": "getEntryConfig",
3962
+ "module": "@teamscala/db/registry/accessors",
3963
+ "returns": {
3964
+ "fonts": {
3965
+ "body": "Inter, sans-serif",
3966
+ "heading": "Inter, sans-serif",
3967
+ "manuscript": "Playfair Display"
3968
+ }
3969
+ }
3970
+ }
3971
+ ]
3972
+ },
3973
+ "suite_type": "function_call",
3974
+ "slug": "service-boot:theme-fonts-link-the-served-link-carries-every-family-the-row-declares"
3975
+ },
3976
+ {
3977
+ "args": [
3978
+ "scala-quiz-ts-dev"
3979
+ ],
3980
+ "note": "This is the property the page_route join depends on: the dev and prod spellings land on one capability slug.",
3981
+ "label": "both lanes of one application normalize to the same identity",
3982
+ "expect": "scala-quiz",
3983
+ "export": "toCapabilitySlug",
3984
+ "module": "src/capability-slug.ts",
3985
+ "package": "@teamscala/service-boot",
3986
+ "suite_type": "function_call",
3987
+ "slug": "service-boot:to-capability-slug-both-lanes-normalize-to-one-identity-scala-quiz-ts-dev"
3988
+ },
3989
+ {
3990
+ "args": [
3991
+ "scala-quiz-ts-prod"
3992
+ ],
3993
+ "note": "This is the property the page_route join depends on: the dev and prod spellings land on one capability slug.",
3994
+ "label": "both lanes of one application normalize to the same identity",
3995
+ "expect": "scala-quiz",
3996
+ "export": "toCapabilitySlug",
3997
+ "module": "src/capability-slug.ts",
3998
+ "package": "@teamscala/service-boot",
3999
+ "suite_type": "function_call",
4000
+ "slug": "service-boot:to-capability-slug-both-lanes-normalize-to-one-identity-scala-quiz-ts-prod"
4001
+ },
4002
+ {
4003
+ "args": [
4004
+ "scala-ai-bun-prod"
4005
+ ],
4006
+ "note": "The fleet was renamed under -bun before the operator ruling of 2026-09-08 fixed the language segment at ts; rows or supervised names still carrying it converge rather than fail the join.",
4007
+ "label": "strips the retired bun spelling to the same capability",
4008
+ "expect": "scala-ai",
4009
+ "export": "toCapabilitySlug",
4010
+ "module": "src/capability-slug.ts",
4011
+ "package": "@teamscala/service-boot",
4012
+ "suite_type": "function_call",
4013
+ "slug": "service-boot:to-capability-slug-converges-the-retired-bun-spelling-scala-ai-bun-prod"
4014
+ },
4015
+ {
4016
+ "args": [
4017
+ "scala-projects-bun-dev"
4018
+ ],
4019
+ "note": "The fleet was renamed under -bun before the operator ruling of 2026-09-08 fixed the language segment at ts; rows or supervised names still carrying it converge rather than fail the join.",
4020
+ "label": "strips the retired bun spelling to the same capability",
4021
+ "expect": "scala-projects",
4022
+ "export": "toCapabilitySlug",
4023
+ "module": "src/capability-slug.ts",
4024
+ "package": "@teamscala/service-boot",
4025
+ "suite_type": "function_call",
4026
+ "slug": "service-boot:to-capability-slug-converges-the-retired-bun-spelling-scala-projects-bun-dev"
4027
+ },
4028
+ {
4029
+ "args": [
4030
+ "bun-dev"
4031
+ ],
4032
+ "note": "Too short to carry both segments.",
4033
+ "label": "leaves a name whose tail is not the closed grammar alone",
4034
+ "expect": "bun-dev",
4035
+ "export": "toCapabilitySlug",
4036
+ "module": "src/capability-slug.ts",
4037
+ "package": "@teamscala/service-boot",
4038
+ "suite_type": "function_call",
4039
+ "slug": "service-boot:to-capability-slug-leaves-a-name-too-short-to-carry-both-segments-bun-dev"
4040
+ },
4041
+ {
4042
+ "args": [
4043
+ "scala-node-dev"
4044
+ ],
4045
+ "note": "node is not a language segment.",
4046
+ "label": "leaves a name whose tail is not the closed grammar alone",
4047
+ "expect": "scala-node-dev",
4048
+ "export": "toCapabilitySlug",
4049
+ "module": "src/capability-slug.ts",
4050
+ "package": "@teamscala/service-boot",
4051
+ "suite_type": "function_call",
4052
+ "slug": "service-boot:to-capability-slug-leaves-a-name-whose-tail-is-not-a-language-segment-scala-node-dev"
4053
+ },
4054
+ {
4055
+ "args": [
4056
+ "scala-bun-staging"
4057
+ ],
4058
+ "note": "staging is not a tier segment.",
4059
+ "label": "leaves a name whose tail is not the closed grammar alone",
4060
+ "expect": "scala-bun-staging",
4061
+ "export": "toCapabilitySlug",
4062
+ "module": "src/capability-slug.ts",
4063
+ "package": "@teamscala/service-boot",
4064
+ "suite_type": "function_call",
4065
+ "slug": "service-boot:to-capability-slug-leaves-a-name-whose-tail-is-not-a-tier-segment-scala-bun-staging"
4066
+ },
4067
+ {
4068
+ "args": [
4069
+ "supavisor"
4070
+ ],
4071
+ "label": "leaves a name whose tail is not the closed grammar alone",
4072
+ "expect": "supavisor",
4073
+ "export": "toCapabilitySlug",
4074
+ "module": "src/capability-slug.ts",
4075
+ "package": "@teamscala/service-boot",
4076
+ "suite_type": "function_call",
4077
+ "slug": "service-boot:to-capability-slug-leaves-a-single-word-unchanged-supavisor"
4078
+ },
4079
+ {
4080
+ "args": [
4081
+ "scala-otp"
4082
+ ],
4083
+ "note": "The prod lane is still bare while the tier migration is in flight, so the SAME function must be correct before and after the rename lands.",
4084
+ "label": "returns an already-capability slug unchanged",
4085
+ "expect": "scala-otp",
4086
+ "export": "toCapabilitySlug",
4087
+ "module": "src/capability-slug.ts",
4088
+ "package": "@teamscala/service-boot",
4089
+ "suite_type": "function_call",
4090
+ "slug": "service-boot:to-capability-slug-returns-an-already-capability-slug-unchanged-scala-otp"
4091
+ },
4092
+ {
4093
+ "args": [
4094
+ "scala-projects"
4095
+ ],
4096
+ "note": "The prod lane is still bare while the tier migration is in flight, so the SAME function must be correct before and after the rename lands.",
4097
+ "label": "returns an already-capability slug unchanged",
4098
+ "expect": "scala-projects",
4099
+ "export": "toCapabilitySlug",
4100
+ "module": "src/capability-slug.ts",
4101
+ "package": "@teamscala/service-boot",
4102
+ "suite_type": "function_call",
4103
+ "slug": "service-boot:to-capability-slug-returns-an-already-capability-slug-unchanged-scala-projects"
4104
+ },
4105
+ {
4106
+ "args": [
4107
+ "scala-ai-ts-dev"
4108
+ ],
4109
+ "label": "strips the language+tier suffix from a dev deployable",
4110
+ "expect": "scala-ai",
4111
+ "export": "toCapabilitySlug",
4112
+ "module": "src/capability-slug.ts",
4113
+ "package": "@teamscala/service-boot",
4114
+ "suite_type": "function_call",
4115
+ "slug": "service-boot:to-capability-slug-strips-the-language-and-tier-suffix-from-a-dev-deployable-scala-ai-ts-dev"
4116
+ },
4117
+ {
4118
+ "args": [
4119
+ "scala-image-optimizer-rust-dev"
4120
+ ],
4121
+ "label": "strips the language+tier suffix from a dev deployable",
4122
+ "expect": "scala-image-optimizer",
4123
+ "export": "toCapabilitySlug",
4124
+ "module": "src/capability-slug.ts",
4125
+ "package": "@teamscala/service-boot",
4126
+ "suite_type": "function_call",
4127
+ "slug": "service-boot:to-capability-slug-strips-the-language-and-tier-suffix-from-a-dev-deployable-scala-image-optimizer-rust-dev"
4128
+ },
4129
+ {
4130
+ "args": [
4131
+ "scala-projects-ts-dev"
4132
+ ],
4133
+ "label": "strips the language+tier suffix from a dev deployable",
4134
+ "expect": "scala-projects",
4135
+ "export": "toCapabilitySlug",
4136
+ "module": "src/capability-slug.ts",
4137
+ "package": "@teamscala/service-boot",
4138
+ "suite_type": "function_call",
4139
+ "slug": "service-boot:to-capability-slug-strips-the-language-and-tier-suffix-from-a-dev-deployable-scala-projects-ts-dev"
4140
+ },
4141
+ {
4142
+ "args": [
4143
+ "scala-messaging-service-rust-prod"
4144
+ ],
4145
+ "label": "strips the language+tier suffix from a prod deployable",
4146
+ "expect": "scala-messaging-service",
4147
+ "export": "toCapabilitySlug",
4148
+ "module": "src/capability-slug.ts",
4149
+ "package": "@teamscala/service-boot",
4150
+ "suite_type": "function_call",
4151
+ "slug": "service-boot:to-capability-slug-strips-the-language-and-tier-suffix-from-a-prod-deployable-scala-messaging-service-rust-prod"
4152
+ },
4153
+ {
4154
+ "args": [
4155
+ "scala-projects-ts-prod"
4156
+ ],
4157
+ "label": "strips the language+tier suffix from a prod deployable",
4158
+ "expect": "scala-projects",
4159
+ "export": "toCapabilitySlug",
4160
+ "module": "src/capability-slug.ts",
4161
+ "package": "@teamscala/service-boot",
4162
+ "suite_type": "function_call",
4163
+ "slug": "service-boot:to-capability-slug-strips-the-language-and-tier-suffix-from-a-prod-deployable-scala-projects-ts-prod"
412
4164
  }
413
4165
  ]
414
4166
  }