@spacefast/common 0.0.23 → 0.0.26

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 (224) hide show
  1. package/brand-assets/LICENSE-Haskoy.txt +93 -0
  2. package/brand-assets/haskoy-latin-variable.woff2 +0 -0
  3. package/brand-assets/spacefast-favicon.svg +4 -4
  4. package/brand-assets/spacefast-sf-full-bleed.svg +3 -3
  5. package/brand-assets/spacefast-wordmark.svg +2 -4
  6. package/dist/agents/connect-targets.js +1 -1
  7. package/dist/agents/private-key-oauth.d.ts +0 -1
  8. package/dist/agents/private-key-oauth.js +46 -63
  9. package/dist/brand-assets-build.js +4 -6
  10. package/dist/brand-assets.d.ts +5 -15
  11. package/dist/brand-assets.js +15 -14
  12. package/dist/config/domains.d.ts +47 -7
  13. package/dist/config/domains.js +66 -10
  14. package/dist/config/index.d.ts +0 -1
  15. package/dist/config/index.js +0 -1
  16. package/dist/contracts/abuse.d.ts +2 -0
  17. package/dist/contracts/abuse.js +12 -0
  18. package/dist/contracts/access.d.ts +124 -12
  19. package/dist/contracts/access.js +73 -9
  20. package/dist/contracts/activity.d.ts +1 -1
  21. package/dist/contracts/activity.js +5 -12
  22. package/dist/contracts/api-keys.d.ts +21 -21
  23. package/dist/contracts/api-keys.js +2 -2
  24. package/dist/contracts/beta.js +1 -1
  25. package/dist/contracts/billing.d.ts +3 -35
  26. package/dist/contracts/billing.js +33 -52
  27. package/dist/contracts/builds.d.ts +30 -18
  28. package/dist/contracts/builds.js +28 -9
  29. package/dist/contracts/channels.js +1 -1
  30. package/dist/contracts/cli.d.ts +10 -0
  31. package/dist/contracts/cli.js +10 -0
  32. package/dist/contracts/collab-public.d.ts +63 -0
  33. package/dist/contracts/collab-public.js +46 -0
  34. package/dist/contracts/comments.d.ts +282 -53
  35. package/dist/contracts/comments.js +173 -52
  36. package/dist/contracts/common.d.ts +3 -3
  37. package/dist/contracts/common.js +5 -5
  38. package/dist/contracts/crons.d.ts +35 -0
  39. package/dist/contracts/crons.js +42 -0
  40. package/dist/contracts/device-auth.d.ts +6 -6
  41. package/dist/contracts/device-auth.js +2 -2
  42. package/dist/contracts/docs.js +2 -2
  43. package/dist/contracts/domains.d.ts +38 -27
  44. package/dist/contracts/domains.js +29 -2
  45. package/dist/contracts/enums.d.ts +34 -30
  46. package/dist/contracts/enums.js +62 -48
  47. package/dist/contracts/error-code-meta.d.ts +50 -125
  48. package/dist/contracts/error-code-meta.js +29 -41
  49. package/dist/contracts/error-codes.d.ts +1 -1
  50. package/dist/contracts/error-codes.js +14 -33
  51. package/dist/contracts/execution.d.ts +47 -66
  52. package/dist/contracts/execution.js +53 -49
  53. package/dist/contracts/feature-lifecycle-core.d.ts +0 -6
  54. package/dist/contracts/feature-lifecycle-core.js +2 -31
  55. package/dist/contracts/feature-lifecycle.d.ts +12 -52
  56. package/dist/contracts/feature-lifecycle.js +16 -59
  57. package/dist/contracts/features.d.ts +48 -60
  58. package/dist/contracts/features.js +59 -51
  59. package/dist/contracts/functions.d.ts +266 -72
  60. package/dist/contracts/functions.js +260 -37
  61. package/dist/contracts/git.d.ts +28 -34
  62. package/dist/contracts/git.js +10 -11
  63. package/dist/contracts/grants.d.ts +9 -5
  64. package/dist/contracts/grants.js +18 -9
  65. package/dist/contracts/ids.js +2 -2
  66. package/dist/contracts/internal.d.ts +8 -6
  67. package/dist/contracts/internal.js +12 -12
  68. package/dist/contracts/mcp.d.ts +11 -0
  69. package/dist/contracts/mcp.js +5 -0
  70. package/dist/contracts/me.js +1 -1
  71. package/dist/contracts/oauth-resources.d.ts +4 -3
  72. package/dist/contracts/oauth-resources.js +12 -3
  73. package/dist/contracts/operations.d.ts +90 -5
  74. package/dist/contracts/operations.js +77 -3
  75. package/dist/contracts/pages.d.ts +12 -7
  76. package/dist/contracts/pages.js +24 -1
  77. package/dist/contracts/plan-policy.d.ts +0 -2
  78. package/dist/contracts/plan-policy.js +2 -3
  79. package/dist/contracts/platform.d.ts +61 -148
  80. package/dist/contracts/platform.js +70 -126
  81. package/dist/contracts/publish-archive.d.ts +508 -0
  82. package/dist/contracts/publish-archive.js +32 -0
  83. package/dist/contracts/push-new.d.ts +4 -4
  84. package/dist/contracts/quotas.js +2 -2
  85. package/dist/contracts/repository-connections.d.ts +43 -30
  86. package/dist/contracts/repository-connections.js +11 -3
  87. package/dist/contracts/resources.d.ts +12 -24
  88. package/dist/contracts/resources.js +36 -16
  89. package/dist/contracts/runtime-api.d.ts +433 -192
  90. package/dist/contracts/runtime-api.js +421 -356
  91. package/dist/contracts/runtime-app.d.ts +127 -120
  92. package/dist/contracts/runtime-app.js +19 -10
  93. package/dist/contracts/runtime-db.d.ts +5 -5
  94. package/dist/contracts/runtime-db.js +2 -2
  95. package/dist/contracts/runtime-purge.d.ts +8 -0
  96. package/dist/contracts/runtime-purge.js +7 -0
  97. package/dist/contracts/runtime-services.d.ts +219 -0
  98. package/dist/contracts/runtime-services.js +437 -0
  99. package/dist/contracts/runtime-storage.d.ts +46 -32
  100. package/dist/contracts/runtime-storage.js +31 -8
  101. package/dist/contracts/sf-config-v1.d.ts +48 -10
  102. package/dist/contracts/space-config.d.ts +69 -18
  103. package/dist/contracts/space-config.js +226 -27
  104. package/dist/contracts/spaces.d.ts +236 -450
  105. package/dist/contracts/spaces.js +131 -151
  106. package/dist/contracts/superadmin-activity.d.ts +57 -4
  107. package/dist/contracts/superadmin-activity.js +48 -2
  108. package/dist/contracts/superadmin-search.d.ts +126 -0
  109. package/dist/contracts/superadmin-search.js +61 -0
  110. package/dist/contracts/superadmin-spaces.d.ts +361 -92
  111. package/dist/contracts/superadmin-spaces.js +97 -24
  112. package/dist/contracts/superadmin-teams.d.ts +28 -10
  113. package/dist/contracts/superadmin-teams.js +5 -8
  114. package/dist/contracts/superadmin-tenants.d.ts +0 -6
  115. package/dist/contracts/superadmin-tenants.js +1 -7
  116. package/dist/contracts/superadmin.d.ts +135 -54
  117. package/dist/contracts/superadmin.js +46 -23
  118. package/dist/contracts/tags.d.ts +12 -12
  119. package/dist/contracts/tags.js +3 -3
  120. package/dist/contracts/teams.d.ts +49 -14
  121. package/dist/contracts/teams.js +40 -22
  122. package/dist/contracts/transfers.d.ts +0 -49
  123. package/dist/contracts/transfers.js +4 -8
  124. package/dist/contracts/usage.d.ts +61 -0
  125. package/dist/contracts/usage.js +64 -0
  126. package/dist/contracts/variables.d.ts +2 -7
  127. package/dist/contracts/variables.js +9 -8
  128. package/dist/contracts/webhooks.d.ts +2 -2
  129. package/dist/contracts/zero.d.ts +102 -73
  130. package/dist/contracts/zero.js +94 -32
  131. package/dist/dashboard-paths/index.d.ts +1 -1
  132. package/dist/dashboard-paths/index.js +1 -0
  133. package/dist/docs/agent-prose.d.ts +2 -2
  134. package/dist/docs/agent-prose.js +63 -70
  135. package/dist/docs/agent-setup.js +45 -15
  136. package/dist/docs/catalog.d.ts +24 -24
  137. package/dist/docs/catalog.js +35 -24
  138. package/dist/docs/error-docs.js +194 -270
  139. package/dist/docs/skills.d.ts +12 -12
  140. package/dist/docs/skills.js +4 -4
  141. package/dist/test-helpers/fetch-stub.d.ts +16 -0
  142. package/dist/test-helpers/fetch-stub.js +25 -0
  143. package/dist/utils/build-settings.d.ts +5 -1
  144. package/dist/utils/build-settings.js +91 -13
  145. package/dist/utils/canonical-json.d.ts +10 -0
  146. package/dist/utils/canonical-json.js +22 -0
  147. package/dist/utils/cast-transport.d.ts +28 -0
  148. package/dist/utils/cast-transport.js +52 -0
  149. package/dist/utils/claim-token.d.ts +0 -8
  150. package/dist/utils/claim-token.js +3 -15
  151. package/dist/utils/concurrency.js +1 -0
  152. package/dist/utils/credential-policy.d.ts +1 -1
  153. package/dist/utils/credential-policy.js +4 -3
  154. package/dist/utils/dns-instructions.js +9 -9
  155. package/dist/utils/env-file.d.ts +17 -0
  156. package/dist/utils/env-file.js +96 -0
  157. package/dist/utils/error-code.d.ts +2 -0
  158. package/dist/utils/error-code.js +8 -0
  159. package/dist/utils/generate-space-name.d.ts +8 -10
  160. package/dist/utils/generate-space-name.js +206 -21
  161. package/dist/utils/grant-decision.fixtures.json +2938 -0
  162. package/dist/utils/grants.d.ts +2 -0
  163. package/dist/utils/grants.js +26 -1
  164. package/dist/utils/gravatar.d.ts +9 -0
  165. package/dist/utils/gravatar.js +31 -0
  166. package/dist/utils/idempotency.d.ts +6 -0
  167. package/dist/utils/idempotency.js +28 -0
  168. package/dist/utils/local-space-state.d.ts +9 -16
  169. package/dist/utils/local-space-state.js +20 -50
  170. package/dist/utils/one-shot-replay.d.ts +4 -1
  171. package/dist/utils/page-colors.d.ts +14 -12
  172. package/dist/utils/page-colors.js +15 -13
  173. package/dist/utils/page-fonts.d.ts +2 -2
  174. package/dist/utils/page-fonts.js +15 -4
  175. package/dist/utils/pages.d.ts +21 -3
  176. package/dist/utils/pages.js +42 -13
  177. package/dist/utils/publish-form-data.d.ts +12 -0
  178. package/dist/utils/publish-form-data.js +10 -0
  179. package/dist/utils/publish-policy.d.ts +27 -0
  180. package/dist/utils/publish-policy.fixtures.json +403 -0
  181. package/dist/utils/publish-policy.js +45 -20
  182. package/dist/utils/push-new.d.ts +7 -0
  183. package/dist/utils/push-new.js +7 -0
  184. package/dist/utils/query-keys.d.ts +4 -5
  185. package/dist/utils/query-keys.js +2 -3
  186. package/dist/utils/runtime-paths.d.ts +5 -0
  187. package/dist/utils/runtime-paths.js +5 -0
  188. package/dist/utils/runtime-upload-batch.d.ts +0 -5
  189. package/dist/utils/runtime-upload-batch.js +1 -27
  190. package/dist/utils/runtime-upload.d.ts +6 -11
  191. package/dist/utils/runtime-upload.js +10 -13
  192. package/dist/utils/secure-local-file.js +5 -16
  193. package/dist/utils/space-config.d.ts +1 -34
  194. package/dist/utils/space-config.js +8 -326
  195. package/dist/utils/static-runtime-policy.d.ts +9 -3
  196. package/dist/utils/static-runtime-policy.fixtures.json +38 -41
  197. package/dist/utils/static-runtime-policy.js +22 -56
  198. package/dist/utils/storage-policy.d.ts +1 -1
  199. package/dist/utils/storage-policy.js +3 -1
  200. package/dist/utils/structured-error.d.ts +14 -0
  201. package/dist/utils/structured-error.js +22 -0
  202. package/dist/utils/upload-session.d.ts +4 -1
  203. package/dist/utils/upload-session.js +33 -5
  204. package/dist/utils/version-path.js +13 -4
  205. package/dist/vocabulary.d.ts +13 -11
  206. package/dist/vocabulary.js +42 -28
  207. package/package.json +7 -17
  208. package/dist/config/postgres-budget.d.ts +0 -129
  209. package/dist/config/postgres-budget.js +0 -140
  210. package/dist/config/postgres-budget.json +0 -51
  211. package/dist/contracts/archives.d.ts +0 -331
  212. package/dist/contracts/archives.js +0 -120
  213. package/dist/contracts/deployments.d.ts +0 -574
  214. package/dist/contracts/deployments.js +0 -97
  215. package/dist/contracts/sites.d.ts +0 -416
  216. package/dist/contracts/sites.js +0 -168
  217. package/dist/contracts/superadmin-queues.d.ts +0 -414
  218. package/dist/contracts/superadmin-queues.js +0 -202
  219. package/dist/contracts/superadmin-runtime.d.ts +0 -27
  220. package/dist/contracts/superadmin-runtime.js +0 -38
  221. package/dist/index.d.ts +0 -1
  222. package/dist/index.js +0 -1
  223. package/dist/utils/api.d.ts +0 -4
  224. package/dist/utils/api.js +0 -13
