@wtfalch/foundry 0.60.0 → 0.61.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 (218) hide show
  1. package/dist/apps/cloudflare.d.ts +173 -0
  2. package/dist/apps/cloudflare.js +17 -0
  3. package/dist/apps/deploy.d.ts +116 -0
  4. package/dist/apps/deploy.js +791 -0
  5. package/dist/apps/github.d.ts +47 -0
  6. package/dist/apps/github.js +201 -0
  7. package/dist/apps/index.d.ts +9 -0
  8. package/dist/apps/index.js +9 -0
  9. package/dist/apps/migrations.d.ts +110 -0
  10. package/dist/apps/migrations.js +458 -0
  11. package/dist/audit/connector.d.ts +43 -0
  12. package/dist/audit/connector.js +22 -0
  13. package/dist/audit/evidence.d.ts +49 -0
  14. package/dist/audit/evidence.js +56 -0
  15. package/dist/audit/index.d.ts +9 -0
  16. package/dist/audit/index.js +9 -0
  17. package/dist/audit/migrations.d.ts +5 -0
  18. package/dist/audit/migrations.js +5 -0
  19. package/dist/audit/registry.d.ts +49 -0
  20. package/dist/audit/registry.js +44 -0
  21. package/dist/audit/seal.d.ts +49 -0
  22. package/dist/audit/seal.js +131 -0
  23. package/dist/audit/sealer-role.d.ts +33 -0
  24. package/dist/audit/sealer-role.js +56 -0
  25. package/dist/audit/signer.d.ts +40 -0
  26. package/dist/audit/signer.js +78 -0
  27. package/dist/audit/tick.d.ts +36 -0
  28. package/dist/audit/tick.js +87 -0
  29. package/dist/catalogue/copy-en.d.ts +1 -0
  30. package/dist/catalogue/copy-en.js +129 -0
  31. package/dist/catalogue/index.d.ts +9 -0
  32. package/dist/catalogue/index.js +21 -0
  33. package/dist/catalogue/integrations.d.ts +4 -0
  34. package/dist/catalogue/integrations.js +104 -0
  35. package/dist/catalogue/systems.d.ts +7 -0
  36. package/dist/catalogue/systems.js +31 -0
  37. package/dist/catalogue/types.d.ts +110 -0
  38. package/dist/catalogue/types.js +1 -0
  39. package/dist/entry-rules.d.ts +53 -0
  40. package/dist/entry-rules.js +71 -0
  41. package/dist/hosted-label.d.ts +13 -0
  42. package/dist/hosted-label.js +81 -0
  43. package/dist/index.d.ts +10 -5
  44. package/dist/index.js +5 -3
  45. package/dist/migrations/0062_hosting_github.sql +6 -0
  46. package/dist/migrations/0063_boule_apps.sql +7 -0
  47. package/dist/migrations/0064_requested_changes_boule_apps.sql +6 -0
  48. package/dist/modules/ai.d.ts +3 -0
  49. package/dist/modules/ai.js +64 -0
  50. package/dist/modules/assistants.d.ts +3 -0
  51. package/dist/modules/assistants.js +72 -0
  52. package/dist/modules/audit-ledger.d.ts +29 -0
  53. package/dist/modules/audit-ledger.js +49 -0
  54. package/dist/modules/audit.d.ts +7 -0
  55. package/dist/modules/audit.js +44 -0
  56. package/dist/modules/database.d.ts +23 -0
  57. package/dist/modules/database.js +189 -0
  58. package/dist/modules/email.d.ts +3 -0
  59. package/dist/modules/email.js +18 -0
  60. package/dist/modules/entry-parts.d.ts +23 -0
  61. package/dist/modules/entry-parts.js +63 -0
  62. package/dist/modules/files.d.ts +3 -0
  63. package/dist/modules/files.js +64 -0
  64. package/dist/modules/index.d.ts +74 -0
  65. package/dist/modules/index.js +774 -0
  66. package/dist/modules/jobs.d.ts +3 -0
  67. package/dist/modules/jobs.js +23 -0
  68. package/dist/modules/organisations.d.ts +3 -0
  69. package/dist/modules/organisations.js +20 -0
  70. package/dist/modules/outputs.d.ts +9 -0
  71. package/dist/modules/outputs.js +38 -0
  72. package/dist/modules/sign-in.d.ts +3 -0
  73. package/dist/modules/sign-in.js +197 -0
  74. package/dist/modules/signed-records.d.ts +3 -0
  75. package/dist/modules/signed-records.js +32 -0
  76. package/dist/modules/types.d.ts +194 -0
  77. package/dist/modules/types.js +1 -0
  78. package/dist/modules/workspaces.d.ts +3 -0
  79. package/dist/modules/workspaces.js +75 -0
  80. package/dist/org.d.ts +163 -22
  81. package/dist/org.js +419 -47
  82. package/dist/plan/apps-db-route.d.ts +90 -0
  83. package/dist/plan/apps-db-route.js +168 -0
  84. package/dist/plan/apps-zones.d.ts +56 -0
  85. package/dist/plan/apps-zones.js +118 -0
  86. package/dist/plan/archon-blue-green.js +11 -1
  87. package/dist/plan/blue-green-apply.d.ts +37 -1
  88. package/dist/plan/blue-green-apply.js +55 -15
  89. package/dist/plan/blue-green.d.ts +41 -1
  90. package/dist/plan/blue-green.js +80 -2
  91. package/dist/plan/boule.d.ts +23 -1
  92. package/dist/plan/boule.js +35 -2
  93. package/dist/plan/broker-entries.d.ts +28 -3
  94. package/dist/plan/broker-entries.js +74 -3
  95. package/dist/plan/broker-registrar.d.ts +168 -0
  96. package/dist/plan/broker-registrar.js +440 -0
  97. package/dist/plan/broker-workspaces-database.d.ts +48 -0
  98. package/dist/plan/broker-workspaces-database.js +87 -0
  99. package/dist/plan/desktop-callback.js +12 -7
  100. package/dist/plan/diff.d.ts +8 -2
  101. package/dist/plan/diff.js +373 -42
  102. package/dist/plan/edge-access.d.ts +6 -0
  103. package/dist/plan/edge-dns.d.ts +6 -0
  104. package/dist/plan/edge-dns.js +9 -7
  105. package/dist/plan/entry-ai-key.d.ts +1 -1
  106. package/dist/plan/entry-ai-key.js +2 -2
  107. package/dist/plan/entry-audit.d.ts +58 -0
  108. package/dist/plan/entry-audit.js +122 -0
  109. package/dist/plan/entry-customer-grants.d.ts +75 -0
  110. package/dist/plan/entry-customer-grants.js +154 -0
  111. package/dist/plan/entry-edge-key.d.ts +26 -1
  112. package/dist/plan/entry-edge-key.js +42 -3
  113. package/dist/plan/entry-jobs.d.ts +64 -0
  114. package/dist/plan/entry-jobs.js +92 -0
  115. package/dist/plan/entry-repo-key-apply.d.ts +55 -0
  116. package/dist/plan/entry-repo-key-apply.js +185 -0
  117. package/dist/plan/entry-repo-key.d.ts +92 -0
  118. package/dist/plan/entry-repo-key.js +235 -0
  119. package/dist/plan/entry-workspaces.d.ts +55 -0
  120. package/dist/plan/entry-workspaces.js +90 -0
  121. package/dist/plan/executor.d.ts +191 -1
  122. package/dist/plan/executor.js +1505 -90
  123. package/dist/plan/gates.d.ts +1 -1
  124. package/dist/plan/gates.js +62 -9
  125. package/dist/plan/github-deploy-keys.d.ts +78 -0
  126. package/dist/plan/github-deploy-keys.js +305 -0
  127. package/dist/plan/github-source.d.ts +53 -0
  128. package/dist/plan/github-source.js +140 -0
  129. package/dist/plan/held-key-refs.d.ts +12 -0
  130. package/dist/plan/held-key-refs.js +12 -0
  131. package/dist/plan/hostnames.d.ts +9 -0
  132. package/dist/plan/hostnames.js +28 -1
  133. package/dist/plan/index.d.ts +9 -0
  134. package/dist/plan/index.js +6 -0
  135. package/dist/plan/jobs-scheduler-http.js +3 -0
  136. package/dist/plan/keys-registrar-http.d.ts +32 -0
  137. package/dist/plan/keys-registrar-http.js +105 -0
  138. package/dist/plan/keys-registrar.d.ts +67 -0
  139. package/dist/plan/keys-registrar.js +103 -0
  140. package/dist/plan/live.d.ts +1 -1
  141. package/dist/plan/locked-hostnames.d.ts +2 -2
  142. package/dist/plan/locked-hostnames.js +2 -2
  143. package/dist/plan/login-host.js +11 -5
  144. package/dist/plan/machine-paths.d.ts +36 -0
  145. package/dist/plan/machine-paths.js +137 -0
  146. package/dist/plan/mcp.d.ts +1 -1
  147. package/dist/plan/mcp.js +49 -17
  148. package/dist/plan/org-apps-admin.d.ts +108 -0
  149. package/dist/plan/org-apps-admin.js +434 -0
  150. package/dist/plan/org-names.js +12 -1
  151. package/dist/plan/own-diff.d.ts +23 -0
  152. package/dist/plan/own-diff.js +53 -0
  153. package/dist/plan/own-hostnames.d.ts +2 -0
  154. package/dist/plan/own-hostnames.js +1 -0
  155. package/dist/plan/own-jobs-route.d.ts +47 -0
  156. package/dist/plan/own-jobs-route.js +91 -0
  157. package/dist/plan/own-services.d.ts +4 -0
  158. package/dist/plan/own-services.js +4 -0
  159. package/dist/plan/plan-apply.d.ts +39 -0
  160. package/dist/plan/plan-apply.js +163 -9
  161. package/dist/plan/platform-diff.d.ts +2 -2
  162. package/dist/plan/platform-diff.js +7 -2
  163. package/dist/plan/platform-org.d.ts +30 -0
  164. package/dist/plan/platform-org.js +12 -1
  165. package/dist/plan/platform-providers.d.ts +2 -0
  166. package/dist/plan/platform-providers.js +7 -2
  167. package/dist/plan/post-logout-uris.js +7 -1
  168. package/dist/plan/private-pages.d.ts +26 -0
  169. package/dist/plan/private-pages.js +39 -0
  170. package/dist/plan/proxy-labels.d.ts +12 -1
  171. package/dist/plan/proxy-labels.js +32 -2
  172. package/dist/plan/release-host.d.ts +6 -2
  173. package/dist/plan/release-host.js +36 -8
  174. package/dist/plan/stage-env.d.ts +19 -1
  175. package/dist/plan/stage-env.js +25 -1
  176. package/dist/plan/stage-guards.d.ts +20 -0
  177. package/dist/plan/stage-guards.js +24 -0
  178. package/dist/plan/stage-isolation.d.ts +24 -0
  179. package/dist/plan/stage-isolation.js +29 -1
  180. package/dist/plan/worker-app-database.d.ts +46 -42
  181. package/dist/plan/worker-app-database.js +150 -153
  182. package/dist/plan/worker-app.d.ts +5 -65
  183. package/dist/plan/worker-app.js +28 -105
  184. package/dist/plan/worker.d.ts +2 -2
  185. package/dist/plan/worker.js +2 -1
  186. package/dist/plan/workspace-client.d.ts +25 -0
  187. package/dist/plan/workspace-client.js +48 -0
  188. package/dist/plan/workspace-sign-in.d.ts +55 -0
  189. package/dist/plan/workspace-sign-in.js +273 -0
  190. package/dist/plan/workspace-worker.d.ts +4 -0
  191. package/dist/plan/workspace-worker.js +13 -0
  192. package/dist/plan/workspace.d.ts +101 -0
  193. package/dist/plan/workspace.js +305 -0
  194. package/dist/release/decide.d.ts +30 -1
  195. package/dist/release/decide.js +73 -11
  196. package/dist/release/health.d.ts +8 -3
  197. package/dist/release/health.js +58 -5
  198. package/dist/release/run.d.ts +2 -5
  199. package/dist/release/run.js +4 -0
  200. package/dist/release/state.d.ts +3 -1
  201. package/dist/release/state.js +6 -0
  202. package/dist/release/types.d.ts +20 -0
  203. package/dist/requested-changes.d.ts +11 -2
  204. package/dist/requested-changes.js +11 -0
  205. package/dist/service-labels.d.ts +4 -0
  206. package/dist/service-labels.js +11 -0
  207. package/dist/slug.d.ts +2 -0
  208. package/dist/slug.js +10 -6
  209. package/dist/store/postgres.js +12 -2
  210. package/dist/store/schema.d.ts +37 -1
  211. package/dist/store/schema.js +4 -0
  212. package/dist/worker-app-config.d.ts +1 -11
  213. package/dist/worker-app-config.js +4 -17
  214. package/dist/worker-app-migrations.d.ts +105 -0
  215. package/dist/worker-app-migrations.js +166 -0
  216. package/dist/worker-app-upload.d.ts +103 -0
  217. package/dist/worker-app-upload.js +128 -0
  218. package/package.json +18 -1
