@k2b/cloud 0.47.0 → 0.49.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 (240) hide show
  1. package/package.json +3 -3
  2. package/src/_internal/app-access-manager-sql.ts +10 -0
  3. package/src/_internal/app-access-resources.ts +2 -1
  4. package/src/_internal/app-capabilities.ts +73 -0
  5. package/src/_internal/app-event-catalog.ts +1 -1
  6. package/src/_internal/app-queries.ts +1 -1
  7. package/src/_internal/application-package.ts +2 -1
  8. package/src/_internal/bounded-json.ts +7 -1
  9. package/src/_internal/capabilities.ts +25 -2
  10. package/src/_internal/define-app.ts +33 -2
  11. package/src/_internal/heartbeat.ts +2 -0
  12. package/src/_internal/nats-connection.ts +10 -9
  13. package/src/_internal/process-sync.ts +6 -6
  14. package/src/_internal/public-surface.ts +76 -0
  15. package/src/_internal/purpose-name.ts +7 -0
  16. package/src/_internal/registry-validation.ts +1 -0
  17. package/src/_internal/registry.ts +49 -3
  18. package/src/_internal/workload-credential.ts +2 -1
  19. package/src/ai/app-skill-store.ts +2 -1
  20. package/src/ai/app-skills.ts +2 -1
  21. package/src/ai/approvals.ts +2 -1
  22. package/src/ai/chat-tasks.ts +2 -1
  23. package/src/ai/credentials.ts +2 -1
  24. package/src/ai/dictation-runtime.ts +1 -1
  25. package/src/ai/dictations.ts +1 -1
  26. package/src/ai/files-store.ts +2 -1
  27. package/src/ai/inference-calls.ts +2 -1
  28. package/src/ai/map-store.ts +1 -1
  29. package/src/ai/map-tool.ts +1 -1
  30. package/src/ai/memories.ts +1 -1
  31. package/src/ai/memory-learning-runs.ts +1 -1
  32. package/src/ai/memory-learning.ts +1 -1
  33. package/src/ai/memory-workflow-evidence.ts +1 -1
  34. package/src/ai/message-queue.ts +2 -1
  35. package/src/ai/migrate.ts +1 -1
  36. package/src/ai/model-access-migrate.ts +1 -1
  37. package/src/ai/model-access.ts +1 -1
  38. package/src/ai/model-catalog.ts +1 -1
  39. package/src/ai/model-delete.ts +1 -1
  40. package/src/ai/model-usage.ts +2 -1
  41. package/src/ai/open-questions.ts +1 -1
  42. package/src/ai/openai-api-slots.ts +2 -1
  43. package/src/ai/prefs.ts +2 -1
  44. package/src/ai/projects.ts +2 -1
  45. package/src/ai/provider-connections.ts +1 -1
  46. package/src/ai/quota-limits.ts +2 -1
  47. package/src/ai/quota-provider.ts +2 -1
  48. package/src/ai/quota-report.ts +2 -1
  49. package/src/ai/quotas-migrate.ts +2 -1
  50. package/src/ai/quotas.ts +2 -1
  51. package/src/ai/request-headers.ts +2 -1
  52. package/src/ai/review-content.ts +2 -1
  53. package/src/ai/skill-search.ts +2 -1
  54. package/src/ai/skills.ts +2 -1
  55. package/src/ai/store.ts +2 -1
  56. package/src/ai/structured-runs.ts +2 -1
  57. package/src/ai/tool-audit.ts +2 -1
  58. package/src/ai/turn-timing.ts +1 -1
  59. package/src/ai/usage.ts +2 -1
  60. package/src/ai/web-provenance.ts +2 -1
  61. package/src/api/admin-ai-quotas.ts +1 -1
  62. package/src/api/admin-ai.ts +1 -1
  63. package/src/api/admin-app-domains.ts +62 -0
  64. package/src/api/admin-app-keys.ts +47 -3
  65. package/src/api/admin-core-settings.ts +1 -1
  66. package/src/api/admin-outgoing-mail.ts +1 -1
  67. package/src/api/app-bootstrap.ts +153 -0
  68. package/src/api/app-events.ts +1 -1
  69. package/src/api/auth.ts +1 -1
  70. package/src/api/authenticate-app-request.ts +129 -0
  71. package/src/api/capabilities.ts +87 -6
  72. package/src/api/index.ts +7 -0
  73. package/src/api/me.ts +1 -1
  74. package/src/api/search.bench.ts +1 -1
  75. package/src/app-pwa/service.ts +2 -1
  76. package/src/app-pwa/transaction.ts +4 -2
  77. package/src/capabilities/claims.ts +2 -1
  78. package/src/capabilities/executions.ts +8 -4
  79. package/src/capabilities/geo-client.ts +1 -1
  80. package/src/capabilities/migrate.ts +3 -1
  81. package/src/capabilities/resource-readers.ts +2 -2
  82. package/src/capabilities/response.ts +2 -1
  83. package/src/capabilities/server-invoke.ts +73 -20
  84. package/src/capabilities/server.ts +2 -1
  85. package/src/cli/admin/app-domains.ts +140 -0
  86. package/src/cli/admin/app-keys.ts +25 -3
  87. package/src/cli/admin/index.ts +107 -88
  88. package/src/config/env.ts +10 -4
  89. package/src/contracts/app-domains.ts +91 -0
  90. package/src/contracts/app-status.ts +104 -0
  91. package/src/contracts/capabilities.ts +37 -2
  92. package/src/contracts/index.ts +1 -0
  93. package/src/contracts/outgoing-mail.ts +1 -1
  94. package/src/contracts/registry.ts +2 -0
  95. package/src/events/app-event-delivery.ts +1 -1
  96. package/src/events/live-delivery.ts +2 -1
  97. package/src/index.ts +1 -0
  98. package/src/runtime/bootstrap-client.ts +195 -0
  99. package/src/runtime/bootstrap-protocol.ts +67 -0
  100. package/src/runtime/clients.ts +6 -2
  101. package/src/runtime/connections.ts +9 -0
  102. package/src/server/app-key.ts +14 -0
  103. package/src/server/index.ts +2 -0
  104. package/src/server/ratelimit.ts +1 -1
  105. package/src/server/services/access.ts +2 -1
  106. package/src/services/account-category-policy.ts +1 -1
  107. package/src/services/account-lifecycle/audit.ts +1 -1
  108. package/src/services/account-lifecycle/index.ts +1 -1
  109. package/src/services/account-lifecycle/ipa-backfill.ts +2 -1
  110. package/src/services/accounts/app.ts +1 -1
  111. package/src/services/accounts/avatar.ts +1 -1
  112. package/src/services/accounts/base-group.ts +1 -1
  113. package/src/services/accounts/directory-shares.ts +1 -1
  114. package/src/services/accounts/duplicate-emails.ts +1 -1
  115. package/src/services/accounts/entities.ts +2 -1
  116. package/src/services/accounts/group-sql.ts +2 -1
  117. package/src/services/accounts/groups.ts +1 -1
  118. package/src/services/accounts/identities.ts +13 -11
  119. package/src/services/accounts/ipa-data.ts +1 -1
  120. package/src/services/accounts/local-groups.ts +2 -1
  121. package/src/services/accounts/machine-group-management.ts +2 -1
  122. package/src/services/accounts/posix.ts +13 -12
  123. package/src/services/accounts/request-policy.ts +2 -1
  124. package/src/services/accounts/switching.ts +1 -1
  125. package/src/services/accounts/users.ts +2 -1
  126. package/src/services/announcements/index.ts +1 -1
  127. package/src/services/app-access-management.ts +3 -9
  128. package/src/services/app-access.ts +2 -1
  129. package/src/services/app-admin-facts.ts +160 -0
  130. package/src/services/app-approval.ts +34 -30
  131. package/src/services/app-bootstrap.ts +217 -0
  132. package/src/services/app-details.ts +3 -2
  133. package/src/services/app-domain-check.ts +152 -0
  134. package/src/services/app-domains.ts +172 -0
  135. package/src/services/app-events/accept.ts +5 -5
  136. package/src/services/app-events/admin.ts +15 -15
  137. package/src/services/app-events/declarations.ts +6 -3
  138. package/src/services/app-events/deliver.ts +6 -6
  139. package/src/services/app-events.ts +3 -2
  140. package/src/services/app-keys.ts +45 -11
  141. package/src/services/approvals/content.ts +1 -1
  142. package/src/services/approvals/index.ts +2 -1
  143. package/src/services/approvals/list.ts +1 -1
  144. package/src/services/approvals/migrate.ts +1 -1
  145. package/src/services/audit/index.ts +2 -1
  146. package/src/services/auth-flows/ipa.ts +1 -1
  147. package/src/services/auth-flows/magic-link.ts +1 -1
  148. package/src/services/auth-flows/password-reset.ts +1 -1
  149. package/src/services/auth-flows/proxy-return.ts +1 -1
  150. package/src/services/downstream-budget.ts +2 -2
  151. package/src/services/geo/admin.ts +13 -12
  152. package/src/services/geo/identity.ts +46 -0
  153. package/src/services/geo/ledger.ts +118 -106
  154. package/src/services/geo/migrate.ts +2 -1
  155. package/src/services/geo/route-chain.ts +3 -3
  156. package/src/services/geo/service.ts +4 -24
  157. package/src/services/geoip/index.ts +5 -5
  158. package/src/services/geoip/store.ts +24 -21
  159. package/src/services/help/index.ts +2 -1
  160. package/src/services/help/store.ts +2 -1
  161. package/src/services/identity/app-request.ts +44 -0
  162. package/src/services/identity/constants.ts +1 -0
  163. package/src/services/identity/index.ts +1 -0
  164. package/src/services/identity/invocation-actor.ts +2 -1
  165. package/src/services/identity/invocation-token.ts +112 -0
  166. package/src/services/identity/key-ring.ts +2 -2
  167. package/src/services/identity/resource-readers.ts +1 -1
  168. package/src/services/identity/routes.ts +11 -3
  169. package/src/services/identity/runtime-config.ts +14 -3
  170. package/src/services/identity/workload-auth.ts +2 -0
  171. package/src/services/identity/workload-runtime.ts +3 -3
  172. package/src/services/index.ts +4 -0
  173. package/src/services/ipa/groups.ts +1 -1
  174. package/src/services/ipa/profile.ts +1 -1
  175. package/src/services/ipa/search.ts +1 -1
  176. package/src/services/ipa/sync.ts +1 -1
  177. package/src/services/ipa/users.ts +1 -1
  178. package/src/services/known-browsers.ts +2 -1
  179. package/src/services/legal-consent.ts +1 -1
  180. package/src/services/links/index.ts +16 -0
  181. package/src/services/links/runtime.ts +44 -0
  182. package/src/services/links/store.ts +105 -0
  183. package/src/services/logging/index.ts +13 -8
  184. package/src/services/logging/redaction.ts +6 -1
  185. package/src/services/logging/trace.ts +9 -9
  186. package/src/services/logging/web-vitals.ts +1 -1
  187. package/src/services/mandates/index.ts +2 -1
  188. package/src/services/notifications/batches.ts +1 -1
  189. package/src/services/notifications/browser.ts +1 -1
  190. package/src/services/notifications/catalog.ts +1 -1
  191. package/src/services/notifications/dispatcher.ts +1 -1
  192. package/src/services/notifications/index.ts +1 -1
  193. package/src/services/notifications/observability.ts +2 -1
  194. package/src/services/notifications/platform.ts +1 -1
  195. package/src/services/notifications/quiet.ts +1 -1
  196. package/src/services/notifications/user.ts +1 -1
  197. package/src/services/oauth-tokens.ts +1 -1
  198. package/src/services/outbox.ts +15 -14
  199. package/src/services/outgoing-mail/admin.ts +1 -1
  200. package/src/services/outgoing-mail/dispatcher.ts +1 -1
  201. package/src/services/outgoing-mail/drain.ts +2 -1
  202. package/src/services/outgoing-mail/enqueue.ts +2 -1
  203. package/src/services/outgoing-mail/messages.ts +2 -1
  204. package/src/services/outgoing-mail/retention.ts +1 -1
  205. package/src/services/outgoing-mail/send.ts +1 -1
  206. package/src/services/outgoing-mail/store.ts +2 -1
  207. package/src/services/panel-context-consent.ts +32 -28
  208. package/src/services/providers/local/auth.ts +1 -1
  209. package/src/services/providers/local/users.ts +1 -1
  210. package/src/services/pwa-devices.ts +2 -1
  211. package/src/services/rail-preferences.ts +16 -12
  212. package/src/services/rail-shortcuts.ts +12 -10
  213. package/src/services/request-cache-redis.ts +3 -3
  214. package/src/services/service-account-credentials.ts +2 -1
  215. package/src/services/service-accounts.ts +2 -1
  216. package/src/services/session/index.ts +2 -1
  217. package/src/services/session/user.ts +2 -1
  218. package/src/services/settings/core-settings.ts +20 -0
  219. package/src/services/settings/crypto.ts +2 -2
  220. package/src/services/settings/index.ts +1 -1
  221. package/src/services/settings/store.ts +6 -1
  222. package/src/services/settings/versions.ts +2 -1
  223. package/src/services/weather/forecast.ts +2 -1
  224. package/src/services/weather/locations.ts +1 -1
  225. package/src/services/weather/migrate.ts +2 -1
  226. package/src/services/weather/short-id.ts +2 -1
  227. package/src/services/webauthn.ts +1 -1
  228. package/src/ssr/admin-navigation.ts +0 -1
  229. package/src/ssr/compact-shell.browser-harness.ts +2 -0
  230. package/src/ssr/platform-messages.ts +0 -2
  231. package/src/start.ts +35 -14
  232. package/src/workflows/ai/store.ts +2 -1
  233. package/src/workflows/store/budget.ts +2 -1
  234. package/src/workflows/store/definitions.ts +2 -1
  235. package/src/workflows/store/events.ts +2 -1
  236. package/src/workflows/store/observability.ts +2 -1
  237. package/src/workflows/store/retention.ts +2 -1
  238. package/src/workflows/store/runs.ts +2 -1
  239. package/src/workflows/store/transaction.ts +2 -1
  240. package/src/workflows/store/worker.ts +2 -1