@@ -0,0 +1,93 @@
1
+ Copyright 2021 The Haskoy Project Authors (https://github.com/ertekinno/haskoy)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -1,14 +1,14 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" role="img" aria-label="Spacefast">
2
2
  <style>
3
- .sf-favicon-primary { fill: #141419; }
4
- @media (prefers-color-scheme: dark) { .sf-favicon-primary { fill: #fbf8f1; } }
3
+ .sf-favicon-primary { fill: #0c0c0c; }
4
+ @media (prefers-color-scheme: dark) { .sf-favicon-primary { fill: #fcfcfa; } }
5
5
  </style>
6
6
  <g transform="rotate(-1 80 80)">
7
- <g transform="translate(22.5 48) scale(2.15)" fill="#ff4217">
7
+ <g transform="translate(22.5 48) scale(2.15)" fill="#d8f24b">
8
8
  <path d="M0 0h24v7H7v7h17v20H0v-7h17v-7H0V0Z"/>
9
9
  <path d="M0 0h25v7H7v6h15v7H7v14H0V0Z" transform="translate(31 0)"/>
10
10
  </g>
11
- <g class="sf-favicon-primary" transform="translate(17.5 43) scale(2.15)" fill="#141419">
11
+ <g class="sf-favicon-primary" transform="translate(17.5 43) scale(2.15)" fill="#0c0c0c">
12
12
  <path d="M0 0h24v7H7v7h17v20H0v-7h17v-7H0V0Z"/>
13
13
  <path d="M0 0h25v7H7v6h15v7H7v14H0V0Z" transform="translate(31 0)"/>
14
14
  </g>
@@ -1,11 +1,11 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" role="img" aria-label="Spacefast">
2
- <rect width="160" height="160" fill="#141419"/>
2
+ <rect width="160" height="160" fill="#0c0c0c"/>
3
3
  <g transform="rotate(-1 80 80)">
4
- <g transform="translate(39.75 55.5) scale(1.5)" fill="#ff4217">
4
+ <g transform="translate(39.75 55.5) scale(1.5)" fill="#d8f24b">
5
5
  <path d="M0 0h24v7H7v7h17v20H0v-7h17v-7H0V0Z"/>
6
6
  <path d="M0 0h25v7H7v6h15v7H7v14H0V0Z" transform="translate(31 0)"/>
7
7
  </g>
8
- <g transform="translate(34.75 50.5) scale(1.5)" fill="#fbf8f1">
8
+ <g transform="translate(34.75 50.5) scale(1.5)" fill="#fcfcfa">
9
9
  <path d="M0 0h24v7H7v7h17v20H0v-7h17v-7H0V0Z"/>
10
10
  <path d="M0 0h25v7H7v6h15v7H7v14H0V0Z" transform="translate(31 0)"/>
11
11
  </g>
@@ -1,5 +1,3 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 326 62" role="img" aria-label="Spacefast">
2
- <rect x="14" y="12" width="306" height="48" fill="#ff4217"/>
3
- <rect x="10" y="8" width="306" height="48" fill="#141419" stroke="#141419" stroke-width="1"/>
4
- <path fill="#fbf8f1" d="M20 15h24v7H27v7h17v20H20v-7h17v-7H20V15ZM51 15h24v18H58v16h-7V15Zm7 11h10v-4H58v4ZM83 15h24l9 34h-8l-2-8H84l-2 8h-8l9-34Zm3 19h18l-4-12H90l-4 12ZM145 22h-19v20h19v7h-26V15h26v7ZM152 15h26v7h-19v6h15v7h-15v7h19v7h-26V15ZM185 15h25v7h-18v6h15v7h-15v14h-7V15ZM215 15h24l9 34h-8l-2-8h-22l-2 8h-8l9-34Zm3 19h18l-4-12h-10l-4 12ZM250 15h24v7h-17v7h17v20h-24v-7h17v-7h-17V15ZM279 15h27v7h-10v27h-7V22h-10v-7Z"/>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 152 28.9062" role="img" aria-label="Spacefast">
2
+ <path fill="#0c0c0c" d="M9.32925 6.99344H20.5187V10.257H12.5929V13.5206H20.5187V22.8452H9.32925V19.5816H17.2551V16.318H9.32925V6.99344ZM23.7824 6.99344H34.9718V15.3856H27.046V22.8452H23.7824V6.99344ZM27.046 12.122H31.7082V10.257H27.046V12.122ZM38.7017 6.99344H49.8912L54.0872 22.8452H50.3574L49.4249 19.1154H39.1679L38.2355 22.8452H34.5056L38.7017 6.99344ZM40.1004 15.8518H48.4925L46.6276 10.257H41.9653L40.1004 15.8518ZM67.6079 10.257H58.7495V19.5816H67.6079V22.8452H55.4859V6.99344H67.6079V10.257ZM70.8715 6.99344H82.9934V10.257H74.1351V13.0544H81.1285V16.318H74.1351V19.5816H82.9934V22.8452H70.8715V6.99344ZM86.257 6.99344H97.9128V10.257H89.5206V13.0544H96.5141V16.318H89.5206V22.8452H86.257V6.99344ZM100.244 6.99344H111.433L115.629 22.8452H111.9L110.967 19.1154H100.71L99.7777 22.8452H96.0479L100.244 6.99344ZM101.643 15.8518H110.035L108.17 10.257H103.508L101.643 15.8518ZM116.562 6.99344H127.751V10.257H119.826V13.5206H127.751V22.8452H116.562V19.5816H124.488V16.318H116.562V6.99344ZM130.083 6.99344H142.671V10.257H138.008V22.8452H134.745V10.257H130.083V6.99344Z"/>
5
3
  </svg>
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * One source of truth for "add Spacefast to your agent": the MCP launch config,
5
5
  * the one-click deeplinks, and the per-agent connect entries. Both the marketing
6
- * site (apps/www/src/lib/llmo.ts + agent-targets.ts, with the hardcoded prod
6
+ * standalone website (with the hardcoded prod
7
7
  * endpoint) and the Team Developer dashboard (with the runtime-derived
8
8
  * hosted endpoint) consume these, so every "connect an agent" surface advertises
9
9
  * the identical command, package, and config — they can never drift apart.
@@ -25,7 +25,6 @@ export declare function resolveAgentApiAuthorization(config: AgentAuthConfig, ap
25
25
  resources: string[];
26
26
  scope: string | undefined;
27
27
  };
28
- export declare function createPrivateKeyJwtAssertion(config: AgentAuthConfig, createInvalidConfigError?: (message: string) => Error): Promise<string>;
29
28
  export declare function exchangeAgentAccessToken(input: {
30
29
  apiUrl: string;
31
30
  client: string;
@@ -1,6 +1,6 @@
1
- import { randomUUID, webcrypto } from "node:crypto";
1
+ import { webcrypto } from "node:crypto";
2
+ import * as oauth from "oauth4webapi";
2
3
  import { OAUTH_API_RESOURCE_SCOPES, oauthApiResourceUrl } from "../contracts/oauth-resources.js";
3
- const PRIVATE_KEY_JWT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
4
4
  const API_RESOURCE_SCOPES = new Set(OAUTH_API_RESOURCE_SCOPES);
5
5
  const INVALID_PRIVATE_KEY_MESSAGE = "SPACEFAST_AGENT_CONFIG private_jwk must be an ES256 P-256 JWK.";
6
6
  function isRecord(value) {
@@ -75,84 +75,67 @@ export function resolveAgentApiAuthorization(config, apiUrl) {
75
75
  scope: apiScopes.length > 0 ? apiScopes.join(" ") : undefined,
76
76
  };
77
77
  }
78
- function base64urlJson(value) {
79
- return Buffer.from(JSON.stringify(value)).toString("base64url");
80
- }
81
- export async function createPrivateKeyJwtAssertion(config, createInvalidConfigError = (message) => new Error(message)) {
78
+ async function privateKeyJwtClientAuth(config, createInvalidConfigError = (message) => new Error(message)) {
82
79
  if (config.private_jwk.kty !== "EC") {
83
80
  throw createInvalidConfigError(INVALID_PRIVATE_KEY_MESSAGE);
84
81
  }
85
- const now = Math.floor(Date.now() / 1000);
86
- const key = await webcrypto.subtle.importKey("jwk", config.private_jwk, { name: "ECDSA", namedCurve: "P-256" }, false, ["sign"]);
87
- const header = base64urlJson({
88
- alg: "ES256",
89
- typ: "JWT",
90
- ...(config.private_jwk.kid ? { kid: config.private_jwk.kid } : {}),
91
- });
92
- const payload = base64urlJson({
93
- iss: config.client_id,
94
- sub: config.client_id,
95
- aud: config.token_endpoint,
96
- jti: randomUUID(),
97
- iat: now,
98
- exp: now + 300,
99
- });
100
- const signingInput = `${header}.${payload}`;
101
- const signature = await webcrypto.subtle.sign({ name: "ECDSA", hash: "SHA-256" }, key, new TextEncoder().encode(signingInput));
102
- return `${signingInput}.${Buffer.from(signature).toString("base64url")}`;
103
- }
104
- function oauthErrorDescription(payload) {
105
- return isRecord(payload) && "error_description" in payload
106
- ? String(payload.error_description)
107
- : undefined;
108
- }
109
- function oauthAccessToken(payload) {
110
- return isRecord(payload) && typeof payload.access_token === "string"
111
- ? payload.access_token
112
- : undefined;
113
- }
114
- function oauthExpiresIn(payload) {
115
- return isRecord(payload) && typeof payload.expires_in === "number" ? payload.expires_in : 300;
82
+ try {
83
+ const key = await webcrypto.subtle.importKey("jwk", config.private_jwk, { name: "ECDSA", namedCurve: "P-256" }, false, ["sign"]);
84
+ return oauth.PrivateKeyJwt({
85
+ key,
86
+ ...(config.private_jwk.kid ? { kid: config.private_jwk.kid } : {}),
87
+ });
88
+ }
89
+ catch {
90
+ throw createInvalidConfigError(INVALID_PRIVATE_KEY_MESSAGE);
91
+ }
116
92
  }
117
93
  export async function exchangeAgentAccessToken(input) {
118
94
  const { resources, scope } = resolveAgentApiAuthorization(input.config, input.apiUrl);
119
- const body = new URLSearchParams({
120
- grant_type: "client_credentials",
121
- client_id: input.config.client_id,
122
- client_assertion_type: PRIVATE_KEY_JWT_ASSERTION_TYPE,
123
- client_assertion: await createPrivateKeyJwtAssertion(input.config, input.createInvalidConfigError),
124
- });
95
+ const authorizationServer = {
96
+ // Agent credentials store the exact token endpoint rather than separate
97
+ // issuer metadata. RFC 7523 permits the endpoint as the assertion audience.
98
+ issuer: input.config.token_endpoint,
99
+ token_endpoint: input.config.token_endpoint,
100
+ };
101
+ const client = { client_id: input.config.client_id };
102
+ const body = new URLSearchParams();
125
103
  if (scope) {
126
104
  body.set("scope", scope);
127
105
  }
128
106
  for (const resource of resources) {
129
107
  body.append("resource", resource);
130
108
  }
131
- const response = await (input.fetch ?? globalThis.fetch)(input.config.token_endpoint, {
132
- method: "POST",
133
- headers: {
134
- accept: "application/json",
135
- "content-type": "application/x-www-form-urlencoded",
136
- "x-spacefast-client": input.client,
137
- },
138
- body,
109
+ const fetchFn = input.fetch ?? globalThis.fetch;
110
+ const response = await oauth.clientCredentialsGrantRequest(authorizationServer, client, await privateKeyJwtClientAuth(input.config, input.createInvalidConfigError), body, {
111
+ headers: { "x-spacefast-client": input.client },
139
112
  signal: input.signal,
113
+ [oauth.customFetch]: (url, init) => {
114
+ const requestInit = {
115
+ method: init.method,
116
+ headers: init.headers,
117
+ body: init.body,
118
+ redirect: init.redirect,
119
+ };
120
+ if (init.signal)
121
+ requestInit.signal = init.signal;
122
+ return fetchFn(url, requestInit);
123
+ },
140
124
  });
141
- const payload = await response.json().catch(() => null);
142
- if (!response.ok) {
143
- throw input.createError({
144
- status: response.status,
145
- code: "agent_token_exchange_failed",
146
- message: oauthErrorDescription(payload) ?? response.statusText,
147
- });
125
+ let tokens;
126
+ try {
127
+ tokens = await oauth.processClientCredentialsResponse(authorizationServer, client, response);
148
128
  }
149
- const accessToken = oauthAccessToken(payload);
150
- if (accessToken === undefined) {
129
+ catch (error) {
130
+ const description = error instanceof oauth.ResponseBodyError ? error.error_description : undefined;
151
131
  throw input.createError({
152
- status: response.status,
132
+ status: error instanceof oauth.ResponseBodyError ? error.status : response.status,
153
133
  code: "agent_token_exchange_failed",
154
- message: "OAuth token endpoint did not return an access_token.",
134
+ message: description ??
135
+ (response.ok
136
+ ? "OAuth token endpoint did not return a valid access-token response."
137
+ : response.statusText),
155
138
  });
156
139
  }
157
- return { accessToken, expiresIn: oauthExpiresIn(payload) };
140
+ return { accessToken: tokens.access_token, expiresIn: tokens.expires_in ?? 300 };
158
141
  }
@@ -5,7 +5,7 @@
5
5
  * and render ordinary SVG markup from its constants. Only asset generators,
6
6
  * plugin packaging, and other build steps may import this module.
7
7
  */
8
- import { SPACEFAST_BRAND_COLORS, SPACEFAST_ICON_F_OFFSET_X, SPACEFAST_ICON_F_PATH, SPACEFAST_ICON_LETTER_ORIGIN, SPACEFAST_ICON_LETTER_SCALE, SPACEFAST_ICON_S_PATH, SPACEFAST_ICON_SHADOW_OFFSET, SPACEFAST_ICON_VIEW_BOX, SPACEFAST_WORDMARK_PATH, SPACEFAST_WORDMARK_PLATE, SPACEFAST_WORDMARK_SHADOW_OFFSET, SPACEFAST_WORDMARK_VIEW_BOX, } from "./brand-assets.js";
8
+ import { SPACEFAST_BRAND_COLORS, SPACEFAST_ICON_F_OFFSET_X, SPACEFAST_ICON_F_PATH, SPACEFAST_ICON_LETTER_ORIGIN, SPACEFAST_ICON_LETTER_SCALE, SPACEFAST_ICON_S_PATH, SPACEFAST_ICON_SHADOW_OFFSET, SPACEFAST_ICON_VIEW_BOX, SPACEFAST_WORDMARK_PATH, SPACEFAST_WORDMARK_VIEW_BOX, } from "./brand-assets.js";
9
9
  function resolvedColors(colors) {
10
10
  return { ...SPACEFAST_BRAND_COLORS, ...colors };
11
11
  }
@@ -26,13 +26,11 @@ function numericAttribute(name, value) {
26
26
  }
27
27
  export function spacefastWordmarkSvg(options = {}) {
28
28
  const colors = resolvedColors(options.colors);
29
- const plate = SPACEFAST_WORDMARK_PLATE;
30
- const shadow = SPACEFAST_WORDMARK_SHADOW_OFFSET;
31
29
  const label = svgAttribute(options.ariaLabel ?? "Spacefast");
30
+ // The logotype is single-color: `plate` (ink) is its fill. The plate/shadow
31
+ // layer idiom retired with the riso system — the wordmark is bare letterforms.
32
32
  return `<svg xmlns="http://www.w3.org/2000/svg"${numericAttribute("width", options.width)}${numericAttribute("height", options.height)} viewBox="${SPACEFAST_WORDMARK_VIEW_BOX}" role="img" aria-label="${label}">
33
- <rect x="${plate.x + shadow.x}" y="${plate.y + shadow.y}" width="${plate.width}" height="${plate.height}" fill="${svgAttribute(colors.shadow)}"/>
34
- <rect x="${plate.x}" y="${plate.y}" width="${plate.width}" height="${plate.height}" fill="${svgAttribute(colors.plate)}" stroke="${svgAttribute(colors.plate)}" stroke-width="1"/>
35
- <path fill="${svgAttribute(colors.paper)}" d="${SPACEFAST_WORDMARK_PATH}"/>
33
+ <path fill="${svgAttribute(colors.plate)}" d="${SPACEFAST_WORDMARK_PATH}"/>
36
34
  </svg>
37
35
  `;
38
36
  }
@@ -6,27 +6,17 @@
6
6
  * build outputs of these constants, never independent sources of truth.
7
7
  */
8
8
  export declare const SPACEFAST_BRAND_COLORS: {
9
- readonly shadow: "#ff4217";
10
- readonly plate: "#141419";
11
- readonly paper: "#fbf8f1";
9
+ readonly shadow: "#d8f24b";
10
+ readonly plate: "#0c0c0c";
11
+ readonly paper: "#fcfcfa";
12
12
  };
13
13
  export type SpacefastBrandColors = {
14
14
  shadow: string;
15
15
  plate: string;
16
16
  paper: string;
17
17
  };
18
- export declare const SPACEFAST_WORDMARK_VIEW_BOX = "0 0 326 62";
19
- export declare const SPACEFAST_WORDMARK_PLATE: {
20
- readonly x: 10;
21
- readonly y: 8;
22
- readonly width: 306;
23
- readonly height: 48;
24
- };
25
- export declare const SPACEFAST_WORDMARK_SHADOW_OFFSET: {
26
- readonly x: 4;
27
- readonly y: 4;
28
- };
29
- export declare const SPACEFAST_WORDMARK_PATH = "M20 15h24v7H27v7h17v20H20v-7h17v-7H20V15ZM51 15h24v18H58v16h-7V15Zm7 11h10v-4H58v4ZM83 15h24l9 34h-8l-2-8H84l-2 8h-8l9-34Zm3 19h18l-4-12H90l-4 12ZM145 22h-19v20h19v7h-26V15h26v7ZM152 15h26v7h-19v6h15v7h-15v7h19v7h-26V15ZM185 15h25v7h-18v6h15v7h-15v14h-7V15ZM215 15h24l9 34h-8l-2-8h-22l-2 8h-8l9-34Zm3 19h18l-4-12h-10l-4 12ZM250 15h24v7h-17v7h17v20h-24v-7h17v-7h-17V15ZM279 15h27v7h-10v27h-7V22h-10v-7Z";
18
+ export declare const SPACEFAST_WORDMARK_VIEW_BOX = "0 0 152 28.9062";
19
+ export declare const SPACEFAST_WORDMARK_PATH = "M9.32925 6.99344H20.5187V10.257H12.5929V13.5206H20.5187V22.8452H9.32925V19.5816H17.2551V16.318H9.32925V6.99344ZM23.7824 6.99344H34.9718V15.3856H27.046V22.8452H23.7824V6.99344ZM27.046 12.122H31.7082V10.257H27.046V12.122ZM38.7017 6.99344H49.8912L54.0872 22.8452H50.3574L49.4249 19.1154H39.1679L38.2355 22.8452H34.5056L38.7017 6.99344ZM40.1004 15.8518H48.4925L46.6276 10.257H41.9653L40.1004 15.8518ZM67.6079 10.257H58.7495V19.5816H67.6079V22.8452H55.4859V6.99344H67.6079V10.257ZM70.8715 6.99344H82.9934V10.257H74.1351V13.0544H81.1285V16.318H74.1351V19.5816H82.9934V22.8452H70.8715V6.99344ZM86.257 6.99344H97.9128V10.257H89.5206V13.0544H96.5141V16.318H89.5206V22.8452H86.257V6.99344ZM100.244 6.99344H111.433L115.629 22.8452H111.9L110.967 19.1154H100.71L99.7777 22.8452H96.0479L100.244 6.99344ZM101.643 15.8518H110.035L108.17 10.257H103.508L101.643 15.8518ZM116.562 6.99344H127.751V10.257H119.826V13.5206H127.751V22.8452H116.562V19.5816H124.488V16.318H116.562V6.99344ZM130.083 6.99344H142.671V10.257H138.008V22.8452H134.745V10.257H130.083V6.99344Z";
30
20
  export declare const SPACEFAST_ICON_VIEW_BOX = "0 0 160 160";
31
21
  export declare const SPACEFAST_ICON_S_PATH = "M0 0h24v7H7v7h17v20H0v-7h17v-7H0V0Z";
32
22
  export declare const SPACEFAST_ICON_F_PATH = "M0 0h25v7H7v6h15v7H7v14H0V0Z";
@@ -5,22 +5,23 @@
5
5
  * renderers, and plugin generators all consume it. Generated SVG/PNG files are
6
6
  * build outputs of these constants, never independent sources of truth.
7
7
  */
8
+ // The 2026-08 "printed matter" palette (DESIGN.md §3). `plate`/`paper` name the
9
+ // icon serializers' layers; the wordmark itself is a single-color logotype and
10
+ // takes whatever ink its surface supplies.
8
11
  export const SPACEFAST_BRAND_COLORS = {
9
- shadow: "#ff4217",
10
- plate: "#141419",
11
- paper: "#fbf8f1",
12
+ shadow: "#d8f24b",
13
+ plate: "#0c0c0c",
14
+ paper: "#fcfcfa",
12
15
  };
13
- export const SPACEFAST_WORDMARK_VIEW_BOX = "0 0 326 62";
14
- export const SPACEFAST_WORDMARK_PLATE = {
15
- x: 10,
16
- y: 8,
17
- width: 306,
18
- height: 48,
19
- };
20
- export const SPACEFAST_WORDMARK_SHADOW_OFFSET = { x: 4, y: 4 };
21
- // Re-kerned and vertically centered on the plate. This is a literal so browser
22
- // consumers render ordinary SVG markup without assembling path text at runtime.
23
- export const SPACEFAST_WORDMARK_PATH = "M20 15h24v7H27v7h17v20H20v-7h17v-7H20V15ZM51 15h24v18H58v16h-7V15Zm7 11h10v-4H58v4ZM83 15h24l9 34h-8l-2-8H84l-2 8h-8l9-34Zm3 19h18l-4-12H90l-4 12ZM145 22h-19v20h19v7h-26V15h26v7ZM152 15h26v7h-19v6h15v7h-15v7h19v7h-26V15ZM185 15h25v7h-18v6h15v7h-15v14h-7V15ZM215 15h24l9 34h-8l-2-8h-22l-2 8h-8l9-34Zm3 19h18l-4-12h-10l-4 12ZM250 15h24v7h-17v7h17v20h-24v-7h17v-7h-17V15ZM279 15h27v7h-10v27h-7V22h-10v-7Z";
16
+ // The logotype: bare "SPACEFAST" letterforms in the right-angle stencil
17
+ // alphabet no plates, no offset shadow (that idiom retired with the riso
18
+ // system). One path, one color; surfaces set the fill (ink on light grounds,
19
+ // paper on dark). Exported from the Spacefast Figma file via the standalone
20
+ // `www` repo (`public/static/brand/spacefast-wordmark.svg`).
21
+ export const SPACEFAST_WORDMARK_VIEW_BOX = "0 0 152 28.9062";
22
+ // This is a literal so browser consumers render ordinary SVG markup without
23
+ // assembling path text at runtime.
24
+ export const SPACEFAST_WORDMARK_PATH = "M9.32925 6.99344H20.5187V10.257H12.5929V13.5206H20.5187V22.8452H9.32925V19.5816H17.2551V16.318H9.32925V6.99344ZM23.7824 6.99344H34.9718V15.3856H27.046V22.8452H23.7824V6.99344ZM27.046 12.122H31.7082V10.257H27.046V12.122ZM38.7017 6.99344H49.8912L54.0872 22.8452H50.3574L49.4249 19.1154H39.1679L38.2355 22.8452H34.5056L38.7017 6.99344ZM40.1004 15.8518H48.4925L46.6276 10.257H41.9653L40.1004 15.8518ZM67.6079 10.257H58.7495V19.5816H67.6079V22.8452H55.4859V6.99344H67.6079V10.257ZM70.8715 6.99344H82.9934V10.257H74.1351V13.0544H81.1285V16.318H74.1351V19.5816H82.9934V22.8452H70.8715V6.99344ZM86.257 6.99344H97.9128V10.257H89.5206V13.0544H96.5141V16.318H89.5206V22.8452H86.257V6.99344ZM100.244 6.99344H111.433L115.629 22.8452H111.9L110.967 19.1154H100.71L99.7777 22.8452H96.0479L100.244 6.99344ZM101.643 15.8518H110.035L108.17 10.257H103.508L101.643 15.8518ZM116.562 6.99344H127.751V10.257H119.826V13.5206H127.751V22.8452H116.562V19.5816H124.488V16.318H116.562V6.99344ZM130.083 6.99344H142.671V10.257H138.008V22.8452H134.745V10.257H130.083V6.99344Z";
24
25
  export const SPACEFAST_ICON_VIEW_BOX = "0 0 160 160";
25
26
  export const SPACEFAST_ICON_S_PATH = "M0 0h24v7H7v7h17v20H0v-7h17v-7H0V0Z";
26
27
  export const SPACEFAST_ICON_F_PATH = "M0 0h25v7H7v6h15v7H7v14H0V0Z";
@@ -1,7 +1,7 @@
1
1
  /** Deployment environment a URL is being built for. */
2
2
  export type DeployEnv = "dev" | "test" | "prod";
3
3
  /** Logical services that each get their own host. */
4
- export type Service = "www" | "api" | "dashboard" | "superadmin" | "cast" | "mcp" | "fieldguide";
4
+ export type Service = "www" | "api" | "access" | "dashboard" | "superadmin" | "cast" | "mcp" | "push" | "fieldguide";
5
5
  export type EnvDomains = {
6
6
  /** Apex/base origin for the marketing site (the `www` service + bare apex). */
7
7
  readonly apex: string;
@@ -16,12 +16,35 @@ export type EnvDomains = {
16
16
  export declare const PROD_ENV_DOMAIN: "spacefast.com";
17
17
  /** The local-dev apex (portless serves every subdomain over HTTPS). */
18
18
  export declare const DEV_ENV_DOMAIN: "sf.localhost";
19
+ /** The deployed staging apex. Not local: staging is a hosted environment. */
20
+ export declare const STAGING_ENV_DOMAIN: "stattic.net";
21
+ /** The deployed dev apex — distinct from local dev, which stays on sf.localhost. */
22
+ export declare const DEV_DEPLOY_ENV_DOMAIN: "stattic.xyz";
23
+ /**
24
+ * The three environments the deploy lanes ship to, keyed by the name each one
25
+ * carries everywhere else: the branch map in scripts/deploy-environment.mjs,
26
+ * the GitHub Environment, and `SPACEFAST_ENV` on the running service.
27
+ *
28
+ * Distinct from `DeployEnv` below, which names the *local* stacks (dev/test on
29
+ * sf.localhost) beside prod.
30
+ */
31
+ export type HostedEnv = "dev" | "staging" | "prod";
32
+ export declare const HOSTED_ENV_DOMAINS: Readonly<Record<HostedEnv, string>>;
33
+ /**
34
+ * The hosted environment a `SPACEFAST_ENV` value names, or null. `production`
35
+ * is accepted for `prod`: it is what the running services already carry, and
36
+ * what their alert routing and email tags key on.
37
+ */
38
+ export declare function hostedEnvFor(environment: string | undefined): HostedEnv | null;
39
+ /** The apex a hosted environment serves from, or null when the name is not one. */
40
+ export declare function hostedEnvDomain(environment: string | undefined): string | null;
19
41
  /**
20
42
  * Construct the full per-service host map from a single env domain
21
- * (`spacefast.com`, `sf.localhost`, …). One knob — services are always
22
- * `<service>.<domain>` over https, with two deliberate exceptions:
23
- * the marketing site sits on the bare prod apex, and the internal handbook
24
- * lives on the view.fast infra apex in prod.
43
+ * (`spacefast.com`, `stattic.net`, `sf.localhost`, …). One knob — services are
44
+ * always `<service>.<domain>` over https, with three deliberate exceptions: the
45
+ * marketing site sits on the bare apex of a hosted environment (so staging
46
+ * rehearses production's shape rather than a `www.` variant of it), and both
47
+ * Git push and the internal handbook live on their own apexes in prod.
25
48
  */
26
49
  export declare function envDomainsFor(domain: string): EnvDomains;
27
50
  /** Origin (scheme + host, no trailing slash) for a service in an environment. */
@@ -37,8 +60,25 @@ export declare const DOCS_BASE_URL: string;
37
60
  export declare const PROD_VIEW_FAST_APEX: "view.fast";
38
61
  /** The local-dev infrastructure apex. Never appears in committed artifacts. */
39
62
  export declare const DEV_VIEW_FAST_APEX: "preview.space";
40
- /** Resolve the infrastructure apex, allowing an explicit deployment override. */
41
- export declare function resolveViewFastApex(environment: Readonly<Partial<Pick<NodeJS.ProcessEnv, "NODE_ENV" | "SPACEFAST_VIEW_FAST_APEX">>>): string;
63
+ /**
64
+ * Resolve the infrastructure apex, allowing an explicit deployment override.
65
+ *
66
+ * Only production has an apex here. Every other hosted environment names its
67
+ * own through `SPACEFAST_VIEW_FAST_APEX`, because a space apex is a zone that
68
+ * has to exist, be delegated, and be attached at the provider — not a name this
69
+ * registry can pick on a deployment's behalf. Two environments allocating from
70
+ * one apex race for the same hostname, and the one that loses is a customer's
71
+ * site.
72
+ *
73
+ * When nothing names the apex, this falls back to the local one rather than
74
+ * production's: a caller that cannot say which environment it is has no claim
75
+ * on production's namespace. Holding deployments to naming it belongs to the
76
+ * process that mints hostnames, not to this module — the control plane's env
77
+ * schema refuses to boot without it, while builds and browser bundles import
78
+ * this registry for its host scheme and must not explode over an environment
79
+ * they do not have.
80
+ */
81
+ export declare function resolveViewFastApex(environment: Readonly<Partial<Pick<NodeJS.ProcessEnv, "NODE_ENV" | "SPACEFAST_ENV" | "SPACEFAST_VIEW_FAST_APEX">>>): string;
42
82
  /** Infrastructure apex used for public managed/custom domains. */
43
83
  export declare const VIEW_FAST_APEX: string;
44
84
  /** Reserved first-label prefix for the management namespace; users may not register it. */
@@ -9,26 +9,57 @@
9
9
  export const PROD_ENV_DOMAIN = "spacefast.com";
10
10
  /** The local-dev apex (portless serves every subdomain over HTTPS). */
11
11
  export const DEV_ENV_DOMAIN = "sf.localhost";
12
+ /** The deployed staging apex. Not local: staging is a hosted environment. */
13
+ export const STAGING_ENV_DOMAIN = "stattic.net";
14
+ /** The deployed dev apex — distinct from local dev, which stays on sf.localhost. */
15
+ export const DEV_DEPLOY_ENV_DOMAIN = "stattic.xyz";
16
+ export const HOSTED_ENV_DOMAINS = {
17
+ dev: DEV_DEPLOY_ENV_DOMAIN,
18
+ staging: STAGING_ENV_DOMAIN,
19
+ prod: PROD_ENV_DOMAIN,
20
+ };
21
+ /**
22
+ * The hosted environment a `SPACEFAST_ENV` value names, or null. `production`
23
+ * is accepted for `prod`: it is what the running services already carry, and
24
+ * what their alert routing and email tags key on.
25
+ */
26
+ export function hostedEnvFor(environment) {
27
+ if (!environment)
28
+ return null;
29
+ const normalized = environment.trim().toLowerCase();
30
+ if (normalized === "production")
31
+ return "prod";
32
+ return Object.hasOwn(HOSTED_ENV_DOMAINS, normalized) ? normalized : null;
33
+ }
34
+ /** The apex a hosted environment serves from, or null when the name is not one. */
35
+ export function hostedEnvDomain(environment) {
36
+ const hosted = hostedEnvFor(environment);
37
+ return hosted ? HOSTED_ENV_DOMAINS[hosted] : null;
38
+ }
12
39
  /**
13
40
  * Construct the full per-service host map from a single env domain
14
- * (`spacefast.com`, `sf.localhost`, …). One knob — services are always
15
- * `<service>.<domain>` over https, with two deliberate exceptions:
16
- * the marketing site sits on the bare prod apex, and the internal handbook
17
- * lives on the view.fast infra apex in prod.
41
+ * (`spacefast.com`, `stattic.net`, `sf.localhost`, …). One knob — services are
42
+ * always `<service>.<domain>` over https, with three deliberate exceptions: the
43
+ * marketing site sits on the bare apex of a hosted environment (so staging
44
+ * rehearses production's shape rather than a `www.` variant of it), and both
45
+ * Git push and the internal handbook live on their own apexes in prod.
18
46
  */
19
47
  export function envDomainsFor(domain) {
20
48
  const prod = domain === PROD_ENV_DOMAIN;
49
+ const hosted = Object.values(HOSTED_ENV_DOMAINS).some((hostedDomain) => hostedDomain === domain);
21
50
  return {
22
51
  apex: domain,
23
52
  cookieDomain: `.${domain}`,
24
53
  protocol: "https",
25
54
  hosts: {
26
- www: prod ? domain : `www.${domain}`,
55
+ www: hosted ? domain : `www.${domain}`,
27
56
  api: `api.${domain}`,
57
+ access: `access.${domain}`,
28
58
  dashboard: `my.${domain}`,
29
59
  superadmin: `superadmin.${domain}`,
30
60
  cast: `cast.${domain}`,
31
61
  mcp: `mcp.${domain}`,
62
+ push: prod ? "push.new" : `push.${domain}`,
32
63
  fieldguide: prod ? "pitch.view.fast" : `fieldguide.${domain}`,
33
64
  },
34
65
  };
@@ -64,13 +95,38 @@ export const DOCS_BASE_URL = `${serviceOrigin("www", "prod")}/docs`;
64
95
  export const PROD_VIEW_FAST_APEX = "view.fast";
65
96
  /** The local-dev infrastructure apex. Never appears in committed artifacts. */
66
97
  export const DEV_VIEW_FAST_APEX = "preview.space";
67
- /** Resolve the infrastructure apex, allowing an explicit deployment override. */
98
+ /**
99
+ * Resolve the infrastructure apex, allowing an explicit deployment override.
100
+ *
101
+ * Only production has an apex here. Every other hosted environment names its
102
+ * own through `SPACEFAST_VIEW_FAST_APEX`, because a space apex is a zone that
103
+ * has to exist, be delegated, and be attached at the provider — not a name this
104
+ * registry can pick on a deployment's behalf. Two environments allocating from
105
+ * one apex race for the same hostname, and the one that loses is a customer's
106
+ * site.
107
+ *
108
+ * When nothing names the apex, this falls back to the local one rather than
109
+ * production's: a caller that cannot say which environment it is has no claim
110
+ * on production's namespace. Holding deployments to naming it belongs to the
111
+ * process that mints hostnames, not to this module — the control plane's env
112
+ * schema refuses to boot without it, while builds and browser bundles import
113
+ * this registry for its host scheme and must not explode over an environment
114
+ * they do not have.
115
+ */
68
116
  export function resolveViewFastApex(environment) {
117
+ const explicit = environment.SPACEFAST_VIEW_FAST_APEX?.trim().toLowerCase();
118
+ if (explicit)
119
+ return explicit;
120
+ // SPACEFAST_ENV names a hosted environment only on a deployed service, where
121
+ // NODE_ENV is production — the same split the control plane's env-domain
122
+ // derivation makes. `dev` is also the local stack's name, and a local stack
123
+ // must keep the local apex rather than allocate under hosted dev's.
69
124
  const nodeEnvironment = environment.NODE_ENV?.trim().toLowerCase();
70
- return (environment.SPACEFAST_VIEW_FAST_APEX?.trim().toLowerCase() ||
71
- (["prod", "production"].includes(nodeEnvironment ?? "")
72
- ? PROD_VIEW_FAST_APEX
73
- : DEV_VIEW_FAST_APEX));
125
+ if (!["prod", "production"].includes(nodeEnvironment ?? ""))
126
+ return DEV_VIEW_FAST_APEX;
127
+ return hostedEnvFor(environment.SPACEFAST_ENV) === "prod"
128
+ ? PROD_VIEW_FAST_APEX
129
+ : DEV_VIEW_FAST_APEX;
74
130
  }
75
131
  /** Infrastructure apex used for public managed/custom domains. */
76
132
  export const VIEW_FAST_APEX = resolveViewFastApex(typeof process === "undefined" ? {} : process.env);
@@ -1,2 +1 @@
1
1
  export * from "./domains.js";
2
- export * from "./postgres-budget.js";
@@ -1,4 +1,3 @@
1
1
  // Public entry for the centralized domain/URL registry.
2
2
  // Consumers import from "@spacefast/common/config".
3
3
  export * from "./domains.js";
4
- export * from "./postgres-budget.js";
@@ -80,6 +80,8 @@ export declare const superadminAbuseReportListQuerySchema: z.ZodObject<{
80
80
  actioned: "actioned";
81
81
  closed: "closed";
82
82
  }>>;
83
+ spaceId: z.ZodOptional<z.ZodString>;
84
+ hostname: z.ZodOptional<z.ZodString>;
83
85
  }, z.core.$strip>;
84
86
  export declare const superadminAbuseReportPatchSchema: z.ZodObject<{
85
87
  status: z.ZodEnum<{
@@ -44,6 +44,18 @@ export const superadminAbuseReportSchema = abuseReportSchema.extend({
44
44
  });
45
45
  export const superadminAbuseReportListQuerySchema = cursorListQuerySchema.extend({
46
46
  status: abuseReportStatusSchema.optional().describe("Filter the triage list by status."),
47
+ spaceId: z
48
+ .string()
49
+ .trim()
50
+ .min(1)
51
+ .optional()
52
+ .describe("Filter to reports that resolved to one Space."),
53
+ hostname: z
54
+ .string()
55
+ .trim()
56
+ .min(1)
57
+ .optional()
58
+ .describe("Filter by the normalized reported hostname; matching is case-insensitive."),
47
59
  });
48
60
  export const superadminAbuseReportPatchSchema = z.object({
49
61
  status: abuseReportStatusSchema.describe("New triage status; must be a valid transition from the current status."),