@treeseed/sdk 0.10.27 → 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 (168) 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 +11 -4
  20. package/dist/index.js +71 -7
  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/template-registry.js +14 -7
  67. package/dist/operations/services/verification-cache.d.ts +25 -0
  68. package/dist/operations/services/verification-cache.js +71 -0
  69. package/dist/operations/services/workspace-dependency-mode.js +9 -1
  70. package/dist/operations/services/workspace-save.js +1 -1
  71. package/dist/operations/services/workspace-tools.js +2 -1
  72. package/dist/platform/contracts.d.ts +32 -1
  73. package/dist/platform/deploy-config.js +73 -8
  74. package/dist/platform/env.yaml +163 -35
  75. package/dist/platform/environment.d.ts +1 -0
  76. package/dist/platform/environment.js +74 -5
  77. package/dist/platform/plugin.d.ts +9 -0
  78. package/dist/platform-operation-store.js +2 -2
  79. package/dist/platform-operations.js +1 -1
  80. package/dist/reconcile/bootstrap-systems.js +2 -2
  81. package/dist/reconcile/builtin-adapters.js +372 -189
  82. package/dist/reconcile/contracts.d.ts +9 -5
  83. package/dist/reconcile/desired-state.d.ts +1 -0
  84. package/dist/reconcile/desired-state.js +5 -5
  85. package/dist/reconcile/engine.d.ts +5 -2
  86. package/dist/reconcile/engine.js +53 -32
  87. package/dist/reconcile/index.d.ts +2 -0
  88. package/dist/reconcile/index.js +2 -0
  89. package/dist/reconcile/live-acceptance.d.ts +79 -0
  90. package/dist/reconcile/live-acceptance.js +1615 -0
  91. package/dist/reconcile/platform.d.ts +104 -0
  92. package/dist/reconcile/platform.js +100 -0
  93. package/dist/reconcile/state.js +4 -4
  94. package/dist/reconcile/units.js +2 -2
  95. package/dist/scripts/deployment-readiness.js +20 -0
  96. package/dist/scripts/generate-treedx-openapi-types.js +186 -0
  97. package/dist/scripts/operations-runner-smoke.js +16 -0
  98. package/dist/scripts/release-verify.js +4 -1
  99. package/dist/scripts/template-catalog.test.js +7 -7
  100. package/dist/scripts/tenant-workflow-action.js +10 -1
  101. package/dist/sdk-types.d.ts +172 -5
  102. package/dist/sdk-types.js +28 -3
  103. package/dist/sdk.d.ts +35 -24
  104. package/dist/sdk.js +186 -17
  105. package/dist/template-launch-requirements.js +9 -0
  106. package/dist/treedx/adapters.d.ts +6 -0
  107. package/dist/treedx/adapters.js +36 -0
  108. package/dist/treedx/client.d.ts +222 -0
  109. package/dist/treedx/client.js +871 -0
  110. package/dist/treedx/errors.d.ts +13 -0
  111. package/dist/treedx/errors.js +17 -0
  112. package/dist/treedx/federated-client.d.ts +27 -0
  113. package/dist/treedx/federated-client.js +158 -0
  114. package/dist/treedx/generated/openapi-types.d.ts +3558 -0
  115. package/dist/treedx/generated/openapi-types.js +0 -0
  116. package/dist/treedx/graph-adapter.d.ts +33 -0
  117. package/dist/treedx/graph-adapter.js +156 -0
  118. package/dist/treedx/index.d.ts +14 -0
  119. package/dist/treedx/index.js +48 -0
  120. package/dist/treedx/market-integration.d.ts +27 -0
  121. package/dist/treedx/market-integration.js +131 -0
  122. package/dist/treedx/ports.d.ts +166 -0
  123. package/dist/treedx/ports.js +231 -0
  124. package/dist/treedx/query-adapter.d.ts +19 -0
  125. package/dist/treedx/query-adapter.js +62 -0
  126. package/dist/treedx/registry-client.d.ts +11 -0
  127. package/dist/treedx/registry-client.js +19 -0
  128. package/dist/treedx/repository-adapter.d.ts +45 -0
  129. package/dist/treedx/repository-adapter.js +308 -0
  130. package/dist/treedx/sdk-integration.d.ts +27 -0
  131. package/dist/treedx/sdk-integration.js +63 -0
  132. package/dist/treedx/types.d.ts +1084 -0
  133. package/dist/treedx/types.js +8 -0
  134. package/dist/treedx/workspace-adapter.d.ts +27 -0
  135. package/dist/treedx/workspace-adapter.js +65 -0
  136. package/dist/treedx-backends.d.ts +218 -0
  137. package/dist/treedx-backends.js +632 -0
  138. package/dist/treedx-client.d.ts +86 -0
  139. package/dist/treedx-client.js +175 -0
  140. package/dist/treeseed/template-catalog/catalog.fixture.json +497 -138
  141. package/dist/workflow/operations.d.ts +119 -13
  142. package/dist/workflow/operations.js +309 -53
  143. package/dist/workflow-state.d.ts +13 -0
  144. package/dist/workflow-state.js +43 -26
  145. package/dist/workflow-support.d.ts +11 -3
  146. package/dist/workflow-support.js +67 -3
  147. package/dist/workflow.d.ts +5 -0
  148. package/drizzle/market/0004_treedx_market_integration.sql +99 -0
  149. package/package.json +34 -3
  150. package/templates/github/deploy-web.workflow.yml +39 -6
  151. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.d.ts +0 -3
  152. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.ts +0 -6
  153. package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +0 -35
  154. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/api/server.js +0 -4
  155. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +0 -65
  156. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/decisions/adopt-initial-proposal-loop.mdx +0 -22
  157. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/empty/.gitkeep +0 -1
  158. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/knowledge/handbook/index.mdx +0 -11
  159. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/pages/welcome.mdx +0 -11
  160. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/people/starter-steward.mdx +0 -11
  161. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/proposals/establish-initial-proposal-loop.mdx +0 -17
  162. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.d.ts +0 -1
  163. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.ts +0 -3
  164. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/env.yaml +0 -1
  165. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +0 -26
  166. package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +0 -74
  167. package/dist/treeseed/template-catalog/templates/starter-basic/template/tsconfig.json +0 -9
  168. package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +0 -103
