@treeseed/sdk 0.6.1 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/operations/services/bootstrap-runner.d.ts +33 -0
  2. package/dist/operations/services/bootstrap-runner.js +136 -0
  3. package/dist/operations/services/config-runtime.d.ts +27 -8
  4. package/dist/operations/services/config-runtime.js +303 -127
  5. package/dist/operations/services/github-api.d.ts +34 -0
  6. package/dist/operations/services/github-api.js +187 -4
  7. package/dist/operations/services/github-automation.d.ts +30 -0
  8. package/dist/operations/services/github-automation.js +107 -1
  9. package/dist/operations/services/project-platform.d.ts +38 -2
  10. package/dist/operations/services/project-platform.js +319 -15
  11. package/dist/operations/services/railway-deploy.d.ts +6 -2
  12. package/dist/operations/services/railway-deploy.js +26 -18
  13. package/dist/operations/services/runtime-tools.d.ts +0 -2
  14. package/dist/operations/services/runtime-tools.js +0 -2
  15. package/dist/platform/env.yaml +71 -96
  16. package/dist/platform/environment.d.ts +4 -0
  17. package/dist/platform/environment.js +54 -0
  18. package/dist/reconcile/bootstrap-systems.d.ts +32 -0
  19. package/dist/reconcile/bootstrap-systems.js +175 -0
  20. package/dist/reconcile/builtin-adapters.js +1 -9
  21. package/dist/reconcile/desired-state.js +16 -14
  22. package/dist/reconcile/engine.d.ts +9 -4
  23. package/dist/reconcile/engine.js +57 -14
  24. package/dist/reconcile/index.d.ts +1 -0
  25. package/dist/reconcile/index.js +1 -0
  26. package/dist/scripts/config-treeseed.js +30 -0
  27. package/dist/scripts/package-tools.js +0 -2
  28. package/dist/scripts/tenant-deploy.js +16 -36
  29. package/dist/scripts/test-cloudflare-local.js +0 -2
  30. package/dist/workflow/operations.js +23 -4
  31. package/dist/workflow.d.ts +5 -0
  32. package/package.json +1 -1
  33. package/templates/github/deploy.workflow.yml +15 -15
@@ -23,6 +23,70 @@ entries:
23
23
  sourcePriority:
24
24
  - machine-config
25
25
  - process-env
26
+ TREESEED_GITHUB_OWNER:
27
+ label: GitHub repository owner
28
+ group: github
29
+ description: GitHub user or organization that owns the Treeseed repository used for bootstrap, CI/CD, and environment sync.
30
+ howToGet: Treeseed suggests this from the origin remote when available. Otherwise enter the GitHub user or organization that should own the repository.
31
+ sensitivity: plain
32
+ targets:
33
+ - local-runtime
34
+ scopes:
35
+ - local
36
+ storage: scoped
37
+ requirement: required
38
+ purposes:
39
+ - config
40
+ validation:
41
+ kind: nonempty
42
+ sourcePriority:
43
+ - machine-config
44
+ - process-env
45
+ defaultValueRef: githubOwnerDefault
46
+ TREESEED_GITHUB_REPOSITORY_NAME:
47
+ label: GitHub repository name
48
+ group: github
49
+ description: GitHub repository name Treeseed should verify or create before GitHub bootstrap.
50
+ howToGet: Treeseed suggests this from the origin remote when available and otherwise defaults it from the site slug.
51
+ sensitivity: plain
52
+ targets:
53
+ - local-runtime
54
+ scopes:
55
+ - local
56
+ storage: scoped
57
+ requirement: required
58
+ purposes:
59
+ - config
60
+ validation:
61
+ kind: nonempty
62
+ sourcePriority:
63
+ - machine-config
64
+ - process-env
65
+ defaultValueRef: githubRepositoryNameDefault
66
+ TREESEED_GITHUB_REPOSITORY_VISIBILITY:
67
+ label: GitHub repository visibility
68
+ group: github
69
+ description: Visibility to use if Treeseed needs to create the GitHub repository during bootstrap.
70
+ howToGet: Choose private, public, or internal. Treeseed defaults new repositories to private.
71
+ sensitivity: plain
72
+ targets:
73
+ - local-runtime
74
+ scopes:
75
+ - local
76
+ storage: scoped
77
+ requirement: optional
78
+ purposes:
79
+ - config
80
+ validation:
81
+ kind: enum
82
+ values:
83
+ - private
84
+ - public
85
+ - internal
86
+ sourcePriority:
87
+ - machine-config
88
+ - process-env
89
+ defaultValueRef: githubRepositoryVisibilityDefault
26
90
  CLOUDFLARE_API_TOKEN:
