@treeseed/sdk 0.10.28 → 0.11.0

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 (148) hide show
  1. package/README.md +207 -6
  2. package/dist/capacity-provider.d.ts +3 -1
  3. package/dist/capacity-provider.js +25 -5
  4. package/dist/control-plane.d.ts +1 -0
  5. package/dist/control-plane.js +38 -13
  6. package/dist/db/market-schema.d.ts +8860 -6172
  7. package/dist/db/market-schema.js +108 -0
  8. package/dist/db/node-sqlite.js +7 -2
  9. package/dist/hosting/apps.d.ts +12 -0
  10. package/dist/hosting/apps.js +107 -0
  11. package/dist/hosting/builtins.d.ts +25 -0
  12. package/dist/hosting/builtins.js +791 -0
  13. package/dist/hosting/contracts.d.ts +207 -0
  14. package/dist/hosting/contracts.js +0 -0
  15. package/dist/hosting/graph.d.ts +192 -0
  16. package/dist/hosting/graph.js +1106 -0
  17. package/dist/hosting/index.d.ts +4 -0
  18. package/dist/hosting/index.js +4 -0
  19. package/dist/index.d.ts +10 -3
  20. package/dist/index.js +63 -6
  21. package/dist/managed-dependencies.js +1 -2
  22. package/dist/market-client.d.ts +63 -3
  23. package/dist/market-client.js +83 -11
  24. package/dist/operations/services/bootstrap-runner.d.ts +3 -1
  25. package/dist/operations/services/bootstrap-runner.js +22 -2
  26. package/dist/operations/services/config-runtime.d.ts +10 -5
  27. package/dist/operations/services/config-runtime.js +209 -66
  28. package/dist/operations/services/deploy.d.ts +70 -7
  29. package/dist/operations/services/deploy.js +579 -64
  30. package/dist/operations/services/deployment-readiness.d.ts +30 -0
  31. package/dist/operations/services/deployment-readiness.js +175 -0
  32. package/dist/operations/services/git-workflow.d.ts +2 -1
  33. package/dist/operations/services/git-workflow.js +9 -3
  34. package/dist/operations/services/github-actions-verification.d.ts +1 -0
  35. package/dist/operations/services/github-actions-verification.js +1 -0
  36. package/dist/operations/services/github-api.js +1 -1
  37. package/dist/operations/services/github-automation.d.ts +1 -1
  38. package/dist/operations/services/github-automation.js +4 -3
  39. package/dist/operations/services/github-credentials.d.ts +13 -0
  40. package/dist/operations/services/github-credentials.js +58 -0
  41. package/dist/operations/services/hosted-service-checks.d.ts +63 -0
  42. package/dist/operations/services/hosted-service-checks.js +327 -0
  43. package/dist/operations/services/hub-provider-launch.js +3 -3
  44. package/dist/operations/services/live-hosted-service-checks.d.ts +25 -0
  45. package/dist/operations/services/live-hosted-service-checks.js +350 -0
  46. package/dist/operations/services/managed-host-security.js +1 -1
  47. package/dist/operations/services/operations-runner-smoke.d.ts +30 -0
  48. package/dist/operations/services/operations-runner-smoke.js +180 -0
  49. package/dist/operations/services/package-adapters.d.ts +95 -0
  50. package/dist/operations/services/package-adapters.js +288 -0
  51. package/dist/operations/services/package-reference-policy.d.ts +1 -0
  52. package/dist/operations/services/package-reference-policy.js +15 -2
  53. package/dist/operations/services/project-platform.d.ts +80 -22
  54. package/dist/operations/services/project-platform.js +49 -8
  55. package/dist/operations/services/project-web-monitor.js +26 -4
  56. package/dist/operations/services/railway-api.d.ts +88 -5
  57. package/dist/operations/services/railway-api.js +626 -35
  58. package/dist/operations/services/railway-deploy.d.ts +46 -40
  59. package/dist/operations/services/railway-deploy.js +261 -293
  60. package/dist/operations/services/release-candidate.d.ts +19 -0
  61. package/dist/operations/services/release-candidate.js +375 -38
  62. package/dist/operations/services/repository-save-orchestrator.d.ts +3 -1
  63. package/dist/operations/services/repository-save-orchestrator.js +279 -66
  64. package/dist/operations/services/runtime-tools.d.ts +1 -0
  65. package/dist/operations/services/runtime-tools.js +10 -9
  66. package/dist/operations/services/verification-cache.d.ts +25 -0
  67. package/dist/operations/services/verification-cache.js +71 -0
  68. package/dist/operations/services/workspace-dependency-mode.js +9 -1
  69. package/dist/operations/services/workspace-save.js +1 -1
  70. package/dist/operations/services/workspace-tools.js +2 -1
  71. package/dist/platform/contracts.d.ts +32 -1
  72. package/dist/platform/deploy-config.js +73 -8
  73. package/dist/platform/env.yaml +163 -35
  74. package/dist/platform/environment.d.ts +1 -0
  75. package/dist/platform/environment.js +74 -5
  76. package/dist/platform/plugin.d.ts +9 -0
  77. package/dist/platform-operation-store.js +2 -2
  78. package/dist/platform-operations.js +1 -1
  79. package/dist/reconcile/bootstrap-systems.js +2 -2
  80. package/dist/reconcile/builtin-adapters.js +372 -189
  81. package/dist/reconcile/contracts.d.ts +9 -5
  82. package/dist/reconcile/desired-state.d.ts +1 -0
  83. package/dist/reconcile/desired-state.js +5 -5
  84. package/dist/reconcile/engine.d.ts +5 -2
  85. package/dist/reconcile/engine.js +53 -32
  86. package/dist/reconcile/index.d.ts +2 -0
  87. package/dist/reconcile/index.js +2 -0
  88. package/dist/reconcile/live-acceptance.d.ts +79 -0
  89. package/dist/reconcile/live-acceptance.js +1615 -0
  90. package/dist/reconcile/platform.d.ts +104 -0
  91. package/dist/reconcile/platform.js +100 -0
  92. package/dist/reconcile/state.js +4 -4
  93. package/dist/reconcile/units.js +2 -2
  94. package/dist/scripts/deployment-readiness.js +20 -0
  95. package/dist/scripts/generate-treedx-openapi-types.js +186 -0
  96. package/dist/scripts/operations-runner-smoke.js +16 -0
  97. package/dist/scripts/release-verify.js +4 -1
  98. package/dist/scripts/tenant-workflow-action.js +10 -1
  99. package/dist/sdk-types.d.ts +169 -4
  100. package/dist/sdk-types.js +20 -2
  101. package/dist/sdk.d.ts +35 -24
  102. package/dist/sdk.js +186 -17
  103. package/dist/template-launch-requirements.js +9 -0
  104. package/dist/treedx/adapters.d.ts +6 -0
  105. package/dist/treedx/adapters.js +36 -0
  106. package/dist/treedx/client.d.ts +222 -0
  107. package/dist/treedx/client.js +871 -0
  108. package/dist/treedx/errors.d.ts +13 -0
  109. package/dist/treedx/errors.js +17 -0
  110. package/dist/treedx/federated-client.d.ts +27 -0
  111. package/dist/treedx/federated-client.js +158 -0
  112. package/dist/treedx/generated/openapi-types.d.ts +3558 -0
  113. package/dist/treedx/generated/openapi-types.js +0 -0
  114. package/dist/treedx/graph-adapter.d.ts +33 -0
  115. package/dist/treedx/graph-adapter.js +156 -0
  116. package/dist/treedx/index.d.ts +14 -0
  117. package/dist/treedx/index.js +48 -0
  118. package/dist/treedx/market-integration.d.ts +27 -0
  119. package/dist/treedx/market-integration.js +131 -0
  120. package/dist/treedx/ports.d.ts +166 -0
  121. package/dist/treedx/ports.js +231 -0
  122. package/dist/treedx/query-adapter.d.ts +19 -0
  123. package/dist/treedx/query-adapter.js +62 -0
  124. package/dist/treedx/registry-client.d.ts +11 -0
  125. package/dist/treedx/registry-client.js +19 -0
  126. package/dist/treedx/repository-adapter.d.ts +45 -0
  127. package/dist/treedx/repository-adapter.js +308 -0
  128. package/dist/treedx/sdk-integration.d.ts +27 -0
  129. package/dist/treedx/sdk-integration.js +63 -0
  130. package/dist/treedx/types.d.ts +1084 -0
  131. package/dist/treedx/types.js +8 -0
  132. package/dist/treedx/workspace-adapter.d.ts +27 -0
  133. package/dist/treedx/workspace-adapter.js +65 -0
  134. package/dist/treedx-backends.d.ts +218 -0
  135. package/dist/treedx-backends.js +632 -0
  136. package/dist/treedx-client.d.ts +86 -0
  137. package/dist/treedx-client.js +175 -0
  138. package/dist/treeseed/template-catalog/catalog.fixture.json +23 -23
  139. package/dist/workflow/operations.d.ts +119 -13
  140. package/dist/workflow/operations.js +309 -53
  141. package/dist/workflow-state.d.ts +13 -0
  142. package/dist/workflow-state.js +43 -26
  143. package/dist/workflow-support.d.ts +11 -3
  144. package/dist/workflow-support.js +67 -3
  145. package/dist/workflow.d.ts +5 -0
  146. package/drizzle/market/0004_treedx_market_integration.sql +99 -0
  147. package/package.json +34 -3
  148. package/templates/github/deploy-web.workflow.yml +39 -6