package/dist/org.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { type WorkerAppConfig } from './worker-app-config.js';
2
2
  export type { WorkerAppConfig } from './worker-app-config.js';
3
+ export { AI_ENTRY_PERMISSIONS, FILES_ENTRY_PERMISSIONS, MCP_PATH, ONBOARDING_PATH_MAX_LENGTH, ROOM_STEPS_MAX, ROOM_STEPS_MIN, ROOM_TEXT_MAX, WORKSPACE_ROLE, WORKSPACE_ROLES_MAX, } from './entry-rules.js';
3
4
  /**
4
5
  * Opaque, minted by foundry when an org is created. Keys the declared org,
5
6
  * the applied state, every estate-wide service's id map, and the chat
@@ -218,6 +219,11 @@ export interface IssuerApp {
218
219
  * validates is always one Coolify itself accepts.
219
220
  */
220
221
  export type HostingBuildPack = 'dockerfile' | 'nixpacks' | 'static' | 'dockercompose';
222
+ /** The company's GitHub App installation: the numeric installation id and the account (user or org login) it is installed on. */
223
+ export interface HostingGithub {
224
+ installationId: number;
225
+ account: string;
226
+ }
221
227
  /**
222
228
  * The org's hosted apps and what runs beside them (#71, part of #14's
223
229
  * adopted/standard/bespoke map) -- distinct from the cms site (`SiteConfig`
@@ -233,6 +239,12 @@ export type HostingBuildPack = 'dockerfile' | 'nixpacks' | 'static' | 'dockercom
233
239
  * be true.
234
240
  */