27
91
  label: Cloudflare API token
28
92
  group: auth
@@ -33,7 +97,6 @@ entries:
33
97
  - local-runtime
34
98
  - github-secret
35
99
  scopes:
36
- - local
37
100
  - staging
38
101
  - prod
39
102
  storage: shared
@@ -53,13 +116,13 @@ entries:
53
116
  label: Railway API token
54
117
  group: auth
55
118
  description: Primary Railway token for user or workspace scoped access, including project creation and most Treeseed-managed Railway flows.
56
- howToGet: In Railway, create a user or workspace API token that can create and manage the target project, then paste it here. Treeseed also accepts the legacy alias RAILWAY_API_KEY from process env.
119
+ howToGet: In Railway, create a user or workspace API token that can create and manage the target project, then paste it here.
57
120
  sensitivity: secret
58
121
  targets:
59
122
  - local-runtime
123
+ - github-secret
60
124
  - railway-secret
61
125
  scopes:
62
- - local
63
126
  - staging
64
127
  - prod
65
128
  storage: shared
@@ -83,10 +146,8 @@ entries:
83
146
  howToGet: In Railway, use the workspace slug or name shown in the workspace switcher. Treeseed defaults this repository to knowledge-coop unless you override it here.
84
147
  sensitivity: plain
85
148
  targets:
86
- - local-runtime
87
149
  - railway-var
88
150
  scopes:
89
- - local
90
151
  - staging
91
152
  - prod
92
153
  storage: shared
@@ -108,9 +169,9 @@ entries:
108
169
  group: cloudflare
109
170
  description: Identifies the Cloudflare account Treeseed should provision and deploy into.
110
171
  howToGet: In the Cloudflare dashboard, open Workers & Pages or Account Home and copy the account ID.
172
+ startupProfile: core
111
173
  sensitivity: plain
112
174
  targets:
113
- - local-runtime
114
175
  - github-variable
115
176
  - config-file
116
177
  scopes:
@@ -251,12 +312,10 @@ entries:
251
312
  howToGet: Treeseed can derive this from the hosting block in treeseed.site.yaml. Override it only when the runtime environment must force a different deployment profile.
252
313
  sensitivity: plain
253
314
  targets:
254
- - local-runtime
255
315
  - github-variable
256
316
  - railway-var
257
317
  - config-file
258
318
  scopes:
259
- - local
260
319
  - staging
261
320
  - prod
262
321
  storage: shared
@@ -282,12 +341,10 @@ entries:
282
341
  howToGet: Treeseed can derive this from the hosting block in treeseed.site.yaml.
283
342
  sensitivity: plain
284
343
  targets:
285
- - local-runtime
286
344
  - github-variable
287
345
  - railway-var
288
346
  - config-file
289
347
  scopes:
290
- - local
291
348
  - staging
292
349
  - prod
293
350
  storage: shared
@@ -312,17 +369,14 @@ entries:
312
369
  howToGet: Use the hosted market API URL if Treeseed manages the project for you. Self-hosted deployments should only set this when registration with the market control plane is enabled.
313
370
  sensitivity: plain