@@ -23,6 +23,51 @@ entries:
23
23
  sourcePriority:
24
24
  - machine-config
25
25
  - process-env
26
+ DOCKERHUB_USERNAME:
27
+ label: Docker Hub username
28
+ group: docker
29
+ description: Docker Hub username used by Treeseed package release workflows to publish container images such as treeseed/treedx and treeseed/treedx-profiler.
30
+ howToGet: Use the Docker Hub account or organization user that owns the Treeseed images.
31
+ sensitivity: plain
32
+ targets:
33
+ - local-runtime
34
+ - github-variable
35
+ scopes:
36
+ - staging
37
+ - prod
38
+ storage: shared
39
+ requirement: optional
40
+ purposes:
41
+ - deploy
42
+ - config
43
+ validation:
44
+ kind: nonempty
45
+ sourcePriority:
46
+ - machine-config
47
+ - process-env
48
+ DOCKERHUB_TOKEN:
49
+ label: Docker Hub token
50
+ group: docker
51
+ description: Docker Hub access token used by Treeseed package release workflows to publish TreeDX service, profiler, and staging development images.
52
+ howToGet: Create a Docker Hub access token with permission to push the Treeseed images, then store it through Treeseed config as DOCKERHUB_TOKEN.
53
+ sensitivity: secret
54
+ targets:
55
+ - local-runtime
56
+ - github-secret
57
+ scopes:
58
+ - staging
59
+ - prod
60
+ storage: shared
61
+ requirement: optional
62
+ purposes:
63
+ - deploy
64
+ - config
65
+ validation:
66
+ kind: nonempty
67
+ minLength: 8
68
+ sourcePriority:
69
+ - machine-config
70
+ - process-env
26
71
  RAILWAY_API_TOKEN:
27
72
  label: Railway API token
28
73
  group: auth
@@ -32,6 +77,9 @@ entries:
32
77
  targets:
33
78
  - local-runtime
34
79
  - github-secret
80
+ - railway-secret
81
+ serviceTargets:
82
+ - operationsRunner
35
83
  scopes:
36
84
  - local
37
85
  - staging
@@ -49,6 +97,56 @@ entries:
49
97
  - process-env
50
98
  relevanceRef: railwayManagedEnabled
51
99
  requiredWhenRef: railwayManagedEnabled
100
+ TREESEED_RAILWAY_WORKSPACE:
101
+ label: Railway workspace
102
+ group: railway
103
+ description: Railway workspace Treeseed should use when listing or creating projects during bootstrap and config reconciliation.
104
+ howToGet: In Railway, use the workspace slug or name shown in the workspace switcher.
105
+ sensitivity: plain
106
+ targets:
107
+ - local-runtime
108
+ - github-variable
109
+ - railway-var
110
+ scopes:
111
+ - staging
112
+ - prod
113
+ storage: shared
114
+ requirement: conditional
115
+ purposes:
116
+ - deploy
117
+ - destroy
118
+ - config
119
+ validation:
120
+ kind: nonempty
121
+ sourcePriority:
122
+ - machine-config
123
+ - process-env
124
+ relevanceRef: railwayManagedEnabled
125
+ requiredWhenRef: railwayManagedEnabled
126
+ TREESEED_RAILWAY_PROJECT_ID:
127
+ label: Railway project ID
128
+ group: hosting
129
+ visibility: system
130
+ description: Railway project identifier used by hosted deploy workflows and reconciliation helpers for the active environment.
131
+ howToGet: Treeseed can derive or persist this after Railway project reconciliation. Override it only when targeting a known Railway project ID.
132
+ sensitivity: plain
133
+ targets:
134
+ - github-variable
135
+ - railway-var
136
+ scopes:
137
+ - staging
138
+ - prod
139
+ storage: scoped
140
+ requirement: optional
141
+ purposes:
142
+ - deploy
143
+ - config
144
+ validation:
145
+ kind: nonempty
146
+ sourcePriority:
147
+ - machine-config
148
+ - process-env
149
+ relevanceRef: railwayManagedEnabled
52
150
  TREESEED_GITHUB_OWNER:
53
151
  label: GitHub repository owner
54
152
  group: github
@@ -116,8 +214,8 @@ entries:
116
214
  CLOUDFLARE_API_TOKEN:
117
215
  label: Cloudflare API token
118
216
  group: auth
119
- description: Account-level Cloudflare API token used by Wrangler, Workers AI, and CI to manage Pages, Workers, Workers KV, D1, Queues, DNS, secrets, and deploys.
120
- howToGet: "Create a Cloudflare account-level API token scoped to the target domain and account. Required permissions: Account Cloudflare Pages edit, Account Workers Scripts edit, Account Workers KV Storage edit, Account D1 edit, Account Queues edit, Zone DNS edit, Workers AI Read, and Workers AI Edit for model execution. If TREESEED_COMMIT_AI_GATEWAY_ID is configured, also grant AI Gateway Read/Run access for the gateway. Then paste it here as CLOUDFLARE_API_TOKEN."
217
+ description: Account-level Cloudflare API token used by Wrangler, Workers AI, and CI to manage Pages, Workers, Workers KV, D1, R2, Queues, Turnstile, DNS, cache settings, secrets, and deploys.
218
+ howToGet: "Create a Cloudflare account-level API token scoped to the target account and domain. Account permissions: Pages Write, Workers Scripts Write, Workers KV Storage Write, Workers R2 Storage Write, D1 Write, Queues Write, Turnstile Sites Write, Account Rulesets Write, and Account Rule Lists Write. Zone permissions for the target domain: Zone Read, DNS Write, Cache Settings Write, and SSL and Certificates Write. Cloudflare API docs may call Cache Settings Write the Cache Rules permission and Account Rule Lists Write the Account Filter Lists permission. If TREESEED_COMMIT_AI_GATEWAY_ID or Workers AI model execution is configured, also grant AI Gateway Run and Workers AI Write. Then paste it here as CLOUDFLARE_API_TOKEN."
121
219
  sensitivity: secret
122
220
  targets:
123
221
  - local-runtime
@@ -169,7 +267,7 @@ entries:
169
267
  TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME:
170
268
  label: Cloudflare Pages project name
171
269
  group: cloudflare
172
- description: Production Pages project used for the Treeseed web deployment.
270
+ description: Static Cloudflare Pages project used for all Treeseed web environments.
173
271
  howToGet: Treeseed can default this from the site slug. Override it if the Cloudflare Pages project should use a different name.