@@ -5,7 +5,9 @@
5
5
  * them. The groups map to the admin UI areas, so a command and the page that
6
6
  * shows the same data stay easy to find together.
7
7
  */
8
+
8
9
  import { defineCliCommands } from "../commands";
10
+ import { type CloudCliContext, localizeCloudCliText } from "../index";
9
11
  import { accountAdministrationCommands } from "./account-administration";
10
12
  import { accountCategoryCommands } from "./account-categories";
11
13
  import { agentCommands } from "./agents";
@@ -14,6 +16,7 @@ import { aiQuotaCommands } from "./ai-quotas";
14
16
  import { aiSkillCommands } from "./ai-skills";
15
17
  import { aiUsageCommands } from "./ai-usage";
16
18
  import { appCredentialCommands } from "./app-credentials";
19
+ import { appDomainCommands } from "./app-domains";
17
20
  import { appKeyCommands } from "./app-keys";
18
21
  import { appSignInCommands } from "./app-sign-in";
19
22
  import { dataCommands } from "./data";
@@ -35,91 +38,107 @@ import { telemetryCommands } from "./telemetry";
35
38
  import { webhookCommands } from "./webhooks";
36
39
  import { workflowCommands } from "./workflows";
37
40
 
38
- export default defineCliCommands({
39
- name: "admin",
40
- summary: "Inspect and operate Cloud administration surfaces.",
41
- groupSummaries: {
42
- accounts: "Manage account policy and account administration.",
43
- ai: "Manage AI models, quotas, Skills, and usage.",
44
- "ai models": "Manage AI model configuration.",
45
- "ai providers": "Manage AI provider connections.",
46
- "ai variants": "Manage named model variants.",
47
- "ai classes": "Manage model classes and tools.",
48
- "ai quotas background": "Inspect and release the background emergency stop.",
49
- "ai skills": "Inspect Assistant Skills and trusted templates.",
50
- "ai usage": "Inspect AI runs and usage facets.",
51
- announcements: "Manage platform announcements and banners.",
52
- "app-credentials": "Manage per-application credentials for background work.",
53
- agents: "Create, list, revoke, and re-key agent accounts with OAuth client credentials, and change their pictures.",
54
- "agents avatar": "Show and change an agent's picture: its robot parts or a photo.",
55
- "app-sign-in": "Manage app sign-in and pairing.",
56
- apps: "Inspect registered apps and manage app keys.",
57
- "apps keys": "Create, list, and revoke Ed25519 app keys.",
58
- documentation: "Manage the administration documentation website.",
59
- geoip: "Replace and inspect sign-in location databases.",
60
- jobs: "Inspect background jobs and their runs.",
61
- logs: "Search, inspect, and clean up retained logs.",
62
- metrics: "Inspect collectors and manage metrics access.",
63
- "metrics tokens": "Manage metrics bearer tokens.",
64
- nats: "Inspect NATS nodes, streams, and consumers.",
65
- "nats consumers": "Inspect NATS consumers.",
66
- "nats streams": "Find NATS streams and buckets.",
67
- "notification-batches": "Manage account notification batches.",
68
- "outgoing-mail": "Manage outgoing mail sender profiles, application access, and the send log.",
69
- "outgoing-mail profiles": "Manage outgoing mail sender profiles.",
70
- "outgoing-mail apps": "Manage application outgoing mail access.",
71
- "outgoing-mail log": "Read and cancel application mail in the send log.",
72
- "outgoing-mail retention": "Show or change how long the send log keeps mail.",
73
- notifications: "Inspect and resend email notifications.",
74
- postgres: "Inspect Postgres diagnostics.",
75
- redis: "Inspect Valkey diagnostics.",
76
- routes: "Inspect gateway routes.",
77
- settings: "Inspect environment migration and change administrator settings.",
78
- sync: "Inspect Sync resources, schedules, and dead letters.",
79
- "sync dead-letters": "Inspect, replay, requeue, or remove dead letters.",
80
- "sync resources": "List Sync resource declarations.",
81
- "sync schedules": "Inspect and run Sync schedules.",
82
- "sync schedules runs": "Read Sync schedule run results.",
83
- telemetry: "Inspect request telemetry.",
84
- webhooks: "Manage gateway health webhooks.",
85
- workflows: "Inspect and operate workflow runs and effects.",
86
- "app-sign-in config": "Manage the trusted app website and pairing policy.",
87
- "accounts config": "Manage account types and sign-in visibility.",
88
- "accounts administration": "Manage account requests and account/group follow-up notices.",
89
- "ai quotas": "Manage direct Assistant chat limits and consumption.",
90
- "ai quotas config": "Export and replace quota policies with revision checks.",
91
- legal: "Manage Terms, Privacy, and Imprint.",
92
- linux: "Prepare Linux identities.",
93
- "linux config": "Manage Linux identity defaults and allocation range.",
94
- },
95
- commands: [
96
- ...appCredentialCommands,
97
- ...appKeyCommands,
98
- ...agentCommands,
99
- ...documentationCommands,
100
- ...appSignInCommands,
101
- ...accountCategoryCommands,
102
- ...accountAdministrationCommands,
103
- ...aiUsageCommands,
104
- ...aiModelCommands,
105
- ...aiQuotaCommands,
106
- ...aiSkillCommands,
107
- ...instanceCommands,
108
- ...gatewayCommands,
109
- ...logCommands,
110
- ...telemetryCommands,
111
- ...jobCommands,
112
- ...legalCommands,
113
- ...geoipCommands,
114
- ...linuxCommands,
115
- ...workflowCommands,
116
- ...dataCommands,
117
- ...notificationCommands,
118
- ...outgoingMailCommands,
119
- ...webhookCommands,
120
- ...metricsCommands,
121
- ...natsCommands,
122
- ...syncCommands,
123
- ...settingsCommands,
124
- ],
125
- });
41
+ const build = (locale?: string) =>
42
+ defineCliCommands({
43
+ name: "admin",
44
+ summary: "Inspect and operate Cloud administration surfaces.",
45
+ groupSummaries: {
46
+ accounts: "Manage account policy and account administration.",
47
+ ai: "Manage AI models, quotas, Skills, and usage.",
48
+ "ai models": "Manage AI model configuration.",
49
+ "ai providers": "Manage AI provider connections.",
50
+ "ai variants": "Manage named model variants.",
51
+ "ai classes": "Manage model classes and tools.",
52
+ "ai quotas background": "Inspect and release the background emergency stop.",
53
+ "ai skills": "Inspect Assistant Skills and trusted templates.",
54
+ "ai usage": "Inspect AI runs and usage facets.",
55
+ announcements: "Manage platform announcements and banners.",
56
+ "app-credentials": "Manage per-application credentials for background work.",
57
+ agents: "Create, list, revoke, and re-key agent accounts with OAuth client credentials, and change their pictures.",
58
+ "agents avatar": "Show and change an agent's picture: its robot parts or a photo.",
59
+ "app-sign-in": "Manage app sign-in and pairing.",
60
+ apps: localizeCloudCliText(locale, {
61
+ en: "Inspect registered apps and manage app keys and domains.",
62
+ de: "Registrierte Apps prüfen und App-Schlüssel und App-Domains verwalten.",
63
+ }),
64
+ "apps domains": localizeCloudCliText(locale, {
65
+ en: "Assign app domains and inspect DNS, TLS and gateway reachability.",
66
+ de: "App-Domains zuordnen und DNS, TLS und Gateway-Erreichbarkeit prüfen.",
67
+ }),
68
+ "apps keys": "Create, list, and revoke Ed25519 app keys.",
69
+ documentation: "Manage the administration documentation website.",
70
+ geoip: "Replace and inspect sign-in location databases.",
71
+ jobs: "Inspect background jobs and their runs.",
72
+ logs: "Search, inspect, and clean up retained logs.",
73
+ metrics: "Inspect collectors and manage metrics access.",
74
+ "metrics tokens": "Manage metrics bearer tokens.",
75
+ nats: "Inspect NATS nodes, streams, and consumers.",
76
+ "nats consumers": "Inspect NATS consumers.",
77
+ "nats streams": "Find NATS streams and buckets.",
78
+ "notification-batches": "Manage account notification batches.",
79
+ "outgoing-mail": "Manage outgoing mail sender profiles, application access, and the send log.",
80
+ "outgoing-mail profiles": "Manage outgoing mail sender profiles.",
81
+ "outgoing-mail apps": "Manage application outgoing mail access.",
82
+ "outgoing-mail log": "Read and cancel application mail in the send log.",
83
+ "outgoing-mail retention": "Show or change how long the send log keeps mail.",
84
+ notifications: "Inspect and resend email notifications.",
85
+ postgres: "Inspect Postgres diagnostics.",
86
+ redis: "Inspect Valkey diagnostics.",
87
+ routes: "Inspect gateway routes.",
88
+ settings: "Inspect environment migration and change administrator settings.",
89
+ sync: "Inspect Sync resources, schedules, and dead letters.",
90
+ "sync dead-letters": "Inspect, replay, requeue, or remove dead letters.",
91
+ "sync resources": "List Sync resource declarations.",
92
+ "sync schedules": "Inspect and run Sync schedules.",
93
+ "sync schedules runs": "Read Sync schedule run results.",
94
+ telemetry: "Inspect request telemetry.",
95
+ webhooks: "Manage gateway health webhooks.",
96
+ workflows: "Inspect and operate workflow runs and effects.",
97
+ "app-sign-in config": "Manage the trusted app website and pairing policy.",
98
+ "accounts config": "Manage account types and sign-in visibility.",
99
+ "accounts administration": "Manage account requests and account/group follow-up notices.",
100
+ "ai quotas": "Manage direct Assistant chat limits and consumption.",
101
+ "ai quotas config": "Export and replace quota policies with revision checks.",
102
+ legal: "Manage Terms, Privacy, and Imprint.",
103
+ linux: "Prepare Linux identities.",
104
+ "linux config": "Manage Linux identity defaults and allocation range.",
105
+ },
106
+ commands: [
107
+ ...appCredentialCommands,
108
+ ...appKeyCommands,
109
+ ...appDomainCommands(locale),
110
+ ...agentCommands,
111
+ ...documentationCommands,
112
+ ...appSignInCommands,
113
+ ...accountCategoryCommands,
114
+ ...accountAdministrationCommands,
115
+ ...aiUsageCommands,
116
+ ...aiModelCommands,
117
+ ...aiQuotaCommands,
118
+ ...aiSkillCommands,
119
+ ...instanceCommands,
120
+ ...gatewayCommands,
121
+ ...logCommands,
122
+ ...telemetryCommands,
123
+ ...jobCommands,
124
+ ...legalCommands,
125
+ ...geoipCommands,
126
+ ...linuxCommands,
127
+ ...workflowCommands,
128
+ ...dataCommands,
129
+ ...notificationCommands,
130
+ ...outgoingMailCommands,
131
+ ...webhookCommands,
132
+ ...metricsCommands,
133
+ ...natsCommands,
134
+ ...syncCommands,
135
+ ...settingsCommands,
136
+ ],
137
+ });
138
+
139
+ const admin = build();
140
+ export default {
141
+ ...admin,
142
+ help: (locale?: string) => build(locale).help?.(locale) ?? "",
143
+ run: (ctx: CloudCliContext) => build(ctx.options.locale).run(ctx),
144
+ };
package/src/config/env.ts CHANGED
@@ -164,17 +164,23 @@ const registry = defineEnv({
164
164
  schema: z.string(),
165
165
  scope: "secret",
166
166
  secretFile: true,
167
- doc: "Core and OAuth only: 64-hex secret that lets the OAuth app request token signatures from Core; generate independently with `openssl rand -hex 32`.",
167
+ doc: "Deprecated: Core and OAuth legacy 64-hex broker secret, used only when OAuth has no app key. Configure an OAuth app key instead; retained for this release.",
168
+ },
169
+ CLOUD_APP_KEY: {
170
+ schema: z.string(),
171
+ scope: "secret",
172
+ secretFile: true,
173
+ doc: "App Ed25519 private key for startup bootstrap, background calls and OAuth issuance; alternatively mount CLOUD_APP_KEY_FILE. Requires the direct Core origin. Core and Gateway refuse app keys. Keep infrastructure env until the platform-client import migration is complete.",
168
174
  },
169
175
  CLOUD_CORE_INTERNAL_ORIGIN: {
170
176
  schema: z.string(),
171
- doc: "Direct Core listener origin for OAuth issuance, mandate-backed background work and internal callbacks; host-run callers use the Core port, not the gateway.",
177
+ doc: "Direct Core listener origin for app connection bootstrap, OAuth issuance, mandate-backed background work and internal callbacks; never the gateway. Cross-host bootstrap requires verified TLS; install private CAs through NODE_EXTRA_CA_CERTS before the first fetch.",
172
178
  },
173
179
  CLOUD_APP_CREDENTIAL: {
174
180
  schema: z.string(),
175
181
  scope: "secret",
176
182
  secretFile: true,
177
- doc: "Optional host-run app override for the automatically delivered app workload credential; provision through Core's admin workload API with `identity:invoke`.",
183
+ doc: "Deprecated: host-run override for the automatically delivered workload credential when no app key is configured; use CLOUD_APP_KEY or CLOUD_APP_KEY_FILE instead. Retained for this release.",
178
184
  },
179
185
  CLOUD_IDENTITY_JWKS_ORIGIN: {
180
186
  schema: z.string(),
@@ -182,7 +188,7 @@ const registry = defineEnv({
182
188
  },
183
189
  CLOUD_OAUTH_JWKS_ORIGIN: {
184
190
  schema: z.string(),
185
- doc: "Optional private origin of the OAuth listener for OAuth JWKS; unset fetches keys from the public issuer origin.",
191
+ doc: "Deprecated: explicit legacy OAuth JWKS origin, honored for this release. Unset uses Core internal OAuth JWKS through CLOUD_CORE_INTERNAL_ORIGIN, then the public issuer origin.",
186
192
  },
187
193
 
188
194
  // Build and standalone development
@@ -0,0 +1,91 @@
1
+ import type { SQL } from "bun";
2
+ import { PWA_COOKIES } from "./pwa";
3
+
4
+ /**
5
+ * App public surface and app domains: the contract Core, the platform, and the gateway share.
6
+ *
7
+ * An app with `defineApp({ public: true })` serves `app.public`. The platform mounts that router below
8
+ * `PUBLIC_SURFACE_PREFIX` on the app upstream. Only the gateway sends requests there, for a host an
9
+ * administrator assigned to the app, and sets `PUBLIC_HOST_HEADER` to the request authority (that host plus the
10
+ * client's port, if its Host header had one). The gateway strips both
11
+ * the prefix and the header from every incoming request on every host.
12
+ */
13
+ export const PUBLIC_SURFACE_PREFIX = "/_cloud/public";
14
+ export const PUBLIC_HOST_HEADER = "X-Cloud-Public-Host";
15
+
16
+ /** The only Cloud path on an app domain: `GET <prefix><nonce>` answers the nonce while Core checks the domain. */
17
+ export const DOMAIN_CHECK_PATH_PREFIX = "/_cloud/domain-check/";
18
+ /**
19
+ * Valkey key Core sets before it requests the check path, with TTL `DOMAIN_CHECK_TTL_SECONDS`. Its value is a
20
+ * separate random answer that never appears in the request; the gateway responds with it, so an unrelated server
21
+ * that echoes the path cannot pass the check.
22
+ */
23
+ export const domainCheckKey = (host: string, nonce: string): string => `cloud:domain-check:${host}:${nonce}`;
24
+ export const DOMAIN_CHECK_TTL_SECONDS = 60;
25
+
26
+ export type AppDomain = {
27
+ /** Normalized host: lowercase ASCII (IDNA), no port, no wildcard. */
28
+ host: string;
29
+ appId: string;
30
+ /** Another domain of the same app; requests then answer 301 (GET/HEAD) or 308 with path and query kept. */
31
+ redirectTo: string | null;
32
+ createdAt: string;
33
+ };
34
+
35
+ /** Durable assignment, owned by Core's migration. Readers before that migration see no table and no domains. */
36
+ export const APP_DOMAINS_DDL = `
37
+ CREATE TABLE IF NOT EXISTS settings.app_domains (
38
+ host TEXT PRIMARY KEY,
39
+ app_id TEXT NOT NULL,
40
+ redirect_to TEXT NULL,
41
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
42
+ )
43
+ `;
44
+
45
+ const HOST_LABEL = /^(?!-)[a-z0-9-]{1,63}(?<!-)$/;
46
+
47
+ /** Returns the normalized host, or null when `input` is not a single DNS host name without port or wildcard. */
48
+ export const normalizeAppDomainHost = (input: string): string | null => {
49
+ const trimmed = input.trim().replace(/\.$/, "");
50
+ if (!trimmed || /[/\\:@?#*\s]/.test(trimmed)) return null;
51
+ let host: string;
52
+ try {
53
+ host = new URL(`http://${trimmed}`).hostname;
54
+ } catch {
55
+ return null;
56
+ }
57
+ if (host.length > 253 || /^\d+(\.\d+){3}$/.test(host) || host.startsWith("[")) return null;
58
+ const labels = host.split(".");
59
+ if (labels.length < 2 && !host.endsWith("localhost")) return null;
60
+ return labels.every((label) => HOST_LABEL.test(label)) ? host : null;
61
+ };
62
+
63
+ /** Reads all assignments. A database without Core's table yet has none. */
64
+ export const readAppDomains = async (db: SQL): Promise<AppDomain[]> => {
65
+ try {
66
+ const rows = await db<{ host: string; app_id: string; redirect_to: string | null; created_at: Date }[]>`
67
+ SELECT host, app_id, redirect_to, created_at FROM settings.app_domains ORDER BY host
68
+ `;
69
+ return rows.map((row) => ({ host: row.host, appId: row.app_id, redirectTo: row.redirect_to, createdAt: row.created_at.toISOString() }));
70
+ } catch (error) {
71
+ const code = error && typeof error === "object" && "errno" in error ? String(error.errno) : "";
72
+ if (code === "42P01") return [];
73
+ throw error;
74
+ }
75
+ };
76
+
77
+ /** Whether a registry entry declares `public: true`, read structurally so older entries stay valid. */
78
+ export const declaresPublicSurface = (entry: object): boolean => "public" in entry && entry.public === true;
79
+
80
+ /** Cookies that carry a Cloud credential. The gateway removes them from every request to a public surface. */
81
+ export const isCloudCredentialCookie = (name: string): boolean =>
82
+ name === "session_token" ||
83
+ name === PWA_COOKIES.session ||
84
+ name === PWA_COOKIES.device ||
85
+ name === PWA_COOKIES.pairing ||
86
+ name === "cloud_browser" ||
87
+ name === "__Host-cloud_browser" ||
88
+ name.startsWith("__Secure-cloud-app-pwa-") ||
89
+ // Access proofs that built-in apps set on the Cloud host.
90
+ name === "mail_attachment_grant" ||
91
+ name === "filesv2-share-access";
@@ -0,0 +1,104 @@
1
+ import { z } from "zod";
2
+ import { CapabilityAppIdSchema, type CapabilityManifest } from "./capabilities";
3
+ import { type CapabilityContractIssue, capabilityContractIssues } from "./capability-compatibility";
4
+
5
+ export const AppStatusWindowSchema = z.enum(["1h", "6h", "24h", "7d", "30d"]);
6
+ export type AppStatusWindow = z.infer<typeof AppStatusWindowSchema>;
7
+ export const AppStatusSummaryInputSchema = z
8
+ .object({
9
+ appIds: z.array(CapabilityAppIdSchema).min(1).max(200).describe("Application IDs whose status is requested."),
10
+ window: AppStatusWindowSchema.describe("Traffic observation window."),
11
+ })
12
+ .strict();
13
+ export const AppStatusDetailInputSchema = z
14
+ .object({
15
+ appId: CapabilityAppIdSchema.describe("Application ID."),
16
+ window: AppStatusWindowSchema.describe("Traffic observation window."),
17
+ cursor: z.string().min(1).max(2048).optional().describe("Opaque continuation cursor from this provider."),
18
+ })
19
+ .strict();
20
+ export const AppStatusForgetInputSchema = z.object({ appId: CapabilityAppIdSchema.describe("Offline application ID to forget.") }).strict();
21
+ const count = z.number().int().nonnegative();
22
+ export const AppStatusTrafficSchema = z
23
+ .object({
24
+ requests: count,
25
+ errors: count,
26
+ avgMs: z.number().nonnegative().nullable(),
27
+ })
28
+ .strict();
29
+ export const AppStatusLinkSchema = z
30
+ .object({
31
+ kind: z.enum(["logs", "metrics", "routes", "capabilities"]).optional(),
32
+ label: z.string().min(1).max(120),
33
+ href: z
34
+ .string()
35
+ .max(2048)
36
+ .regex(/^\/admin\/[^\\\s\u0000-\u001f\u007f]*$/),
37
+ })
38
+ .strict();
39
+ export const AppStatusAppSchema = z
40
+ .object({
41
+ appId: CapabilityAppIdSchema.describe("Application ID."),
42
+ traffic: AppStatusTrafficSchema.nullable(),
43
+ links: z.array(AppStatusLinkSchema).max(4),
44
+ lastSeenAt: z.string().datetime({ offset: true }).nullable().optional(),
45
+ })
46
+ .strict();
47
+ export const AppStatusSummaryDataSchema = z
48
+ .object({
49
+ // Requested apps plus the fifty provider-only apps; their rows carry lastSeenAt.
50
+ apps: z.array(AppStatusAppSchema).max(250),
51
+ otherApps: z.array(CapabilityAppIdSchema).max(50),
52
+ })
53
+ .strict();
54
+ export const AppStatusDetailDataSchema = z
55
+ .object({
56
+ routes: z.array(z.object({ prefix: z.string().min(1).max(2048), requests: count, errors: count }).strict()).max(200),
57
+ failedRequests: z
58
+ .array(
59
+ z
60
+ .object({
61
+ at: z.string().datetime({ offset: true }),
62
+ method: z.string().min(1).max(32),
63
+ path: z.string().min(1).max(2048),
64
+ status: z.number().int().min(100).max(599),
65
+ })
66
+ .strict(),
67
+ )
68
+ .max(50),
69
+ totalFailedRequests: count.nullable().optional(),
70
+ nextCursor: z.string().min(1).max(2048).nullable(),
71
+ })
72
+ .strict();
73
+ export const AppStatusForgetDataSchema = z.object({ forgotten: z.boolean() }).strict();
74
+ export type AppStatusSummaryData = z.infer<typeof AppStatusSummaryDataSchema>;
75
+ export type AppStatusDetailData = z.infer<typeof AppStatusDetailDataSchema>;
76
+
77
+ /** Shared role validation at startup, registry read, and consumer discovery. */
78
+ export const appStatusIssues = (manifest: CapabilityManifest): CapabilityContractIssue[] => {
79
+ const role = manifest.appStatus;
80
+ if (!role) return [];
81
+ const issues: CapabilityContractIssue[] = [];
82
+ for (const [localId, input, data] of [
83
+ [role.summary, AppStatusSummaryInputSchema, AppStatusSummaryDataSchema],
84
+ [role.detail, AppStatusDetailInputSchema, AppStatusDetailDataSchema],
85
+ ] as const) {
86
+ const query = manifest.queries.find((query) => query.localId === localId);
87
+ if (!query) issues.push({ code: "kind", path: "$", message: `Missing app-status Query ${localId}` });
88
+ else {
89
+ issues.push(...capabilityContractIssues({ kind: "query", input, data }, { kind: "query", operation: query }));
90
+ if (query.appOnly || query.openWorld)
91
+ issues.push({ code: "kind", path: "$", message: "App-status Queries must be closed-world and person-readable" });
92
+ }
93
+ }
94
+ const action = manifest.actions.find((action) => action.localId === role.forget);
95
+ if (!action) issues.push({ code: "kind", path: "$", message: `Missing app-status Action ${role.forget}` });
96
+ else
97
+ issues.push(
98
+ ...capabilityContractIssues(
99
+ { kind: "action", input: AppStatusForgetInputSchema, data: AppStatusForgetDataSchema, idempotency: "required" },
100
+ { kind: "action", operation: action },
101
+ ),
102
+ );
103
+ return issues;
104
+ };
@@ -12,6 +12,7 @@ import { z } from "zod";
12
12
  import type { RequestAuthority } from "../server/middleware/auth";
13
13
  import type { AppEventDefinition, AppEventSubscriptionDefinition } from "./app-events";
14
14
  import { CommandPathSchema } from "./commands";
15
+ import { type PlatformPermission, PlatformPermissionSchema } from "./outgoing-mail";
15
16
  import type { AccessSubject, RequestActor, User } from "./shared";
16
17
  import { AuthenticatedPrincipalSchema } from "./shared";
17
18
 
@@ -955,12 +956,12 @@ export type CapabilityPresentationCatalog = {
955
956
 
956
957
  /** App authority has no grant-bearing subject, user, nested exchange, or interactive credential. */
957
958
  export type CapabilityAppExecutionContext = {
958
- actor: { kind: "app"; appId: string };
959
+ actor: { kind: "app"; appId: string; keyId?: string };
959
960
  accessSubject: { type: "none" };
960
961
  user: null;
961
962
  authority?: never;
962
963
  query?: never;
963
- idempotencyKey?: never;
964
+ idempotencyKey?: string;
964
965
  locale: string;
965
966
  requestId: string;
966
967
  origin: CapabilityOrigin;
@@ -968,8 +969,18 @@ export type CapabilityAppExecutionContext = {
968
969
  signal: AbortSignal;
969
970
  };
970
971
 
972
+ /** Explicit provider entry for calls paid for and authorized as the calling application. */
973
+ export type CapabilityAppHandler<Input extends z.ZodType, Data extends z.ZodType> = {
974
+ permission: PlatformPermission;
975
+ run: (
976
+ input: z.output<Input>,
977
+ context: CapabilityAppExecutionContext,
978
+ ) => CapabilityInvocationResult<z.output<Data>> | Promise<CapabilityInvocationResult<z.output<Data>>>;
979
+ };
980
+
971
981
  export type CapabilityQueryDefinition<Input extends z.ZodType = z.ZodType<any>, Data extends z.ZodType = z.ZodType<any>> = {
972
982
  appOnly?: never;
983
+ app?: CapabilityAppHandler<Input, Data>;
973
984
  title: string;
974
985
  description: string;
975
986
  input: Input;
@@ -988,6 +999,7 @@ export type CapabilityActionApprovalPolicy = "rememberable" | "none";
988
999
 
989
1000
  export type CapabilityActionDefinition<Input extends z.ZodType = z.ZodType<any>, Data extends z.ZodType = z.ZodType<any>> = {
990
1001
  appOnly?: never;
1002
+ app?: CapabilityAppHandler<Input, Data>;
991
1003
  title: string;
992
1004
  description: string;
993
1005
  input: Input;
@@ -1039,6 +1051,8 @@ export type CapabilityFileProviderDeclaration = { list: string; read: string; sa
1039
1051
 
1040
1052
  export type CapabilityCalendarSourceDeclaration = { calendars: string; events: string; update?: string; move?: string; delete?: string };
1041
1053
 
1054
+ export type CapabilityAppStatusDeclaration = { summary: string; detail: string; forget: string };
1055
+
1042
1056
  export type CapabilityDiscussionsDeclaration = { item: string; containers: string; activity?: string };
1043
1057
 
1044
1058
  export type CapabilityDefinitions = {
@@ -1051,6 +1065,7 @@ export type CapabilityDefinitions = {
1051
1065
  fileProvider?: CapabilityFileProviderDeclaration;
1052
1066
  calendarSource?: CapabilityCalendarSourceDeclaration;
1053
1067
  discussions?: CapabilityDiscussionsDeclaration;
1068
+ appStatus?: CapabilityAppStatusDeclaration;
1054
1069
  events?: CapabilityDefinitionCatalog<AppEventDefinition>;
1055
1070
  subscribes?: CapabilityDefinitionCatalog<AppEventSubscriptionDefinition>;
1056
1071
  };
@@ -1101,6 +1116,7 @@ const CapabilityOperationManifestBaseSchema = z
1101
1116
  inputSchema: z.record(z.string(), z.unknown()),
1102
1117
  dataSchema: z.record(z.string(), z.unknown()),
1103
1118
  stream: CapabilityStreamPolicySchema.optional(),
1119
+ appPermission: PlatformPermissionSchema.optional(),
1104
1120
  schemaHash: z.string().regex(/^[a-f0-9]{64}$/),
1105
1121
  })
1106
1122
  .strict();
@@ -1179,6 +1195,14 @@ export const CapabilityResourcePageManifestSchema = z
1179
1195
  })
1180
1196
  .strict();
1181
1197
 
1198
+ export const CapabilityAppStatusManifestSchema = z
1199
+ .object({
1200
+ summary: CapabilityLocalIdSchema,
1201
+ detail: CapabilityLocalIdSchema,
1202
+ forget: CapabilityLocalIdSchema,
1203
+ })
1204
+ .strict();
1205
+
1182
1206
  export const CapabilityDiscussionsManifestSchema = z
1183
1207
  .object({
1184
1208
  item: CapabilityLocalIdSchema,
@@ -1268,6 +1292,7 @@ const readableManifest = (value: unknown, personCatalog = false): unknown => {
1268
1292
  resourcePages: sentPages,
1269
1293
  resourceTypes: sentModels,
1270
1294
  discussions: sentDiscussions,
1295
+ appStatus: sentAppStatus,
1271
1296
  ...rest
1272
1297
  } = sent;
1273
1298
  const models = readEntries(sentModels ?? [], CapabilityResourceTypeModelSchema) ?? [];
@@ -1309,6 +1334,14 @@ const readableManifest = (value: unknown, personCatalog = false): unknown => {
1309
1334
  (!role.data.activity || queryIds.has(role.data.activity))
1310
1335
  ? role.data
1311
1336
  : undefined;
1337
+ const statusRole = CapabilityAppStatusManifestSchema.safeParse(sentAppStatus);
1338
+ const appStatus =
1339
+ statusRole.success &&
1340
+ queryIds.has(statusRole.data.summary) &&
1341
+ queryIds.has(statusRole.data.detail) &&
1342
+ readableActions.some((action) => action.localId === statusRole.data.forget)
1343
+ ? statusRole.data
1344
+ : undefined;
1312
1345
  const provider = CapabilityFileProviderManifestSchema.safeParse(sentProvider);
1313
1346
  const calendar = CapabilityCalendarSourceManifestSchema.safeParse(sentCalendarSource);
1314
1347
  const pageCounts = new Map<string, number>();
@@ -1328,6 +1361,7 @@ const readableManifest = (value: unknown, personCatalog = false): unknown => {
1328
1361
  ...rest,
1329
1362
  ...(sentModels !== undefined ? { resourceTypes } : {}),
1330
1363
  ...(discussions ? { discussions } : {}),
1364
+ ...(appStatus ? { appStatus } : {}),
1331
1365
  ...(sentPages !== undefined ? { resourcePages } : {}),
1332
1366
  ...(provider.success ? { fileProvider: provider.data } : {}),
1333
1367
  ...(calendar.success ? { calendarSource: calendar.data } : {}),
@@ -1371,6 +1405,7 @@ export const CapabilityManifestSchema = z.preprocess(
1371
1405
  fileProvider: CapabilityFileProviderManifestSchema.optional(),
1372
1406
  calendarSource: CapabilityCalendarSourceManifestSchema.optional(),
1373
1407
  discussions: CapabilityDiscussionsManifestSchema.optional(),
1408
+ appStatus: CapabilityAppStatusManifestSchema.optional(),
1374
1409
  resourceTypes: z.array(CapabilityResourceTypeModelSchema).max(MAX_MANIFEST_ENTRIES).optional(),
1375
1410
  policies: z.record(CapabilityLocalIdSchema, CapabilityActionPolicySchema).optional(),
1376
1411
  events: z.array(CapabilityEventManifestSchema).max(MAX_MANIFEST_ENTRIES).optional(),
@@ -3,6 +3,7 @@ export * from "./announcements";
3
3
  export * from "./app";
4
4
  export * from "./app-approval";
5
5
  export * from "./app-details";
6
+ export * from "./app-status";
6
7
  export * from "./avatar";
7
8
  export * from "./calendar-source";
8
9
  export * from "./calendar-view";
@@ -2,7 +2,7 @@ import type { PageParams, Paginated, ServiceError } from "@k2b/stdlib";
2
2
  import { z } from "zod";
3
3
  import { type RequestActor, ServiceAccountSchema, UserSchema } from "./shared";
4
4
 
5
- export const PlatformPermissionSchema = z.enum(["mail:send", "mail:read", "resources:readers"]);
5
+ export const PlatformPermissionSchema = z.enum(["mail:send", "mail:read", "resources:readers", "geo:query"]);
6
6
  export type PlatformPermission = z.infer<typeof PlatformPermissionSchema>;
7
7
  export const MailRetentionSchema = z.object({ contentDays: z.int().min(1).max(36500), recordDays: z.int().min(1).max(36500) }).strict();
8
8
  export type MailRetention = z.infer<typeof MailRetentionSchema> & {
@@ -83,6 +83,8 @@ export type AppRuntimeMetadata = {
83
83
  };
84
84
 
85
85
  export type AppRegistryEntry = {
86
+ /** Opt-in public site, served only through the app public router. */
87
+ public?: true;
86
88
  access?: AppAccessRule;
87
89
  platformPermissions?: readonly PlatformPermission[];
88
90
  id: string;
@@ -1,8 +1,8 @@
1
1
  import type { Topic, TopicConfig } from "@k2b/sync";
2
- import { sql } from "bun";
3
2
  import { assertAppEventSize } from "../_internal/app-event-schemas";
4
3
  import { lazySync } from "../_internal/process-sync";
5
4
  import { type AppEventEnvelope, AppEventEnvelopeSchema } from "../contracts/app-events";
5
+ import { sql } from "../runtime/clients";
6
6
  import { logger } from "../services/logging";
7
7
  import { createPgOutbox } from "../services/outbox";
8
8
 
@@ -1,7 +1,8 @@
1
1
  import type { Topic, TopicConfig } from "@k2b/sync";
2
- import { type SQL, sql } from "bun";
2
+ import type { SQL } from "bun";
3
3
  import type { z } from "zod";
4
4
  import { lazySync } from "../_internal/process-sync";
5
+ import { sql } from "../runtime/clients";
5
6
  import { logger } from "../services/logging";
6
7
  import { createPgOutbox } from "../services/outbox";
7
8
  import type { LiveEnvelope } from "./live-engine";
package/src/index.ts CHANGED
@@ -64,6 +64,7 @@ export { createRedis, createSql, redis, type SqlPoolOptions, sql } from "./runti
64
64
  export {
65
65
  type ConnectionSource,
66
66
  connections,
67
+ type PlatformBootstrapMetadata,
67
68
  type PlatformConnectionSources,
68
69
  type PlatformConnections,
69
70
  type PlatformConnectionValues,