314
371
  targets:
315
- - local-runtime
316
372
  - github-variable
317
373
  - railway-var
318
374
  scopes:
319
- - local
320
375
  - staging
321
376
  - prod
322
377
  storage: shared
323
378
  requirement: conditional
324
379
  purposes:
325
- - dev
326
380
  - deploy
327
381
  - config
328
382
  validation:
@@ -341,17 +395,14 @@ entries:
341
395
  howToGet: Treeseed defaults this to the site slug unless you need a different hosted team identifier.
342
396
  sensitivity: plain
343
397
  targets:
344
- - local-runtime
345
398
  - github-variable
346
399
  - railway-var
347
400
  scopes:
348
- - local
349
401
  - staging
350
402
  - prod
351
403
  storage: shared
352
404
  requirement: conditional
353
405
  purposes:
354
- - dev
355
406
  - deploy
356
407
  - config
357
408
  validation:
@@ -369,17 +420,14 @@ entries:
369
420
  howToGet: Treeseed defaults this to the site slug unless you need a different hosted project identifier.
370
421
  sensitivity: plain
371
422
  targets:
372
- - local-runtime
373
423
  - github-variable
374
424
  - railway-var
375
425
  scopes:
376
- - local
377
426
  - staging
378
427
  - prod
379
428
  storage: shared
380
429
  requirement: conditional
381
430
  purposes:
382
- - dev
383
431
  - deploy
384
432
  - config
385
433
  validation:
@@ -397,17 +445,14 @@ entries:
397
445
  howToGet: Generate or rotate this token from the market control plane after connecting a project environment.
398
446
  sensitivity: secret
399
447
  targets:
400
- - local-runtime
401
448
  - github-secret
402
449
  - railway-secret
403
450
  scopes:
404
- - local
405
451
  - staging
406
452
  - prod
407
453
  storage: scoped
408
454
  requirement: conditional
409
455
  purposes:
410
- - dev
411
456
  - deploy
412
457
  - config
413
458
  validation:
@@ -423,17 +468,14 @@ entries:
423
468
  howToGet: Set this to 0 for scale-to-zero by default unless the project requires warm workers.
424
469
  sensitivity: plain
425
470
  targets:
426
- - local-runtime
427
471
  - github-variable
428
472
  - railway-var
429
473
  scopes:
430
- - local
431
474
  - staging
432
475
  - prod
433
476
  storage: scoped
434
477
  requirement: conditional
435
478
  purposes:
436
- - dev
437
479
  - deploy
438
480
  - config
439
481
  validation:
@@ -450,17 +492,14 @@ entries:
450
492
  howToGet: Choose a value that reflects your budget and expected concurrency ceiling.
451
493
  sensitivity: plain
452
494
  targets:
453
- - local-runtime
454
495
  - github-variable
455
496
  - railway-var
456
497
  scopes:
457
- - local
458
498
  - staging
459
499
  - prod
460
500
  storage: scoped
461
501
  requirement: conditional
462
502
  purposes:
463
- - dev
464
503
  - deploy
465
504
  - config
466
505
  validation:
@@ -477,17 +516,14 @@ entries:
477
516
  howToGet: Start with 1 for conservative scaling, then raise it only after observing stable worker latency.
478
517
  sensitivity: plain
479
518
  targets:
480
- - local-runtime
481
519
  - github-variable
482
520
  - railway-var
483
521
  scopes:
484
- - local
485
522
  - staging
486
523
  - prod
487
524
  storage: scoped
488
525
  requirement: conditional
489
526
  purposes:
490
- - dev
491
527
  - deploy
492
528
  - config
493
529
  validation:
@@ -504,17 +540,14 @@ entries:
504
540
  howToGet: Start with 60 seconds to prevent worker thrash in lightly bursty environments.
505
541
  sensitivity: plain
506
542
  targets:
507
- - local-runtime
508
543
  - github-variable