174
272
  sensitivity: plain
175
273
  targets:
@@ -190,10 +288,10 @@ entries:
190
288
  - process-env
191
289
  defaultValueRef: pagesProjectNameDefault
192
290
  TREESEED_CLOUDFLARE_PAGES_PREVIEW_PROJECT_NAME:
193
- label: Cloudflare staging Pages project
291
+ label: Cloudflare preview Pages project
194
292
  group: cloudflare
195
- description: Staging Pages project used for non-production Treeseed web deployments.
196
- howToGet: Treeseed can default this from the production Pages project name with a -staging suffix.
293
+ description: Legacy alias for the shared Cloudflare Pages project used by non-production branch deployments. Do not configure a separate project per environment.
294
+ howToGet: Treeseed defaults this to TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME so staging deploys use the shared Pages project preview environment.
197
295
  sensitivity: plain
198
296
  targets:
199
297
  - local-runtime
@@ -303,7 +401,7 @@ entries:
303
401
  validation:
304
402
  kind: enum
305
403
  values:
306
- - market_control_plane
404
+ - treeseed_control_plane
307
405
  - hosted_project
308
406
  - self_hosted_project
309
407
  sourcePriority:
@@ -340,7 +438,7 @@ entries:
340
438
  - treeseed.site.yaml
341
439
  defaultValueRef: hostingRegistrationDefault
342
440
  TREESEED_CENTRAL_MARKET_API_BASE_URL:
343
- label: Treeseed central market API base URL
441
+ label: Treeseed central API base URL
344
442
  group: hosting
345
443
  description: Base URL for the always-available central TreeSeed market used when no team-specific specialized market is selected.
346
444
  howToGet: The production TreeSeed market defaults to https://api.treeseed.ai. Set this only when an environment should use another central-compatible market endpoint.
@@ -364,8 +462,8 @@ entries:
364
462
  - process-env
365
463
  - treeseed.site.yaml
366
464
  defaultValueRef: centralMarketBaseUrlDefault
367
- TREESEED_MARKET_API_BASE_URL:
368
- label: Treeseed default market API base URL
465
+ TREESEED_API_BASE_URL:
466
+ label: Treeseed default API base URL
369
467
  group: hosting
370
468
  description: Primary market control-plane API URL used by hosted and optionally registered self-hosted project platforms.
371
469
  howToGet: The production TreeSeed market defaults to https://api.treeseed.ai. Set this to a staging, enterprise, or specialized market endpoint when that environment should register with a different market.
@@ -390,19 +488,19 @@ entries:
390
488
  relevanceRef: projectRegistrationEnabled
391
489
  requiredWhenRef: projectRegistrationEnabled
392
490
  defaultValueRef: marketBaseUrlDefault
393
- TREESEED_MARKET_DATABASE_URL:
394
- label: Market PostgreSQL database URL
491
+ TREESEED_DATABASE_URL:
492
+ label: Treeseed PostgreSQL database URL
395
493
  group: hosting
396
- cluster: hosting:market-control-plane
494
+ cluster: hosting:treeseed-control-plane
397
495
  visibility: system
398
- description: Railway PostgreSQL connection URL for Market control-plane tables. Browser/UI code must never receive this value.
399
- howToGet: Provision the managed Market PostgreSQL resource through Treeseed/Railway reconciliation and store the generated connection URL as a service secret.
496
+ description: Railway PostgreSQL connection URL for Treeseed control-plane tables. Browser/UI code must never receive this value.
497
+ howToGet: Provision the managed Treeseed PostgreSQL resource through Treeseed/Railway reconciliation and store the generated connection URL as a service secret.
400
498
  sensitivity: secret
401
499
  targets:
402
500
  - railway-secret
403
501
  serviceTargets:
404
502
  - api
405
- - marketOperationsRunner
503
+ - operationsRunner
406
504
  scopes:
407
505
  - staging
408
506
  - prod
@@ -418,18 +516,19 @@ entries:
418
516
  - process-env
419
517
  - treeseed.site.yaml
420
518
  TREESEED_PLATFORM_RUNNER_SECRET:
421
- label: Market operations runner secret
519
+ label: Treeseed operations runner secret
422
520
  group: hosting
423
- cluster: hosting:market-operations-runner
521
+ cluster: hosting:operations-runner
424
522
  visibility: system
425
- description: Bearer credential used only by the TreeSeed-owned Market operations runner to claim and update platform operation jobs.
523
+ description: Bearer credential used only by the TreeSeed-owned Treeseed operations runner to claim and update platform operation jobs.
426
524
  howToGet: Generate a strong secret with `openssl rand -base64 48` and store it through `treeseed config` for staging and production.
427
525
  sensitivity: secret
428
526
  targets:
527
+ - github-secret
429
528
  - railway-secret
430
529
  serviceTargets:
431
530
  - api
432
- - marketOperationsRunner
531
+ - operationsRunner
433
532
  scopes:
434
533
  - staging
435
534
  - prod
@@ -446,17 +545,17 @@ entries:
446
545
  - process-env
447
546
  defaultValueRef: generatedSecret
448
547
  TREESEED_PLATFORM_RUNNER_ID:
449
- label: Market operations runner ID
548
+ label: Treeseed operations runner ID
450
549
  group: hosting