@@ -1,55 +1,7 @@
1
1
  {
2
2
  "items": [
3
3
  {
4
- "id": "starter-basic",
5
- "displayName": "TreeSeed Basic",
6
- "description": "Opinionated first-party TreeSeed starter for documentation-first teams.",
7
- "summary": "A general-purpose starter for Astro, Cloudflare, docs, and the standard Treeseed workflow.",
8
- "status": "live",
9
- "featured": true,
10
- "category": "starter",
11
- "audience": [
12
- "maintainers",
13
- "teams"
14
- ],
15
- "tags": [
16
- "starter",
17
- "astro",
18
- "cloudflare",
19
- "docs"
20
- ],
21
- "publisher": {
22
- "id": "treeseed",
23
- "name": "TreeSeed",
24
- "url": "https://treeseed.ai"
25
- },
26
- "publisherVerified": true,
27
- "templateVersion": "1.0.0",
28
- "templateApiVersion": 1,
29
- "minCliVersion": "0.1.1",
30
- "minCoreVersion": "0.1.2",
31
- "fulfillment": {
32
- "source": {
33
- "kind": "git",
34
- "repoUrl": "https://github.com/treeseed-ai/market.git",
35
- "directory": "templates/starter-basic",
36
- "ref": "main",
37
- "integrity": "catalog-fixture"
38
- },
39
- "hooksPolicy": "builtin_only",
40
- "supportsReconcile": true
41
- },
42
- "offer": {
43
- "priceModel": "free",
44
- "license": "AGPL-3.0-only",
45
- "support": "community"
46
- },
47
- "relatedBooks": [],
48
- "relatedKnowledge": [],
49
- "relatedObjectives": []
50
- },
51
- {
52
- "id": "starter-research",
4
+ "id": "research",
53
5
  "displayName": "TreeSeed Research",
54
6
  "description": "First-party TreeSeed starter for freestanding research projects and knowledge-pack publishing.",
55
7
  "summary": "A research starter for building source-backed books, gathered assets, synthesis notes, and reusable knowledge packs.",
@@ -81,7 +33,7 @@
81
33
  "mode": "git",
82
34
  "source": {
83
35
  "kind": "git",
84
- "repoUrl": "https://github.com/treeseed-ai/starter-research.git",
36
+ "repoUrl": "https://github.com/treeseed-templates/research.git",
85
37
  "directory": ".",
86
38
  "ref": "staging",
87
39
  "integrity": "pending-external-repo"
@@ -102,17 +54,42 @@
102
54
  "key": "sourceRepository",
103
55
  "type": "repository",
104
56
  "required": true,
105
- "compatibleProviders": ["github"],
57
+ "compatibleProviders": [
58
+ "github"
59
+ ],
106
60
  "displayName": "Source repository",
107
61
  "purpose": "Create and push the generated research project repository.",
108
62
  "defaultSelection": "team-default",
109
63
  "configWrites": [
110
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.provider", "valueFrom": "selectedHost.provider" },
111
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.owner", "valueFrom": "selectedHost.github.owner" },
112
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.repository", "valueFrom": "derived.repositoryName" }
64
+ {
65
+ "target": "treeseed.site.yaml",
66
+ "path": "hosting.hostBindings.sourceRepository.provider",
67
+ "valueFrom": "selectedHost.provider"
68
+ },
69
+ {
70
+ "target": "treeseed.site.yaml",
71
+ "path": "hosting.hostBindings.sourceRepository.owner",
72
+ "valueFrom": "selectedHost.github.owner"
73
+ },
74
+ {
75
+ "target": "treeseed.site.yaml",
76
+ "path": "hosting.hostBindings.sourceRepository.repository",
77
+ "valueFrom": "derived.repositoryName"
78
+ }
113
79
  ],
114
80
  "environmentWrites": [
115
- { "env": "GITHUB_TOKEN", "valueFrom": "selectedHost.token", "targets": ["github-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" }
81
+ {
82
+ "env": "GITHUB_TOKEN",
83
+ "valueFrom": "selectedHost.token",
84
+ "targets": [
85
+ "github-secret"
86
+ ],
87
+ "scopes": [
88
+ "staging",
89
+ "prod"
90
+ ],
91
+ "sensitivity": "secret"
92
+ }
116
93
  ]
117
94
  },
118
95
  {
@@ -120,18 +97,50 @@
120
97
  "key": "publicWeb",
121
98
  "type": "web",
122
99
  "required": true,
123
- "compatibleProviders": ["cloudflare"],
100
+ "compatibleProviders": [
101
+ "cloudflare"
102
+ ],
124
103
  "displayName": "Public web host",
125
104
  "purpose": "Deploy the research site, previews, content storage, and web runtime resources.",
126
105
  "defaultSelection": "managed",
127
106
  "configWrites": [
128
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.publicWeb.provider", "valueFrom": "selectedHost.provider" },
129
- { "target": "treeseed.site.yaml", "path": "surfaces.web.provider", "valueFrom": "selectedHost.provider" },
130
- { "target": "treeseed.site.yaml", "path": "surfaces.web.environments.prod.domain", "valueFrom": "launchInput.domains.productionDomain", "writeWhen": "host-selected" },
131
- { "target": "treeseed.site.yaml", "path": "surfaces.web.environments.staging.domain", "valueFrom": "launchInput.domains.stagingDomain", "writeWhen": "host-selected" }
107
+ {
108
+ "target": "treeseed.site.yaml",
109
+ "path": "hosting.hostBindings.publicWeb.provider",
110
+ "valueFrom": "selectedHost.provider"
111
+ },
112
+ {
113
+ "target": "treeseed.site.yaml",
114
+ "path": "surfaces.web.provider",
115
+ "valueFrom": "selectedHost.provider"
116
+ },
117
+ {
118
+ "target": "treeseed.site.yaml",
119
+ "path": "surfaces.web.environments.prod.domain",
120
+ "valueFrom": "launchInput.domains.productionDomain",
121
+ "writeWhen": "host-selected"
122
+ },
123
+ {
124
+ "target": "treeseed.site.yaml",
125
+ "path": "surfaces.web.environments.staging.domain",
126
+ "valueFrom": "launchInput.domains.stagingDomain",
127
+ "writeWhen": "host-selected"
128
+ }
132
129
  ],
133
130
  "environmentWrites": [
134
- { "env": "TREESEED_PUBLIC_WEB_PROVIDER", "valueFrom": "selectedHost.provider", "targets": ["github-variable", "cloudflare-var"], "scopes": ["staging", "prod"], "sensitivity": "plain" }
131
+ {
132
+ "env": "TREESEED_PUBLIC_WEB_PROVIDER",
133
+ "valueFrom": "selectedHost.provider",
134
+ "targets": [
135
+ "github-variable",
136
+ "cloudflare-var"
137
+ ],
138
+ "scopes": [
139
+ "staging",
140
+ "prod"
141
+ ],
142
+ "sensitivity": "plain"
143
+ }
135
144
  ]
136
145
  },
137
146
  {
@@ -139,15 +148,34 @@
139
148
  "key": "transactionalEmail",
140
149
  "type": "email",
141
150
  "required": false,
142
- "compatibleProviders": ["smtp"],
151
+ "compatibleProviders": [
152
+ "smtp"
153
+ ],
143
154
  "displayName": "Transactional email",
144
155
  "purpose": "Send form, account, and research project notification email.",
145
156
  "defaultSelection": "managed",
146
157
  "configWrites": [
147
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.transactionalEmail.provider", "valueFrom": "selectedHost.provider", "writeWhen": "host-selected" }
158
+ {
159
+ "target": "treeseed.site.yaml",
160
+ "path": "hosting.hostBindings.transactionalEmail.provider",
161
+ "valueFrom": "selectedHost.provider",
162
+ "writeWhen": "host-selected"
163
+ }
148
164
  ],
149
165
  "environmentWrites": [
150
- { "env": "SMTP_HOST", "valueFrom": "selectedHost.smtpHost", "targets": ["github-secret", "railway-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" }
166
+ {
167
+ "env": "SMTP_HOST",
168
+ "valueFrom": "selectedHost.smtpHost",
169
+ "targets": [
170
+ "github-secret",
171
+ "railway-secret"
172
+ ],
173
+ "scopes": [
174
+ "staging",
175
+ "prod"
176
+ ],
177
+ "sensitivity": "secret"
178
+ }
151
179
  ]
152
180
  }
153
181
  ]
@@ -157,7 +185,7 @@
157
185
  "relatedObjectives": []
158
186
  },
159
187
  {
160
- "id": "starter-engineering",
188
+ "id": "engineering",
161
189
  "displayName": "TreeSeed Engineering",
162
190
  "description": "First-party TreeSeed starter for integrated software guidance, docs, and engineering agents.",
163
191
  "summary": "An engineering starter for guiding software projects with research, architecture, implementation, review, and release agents.",
@@ -189,7 +217,7 @@
189
217
  "mode": "git",
190
218
  "source": {
191
219
  "kind": "git",
192
- "repoUrl": "https://github.com/treeseed-ai/starter-engineering.git",
220
+ "repoUrl": "https://github.com/treeseed-templates/engineering.git",
193
221
  "directory": ".",
194
222
  "ref": "staging",
195
223
  "integrity": "pending-external-repo"
@@ -210,17 +238,42 @@
210
238
  "key": "sourceRepository",
211
239
  "type": "repository",
212
240
  "required": true,
213
- "compatibleProviders": ["github"],
241
+ "compatibleProviders": [
242
+ "github"
243
+ ],
214
244
  "displayName": "Source repository",
215
245
  "purpose": "Create and push the generated engineering project repository.",
216
246
  "defaultSelection": "team-default",
217
247
  "configWrites": [
218
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.provider", "valueFrom": "selectedHost.provider" },
219
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.owner", "valueFrom": "selectedHost.github.owner" },
220
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.repository", "valueFrom": "derived.repositoryName" }
248
+ {
249
+ "target": "treeseed.site.yaml",
250
+ "path": "hosting.hostBindings.sourceRepository.provider",
251
+ "valueFrom": "selectedHost.provider"
252
+ },
253
+ {
254
+ "target": "treeseed.site.yaml",
255
+ "path": "hosting.hostBindings.sourceRepository.owner",
256
+ "valueFrom": "selectedHost.github.owner"
257
+ },
258
+ {
259
+ "target": "treeseed.site.yaml",
260
+ "path": "hosting.hostBindings.sourceRepository.repository",
261
+ "valueFrom": "derived.repositoryName"
262
+ }
221
263
  ],
222
264
  "environmentWrites": [
223
- { "env": "GITHUB_TOKEN", "valueFrom": "selectedHost.token", "targets": ["github-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" }
265
+ {
266
+ "env": "GITHUB_TOKEN",
267
+ "valueFrom": "selectedHost.token",
268
+ "targets": [
269
+ "github-secret"
270
+ ],
271
+ "scopes": [
272
+ "staging",
273
+ "prod"
274
+ ],
275
+ "sensitivity": "secret"
276
+ }
224
277
  ]
225
278
  },
226
279
  {
@@ -228,18 +281,50 @@
228
281
  "key": "publicWeb",
229
282
  "type": "web",
230
283
  "required": true,
231
- "compatibleProviders": ["cloudflare"],
284
+ "compatibleProviders": [
285
+ "cloudflare"
286
+ ],
232
287
  "displayName": "Public web host",
233
288
  "purpose": "Deploy the engineering site, previews, content storage, and web runtime resources.",
234
289
  "defaultSelection": "managed",
235
290
  "configWrites": [
236
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.publicWeb.provider", "valueFrom": "selectedHost.provider" },
237
- { "target": "treeseed.site.yaml", "path": "surfaces.web.provider", "valueFrom": "selectedHost.provider" },
238
- { "target": "treeseed.site.yaml", "path": "surfaces.web.environments.prod.domain", "valueFrom": "launchInput.domains.productionDomain", "writeWhen": "host-selected" },
239
- { "target": "treeseed.site.yaml", "path": "surfaces.web.environments.staging.domain", "valueFrom": "launchInput.domains.stagingDomain", "writeWhen": "host-selected" }
291
+ {
292
+ "target": "treeseed.site.yaml",
293
+ "path": "hosting.hostBindings.publicWeb.provider",
294
+ "valueFrom": "selectedHost.provider"
295
+ },
296
+ {
297
+ "target": "treeseed.site.yaml",
298
+ "path": "surfaces.web.provider",
299
+ "valueFrom": "selectedHost.provider"
300
+ },
301
+ {
302
+ "target": "treeseed.site.yaml",
303
+ "path": "surfaces.web.environments.prod.domain",
304
+ "valueFrom": "launchInput.domains.productionDomain",
305
+ "writeWhen": "host-selected"
306
+ },
307
+ {
308
+ "target": "treeseed.site.yaml",
309
+ "path": "surfaces.web.environments.staging.domain",
310
+ "valueFrom": "launchInput.domains.stagingDomain",
311
+ "writeWhen": "host-selected"
312
+ }
240
313
  ],
241
314
  "environmentWrites": [
242
- { "env": "TREESEED_PUBLIC_WEB_PROVIDER", "valueFrom": "selectedHost.provider", "targets": ["github-variable", "cloudflare-var"], "scopes": ["staging", "prod"], "sensitivity": "plain" }
315
+ {
316
+ "env": "TREESEED_PUBLIC_WEB_PROVIDER",
317
+ "valueFrom": "selectedHost.provider",
318
+ "targets": [
319
+ "github-variable",
320
+ "cloudflare-var"
321
+ ],
322
+ "scopes": [
323
+ "staging",
324
+ "prod"
325
+ ],
326
+ "sensitivity": "plain"
327
+ }
243
328
  ]
244
329
  },
245
330
  {
@@ -247,15 +332,34 @@
247
332
  "key": "transactionalEmail",
248
333
  "type": "email",
249
334
  "required": false,
250
- "compatibleProviders": ["smtp"],
335
+ "compatibleProviders": [
336
+ "smtp"
337
+ ],
251
338
  "displayName": "Transactional email",
252
339
  "purpose": "Send form, account, and engineering project notification email.",
253
340
  "defaultSelection": "managed",
254
341
  "configWrites": [
255
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.transactionalEmail.provider", "valueFrom": "selectedHost.provider", "writeWhen": "host-selected" }
342
+ {
343
+ "target": "treeseed.site.yaml",
344
+ "path": "hosting.hostBindings.transactionalEmail.provider",
345
+ "valueFrom": "selectedHost.provider",
346
+ "writeWhen": "host-selected"
347
+ }
256
348
  ],
257
349
  "environmentWrites": [
258
- { "env": "SMTP_HOST", "valueFrom": "selectedHost.smtpHost", "targets": ["github-secret", "railway-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" }
350
+ {
351
+ "env": "SMTP_HOST",
352
+ "valueFrom": "selectedHost.smtpHost",
353
+ "targets": [
354
+ "github-secret",
355
+ "railway-secret"
356
+ ],
357
+ "scopes": [
358
+ "staging",
359
+ "prod"
360
+ ],
361
+ "sensitivity": "secret"
362
+ }
259
363
  ]
260
364
  }
261
365
  ]
@@ -265,7 +369,7 @@
265
369
  "relatedObjectives": []
266
370
  },
267
371
  {
268
- "id": "starter-information-hub",
372
+ "id": "information-hub",
269
373
  "displayName": "TreeSeed Information Hub",
270
374
  "description": "First-party TreeSeed starter for recurring information retrieval, distillation, and downstream distribution.",
271
375
  "summary": "An information distribution starter for retrieving updates over time, distilling derived knowledge, and packaging it for downstream projects.",
@@ -297,7 +401,7 @@
297
401
  "mode": "git",
298
402
  "source": {
299
403
  "kind": "git",
300
- "repoUrl": "https://github.com/treeseed-ai/starter-information-hub.git",
404
+ "repoUrl": "https://github.com/treeseed-templates/information-hub.git",
301
405
  "directory": ".",
302
406
  "ref": "staging",
303
407
  "integrity": "pending-external-repo"
@@ -318,17 +422,42 @@
318
422
  "key": "sourceRepository",
319
423
  "type": "repository",
320
424
  "required": true,
321
- "compatibleProviders": ["github"],
425
+ "compatibleProviders": [
426
+ "github"
427
+ ],
322
428
  "displayName": "Source repository",
323
429
  "purpose": "Create and push the generated information hub project repository.",
324
430
  "defaultSelection": "team-default",
325
431
  "configWrites": [
326
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.provider", "valueFrom": "selectedHost.provider" },
327
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.owner", "valueFrom": "selectedHost.github.owner" },
328
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.repository", "valueFrom": "derived.repositoryName" }
432
+ {
433
+ "target": "treeseed.site.yaml",
434
+ "path": "hosting.hostBindings.sourceRepository.provider",
435
+ "valueFrom": "selectedHost.provider"
436
+ },
437
+ {
438
+ "target": "treeseed.site.yaml",
439
+ "path": "hosting.hostBindings.sourceRepository.owner",
440
+ "valueFrom": "selectedHost.github.owner"
441
+ },
442
+ {
443
+ "target": "treeseed.site.yaml",
444
+ "path": "hosting.hostBindings.sourceRepository.repository",
445
+ "valueFrom": "derived.repositoryName"
446
+ }
329
447
  ],
330
448
  "environmentWrites": [
331
- { "env": "GITHUB_TOKEN", "valueFrom": "selectedHost.token", "targets": ["github-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" }
449
+ {
450
+ "env": "GITHUB_TOKEN",
451
+ "valueFrom": "selectedHost.token",
452
+ "targets": [
453
+ "github-secret"
454
+ ],
455
+ "scopes": [
456
+ "staging",
457
+ "prod"
458
+ ],
459
+ "sensitivity": "secret"
460
+ }
332
461
  ]
333
462
  },
334
463
  {
@@ -336,18 +465,50 @@
336
465
  "key": "publicWeb",
337
466
  "type": "web",
338
467
  "required": true,
339
- "compatibleProviders": ["cloudflare"],
468
+ "compatibleProviders": [
469
+ "cloudflare"
470
+ ],
340
471
  "displayName": "Public web host",
341
472
  "purpose": "Deploy the information hub site, previews, content storage, and web runtime resources.",
342
473
  "defaultSelection": "managed",
343
474
  "configWrites": [
344
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.publicWeb.provider", "valueFrom": "selectedHost.provider" },
345
- { "target": "treeseed.site.yaml", "path": "surfaces.web.provider", "valueFrom": "selectedHost.provider" },
346
- { "target": "treeseed.site.yaml", "path": "surfaces.web.environments.prod.domain", "valueFrom": "launchInput.domains.productionDomain", "writeWhen": "host-selected" },
347
- { "target": "treeseed.site.yaml", "path": "surfaces.web.environments.staging.domain", "valueFrom": "launchInput.domains.stagingDomain", "writeWhen": "host-selected" }
475
+ {
476
+ "target": "treeseed.site.yaml",
477
+ "path": "hosting.hostBindings.publicWeb.provider",
478
+ "valueFrom": "selectedHost.provider"
479
+ },
480
+ {
481
+ "target": "treeseed.site.yaml",
482
+ "path": "surfaces.web.provider",
483
+ "valueFrom": "selectedHost.provider"
484
+ },
485
+ {
486
+ "target": "treeseed.site.yaml",
487
+ "path": "surfaces.web.environments.prod.domain",
488
+ "valueFrom": "launchInput.domains.productionDomain",
489
+ "writeWhen": "host-selected"
490
+ },
491
+ {
492
+ "target": "treeseed.site.yaml",
493
+ "path": "surfaces.web.environments.staging.domain",
494
+ "valueFrom": "launchInput.domains.stagingDomain",
495
+ "writeWhen": "host-selected"
496
+ }
348
497
  ],
349
498
  "environmentWrites": [
350
- { "env": "TREESEED_PUBLIC_WEB_PROVIDER", "valueFrom": "selectedHost.provider", "targets": ["github-variable", "cloudflare-var"], "scopes": ["staging", "prod"], "sensitivity": "plain" }
499
+ {
500
+ "env": "TREESEED_PUBLIC_WEB_PROVIDER",
501
+ "valueFrom": "selectedHost.provider",
502
+ "targets": [
503
+ "github-variable",
504
+ "cloudflare-var"
505
+ ],
506
+ "scopes": [
507
+ "staging",
508
+ "prod"
509
+ ],
510
+ "sensitivity": "plain"
511
+ }
351
512
  ]
352
513
  },
353
514
  {
@@ -355,15 +516,34 @@
355
516
  "key": "transactionalEmail",
356
517
  "type": "email",
357
518
  "required": false,
358
- "compatibleProviders": ["smtp"],
519
+ "compatibleProviders": [
520
+ "smtp"
521
+ ],
359
522
  "displayName": "Transactional email",
360
523
  "purpose": "Send form, account, and information hub project notification email.",
361
524
  "defaultSelection": "managed",
362
525
  "configWrites": [
363
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.transactionalEmail.provider", "valueFrom": "selectedHost.provider", "writeWhen": "host-selected" }
526
+ {
527
+ "target": "treeseed.site.yaml",
528
+ "path": "hosting.hostBindings.transactionalEmail.provider",
529
+ "valueFrom": "selectedHost.provider",
530
+ "writeWhen": "host-selected"
531
+ }
364
532
  ],
365
533
  "environmentWrites": [
366
- { "env": "SMTP_HOST", "valueFrom": "selectedHost.smtpHost", "targets": ["github-secret", "railway-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" }
534
+ {
535
+ "env": "SMTP_HOST",
536
+ "valueFrom": "selectedHost.smtpHost",
537
+ "targets": [
538
+ "github-secret",
539
+ "railway-secret"
540
+ ],
541
+ "scopes": [
542
+ "staging",
543
+ "prod"
544
+ ],
545
+ "sensitivity": "secret"
546
+ }
367
547
  ]
368
548
  }
369
549
  ]
@@ -426,17 +606,42 @@
426
606
  "key": "sourceRepository",
427
607
  "type": "repository",
428
608
  "required": true,
429
- "compatibleProviders": ["github"],
609
+ "compatibleProviders": [
610
+ "github"
611
+ ],
430
612
  "displayName": "Source repository",
431
613
  "purpose": "Create and push the Market control-plane repository.",
432
614
  "defaultSelection": "team-default",
433
615
  "configWrites": [
434
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.provider", "valueFrom": "selectedHost.provider" },
435
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.owner", "valueFrom": "selectedHost.github.owner" },
436
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.sourceRepository.repository", "valueFrom": "derived.repositoryName" }
616
+ {
617
+ "target": "treeseed.site.yaml",
618
+ "path": "hosting.hostBindings.sourceRepository.provider",
619
+ "valueFrom": "selectedHost.provider"
620
+ },
621
+ {
622
+ "target": "treeseed.site.yaml",
623
+ "path": "hosting.hostBindings.sourceRepository.owner",
624
+ "valueFrom": "selectedHost.github.owner"
625
+ },
626
+ {
627
+ "target": "treeseed.site.yaml",
628
+ "path": "hosting.hostBindings.sourceRepository.repository",
629
+ "valueFrom": "derived.repositoryName"
630
+ }
437
631
  ],
438
632
  "environmentWrites": [
439
- { "env": "GITHUB_TOKEN", "valueFrom": "selectedHost.token", "targets": ["github-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" }
633
+ {
634
+ "env": "GITHUB_TOKEN",
635
+ "valueFrom": "selectedHost.token",
636
+ "targets": [
637
+ "github-secret"
638
+ ],
639
+ "scopes": [
640
+ "staging",
641
+ "prod"
642
+ ],
643
+ "sensitivity": "secret"
644
+ }
440
645
  ]
441
646
  },
442
647
  {
@@ -444,40 +649,110 @@
444
649
  "key": "publicWeb",
445
650
  "type": "web",
446
651
  "required": true,
447
- "compatibleProviders": ["cloudflare"],
652
+ "compatibleProviders": [
653
+ "cloudflare"
654
+ ],
448
655
  "displayName": "Public web host",
449
656
  "purpose": "Deploy the Market web surface and public control-plane routes.",
450
657
  "defaultSelection": "managed",
451
658
  "configWrites": [
452
- { "target": "treeseed.site.yaml", "path": "hosting.hostBindings.publicWeb.provider", "valueFrom": "selectedHost.provider" },
453
- { "target": "treeseed.site.yaml", "path": "hosting.kind", "valueFrom": "literal.market_control_plane" },
454
- { "target": "treeseed.site.yaml", "path": "surfaces.web.provider", "valueFrom": "selectedHost.provider" },
455
- { "target": "treeseed.site.yaml", "path": "surfaces.web.environments.prod.domain", "valueFrom": "launchInput.domains.productionDomain", "writeWhen": "host-selected" },
456
- { "target": "treeseed.site.yaml", "path": "surfaces.web.environments.staging.domain", "valueFrom": "launchInput.domains.stagingDomain", "writeWhen": "host-selected" }
659
+ {
660
+ "target": "treeseed.site.yaml",
661
+ "path": "hosting.hostBindings.publicWeb.provider",
662
+ "valueFrom": "selectedHost.provider"
663
+ },
664
+ {
665
+ "target": "treeseed.site.yaml",
666
+ "path": "hosting.kind",
667
+ "valueFrom": "literal.treeseed_control_plane"
668
+ },
669
+ {
670
+ "target": "treeseed.site.yaml",
671
+ "path": "surfaces.web.provider",
672
+ "valueFrom": "selectedHost.provider"
673
+ },
674
+ {
675
+ "target": "treeseed.site.yaml",
676
+ "path": "surfaces.web.environments.prod.domain",
677
+ "valueFrom": "launchInput.domains.productionDomain",
678
+ "writeWhen": "host-selected"
679
+ },
680
+ {
681
+ "target": "treeseed.site.yaml",
682
+ "path": "surfaces.web.environments.staging.domain",
683
+ "valueFrom": "launchInput.domains.stagingDomain",
684
+ "writeWhen": "host-selected"
685
+ }
457
686
  ],
458
687
  "environmentWrites": [
459
- { "env": "TREESEED_PUBLIC_WEB_PROVIDER", "valueFrom": "selectedHost.provider", "targets": ["github-variable", "cloudflare-var"], "scopes": ["staging", "prod"], "sensitivity": "plain" }
688
+ {
689
+ "env": "TREESEED_PUBLIC_WEB_PROVIDER",
690
+ "valueFrom": "selectedHost.provider",
691
+ "targets": [
692
+ "github-variable",
693
+ "cloudflare-var"
694
+ ],
695
+ "scopes": [
696
+ "staging",
697
+ "prod"
698
+ ],
699
+ "sensitivity": "plain"
700
+ }
460
701
  ]
461
702
  }
462
703
  ],
463
704
  "resources": [
464
705
  {
465
706
  "kind": "resource",
466
- "key": "marketDatabase",
707
+ "key": "treeseedDatabase",
467
708
  "type": "database",
468
709
  "required": true,
469
- "compatibleProviders": ["railway-postgres"],
470
- "displayName": "Market database",
471
- "purpose": "Provide the PostgreSQL database used by the Market API control plane.",
710
+ "compatibleProviders": [
711
+ "railway-postgres"
712
+ ],
713
+ "displayName": "Treeseed database",
714
+ "purpose": "Provide the PostgreSQL database used by the API control plane.",
472
715
  "configWrites": [
473
- { "target": "treeseed.site.yaml", "path": "services.marketDatabase.enabled", "valueFrom": "literal.true" },
474
- { "target": "treeseed.site.yaml", "path": "services.marketDatabase.provider", "valueFrom": "literal.railway" },
475
- { "target": "treeseed.site.yaml", "path": "services.marketDatabase.railway.resourceType", "valueFrom": "literal.postgres" },
476
- { "target": "treeseed.site.yaml", "path": "services.marketDatabase.railway.serviceName", "valueFrom": "selectedResource.configValues.serviceName" },
477
- { "target": "treeseed.site.yaml", "path": "services.marketDatabase.railway.environmentVariable", "valueFrom": "literal.TREESEED_MARKET_DATABASE_URL" }
716
+ {
717
+ "target": "treeseed.site.yaml",
718
+ "path": "services.treeseedDatabase.enabled",
719
+ "valueFrom": "literal.true"
720
+ },
721
+ {
722
+ "target": "treeseed.site.yaml",
723
+ "path": "services.treeseedDatabase.provider",
724
+ "valueFrom": "literal.railway"
725
+ },
726
+ {
727
+ "target": "treeseed.site.yaml",
728
+ "path": "services.treeseedDatabase.railway.resourceType",
729
+ "valueFrom": "literal.postgres"
730
+ },
731
+ {
732
+ "target": "treeseed.site.yaml",
733
+ "path": "services.treeseedDatabase.railway.serviceName",
734
+ "valueFrom": "selectedResource.configValues.serviceName"
735
+ },
736
+ {
737
+ "target": "treeseed.site.yaml",
738
+ "path": "services.treeseedDatabase.railway.environmentVariable",
739
+ "valueFrom": "literal.TREESEED_DATABASE_URL"
740
+ }
478
741
  ],
479
742
  "environmentWrites": [
480
- { "env": "TREESEED_MARKET_DATABASE_URL", "valueFrom": "selectedResource.secretRefs.databaseUrl", "targets": ["github-secret", "railway-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" }
743
+ {
744
+ "env": "TREESEED_DATABASE_URL",
745
+ "valueFrom": "selectedResource.secretRefs.databaseUrl",
746
+ "targets": [
747
+ "github-secret",
748
+ "railway-secret"
749
+ ],
750
+ "scopes": [
751
+ "staging",
752
+ "prod"
753
+ ],
754
+ "sensitivity": "secret"
755
+ }
481
756
  ]
482
757
  },
483
758
  {
@@ -485,38 +760,122 @@
485
760
  "key": "api",
486
761
  "type": "service",
487
762
  "required": true,
488
- "compatibleProviders": ["railway"],
489
- "displayName": "Market API service",
490
- "purpose": "Run the Market API service that serves the control-plane routes.",
763
+ "compatibleProviders": [
764
+ "railway"
765
+ ],
766
+ "displayName": "API service",
767
+ "purpose": "Run the API service that serves the control-plane routes.",
491
768
  "configWrites": [
492
- { "target": "treeseed.site.yaml", "path": "services.api.enabled", "valueFrom": "literal.true" },
493
- { "target": "treeseed.site.yaml", "path": "services.api.provider", "valueFrom": "literal.railway" },
494
- { "target": "treeseed.site.yaml", "path": "services.api.railway.serviceName", "valueFrom": "selectedResource.configValues.serviceName" },
495
- { "target": "treeseed.site.yaml", "path": "services.api.railway.rootDirectory", "valueFrom": "literal." },
496
- { "target": "treeseed.site.yaml", "path": "services.api.railway.startCommand", "valueFrom": "literal.node dist/api/server.js" }
769
+ {
770
+ "target": "treeseed.site.yaml",
771
+ "path": "services.api.enabled",
772
+ "valueFrom": "literal.true"
773
+ },
774
+ {
775
+ "target": "treeseed.site.yaml",
776
+ "path": "services.api.provider",
777
+ "valueFrom": "literal.railway"
778
+ },
779
+ {
780
+ "target": "treeseed.site.yaml",
781
+ "path": "services.api.railway.serviceName",
782
+ "valueFrom": "selectedResource.configValues.serviceName"
783
+ },
784
+ {
785
+ "target": "treeseed.site.yaml",
786
+ "path": "services.api.railway.rootDirectory",
787
+ "valueFrom": "literal."
788
+ },
789
+ {
790
+ "target": "treeseed.site.yaml",
791
+ "path": "services.api.railway.startCommand",
792
+ "valueFrom": "literal.node dist/api/server.js"
793
+ }
497
794
  ],
498
795
  "environmentWrites": [
499
- { "env": "TREESEED_MARKET_DATABASE_URL", "valueFrom": "selectedResource.secretRefs.databaseUrl", "targets": ["railway-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" }
796
+ {
797
+ "env": "TREESEED_DATABASE_URL",
798
+ "valueFrom": "selectedResource.secretRefs.databaseUrl",
799
+ "targets": [
800
+ "railway-secret"
801
+ ],
802
+ "scopes": [
803
+ "staging",
804
+ "prod"
805
+ ],
806
+ "sensitivity": "secret"
807
+ }
500
808
  ]
501
809
  },
502
810
  {
503
811
  "kind": "resource",
504
- "key": "marketOperationsRunner",
812
+ "key": "operationsRunner",
505
813
  "type": "service",
506
814
  "required": true,
507
- "compatibleProviders": ["railway"],
508
- "displayName": "Market operations runner",
509
- "purpose": "Run the governed Market operations runner for queued control-plane operations.",
815
+ "compatibleProviders": [
816
+ "railway"
817
+ ],
818
+ "displayName": "Treeseed operations runner",
819
+ "purpose": "Run the governed Treeseed operations runner for queued control-plane operations.",
510
820
  "configWrites": [
511
- { "target": "treeseed.site.yaml", "path": "services.marketOperationsRunner.enabled", "valueFrom": "literal.true" },
512
- { "target": "treeseed.site.yaml", "path": "services.marketOperationsRunner.provider", "valueFrom": "literal.railway" },
513
- { "target": "treeseed.site.yaml", "path": "services.marketOperationsRunner.railway.serviceName", "valueFrom": "selectedResource.configValues.serviceName" },
514
- { "target": "treeseed.site.yaml", "path": "services.marketOperationsRunner.railway.startCommand", "valueFrom": "literal.node dist/market-operations-runner/runner.js" }
821
+ {
822
+ "target": "treeseed.site.yaml",
823
+ "path": "services.operationsRunner.enabled",
824
+ "valueFrom": "literal.true"
825
+ },
826
+ {
827
+ "target": "treeseed.site.yaml",
828
+ "path": "services.operationsRunner.provider",
829
+ "valueFrom": "literal.railway"
830
+ },
831
+ {
832
+ "target": "treeseed.site.yaml",
833
+ "path": "services.operationsRunner.railway.serviceName",
834
+ "valueFrom": "selectedResource.configValues.serviceName"
835
+ },
836
+ {
837
+ "target": "treeseed.site.yaml",
838
+ "path": "services.operationsRunner.railway.startCommand",
839
+ "valueFrom": "literal.node dist/operations-runner/runner.js"
840
+ }
515
841
  ],
516
842
  "environmentWrites": [
517
- { "env": "TREESEED_MARKET_DATABASE_URL", "valueFrom": "selectedResource.secretRefs.databaseUrl", "targets": ["railway-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" },
518
- { "env": "TREESEED_PLATFORM_RUNNER_TOKEN", "valueFrom": "selectedResource.secretRefs.runnerToken", "targets": ["railway-secret"], "scopes": ["staging", "prod"], "sensitivity": "secret" },
519
- { "env": "TREESEED_PLATFORM_RUNNER_ID", "valueFrom": "selectedResource.environmentValues.runnerId", "targets": ["railway-var"], "scopes": ["staging", "prod"], "sensitivity": "plain" }
843
+ {
844
+ "env": "TREESEED_DATABASE_URL",
845
+ "valueFrom": "selectedResource.secretRefs.databaseUrl",
846
+ "targets": [
847
+ "railway-secret"
848
+ ],
849
+ "scopes": [
850
+ "staging",
851
+ "prod"
852
+ ],
853
+ "sensitivity": "secret"
854
+ },
855
+ {
856
+ "env": "TREESEED_PLATFORM_RUNNER_TOKEN",
857
+ "valueFrom": "selectedResource.secretRefs.runnerToken",
858
+ "targets": [
859
+ "railway-secret"
860
+ ],
861
+ "scopes": [
862
+ "staging",
863
+ "prod"
864
+ ],
865
+ "sensitivity": "secret"
866
+ },
867
+ {
868
+ "env": "TREESEED_PLATFORM_RUNNER_ID",
869
+ "valueFrom": "selectedResource.environmentValues.runnerId",
870
+ "targets": [
871
+ "railway-var"
872
+ ],
873
+ "scopes": [
874
+ "staging",
875
+ "prod"
876
+ ],
877
+ "sensitivity": "plain"
878
+ }
520
879
  ]
521
880
  }
522
881
  ]