509
544
  - railway-var
510
545
  scopes:
511
- - local
512
546
  - staging
513
547
  - prod
514
548
  storage: scoped
515
549
  requirement: conditional
516
550
  purposes:
517
- - dev
518
551
  - deploy
519
552
  - config
520
553
  validation:
@@ -531,17 +564,14 @@ entries:
531
564
  howToGet: Use the project team's operating timezone, such as America/New_York.
532
565
  sensitivity: plain
533
566
  targets:
534
- - local-runtime
535
567
  - github-variable
536
568
  - railway-var
537
569
  scopes:
538
- - local
539
570
  - staging
540
571
  - prod
541
572
  storage: scoped
542
573
  requirement: optional
543
574
  purposes:
544
- - dev
545
575
  - deploy
546
576
  - config
547
577
  validation:
@@ -557,17 +587,14 @@ entries:
557
587
  howToGet: Provide a JSON value like [{"days":[1,2,3,4,5],"startTime":"09:00","endTime":"17:00"}].
558
588
  sensitivity: plain
559
589
  targets:
560
- - local-runtime
561
590
  - github-variable
562
591
  - railway-var
563
592
  scopes:
564
- - local
565
593
  - staging
566
594
  - prod
567
595
  storage: scoped
568
596
  requirement: optional
569
597
  purposes:
570
- - dev
571
598
  - deploy
572
599
  - config
573
600
  validation:
@@ -583,17 +610,14 @@ entries:
583
610
  howToGet: Choose the daily throughput ceiling that matches the team's Copilot and infrastructure budget.
584
611
  sensitivity: plain
585
612
  targets:
586
- - local-runtime
587
613
  - github-variable
588
614
  - railway-var
589
615
  scopes:
590
- - local
591
616
  - staging
592
617
  - prod
593
618
  storage: scoped
594
619
  requirement: optional
595
620
  purposes:
596
- - dev
597
621
  - deploy
598
622
  - config
599
623
  validation:
@@ -609,17 +633,14 @@ entries:
609
633
  howToGet: Start small so queue top-ups stay budget-aware and incremental.
610
634
  sensitivity: plain
611
635
  targets:
612
- - local-runtime
613
636
  - github-variable
614
637
  - railway-var
615
638
  scopes:
616
- - local
617
639
  - staging
618
640
  - prod
619
641
  storage: scoped
620
642
  requirement: optional
621
643
  purposes:
622
- - dev
623
644
  - deploy
624
645
  - config
625
646
  validation:
@@ -635,17 +656,14 @@ entries:
635
656
  howToGet: Set this lower than or equal to the daily task-credit budget.
636
657
  sensitivity: plain
637
658
  targets:
638
- - local-runtime
639
659
  - github-variable
640
660
  - railway-var
641
661
  scopes:
642
- - local
643
662
  - staging
644
663
  - prod
645
664
  storage: scoped
646
665
  requirement: optional
647
666
  purposes:
648
- - dev
649
667
  - deploy
650
668
  - config
651
669
  validation:
@@ -661,17 +679,14 @@ entries:
661
679
  howToGet: Leave unset to use the default objective/question/note/page/book/knowledge set.
662
680
  sensitivity: plain
663
681
  targets:
664
- - local-runtime
665
682
  - github-variable
666
683
  - railway-var
667
684
  scopes:
668
- - local
669
685
  - staging
670
686
  - prod
671
687
  storage: scoped
672
688
  requirement: optional
673
689
  purposes:
674
- - dev
675
690
  - deploy
676
691
  - config
677
692
  validation:
@@ -687,17 +702,14 @@ entries:
687
702
  howToGet: Provide a JSON value such as [{"type":"question","credits":3}].
688
703
  sensitivity: plain
689
704
  targets:
690
- - local-runtime
691
705
  - github-variable
692
706
  - railway-var
693
707
  scopes:
694
- - local
695
708
  - staging
696
709
  - prod
697
710
  storage: scoped
698
711
  requirement: optional
699
712
  purposes:
700
- - dev
701
713
  - deploy
702
714
  - config
703
715
  validation:
@@ -713,17 +725,14 @@ entries:
713
725
  howToGet: Set this to railway for hosted projects or noop/manual for self-hosted environments without automatic scale control.
714
726
  sensitivity: plain
715
727
  targets:
716
- - local-runtime
717
728
  - github-variable
718
729
  - railway-var
719
730
  scopes:
720
- - local
721
731
  - staging
722
732
  - prod
723
733
  storage: scoped
724
734
  requirement: optional
725
735
  purposes:
726
- - dev
727
736
  - deploy
728
737
  - config
729
738
  validation:
@@ -739,21 +748,19 @@ entries:
739
748
  TREESEED_RAILWAY_PROJECT_ID:
740
749
  label: Railway project ID
741
750
  group: hosting
751
+ visibility: system
742
752
  description: Railway project identifier used by runtime scaling and reconciliation helpers for the active environment.
743
753
  howToGet: Copy the project ID from Railway when automatic worker scaling is enabled.
744
754
  sensitivity: plain
745
755
  targets:
746
- - local-runtime
747
756
  - github-variable
748
757
  - railway-var
749
758
  scopes:
750
- - local
751
759
  - staging
752
760
  - prod
753
761
  storage: scoped
754
762
  requirement: optional
755
763
  purposes:
756
- - dev
757
764
  - deploy
758
765
  - config
759
766
  validation:
@@ -764,21 +771,19 @@ entries:
764
771
  TREESEED_RAILWAY_ENVIRONMENT_ID:
765
772
  label: Railway environment ID
766
773
  group: hosting
774
+ visibility: system
767
775
  description: Railway environment identifier used by the runtime scaler when adjusting worker replicas.
768
776
  howToGet: Copy the environment ID from Railway for the matching staging or production environment.
769
777
  sensitivity: plain
770
778
  targets:
771
- - local-runtime
772
779
  - github-variable
773
780
  - railway-var
774
781
  scopes:
775
- - local
776
782
  - staging
777
783
  - prod
778
784
  storage: scoped
779
785
  requirement: optional
780
786
  purposes:
781
- - dev
782
787
  - deploy
783
788
  - config
784
789
  validation:
@@ -789,21 +794,19 @@ entries:
789
794
  TREESEED_RAILWAY_WORKER_SERVICE_ID:
790
795
  label: Railway worker service ID
791
796
  group: hosting
797
+ visibility: system
792
798
  description: Railway service identifier for the scalable worker pool that the manager adjusts at runtime.
793
799
  howToGet: Copy the worker service ID from Railway after the hosted project environment is provisioned.
794
800
  sensitivity: plain
795
801
  targets:
796
- - local-runtime
797
802
  - github-variable
798
803
  - railway-var
799
804
  scopes:
800
- - local
801
805
  - staging
802
806
  - prod
803
807
  storage: scoped
804
808
  requirement: optional
805
809
  purposes:
806
- - dev
807
810
  - deploy
808
811
  - config
809
812
  validation:
@@ -842,6 +845,7 @@ entries:
842
845
  - process-env
843
846
  defaultValueRef: generatedSecret
844
847
  localDefaultValueRef: generatedSecret
848
+ relevanceRef: formsEnabled
845
849
  TREESEED_PUBLIC_TURNSTILE_SITE_KEY:
846
850
  label: Turnstile site key
847
851
  group: forms
@@ -850,18 +854,14 @@ entries:
850
854
  howToGet: Create a Turnstile widget in Cloudflare Turnstile and copy the site key.
851
855
  sensitivity: plain
852
856
  targets:
853
- - local-runtime
854
- - local-cloudflare
855
857
  - github-variable
856
858
  - cloudflare-var