451
- cluster: hosting:market-operations-runner
550
+ cluster: hosting:operations-runner
452
551
  visibility: system
453
- description: Stable identity for the TreeSeed-owned Market operations runner service in each environment.
552
+ description: Stable identity for the TreeSeed-owned Treeseed operations runner service in each environment.
454
553
  howToGet: Treeseed derives this from the environment. Override it only when replacing a runner identity deliberately.
455
554
  sensitivity: plain
456
555
  targets:
457
556
  - railway-var
458
557
  serviceTargets:
459
- - marketOperationsRunner
558
+ - operationsRunner
460
559
  scopes:
461
560
  - staging
462
561
  - prod
@@ -473,17 +572,17 @@ entries:
473
572
  - treeseed.site.yaml
474
573
  defaultValueRef: platformRunnerIdDefault
475
574
  TREESEED_PLATFORM_RUNNER_DATA_DIR:
476
- label: Market operations runner data directory
575
+ label: Treeseed operations runner data directory
477
576
  group: hosting
478
- cluster: hosting:market-operations-runner
577
+ cluster: hosting:operations-runner
479
578
  visibility: system
480
- description: Writable data directory mounted into the Market operations runner for repository workspaces and operation state.
579
+ description: Writable data directory mounted into the Treeseed operations runner for repository workspaces and operation state.
481
580
  howToGet: Use `/data` for Railway runner services with an attached volume.
482
581
  sensitivity: plain
483
582
  targets:
484
583
  - railway-var
485
584
  serviceTargets:
486
- - marketOperationsRunner
585
+ - operationsRunner
487
586
  scopes:
488
587
  - staging
489
588
  - prod
@@ -500,17 +599,17 @@ entries:
500
599
  - treeseed.site.yaml
501
600
  defaultValueRef: platformRunnerDataDirDefault
502
601
  TREESEED_PLATFORM_RUNNER_ENVIRONMENT:
503
- label: Market operations runner environment
602
+ label: Treeseed operations runner environment
504
603
  group: hosting
505
- cluster: hosting:market-operations-runner
604
+ cluster: hosting:operations-runner
506
605
  visibility: system
507
- description: Runtime environment label reported by the Market operations runner in registration and heartbeat records.
606
+ description: Runtime environment label reported by the Treeseed operations runner in registration and heartbeat records.
508
607
  howToGet: Treeseed derives this from the selected environment.
509
608
  sensitivity: plain
510
609
  targets:
511
610
  - railway-var
512
611
  serviceTargets:
513
- - marketOperationsRunner
612
+ - operationsRunner
514
613
  scopes:
515
614
  - staging
516
615
  - prod
@@ -526,11 +625,40 @@ entries:
526
625
  - process-env
527
626
  - treeseed.site.yaml
528
627
  defaultValueRef: platformRunnerEnvironmentDefault
628
+ TREESEED_CREDENTIAL_SESSION_SECRET:
629
+ label: Treeseed credential session secret
630
+ group: hosting
631
+ cluster: hosting:treeseed-control-plane
632
+ visibility: system
633
+ description: Secret used by the API and operations runner to encrypt provider credential session payloads.
634
+ howToGet: Generate a strong random secret and store it through `treeseed config` for staging and production.
635
+ sensitivity: secret
636
+ targets:
637
+ - github-secret
638
+ - railway-secret
639
+ serviceTargets:
640
+ - api
641
+ - operationsRunner
642
+ scopes:
643
+ - staging
644
+ - prod
645
+ storage: scoped
646
+ requirement: conditional
647
+ purposes:
648
+ - deploy
649
+ - config
650
+ validation:
651
+ kind: nonempty
652
+ minLength: 24
653
+ sourcePriority:
654
+ - machine-config
655
+ - process-env
656
+ defaultValueRef: generatedSecret
529
657
  TREESEED_CATALOG_MARKET_API_BASE_URLS:
530
- label: Treeseed catalog market API URLs
658
+ label: Treeseed catalog API URLs
531
659
  group: hosting
532
- description: Comma-separated market API base URLs that contribute templates, knowledge packs, and shared resources to the integrated catalog.
533
- howToGet: Start with the production TreeSeed market at https://api.treeseed.ai and add specialized team or enterprise market API URLs as needed.
660
+ description: Comma-separated API base URLs that contribute templates, knowledge packs, and shared resources to the integrated catalog.
661
+ howToGet: Start with the production TreeSeed market at https://api.treeseed.ai and add specialized team or enterprise API URLs as needed.
534
662
  sensitivity: plain
535
663
  targets:
536
664
  - github-variable