235
241
  export interface HostingConfig {
242
+ /**
243
+ * The company's installation of the platform's GitHub App. With it an entry's `repo` may be
244
+ * `<account>/<name>` as well as `wtfalch/<name>`, and the planner makes the company its own Coolify GitHub
245
+ * source (`coolify:github-source`) from the installation id. Absent: only `wtfalch/<name>`.
246
+ */
247
+ github?: HostingGithub;
236
248
  /** The org's apps run on Coolify. */
237
249
  enabled: boolean;
238
250
  /** Served on `DeclaredOrg.domain` (and its Cloudflare zone managed) instead of `<slug>.oikos.host` (`../slug.ts`). */
@@ -289,7 +301,7 @@ export type AccessRule = {
289
301
  /** The key of the entry that is today's one app: the Coolify app named `<slug>`. */
290
302
  export declare const APP_ENTRY_KEY = "app";
291
303
  /** Why a validator refused. `code` is stable and never reworded; `message` is for people. */
292
- export type OrgRefusalCode = 'hosting_tunnel_needs_hosting' | 'issuer_app_name_missing' | 'issuer_app_name_not_unique' | 'issuer_app_kind_unknown' | 'issuer_app_name_reserved_agora' | 'issuer_app_name_reserved_boule' | 'hosting_needs_entry' | 'hosting_main_count' | 'entry_key_not_unique' | 'ai_webhook_path_not_unique' | 'worker_route_not_unique' | 'database_not_unique' | 'access_hostname_not_unique' | 'access_hostname_invalid' | 'access_needs_hosting' | 'access_kind_unknown' | 'access_service_token_name_missing' | 'access_hostname_locked' | 'access_hostname_not_served' | 'gate_limit_invalid' | 'hosting_repo_invalid' | 'gate_needs_domain' | 'gate_key_invalid' | 'gate_key_not_unique' | 'gate_needs_hostname' | 'gate_hostname_not_entry_hostname' | 'gate_hostname_held_twice' | 'gate_hostname_locked' | 'gate_limit_exceeded' | 'wildcard_needs_domain' | 'wildcard_held_twice' | 'hostnames_need_domain' | 'hostname_needed' | 'hostname_invalid' | 'hostname_not_unique' | 'hostname_locked' | 'entry_key_invalid' | 'entry_key_reserved' | 'entry_repo_invalid' | 'entry_folder_invalid' | 'entry_branch_empty' | 'entry_build_pack_unknown' | 'entry_build_pack_unavailable' | 'entry_port_invalid' | 'entry_health_path_invalid' | 'entry_capabilities_invalid' | 'entry_database_needs_hosting' | 'blue_green_needs_hostname' | 'env_name_empty' | 'env_name_reserved' | 'env_source_platform_mail_key' | 'env_source_unknown' | 'env_shared_secret_name_invalid' | 'env_held_secret_name_mismatch' | 'env_held_secret_name_invalid' | 'env_looks_like_secret' | 'builtin_app_invalid' | 'blue_green_not_object' | 'blue_green_steps_length' | 'blue_green_steps_range' | 'blue_green_steps_order' | 'blue_green_steps_end' | 'blue_green_hold_invalid' | 'volumes_not_list' | 'volumes_too_many' | 'volume_name_invalid' | 'volume_name_logs' | 'volume_name_not_unique' | 'volume_mount_path_invalid' | 'volume_mount_path_too_long' | 'volume_mount_path_log_dir' | 'volume_mount_path_forbidden' | 'volume_mount_path_not_unique' | 'auth_needs_hosting' | 'auth_users_invalid' | 'auth_registration_invalid' | 'registration_open_needs_customers' | 'auth_replaces_broker_entry_invalid' | 'auth_replaces_broker_entry_owned' | 'auth_needs_exact_hostname' | 'mcp_needs_open_customers' | 'mcp_path_invalid' | 'mcp_onboarding_path_invalid' | 'auth_sign_in_invalid' | 'email_code_needs_customers' | 'auth_room_invalid' | 'auth_room_needs_customers' | 'auth_room_not_unique' | 'client_name_taken' | 'ai_needs_hosting' | 'ai_offerings_invalid' | 'ai_permissions_invalid' | 'ai_webhook_path_invalid' | 'ai_webhook_needs_exact_hostname' | 'ai_env_clash' | 'files_needs_hosting' | 'files_collections_invalid' | 'files_permissions_invalid' | 'files_share_host_invalid' | 'files_share_host_needs_domain' | 'files_env_clash' | 'worker_needs_hosting' | 'worker_needs_repo' | 'worker_key_too_long' | 'worker_artifact_invalid' | 'worker_route_invalid' | 'worker_route_off_domain' | 'worker_rate_limit_name_missing' | 'worker_rate_limit_namespace_missing' | 'worker_rate_limit_invalid' | 'worker_rate_limit_period_invalid' | 'worker_app_invalid' | 'edge_not_true' | 'edge_needs_hosting' | 'edge_needs_domain' | 'edge_env_clash' | 'customers_invalid' | 'customers_sign_up_needs_enabled' | 'registration_open_needs_sign_up';
304
+ export type OrgRefusalCode = 'hosting_tunnel_needs_hosting' | 'issuer_app_name_missing' | 'issuer_app_name_not_unique' | 'issuer_app_kind_unknown' | 'issuer_app_name_reserved_agora' | 'issuer_app_name_reserved_boule' | 'hosting_needs_entry' | 'hosting_main_count' | 'entry_key_not_unique' | 'ai_webhook_path_not_unique' | 'worker_route_not_unique' | 'database_not_unique' | 'access_hostname_not_unique' | 'access_hostname_invalid' | 'access_needs_hosting' | 'access_kind_unknown' | 'access_service_token_name_missing' | 'access_hostname_locked' | 'access_hostname_not_served' | 'gate_limit_invalid' | 'hosting_repo_invalid' | 'hosting_github_invalid' | 'gate_needs_domain' | 'gate_key_invalid' | 'gate_key_not_unique' | 'gate_needs_hostname' | 'gate_hostname_not_entry_hostname' | 'gate_hostname_held_twice' | 'gate_hostname_locked' | 'gate_limit_exceeded' | 'wildcard_needs_domain' | 'wildcard_held_twice' | 'hostnames_need_domain' | 'hostname_needed' | 'hostname_invalid' | 'hostname_not_unique' | 'hostname_locked' | 'hosted_name_invalid' | 'hosted_name_not_unique' | 'hosted_name_worker_app' | 'entry_workspace_invalid' | 'entry_workspace_unsupported' | 'entry_live_needs_workspace' | 'entry_live_commit_invalid' | 'gate_key_taken_by_workspace' | 'gate_key_taken_by_private_page' | 'private_page_invalid' | 'private_page_path_invalid' | 'private_page_duplicate' | 'private_page_limit' | 'private_page_needs_hosting' | 'private_page_roles_invalid' | 'private_page_people_invalid' | 'entry_key_invalid' | 'entry_key_reserved' | 'entry_repo_invalid' | 'entry_folder_invalid' | 'entry_branch_empty' | 'entry_build_pack_unknown' | 'entry_build_pack_unavailable' | 'entry_port_invalid' | 'entry_health_path_invalid' | 'entry_capabilities_invalid' | 'entry_database_needs_hosting' | 'blue_green_needs_hostname' | 'env_name_empty' | 'env_name_reserved' | 'env_source_platform_mail_key' | 'env_source_unknown' | 'env_shared_secret_name_invalid' | 'env_held_secret_name_mismatch' | 'env_held_secret_name_invalid' | 'env_looks_like_secret' | 'builtin_app_invalid' | 'blue_green_not_object' | 'blue_green_steps_length' | 'blue_green_steps_range' | 'blue_green_steps_order' | 'blue_green_steps_end' | 'blue_green_hold_invalid' | 'blue_green_advance_invalid' | 'blue_green_min_requests_invalid' | 'blue_green_error_margin_invalid' | 'blue_green_staff_first_invalid' | 'volumes_not_list' | 'volumes_too_many' | 'volume_name_invalid' | 'volume_name_logs' | 'volume_name_not_unique' | 'volume_mount_path_invalid' | 'volume_mount_path_too_long' | 'volume_mount_path_log_dir' | 'volume_mount_path_forbidden' | 'volume_mount_path_not_unique' | 'auth_needs_hosting' | 'auth_users_invalid' | 'auth_registration_invalid' | 'registration_open_needs_customers' | 'auth_replaces_broker_entry_invalid' | 'auth_replaces_broker_entry_owned' | 'auth_needs_exact_hostname' | 'mcp_needs_open_customers' | 'mcp_path_invalid' | 'mcp_onboarding_path_invalid' | 'auth_sign_in_invalid' | 'email_code_needs_customers' | 'auth_room_invalid' | 'auth_room_needs_customers' | 'auth_room_not_unique' | 'client_name_taken' | 'workspaces_needs_customers' | 'workspaces_needs_server' | 'workspaces_roles_invalid' | 'workspaces_role_reserved' | 'workspaces_invite_path_invalid' | 'workspaces_env_clash' | 'ai_needs_hosting' | 'ai_offerings_invalid' | 'ai_permissions_invalid' | 'ai_webhook_path_invalid' | 'ai_webhook_needs_exact_hostname' | 'ai_env_clash' | 'files_needs_hosting' | 'files_collections_invalid' | 'files_permissions_invalid' | 'files_share_host_invalid' | 'files_share_host_needs_domain' | 'files_env_clash' | 'worker_needs_hosting' | 'worker_needs_repo' | 'worker_needs_own_repo' | 'worker_key_too_long' | 'worker_artifact_invalid' | 'worker_route_invalid' | 'worker_route_off_domain' | 'worker_rate_limit_name_missing' | 'worker_rate_limit_namespace_missing' | 'worker_rate_limit_invalid' | 'worker_rate_limit_period_invalid' | 'worker_app_invalid' | 'edge_not_true' | 'edge_needs_hosting' | 'edge_needs_domain' | 'edge_env_clash' | 'mail_not_true' | 'mail_needs_hosting' | 'mail_env_clash' | 'jobs_not_true' | 'jobs_needs_hosting' | 'jobs_env_clash' | 'customer_grants_not_true' | 'customer_grants_needs_customers' | 'customer_grants_env_clash' | 'repo_use_invalid' | 'repo_use_needs_repo' | 'repo_use_env_clash' | 'audit_not_true' | 'audit_needs_hosting' | 'audit_needs_worker_database' | 'customers_invalid' | 'customers_sign_up_needs_enabled' | 'registration_open_needs_sign_up';
293
305
  /**
294
306
  * One refusal: a stable `code`, the dotted `path` into {@link DeclaredOrg} it is about
295
307
  * (`hosting.entries.terminal.uses.auth.registration`) and the sentence for people.
@@ -322,6 +334,11 @@ export interface HostingEntry {
322
334
  buildPack: HostingBuildPack;
323
335
  /** The port the app listens on. `null` is Coolify's default. */
324
336
  port: number | null;
337
+ /**
338
+ * The app's live address on the platform's apps domain: `<hostedName>.companyincluded.app`. A
339
+ * label {@link hostedLabelRefusal} accepts; unique within the org (the host checks it across orgs).
340
+ */
341
+ hostedName?: string;
325
342
  /**
326
343
  * The org's main app: served at the org's main address (`<slug>.oikos.host`, or the domain's
327
344
  * apex), whatever its key. An entry keyed {@link APP_ENTRY_KEY} with `main` unset is main.
@@ -374,8 +391,8 @@ export interface HostingEntry {
374
391
  * F8: a Cloudflare Worker foundry deploys from this entry's own repo,
375
392
  * beside the app, on the org's own zone. Only our own repos may use this
376
393
  * (#318: outside customers need Workers for Platforms, not built yet), so
377
- * `validateEntryWorker` refuses it unless `repo` is set (every non-null
378
- * `repo` already matches `wtfalch/...`, {@link REPO}) and the route's zone
394
+ * `validateEntryWorker` refuses it unless `repo` is set and under `wtfalch`
395
+ * ({@link REPO}; a company's own GitHub account is refused) and the route's zone
379
396
  * is the org's own domain.
380
397
  */
381
398
  worker?: WorkerConfig;
@@ -390,7 +407,63 @@ export interface HostingEntry {
390
407
  * blue and a green copy behind a load balancer on every server it manages, and the tunnel routes to the balancer.
391
408
  */
392
409
  blueGreen?: BlueGreenConfig;
410
+ /**
411
+ * A private workspace for the app: it runs at `workspaceHost(slug, key)` behind a Cloudflare Access gate that
412
+ * lets in the company's people and `testers`. A server entry's workspace is the blue/green stage machinery
413
+ * (its own empty database, the stage mail sink, the stage guards) without colors; a `workerApp` entry's is a
414
+ * second Worker script `<slug>-<key>-work`. See `plan/workspace.ts`. Not combined with `blueGreen`.
415
+ */
416
+ workspace?: EntryWorkspace;
417
+ /**
418
+ * Whether the app is live. Absent means true. `false` plans no public hostname, DNS record, live app or live
419
+ * Worker: only the workspace exists, so it needs `workspace`. Setting it to true makes the live app from the
420
+ * commit the workspace runs, with its own database; the workspace stays.
421
+ */
422
+ live?: boolean;
423
+ /**
424
+ * The 40 character commit the live app runs, set by a promote. Needs `workspace` and a server (repo) entry.
425
+ * When set, the live app is made from it and later moved to it (`git_commit_sha` patched, then deployed),
426
+ * whatever the workspace runs. Absent: the app is made from the workspace's commit and stays there. It may be
427
+ * a commit the workspace never ran (a rollback).
428
+ */
429
+ liveCommit?: string;
430
+ /**
431
+ * Parts of the app only the company's people may open, each gated by a path-scoped Cloudflare Access
432
+ * application on `<host><path>`, on the live hosts and (with a `workspace`) on the workspace host. See
433
+ * `plan/private-pages.ts`.
434
+ */
435
+ privatePages?: PrivatePage[];
436
+ }
437
+ /** One private page of an entry. */
438
+ export interface PrivatePage {
439
+ /** Starts with `/`; letters, digits and `. _ ~ - /`; no query, no trailing slash, not `/` itself. */
440
+ path: string;
441
+ /** The company's role ids that may open the page. Foundry cannot resolve roles; see `people`. */
442
+ roles: string[];
443
+ /**
444
+ * The company people holding `roles`, as email addresses, resolved by the host that declares the org (as
445
+ * `workspace.testers` is supplied). The gate admits the owners plus these. Absent: the owners only.
446
+ */
447
+ people?: string[];
448
+ }
449
+ export declare const MAX_PRIVATE_PAGES = 20;
450
+ export declare const MAX_PRIVATE_PAGE_ROLES = 50;
451
+ export declare const MAX_PRIVATE_PAGE_PEOPLE = 200;
452
+ export declare const PRIVATE_PAGE_PATH: RegExp;
453
+ /** The keys of the Access gates private pages get: `pp-` (live) or `wp-` (workspace) and 16 hex characters. */
454
+ export declare const PRIVATE_PAGE_GATE_KEY: RegExp;
455
+ /** A full git commit: 40 lowercase hex characters. */
456
+ export declare const FULL_COMMIT_SHA: RegExp;
457
+ /** The people outside the company who may open an entry's workspace. */
458
+ export interface EntryWorkspace {
459
+ /** Email addresses, at most {@link MAX_WORKSPACE_TESTERS}, distinct when lowercased. */
460
+ testers: string[];
393
461
  }
462
+ export declare const MAX_WORKSPACE_TESTERS = 50;
463
+ /** An entry is live unless it says `live: false`. */
464
+ export declare const isLiveEntry: (entry: Pick<HostingEntry, "live">) => boolean;
465
+ /** Trimmed, lowercased and distinct testers, in the order first seen. The planner and hosts read testers through this. */
466
+ export declare function normalizeTesters(testers: readonly string[]): string[];
394
467
  /**
395
468
  * `boule` and `agora` on a company: the built-in apps foundry runs for every company (`<slug>-boule`,
396
469
  * `<slug>-agora`). Only blue/green is declared here; absent means off. Optional so every existing literal and
@@ -399,11 +472,34 @@ export interface HostingEntry {
399
472
  export interface OrgBuiltinApp {
400
473
  blueGreen?: BlueGreenConfig;
401
474
  }
475
+ /**
476
+ * The company's Boule. `apps` (F3, F5, F7) turns on the managed-apps platform keys: Boule installs and runs apps
477
+ * for the company, so foundry gives it an edge key that may deploy the company's own Workers
478
+ * (`plan/entry-edge-key.ts`), a registrar key at the sign-in broker (`plan/broker-registrar.ts`) and a registrar key
479
+ * at the signed-records service (`plan/keys-registrar.ts`). Absent is off. Boule's apps are not in `hosting.entries`,
480
+ * so this switch is how the plan knows the company has any.
481
+ */
482
+ export interface BouleApp extends OrgBuiltinApp {
483
+ apps?: boolean;
484
+ }
485
+ /** True while the company's Boule runs apps (`org.boule.apps`). */
486
+ export declare const appsOn: (org: Pick<DeclaredOrg, "boule">) => boolean;
402
487
  /** The traffic steps (percent to the new color) and the hold at each step. Both default in `plan/blue-green.ts`. */
403
488
  export interface BlueGreenConfig {
404
489
  /** Ascending, each 1..100, ending at 100. */
405
490
  steps?: number[];
406
491
  stepHoldMinutes?: number;
492
+ /**
493
+ * How a step is left. `signal` (default): the hold passed and the error rate matches the old color's.
494
+ * `time`: the hold passed and the error rate is not failing. `approval`: a person approves each step.
495
+ */
496
+ advance?: 'time' | 'signal' | 'approval';
497
+ /** Requests the new color needs before its error rate counts (whole number 1..100000). Default 20. */
498
+ minRequests?: number;
499
+ /** The new color matches the old while its error rate is at most the old plus this (0..1). Default 0.02. */
500
+ errorMargin?: number;
501
+ /** A promote deploys the idle color and holds it at weight 0 for staff until an `open` action. Default false. */
502
+ staffFirst?: boolean;
407
503
  }
408
504
  /** One named volume on a hosting entry's app. */
409
505
  export interface EntryVolume {
@@ -498,6 +594,16 @@ export interface EntryAuth {
498
594
  * `users: 'customers'`.
499
595
  */
500
596
  signIn?: 'password' | 'email-code';
597
+ /**
598
+ * The entry's own customers get workspaces in the broker: they make one, invite people by email and give
599
+ * each member one of `roles`. The first role is the owner role. `invitePath` is the page on the entry's
600
+ * host the invitation mail links to (`<host><invitePath>?token=`). Needs `users: 'customers'` and an
601
+ * entry that runs as a server. The entry gets `WORKSPACES_URL` and `WORKSPACES_API_KEY`.
602
+ */
603
+ workspaces?: {
604
+ roles: string[];
605
+ invitePath: string;
606
+ };
501
607
  /**
502
608
  * The left-half text of the customers' sign-in window. Written on the
503
609
  * customers organisation as metadata `wtfalch.room` (JSON, keys in the
@@ -506,6 +612,8 @@ export interface EntryAuth {
506
612
  */
507
613
  room?: EntryAuthRoom;
508
614
  }
615
+ /** The env names `uses.auth.workspaces` writes; `env` may not name them. */
616
+ export declare const WORKSPACES_ENTRY_ENV_NAMES: readonly ["WORKSPACES_URL", "WORKSPACES_API_KEY"];
509
617
  export interface EntryAuthRoom {
510
618
  name: string;
511
619
  headline: string;
@@ -514,20 +622,6 @@ export interface EntryAuthRoom {
514
622
  description?: string;
515
623
  steps?: number;
516
624
  }
517
- /** Longest value of each `uses.auth.room` text field. */
518
- export declare const ROOM_TEXT_MAX: {
519
- readonly name: 40;
520
- readonly headline: 120;
521
- readonly line: 200;
522
- readonly title: 60;
523
- readonly description: 200;
524
- };
525
- export declare const ROOM_STEPS_MIN = 2;
526
- export declare const ROOM_STEPS_MAX = 9;
527
- /** `uses.auth.mcp.onboardingPath`: absolute, no query, no fragment, no dot segments. */
528
- export declare const ONBOARDING_PATH_MAX_LENGTH = 200;
529
- /** The MCP endpoint path: absolute, plain characters, no dot segments, no query. */
530
- export declare const MCP_PATH: RegExp;
531
625
  /**
532
626
  * AI for one entry: a key below the org's own ai key, the `AI_*` env and,
533
627
  * with `webhookPath`, the ai webhook. `offerings` is what the app may call,
@@ -540,8 +634,6 @@ export interface EntryAi {
540
634
  permissions?: string[];
541
635
  webhookPath?: string;
542
636
  }
543
- /** What an entry's ai key may hold: the most the org's own key holds. */
544
- export declare const AI_ENTRY_PERMISSIONS: readonly ["ai.offerings:invoke", "ai.runs:create"];
545
637
  /** The env names `uses.ai` writes; `env` may not name them. */
546
638
  export declare const AI_ENTRY_ENV_NAMES: readonly ["AI_URL", "AI_ORGANISATION_ID", "AI_API_KEY", "AI_WEBHOOK_SECRET", "AI_OFFERINGS_JSON"];
547
639
  /**
@@ -559,8 +651,6 @@ export interface EntryFiles {
559
651
  permissions?: string[];
560
652
  shareHost?: boolean;
561
653
  }
562
- /** What an entry's files key may hold: read and write on its collections, and the most the org's own key holds besides minting. */
563
- export declare const FILES_ENTRY_PERMISSIONS: readonly ["files.collections:read", "files.files:read", "files.files:download", "files.files:upload", "files.files:replace", "files.files:delete"];
564
654
  /** The env names `uses.files` always writes, besides one `FILES_COLLECTION_<NAME>_ID` per collection. */
565
655
  export declare const FILES_ENTRY_ENV_NAMES: readonly ["FILES_URL", "FILES_ORGANISATION_ID", "FILES_API_KEY"];
566
656
  export declare const filesCollectionEnvName: (name: string) => string;
@@ -576,9 +666,49 @@ export interface HostingEntryUses {
576
666
  * org `domain`.
577
667
  */
578
668
  edge?: true;
669
+ /**
670
+ * The entry sends mail from the company's mail domain: it gets the company's
671
+ * Lettermint token and `MAIL_FROM`, as the main app does. In a workspace the
672
+ * stage gets the mail sink's env only (`stageMailEnv`).
673
+ */
674
+ mail?: true;
675
+ /**
676
+ * The entry is a project of its own in the jobs scheduler and gets
677
+ * `JOBS_SCHEDULER_URL` (the scheduler's public origin), `JOBS_SIGNING_SECRET`
678
+ * and `JOBS_SYNC_KEY` (`plan/entry-jobs.ts`). Blocked, not planned, until the
679
+ * scheduler's public route (`plan/own-jobs-route.ts`) is recorded: the owner
680
+ * company's for a company on shared services, the company's own otherwise.
681
+ * A workspace gets none of the three.
682
+ */
683
+ jobs?: true;
684
+ /**
685
+ * The app keeps a tamper-evident audit log (`@wtfalch/audit`). A Worker app with a database: the append-only
686
+ * tables and the two chain functions are derived (`audit/ledger-set.ts`), never listed by hand, and the
687
+ * platform's sealing service signs and anchors the ledger on a schedule with a key the app never holds
688
+ * (`plan/entry-audit.ts`, `audit/`). The erase functions are not granted.
689
+ */
690
+ audit?: true;
691
+ /**
692
+ * The app implements Boule's customer-grants routes under `/api/customer-grants`, called by a machine
693
+ * (Boule), not a person. F11 only lets that path through a gated host (`entryMachinePaths`); F13 builds
694
+ * the rest (the credential, the app env and Boule's entry).
695
+ */
696
+ customerGrants?: true;
697
+ /**
698
+ * F12: the entry gets credentials for its own `repo`: a GitHub deploy key made for it (write only with
699
+ * `access: 'write'`), delivered as `GIT_REPO_URL` (`git@github.com:<owner>/<name>.git`) and `GIT_SSH_KEY`
700
+ * (`plan/entry-repo-key.ts`). Needs `repo`. Removed with the entry or the flag; a workspace copy gets none.
701
+ */
702
+ repo?: {
703
+ access: 'read' | 'write';
704
+ };
579
705
  }
580
706
  /** The env names `uses.edge` writes; `env` may not name them (#317). */
581
707
  export declare const EDGE_ENTRY_ENV_NAMES: readonly ["EDGE_URL", "EDGE_API_KEY"];
708
+ /** The env names `uses.mail` writes; `env` may not name them. */
709
+ export declare const MAIL_ENTRY_ENV_NAMES: readonly ["LETTERMINT_API_TOKEN", "MAIL_FROM"];
710
+ /** The env names `uses.jobs` writes; `env` may not name them. */
711
+ export declare const JOBS_ENTRY_ENV_NAMES: readonly ["JOBS_SCHEDULER_URL", "JOBS_SIGNING_SECRET", "JOBS_SYNC_KEY"];
582
712
  /**
583
713
  * A plain string is pushed as it is, so `validateHosting` refuses one that
584
714
  * looks like a secret. `{ from }` names a value the plan already mints.
@@ -661,10 +791,21 @@ export interface HostingNames {
661
791
  export declare function normalizeHostingRepos(repos: readonly string[] | undefined): string[];
662
792
  /** {@link validateHosting} with the code and path of the first refusal. */
663
793
  export declare function refuseHosting(hosting: HostingConfig, names?: HostingNames): OrgRefusal | null;
794
+ /**
795
+ * The company's GitHub config when `repo` is under its account, else `undefined`: such an entry is built
796
+ * through the company's own Coolify source, any other through the platform's. Read it only through this.
797
+ */
798
+ export declare function companyGithubFor(hosting: Pick<HostingConfig, 'github'>, repo: string | null): HostingGithub | undefined;
664
799
  /** `blueGreen`: steps ascending, each a whole number 1..100, the last 100; a hold of 1..1440 minutes. */
665
800
  export declare function validateBlueGreen(value: unknown, at: string): string | null;
666
801
  /** {@link refuseBlueGreen} for the `blueGreen` of the company's Boule and Agora; the same codes. */
667
802
  export declare function refuseBuiltinBlueGreen(org: Pick<DeclaredOrg, 'boule' | 'agora'>): OrgRefusal | null;
803
+ /** The env names `uses.repo` writes; `env` may not name them. */
804
+ export declare const REPO_ENTRY_ENV_NAMES: readonly ["GIT_REPO_URL", "GIT_SSH_KEY"];
805
+ /** The env name `uses.customerGrants` writes; `env` may not name it. */
806
+ export declare const CUSTOMER_GRANTS_ENTRY_ENV_NAMES: readonly ["CUSTOMER_GRANTS_CREDENTIAL"];
807
+ /** The platform zone new app addresses (`<hostedName>.companyincluded.app`) and every workspace live in. */
808
+ export declare const APPS_DOMAIN = "companyincluded.app";
668
809
  export declare function validateDomain(domain: string): string | null;
669
810
  /**
670
811
  * A broker entry name foundry writes itself: Archon's, and any company's Boule.
@@ -1082,7 +1223,7 @@ export interface DeclaredOrg {
1082
1223
  /** Absent means `{ inApp: true }`. Optional so every existing literal and fixture compiles unchanged. */
1083
1224
  signIn?: SignInConfig;
1084
1225
  /** The company's Boule. Absent means no blue/green. */
1085
- boule?: OrgBuiltinApp;
1226
+ boule?: BouleApp;
1086
1227
  /** The company's Agora, a static app: its release moves on hard fails and time only. Absent means no blue/green. */
1087
1228
  agora?: OrgBuiltinApp;
1088
1229
  /** Absent means `{ enabled: false, signUp: false }`. Optional so every existing literal and fixture compiles unchanged. */