857
859
  scopes:
858
- - local
859
860
  - staging
860
861
  - prod
861
862
  storage: shared
862
863
  requirement: conditional
863
864
  purposes:
864
- - dev
865
865
  - save
866
866
  - deploy
867
867
  - config
@@ -880,18 +880,14 @@ entries:
880
880
  howToGet: Create a Turnstile widget in Cloudflare Turnstile and copy the secret key.
881
881
  sensitivity: secret
882
882
  targets:
883
- - local-runtime
884
- - local-cloudflare
885
883
  - github-secret
886
884
  - cloudflare-secret
887
885
  scopes:
888
- - local
889
886
  - staging
890
887
  - prod
891
888
  storage: shared
892
889
  requirement: conditional
893
890
  purposes:
894
- - dev
895
891
  - save
896
892
  - deploy
897
893
  - config
@@ -902,27 +898,6 @@ entries:
902
898
  - process-env
903
899
  relevanceRef: turnstileEnabled
904
900
  requiredWhenRef: turnstileNonLocal
905
- TREESEED_PUBLIC_FORMS_LOCAL_BYPASS_TURNSTILE:
906
- label: Local Turnstile bypass
907
- group: local-development
908
- description: Lets contributors edit content and exercise forms locally without a live Turnstile widget.
909
- howToGet: Treeseed defaults this to true for local development. You can switch it off if you want to test with real Turnstile keys locally.
910
- sensitivity: plain
911
- targets:
912
- - local-runtime
913
- - local-cloudflare
914
- scopes:
915
- - local
916
- requirement: optional
917
- purposes:
918
- - dev
919
- - config
920
- validation:
921
- kind: boolean
922
- sourcePriority:
923
- - machine-config
924
- - process-env
925
- localDefaultValueRef: localFormsBypassDefault
926
901
  TREESEED_SMTP_HOST:
927
902
  label: SMTP host
928
903
  group: smtp