@@ -75,6 +75,7 @@ export type TreeseedEnvironmentEntry = {
75
75
  howToGet: string;
76
76
  sensitivity: TreeseedEnvironmentSensitivity;
77
77
  targets: TreeseedEnvironmentTarget[];
78
+ appTargets?: string[];
78
79
  serviceTargets?: string[];
79
80
  scopes: TreeseedEnvironmentScope[];
80
81
  requirement: TreeseedEnvironmentRequirement;
@@ -4,6 +4,9 @@ import { existsSync, readFileSync } from "node:fs";
4
4
  import { dirname, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { parse as parseYaml } from "yaml";
7
+ import { discoverTreeseedApplications } from "../hosting/apps.js";
8
+ import { githubRepositoryCredentialEnvName } from "../operations/services/github-credentials.js";
9
+ import { discoverTreeseedPackageAdapters } from "../operations/services/package-adapters.js";
7
10
  import { loadTreeseedDeployConfig } from "./deploy-config.js";
8
11
  import { loadTreeseedPlugins } from "./plugins.js";
9
12
  import { loadTreeseedManifest } from "./tenant-config.js";
@@ -47,6 +50,7 @@ function resolveSiblingPackageEnvironmentPath(packageDir) {
47
50
  }
48
51
  const SDK_ENVIRONMENT_PATH = resolveSdkEnvironmentPath();
49
52
  const CORE_ENVIRONMENT_PATH = resolveSiblingPackageEnvironmentPath("core");
53
+ const API_ENVIRONMENT_PATH = resolveSiblingPackageEnvironmentPath("api");
50
54
  const AGENT_ENVIRONMENT_PATH = resolveSiblingPackageEnvironmentPath("agent");
51
55
  const TENANT_ENVIRONMENT_OVERLAY_PATH = "src/env.yaml";
52
56
  const DEFAULT_TREESEED_MARKET_BASE_URL = "https://api.treeseed.ai";
@@ -146,7 +150,7 @@ function resolveHostingRegistration(context) {
146
150
  return context.deployConfig.hosting?.registration ?? "none";
147
151
  }
148
152
  function marketControlPlaneEnabled(context) {
149
- return resolveHostingKind(context) === "market_control_plane";
153
+ return resolveHostingKind(context) === "treeseed_control_plane";
150
154
  }
151
155
  function hostedProjectEnabled(context) {
152
156
  return resolveHostingKind(context) === "hosted_project";
@@ -235,7 +239,7 @@ function resolvePagesProjectName(context) {
235
239
  return context.deployConfig.slug;
236
240
  }
237
241
  function resolvePagesPreviewProjectName(context, _scope, values = {}) {
238
- return values.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME?.trim() || `${context.deployConfig.slug}-staging`;
242
+ return values.TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME?.trim() || context.deployConfig.cloudflare.pages?.projectName?.trim() || context.deployConfig.slug;
239
243
  }
240
244
  function resolveContentBucketName(context) {
241
245
  return `${context.deployConfig.slug}-content`;
@@ -244,13 +248,13 @@ function resolveContentBucketBinding(context) {
244
248
  return context.deployConfig.cloudflare.r2?.binding?.trim() || "TREESEED_CONTENT_BUCKET";
245
249
  }
246
250
  function resolveMarketBaseUrl(context, _scope, values = {}) {
247
- return values.TREESEED_MARKET_API_BASE_URL?.trim() || values.TREESEED_CENTRAL_MARKET_API_BASE_URL?.trim() || process.env.TREESEED_MARKET_API_BASE_URL?.trim() || process.env.TREESEED_CENTRAL_MARKET_API_BASE_URL?.trim() || context.deployConfig.runtime?.marketBaseUrl?.trim() || context.deployConfig.hosting?.marketBaseUrl?.trim() || DEFAULT_TREESEED_MARKET_BASE_URL;
251
+ return values.TREESEED_API_BASE_URL?.trim() || values.TREESEED_CENTRAL_MARKET_API_BASE_URL?.trim() || process.env.TREESEED_API_BASE_URL?.trim() || process.env.TREESEED_CENTRAL_MARKET_API_BASE_URL?.trim() || context.deployConfig.runtime?.marketBaseUrl?.trim() || context.deployConfig.hosting?.marketBaseUrl?.trim() || DEFAULT_TREESEED_MARKET_BASE_URL;
248
252
  }
249
253
  function resolveCentralMarketBaseUrl(context, scope, values = {}) {
250
254
  return values.TREESEED_CENTRAL_MARKET_API_BASE_URL?.trim() || process.env.TREESEED_CENTRAL_MARKET_API_BASE_URL?.trim() || resolveMarketBaseUrl(context, scope, values) || DEFAULT_TREESEED_MARKET_BASE_URL;
251
255
  }
252
256
  function resolveCatalogMarketBaseUrls(context, scope, values = {}) {
253
- return values.TREESEED_CATALOG_MARKET_API_BASE_URLS?.trim() || values.TREESEED_MARKET_API_BASE_URL?.trim() || values.TREESEED_CENTRAL_MARKET_API_BASE_URL?.trim() || process.env.TREESEED_CATALOG_MARKET_API_BASE_URLS?.trim() || resolveCentralMarketBaseUrl(context, scope, values);
257
+ return values.TREESEED_CATALOG_MARKET_API_BASE_URLS?.trim() || values.TREESEED_API_BASE_URL?.trim() || values.TREESEED_CENTRAL_MARKET_API_BASE_URL?.trim() || process.env.TREESEED_CATALOG_MARKET_API_BASE_URLS?.trim() || resolveCentralMarketBaseUrl(context, scope, values);
254
258
  }
255
259
  function resolveHostedTeamId(context) {
256
260
  return context.deployConfig.slug;
@@ -262,7 +266,7 @@ function resolveRailwayWorkspaceDefault() {
262
266
  return "knowledge-coop";
263
267
  }
264
268
  function resolvePlatformRunnerIdDefault(_context, scope) {
265
- return scope === "prod" ? "market-ops-prod-1" : scope === "staging" ? "market-ops-staging-1" : "market-ops-local-1";
269
+ return scope === "prod" ? "treeseed-ops-prod-1" : scope === "staging" ? "treeseed-ops-staging-1" : "treeseed-ops-local-1";
266
270
  }
267
271
  function resolvePlatformRunnerEnvironmentDefault(_context, scope) {
268
272
  return scope === "prod" ? "production" : scope;
@@ -324,6 +328,7 @@ const VALUE_RESOLVERS = {
324
328
  platformRunnerIdDefault: (context, scope) => resolvePlatformRunnerIdDefault(context, scope),
325
329
  platformRunnerEnvironmentDefault: (context, scope) => resolvePlatformRunnerEnvironmentDefault(context, scope),
326
330
  platformRunnerDataDirDefault: () => "/data",
331
+ treedxDockerImageDefault: () => "treeseed/treedx:latest",
327
332
  githubOwnerDefault: (context) => resolveGitHubOwnerDefault(context),
328
333
  githubRepositoryNameDefault: (context) => resolveGitHubRepositoryNameDefault(context),
329
334
  githubRepositoryVisibilityDefault: () => "private",
@@ -413,6 +418,44 @@ function readPluginEnvironmentOverlay(baseDir) {
413
418
  }
414
419
  return null;
415
420
  }
421
+ function packageRepositoryCredentialOverlay(tenantRoot) {
422
+ const entries = {};
423
+ let packages = [];
424
+ try {
425
+ packages = discoverTreeseedPackageAdapters(tenantRoot);
426
+ } catch {
427
+ packages = [];
428
+ }
429
+ for (const pkg of packages) {
430
+ const repository = typeof pkg.metadata.repository === "string" && pkg.metadata.repository.trim() ? pkg.metadata.repository.trim() : null;
431
+ if (!repository) continue;
432
+ let id = "";
433
+ try {
434
+ id = githubRepositoryCredentialEnvName(repository);
435
+ } catch {
436
+ continue;
437
+ }
438
+ entries[id] = {
439
+ label: `${pkg.name} GitHub token`,
440
+ group: "github",
441
+ cluster: `github:${repository}`,
442
+ description: `GitHub token used by Treeseed package workflows for ${pkg.name} in ${repository}.`,
443
+ howToGet: `Create a GitHub token with Actions workflow and environment secret permissions for ${repository}, then store it as ${id}.`,
444
+ sensitivity: "secret",
445
+ targets: ["local-runtime"],
446
+ scopes: ["staging", "prod"],
447
+ storage: "shared",
448
+ requirement: "optional",
449
+ purposes: ["deploy", "config"],
450
+ validation: {
451
+ kind: "nonempty",
452
+ minLength: 8
453
+ },
454
+ sourcePriority: ["machine-config", "process-env"]
455
+ };
456
+ }
457
+ return { entries };
458
+ }
416
459
  function loadTreeseedEnvironmentOverlay(tenantRoot) {
417
460
  const overlayPath = resolve(tenantRoot, TENANT_ENVIRONMENT_OVERLAY_PATH);
418
461
  return {
@@ -472,11 +515,37 @@ function collectOverlaySources(context) {
472
515
  }
473
516
  }
474
517
  if (apiSurfaceEnabled(context) || processingPlaneEnabled(context)) {
518
+ const apiOverlay = readYamlOverlayIfPresent(API_ENVIRONMENT_PATH);
519
+ if (apiOverlay) {
520
+ sources.push({ label: API_ENVIRONMENT_PATH, overlay: apiOverlay });
521
+ }
475
522
  const agentOverlay = readYamlOverlayIfPresent(AGENT_ENVIRONMENT_PATH);
476
523
  if (agentOverlay) {
477
524
  sources.push({ label: AGENT_ENVIRONMENT_PATH, overlay: agentOverlay });
478
525
  }
479
526
  }
527
+ let discoveredApiApps = [];
528
+ try {
529
+ discoveredApiApps = discoverTreeseedApplications(context.tenantRoot).filter((application) => application.root !== context.tenantRoot && application.roles.some((role) => role === "api" || role === "operations-runner" || role === "treeseed-control-plane"));
530
+ } catch {
531
+ discoveredApiApps = [];
532
+ }
533
+ if (discoveredApiApps.length > 0 && !sources.some((source) => source.label === API_ENVIRONMENT_PATH)) {
534
+ const apiOverlay = readYamlOverlayIfPresent(API_ENVIRONMENT_PATH);
535
+ if (apiOverlay) {
536
+ sources.push({ label: API_ENVIRONMENT_PATH, overlay: apiOverlay });
537
+ }
538
+ }
539
+ for (const application of discoveredApiApps) {
540
+ const overlay = readYamlOverlayIfPresent(resolve(application.root, "src/env.yaml"));
541
+ if (overlay) {
542
+ sources.push({ label: resolve(application.root, "src/env.yaml"), overlay });
543
+ }
544
+ }
545
+ const packageCredentialOverlay = packageRepositoryCredentialOverlay(context.tenantRoot);
546
+ if (Object.keys(packageCredentialOverlay.entries ?? {}).length > 0) {
547
+ sources.push({ label: "discovered package repository credentials", overlay: packageCredentialOverlay });
548
+ }
480
549
  for (const pluginEntry of context.plugins) {
481
550
  const fileOverlay = readPluginEnvironmentOverlay(pluginEntry.baseDir);
482
551
  if (fileOverlay) {
@@ -2,6 +2,7 @@ import type { TreeseedDeployConfig, TreeseedPlatformLayerDefinition, TreeseedPla
2
2
  import type { TreeseedEnvironmentRegistryOverlay } from './environment.ts';
3
3
  import type { SdkGraphRankingProvider } from '../sdk-types.ts';
4
4
  import type { TreeseedReconcileAdapter } from '../reconcile/contracts.ts';
5
+ import type { TreeseedApplicationHostingProfile, TreeseedHostAdapter, TreeseedServiceTypeAdapter } from '../hosting/contracts.ts';
5
6
  export type TreeseedSiteLayerDefinition = TreeseedPlatformLayerDefinition & {
6
7
  kinds?: Array<'pages' | 'styles' | 'components'>;
7
8
  };
@@ -65,6 +66,13 @@ export type TreeseedContentProviderContext = TreeseedPluginEnvironmentContext &
65
66
  tenantConfig: TreeseedTenantConfig;
66
67
  };
67
68
  export type TreeseedGraphRankingProviderContribution = SdkGraphRankingProvider | ((context: TreeseedPluginEnvironmentContext) => SdkGraphRankingProvider | undefined);
69
+ export type TreeseedHostingContribution = {
70
+ hostAdapters?: Record<string, TreeseedHostAdapter>;
71
+ serviceTypeAdapters?: Record<string, TreeseedServiceTypeAdapter>;
72
+ profiles?: TreeseedApplicationHostingProfile[];
73
+ uiPlacements?: Record<string, unknown>;
74
+ environmentDefaults?: Record<string, unknown>;
75
+ };
68
76
  export interface TreeseedPlugin {
69
77
  id?: string;
70
78
  provides?: Record<string, any> & {
@@ -88,6 +96,7 @@ export interface TreeseedPlugin {
88
96
  platformLayers?: TreeseedPlatformLayerContribution[] | ((context: TreeseedPluginPlatformContext) => TreeseedPlatformLayerContribution[] | undefined);
89
97
  environmentRegistry?: TreeseedEnvironmentRegistryOverlay | ((context: TreeseedPluginEnvironmentContext) => TreeseedEnvironmentRegistryOverlay | undefined);
90
98
  reconcileAdapters?: Record<string, TreeseedReconcileAdapter | ((context: TreeseedPluginEnvironmentContext) => TreeseedReconcileAdapter | undefined)> | ((context: TreeseedPluginEnvironmentContext) => Record<string, TreeseedReconcileAdapter | ((context: TreeseedPluginEnvironmentContext) => TreeseedReconcileAdapter | undefined)> | undefined);
99
+ hosting?: TreeseedHostingContribution | ((context: TreeseedPluginEnvironmentContext) => TreeseedHostingContribution | undefined);
91
100
  graphRankingProviders?: Record<string, TreeseedGraphRankingProviderContribution>;
92
101
  [key: string]: unknown;
93
102
  }
@@ -211,8 +211,8 @@ async function createRelationalAdapterFromUrl(databaseUrl) {
211
211
  return createSqliteRelationalAdapter(value);
212
212
  }
213
213
  async function createPlatformOperationStoreFromEnv(options = {}) {
214
- const databaseUrl = options.databaseUrl ?? globalThis.process?.env?.TREESEED_MARKET_DATABASE_URL ?? null;
215
- if (!databaseUrl?.trim()) throw new Error("TREESEED_MARKET_DATABASE_URL is required for direct database platform operations.");
214
+ const databaseUrl = options.databaseUrl ?? globalThis.process?.env?.TREESEED_DATABASE_URL ?? null;
215
+ if (!databaseUrl?.trim()) throw new Error("TREESEED_DATABASE_URL is required for direct database platform operations.");
216
216
  const database = await createRelationalAdapterFromUrl(databaseUrl);
217
217
  return new PlatformOperationStore({ database, initializeSchema: options.initializeSchema ?? true });
218
218
  }
@@ -295,7 +295,7 @@ class PlatformRunnerClient {
295
295
  this.marketUrl = normalizeBaseUrl(options.marketUrl);
296
296
  this.marketId = options.marketId.trim();
297
297
  this.runnerSecret = options.runnerSecret.trim();
298
- if (!this.marketUrl) throw new Error("Market API URL is required.");
298
+ if (!this.marketUrl) throw new Error("API URL is required.");
299
299
  if (!this.marketId) throw new Error("Market ID is required.");
300
300
  if (!this.runnerSecret) throw new Error("Platform runner secret is required.");
301
301
  this.fetchImpl = options.fetchImpl ?? fetch;
@@ -55,8 +55,8 @@ function agentsSystemDisabled(config) {
55
55
  if (config.runtime?.mode === "none") {
56
56
  return "runtime.mode is none.";
57
57
  }
58
- const enabled = ["marketOperationsRunner", "workdayManager", "workerRunner"].some((serviceKey) => serviceEnabled(config, serviceKey));
59
- return enabled ? null : "No agent or market operations runner Railway services are enabled.";
58
+ const enabled = ["operationsRunner", "workdayManager", "workerRunner"].some((serviceKey) => serviceEnabled(config, serviceKey));
59
+ return enabled ? null : "No agent or Treeseed operations runner Railway services are enabled.";
60
60
  }
61
61
  function hasValue(env, key) {
62
62
  return typeof env[key] === "string" && String(env[key]).trim().length > 0;