@@ -7,6 +7,7 @@ export declare const TREESEED_ENVIRONMENT_PURPOSES: readonly ["dev", "save", "de
7
7
  export declare const TREESEED_ENVIRONMENT_SENSITIVITY: readonly ["secret", "plain", "derived"];
8
8
  export declare const TREESEED_ENVIRONMENT_STORAGE: readonly ["scoped", "shared"];
9
9
  export declare const TREESEED_CONFIG_STARTUP_PROFILES: readonly ["core", "optional", "advanced"];
10
+ export declare const TREESEED_ENVIRONMENT_VISIBILITY: readonly ["user", "system"];
10
11
  export type TreeseedEnvironmentScope = (typeof TREESEED_ENVIRONMENT_SCOPES)[number];
11
12
  export type TreeseedEnvironmentRequirement = (typeof TREESEED_ENVIRONMENT_REQUIREMENTS)[number];
12
13
  export type TreeseedEnvironmentTarget = (typeof TREESEED_ENVIRONMENT_TARGETS)[number];
@@ -14,6 +15,7 @@ export type TreeseedEnvironmentPurpose = (typeof TREESEED_ENVIRONMENT_PURPOSES)[
14
15
  export type TreeseedEnvironmentSensitivity = (typeof TREESEED_ENVIRONMENT_SENSITIVITY)[number];
15
16
  export type TreeseedEnvironmentStorage = (typeof TREESEED_ENVIRONMENT_STORAGE)[number];
16
17
  export type TreeseedConfigStartupProfile = (typeof TREESEED_CONFIG_STARTUP_PROFILES)[number];
18
+ export type TreeseedEnvironmentVisibility = (typeof TREESEED_ENVIRONMENT_VISIBILITY)[number];
17
19
  export type TreeseedEnvironmentValidation = {
18
20
  kind: 'string' | 'nonempty' | 'url' | 'email';
19
21
  minLength?: number;
@@ -68,6 +70,7 @@ export type TreeseedEnvironmentEntry = {
68
70
  cluster?: string;
69
71
  onboardingFeature?: string;
70
72
  startupProfile?: TreeseedConfigStartupProfile;
73
+ visibility?: TreeseedEnvironmentVisibility;
71
74
  description: string;
72
75
  howToGet: string;
73
76
  sensitivity: TreeseedEnvironmentSensitivity;
@@ -87,6 +90,7 @@ export type TreeseedEnvironmentEntryYaml = Omit<TreeseedEnvironmentEntry, 'id' |
87
90
  cluster?: string;
88
91
  onboardingFeature?: string;
89
92
  startupProfile?: TreeseedConfigStartupProfile;
93
+ visibility?: TreeseedEnvironmentVisibility;
90
94
  defaultValueRef?: string;
91
95
  localDefaultValueRef?: string;
92
96
  relevanceRef?: string;
@@ -1,4 +1,5 @@
1
1
  import { randomBytes } from "node:crypto";
2
+ import { spawnSync } from "node:child_process";
2
3
  import { existsSync, readFileSync } from "node:fs";
3
4
  import { dirname, resolve } from "node:path";
4
5
  import { fileURLToPath } from "node:url";
@@ -23,6 +24,7 @@ const TREESEED_ENVIRONMENT_PURPOSES = ["dev", "save", "deploy", "destroy", "conf
23
24
  const TREESEED_ENVIRONMENT_SENSITIVITY = ["secret", "plain", "derived"];
24
25
  const TREESEED_ENVIRONMENT_STORAGE = ["scoped", "shared"];
25
26
  const TREESEED_CONFIG_STARTUP_PROFILES = ["core", "optional", "advanced"];
27
+ const TREESEED_ENVIRONMENT_VISIBILITY = ["user", "system"];
26
28
  const moduleDir = dirname(fileURLToPath(import.meta.url));
27
29
  function resolveCoreEnvironmentPath() {
28
30
  const candidates = [
@@ -47,6 +49,21 @@ function turnstileEnabled(context) {
47
49
  function smtpEnabled(context) {
48
50
  return context.deployConfig.smtp?.enabled === true;
49
51
  }
52
+ function platformSurfaceEnabled(context, surface) {
53
+ return context.deployConfig.surfaces?.[surface]?.enabled !== false;
54
+ }
55
+ function managedServiceEnabled(context, service) {
56
+ return context.deployConfig.services?.[service]?.enabled !== false;
57
+ }
58
+ function webSurfaceEnabled(context) {
59
+ return platformSurfaceEnabled(context, "web");
60
+ }
61
+ function apiSurfaceEnabled(context) {
62
+ return platformSurfaceEnabled(context, "api") && managedServiceEnabled(context, "api");
63
+ }
64
+ function formsEnabled(context) {
65
+ return webSurfaceEnabled(context) && (context.deployConfig.providers?.forms ?? "store_only") !== "none";
66
+ }
50
67
  function railwayManagedEnabled(context) {
51
68
  if (context.deployConfig.runtime?.mode === "treeseed_managed") {
52
69
  return true;
@@ -183,6 +200,35 @@ function resolveHostedProjectId(context) {
183
200
  function resolveRailwayWorkspaceDefault() {
184
201
  return "knowledge-coop";
185
202
  }
203
+ function parseGitHubRepositorySlugFromRemote(remoteUrl) {
204
+ const normalized = String(remoteUrl ?? "").trim();
205
+ const sshMatch = normalized.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/u);
206
+ if (sshMatch) {
207
+ return { owner: sshMatch[1], name: sshMatch[2] };
208
+ }
209
+ const httpsMatch = normalized.match(/^https:\/\/github\.com\/([^/]+)\/(.+?)(?:\.git)?$/u);
210
+ if (httpsMatch) {
211
+ return { owner: httpsMatch[1], name: httpsMatch[2] };
212
+ }
213
+ return null;
214
+ }
215
+ function resolveGitHubOriginRepository(context) {
216
+ const result = spawnSync("git", ["remote", "get-url", "origin"], {
217
+ cwd: context.tenantRoot,
218
+ stdio: "pipe",
219
+ encoding: "utf8"
220
+ });
221
+ if (result.status !== 0) {
222
+ return null;
223
+ }
224
+ return parseGitHubRepositorySlugFromRemote(result.stdout);
225
+ }
226
+ function resolveGitHubOwnerDefault(context) {
227
+ return resolveGitHubOriginRepository(context)?.owner;
228
+ }
229
+ function resolveGitHubRepositoryNameDefault(context) {
230
+ return resolveGitHubOriginRepository(context)?.name || context.deployConfig.slug;
231
+ }
186
232
  const VALUE_RESOLVERS = {
187
233
  generatedSecret: () => generatedSecret(),
188
234
  localFormsBypassDefault: () => "true",
@@ -206,6 +252,9 @@ const VALUE_RESOLVERS = {
206
252
  hostingTeamIdDefault: (context) => resolveHostedTeamId(context),
207
253
  hostingProjectIdDefault: (context) => resolveHostedProjectId(context),
208
254
  railwayWorkspaceDefault: () => resolveRailwayWorkspaceDefault(),
255
+ githubOwnerDefault: (context) => resolveGitHubOwnerDefault(context),
256
+ githubRepositoryNameDefault: (context) => resolveGitHubRepositoryNameDefault(context),
257
+ githubRepositoryVisibilityDefault: () => "private",
209
258
  agentPoolMinWorkersDefault: () => "0",
210
259
  agentPoolMaxWorkersDefault: () => "2",
211
260
  agentPoolTargetQueueDepthDefault: () => "1",
@@ -224,6 +273,9 @@ const PREDICATES = {
224
273
  turnstileNonLocal: (context, scope) => turnstileEnabled(context) && scope !== "local",
225
274
  smtpEnabled: (context) => smtpEnabled(context),
226
275
  smtpNonLocal: (context, scope) => smtpEnabled(context) && scope !== "local",
276
+ webSurfaceEnabled: (context) => webSurfaceEnabled(context),
277
+ apiSurfaceEnabled: (context) => apiSurfaceEnabled(context),
278
+ formsEnabled: (context) => formsEnabled(context),
227
279
  railwayManagedEnabled: (context) => railwayManagedEnabled(context),
228
280
  hubTreeseedHosted: (context) => resolveHubMode(context) === "treeseed_hosted",
229
281
  hubCustomerHosted: (context) => resolveHubMode(context) === "customer_hosted",
@@ -316,6 +368,7 @@ function materializeEntry(id, entry) {
316
368
  id,
317
369
  cluster: entry.cluster ?? `${entry.group}:${id}`,
318
370
  onboardingFeature: entry.onboardingFeature,
371
+ visibility: entry.visibility ?? "user",
319
372
  startupProfile: entry.startupProfile ?? (entry.onboardingFeature ? "optional" : entry.group === "auth" || entry.id === "TREESEED_FORM_TOKEN_SECRET" || entry.group === "local-development" ? "core" : "advanced"),
320
373
  storage: entry.storage ?? "scoped",
321
374
  defaultValue: resolveNamedValueResolver(entry.defaultValueRef),
@@ -527,6 +580,7 @@ export {
527
580
  TREESEED_ENVIRONMENT_SENSITIVITY,
528
581
  TREESEED_ENVIRONMENT_STORAGE,
529
582
  TREESEED_ENVIRONMENT_TARGETS,
583
+ TREESEED_ENVIRONMENT_VISIBILITY,
530
584
  getTreeseedEnvironmentSuggestedValues,
531
585
  isTreeseedEnvironmentEntryRelevant,
532
586
  isTreeseedEnvironmentEntryRequired,