@spacefast/common 0.0.24 → 0.2.1

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 (320) 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.d.ts +6 -146
  7. package/dist/agents/connect-targets.js +63 -295
  8. package/dist/agents/private-key-oauth.d.ts +31 -2
  9. package/dist/agents/private-key-oauth.js +166 -92
  10. package/dist/agents/registry/core.d.ts +292 -0
  11. package/dist/agents/registry/core.js +1388 -0
  12. package/dist/agents/registry/deeplink-probes.d.ts +23 -0
  13. package/dist/agents/registry/deeplink-probes.js +18 -0
  14. package/dist/agents/registry/node.d.ts +56 -0
  15. package/dist/agents/registry/node.js +339 -0
  16. package/dist/brand-assets-build.js +3 -6
  17. package/dist/brand-assets.d.ts +5 -15
  18. package/dist/brand-assets.js +12 -14
  19. package/dist/brand.d.ts +17 -0
  20. package/dist/brand.js +24 -4
  21. package/dist/config/domains.d.ts +79 -12
  22. package/dist/config/domains.js +128 -29
  23. package/dist/config/index.js +1 -2
  24. package/dist/contracts/abuse.js +9 -24
  25. package/dist/contracts/access-profiles.d.ts +86 -0
  26. package/dist/contracts/access-profiles.js +89 -0
  27. package/dist/contracts/access.d.ts +24 -30
  28. package/dist/contracts/access.js +33 -64
  29. package/dist/contracts/activity.d.ts +18 -1
  30. package/dist/contracts/activity.js +72 -26
  31. package/dist/contracts/analytics.js +8 -10
  32. package/dist/contracts/api-keys.d.ts +77 -52
  33. package/dist/contracts/api-keys.js +44 -24
  34. package/dist/contracts/application-journal.d.ts +216 -0
  35. package/dist/contracts/application-journal.js +167 -0
  36. package/dist/contracts/auth.d.ts +90 -17
  37. package/dist/contracts/auth.js +86 -17
  38. package/dist/contracts/beta.d.ts +9 -4
  39. package/dist/contracts/beta.js +20 -16
  40. package/dist/contracts/billing.d.ts +2 -1
  41. package/dist/contracts/billing.js +37 -11
  42. package/dist/contracts/bootstrap.d.ts +791 -0
  43. package/dist/contracts/bootstrap.js +51 -0
  44. package/dist/contracts/builds.d.ts +209 -18
  45. package/dist/contracts/builds.js +93 -27
  46. package/dist/contracts/channels.d.ts +43 -0
  47. package/dist/contracts/channels.js +25 -9
  48. package/dist/contracts/cli.d.ts +7 -0
  49. package/dist/contracts/cli.js +6 -0
  50. package/dist/contracts/collab-public.d.ts +1 -1
  51. package/dist/contracts/collab-public.js +5 -8
  52. package/dist/contracts/comments.d.ts +44 -34
  53. package/dist/contracts/comments.js +107 -77
  54. package/dist/contracts/commerce.d.ts +165 -0
  55. package/dist/contracts/commerce.js +146 -0
  56. package/dist/contracts/common.d.ts +3 -3
  57. package/dist/contracts/common.js +20 -31
  58. package/dist/contracts/content-contract-verification.d.ts +521 -0
  59. package/dist/contracts/content-contract-verification.js +320 -0
  60. package/dist/contracts/content-platform-fixture.d.ts +1278 -0
  61. package/dist/contracts/content-platform-fixture.js +44 -0
  62. package/dist/contracts/content-program.d.ts +994 -0
  63. package/dist/contracts/content-program.js +658 -0
  64. package/dist/contracts/content-sync.d.ts +290 -0
  65. package/dist/contracts/content-sync.js +167 -0
  66. package/dist/contracts/content.d.ts +432 -0
  67. package/dist/contracts/content.js +303 -0
  68. package/dist/contracts/continuation.d.ts +17 -1
  69. package/dist/contracts/continuation.js +23 -23
  70. package/dist/contracts/countries.js +3 -4
  71. package/dist/contracts/crons.d.ts +52 -0
  72. package/dist/contracts/crons.js +60 -0
  73. package/dist/contracts/dashboard-prefs.d.ts +56 -0
  74. package/dist/contracts/dashboard-prefs.js +51 -0
  75. package/dist/contracts/device-auth.d.ts +234 -37
  76. package/dist/contracts/device-auth.js +267 -53
  77. package/dist/contracts/docs.d.ts +1 -5
  78. package/dist/contracts/docs.js +7 -15
  79. package/dist/contracts/domains.d.ts +501 -93
  80. package/dist/contracts/domains.js +193 -55
  81. package/dist/contracts/email-preferences.d.ts +3 -3
  82. package/dist/contracts/email-preferences.js +6 -7
  83. package/dist/contracts/enums.d.ts +27 -26
  84. package/dist/contracts/enums.js +68 -61
  85. package/dist/contracts/error-code-meta.d.ts +283 -7
  86. package/dist/contracts/error-code-meta.js +97 -5
  87. package/dist/contracts/error-codes.d.ts +5 -5
  88. package/dist/contracts/error-codes.js +82 -17
  89. package/dist/contracts/events.d.ts +100 -20
  90. package/dist/contracts/events.js +107 -20
  91. package/dist/contracts/execution.d.ts +48 -64
  92. package/dist/contracts/execution.js +52 -62
  93. package/dist/contracts/feature-lifecycle.d.ts +73 -27
  94. package/dist/contracts/feature-lifecycle.js +86 -26
  95. package/dist/contracts/features.d.ts +68 -19
  96. package/dist/contracts/features.js +42 -41
  97. package/dist/contracts/fixtures/content-platform-v1.json +1108 -0
  98. package/dist/contracts/frame-session.d.ts +192 -0
  99. package/dist/contracts/frame-session.js +164 -0
  100. package/dist/contracts/functions.d.ts +338 -164
  101. package/dist/contracts/functions.js +367 -198
  102. package/dist/contracts/git.d.ts +27 -33
  103. package/dist/contracts/git.js +10 -11
  104. package/dist/contracts/grant-copy.d.ts +43 -0
  105. package/dist/contracts/grant-copy.js +44 -0
  106. package/dist/contracts/grants.d.ts +62 -54
  107. package/dist/contracts/grants.js +124 -23
  108. package/dist/contracts/ids.d.ts +4 -1
  109. package/dist/contracts/ids.js +6 -3
  110. package/dist/contracts/internal.d.ts +8 -18
  111. package/dist/contracts/internal.js +13 -14
  112. package/dist/contracts/mcp.d.ts +28 -0
  113. package/dist/contracts/mcp.js +28 -0
  114. package/dist/contracts/me.d.ts +6 -1
  115. package/dist/contracts/me.js +12 -6
  116. package/dist/contracts/notifications.d.ts +27 -29
  117. package/dist/contracts/notifications.js +9 -4
  118. package/dist/contracts/oauth-resources.d.ts +112 -10
  119. package/dist/contracts/oauth-resources.js +116 -11
  120. package/dist/contracts/oauth-scope-actions.d.ts +90 -0
  121. package/dist/contracts/oauth-scope-actions.js +126 -0
  122. package/dist/contracts/operations.d.ts +27 -4
  123. package/dist/contracts/operations.js +12 -6
  124. package/dist/contracts/pages.d.ts +31 -7
  125. package/dist/contracts/pages.js +22 -5
  126. package/dist/contracts/partner-notifications.d.ts +3 -0
  127. package/dist/contracts/partner-notifications.js +65 -0
  128. package/dist/contracts/{platform.d.ts → partner.d.ts} +29 -42
  129. package/dist/contracts/{platform.js → partner.js} +27 -40
  130. package/dist/contracts/plan-policy.js +1 -1
  131. package/dist/contracts/principal-assertion.d.ts +43 -0
  132. package/dist/contracts/principal-assertion.js +67 -0
  133. package/dist/contracts/principals.d.ts +73 -0
  134. package/dist/contracts/principals.js +59 -0
  135. package/dist/contracts/privacy.d.ts +11 -0
  136. package/dist/contracts/privacy.js +17 -0
  137. package/dist/contracts/problem-document.js +3 -4
  138. package/dist/contracts/publish-archive.d.ts +269 -161
  139. package/dist/contracts/publish-archive.js +11 -1
  140. package/dist/contracts/push-new.d.ts +8 -8
  141. package/dist/contracts/quotas.js +5 -5
  142. package/dist/contracts/realtime.d.ts +52 -0
  143. package/dist/contracts/realtime.js +54 -0
  144. package/dist/contracts/repository-connections.d.ts +44 -31
  145. package/dist/contracts/repository-connections.js +17 -5
  146. package/dist/contracts/resources.d.ts +105 -14
  147. package/dist/contracts/resources.js +150 -26
  148. package/dist/contracts/route-inventory.d.ts +358 -0
  149. package/dist/contracts/route-inventory.js +141 -0
  150. package/dist/contracts/runtime-api.d.ts +206 -82
  151. package/dist/contracts/runtime-api.js +131 -70
  152. package/dist/contracts/runtime-app.d.ts +13 -23
  153. package/dist/contracts/runtime-app.js +39 -24
  154. package/dist/contracts/runtime-components.d.ts +143 -0
  155. package/dist/contracts/runtime-components.js +199 -0
  156. package/dist/contracts/runtime-db.d.ts +49 -23
  157. package/dist/contracts/runtime-db.js +87 -22
  158. package/dist/contracts/runtime-purge.d.ts +8 -0
  159. package/dist/contracts/runtime-purge.js +5 -0
  160. package/dist/contracts/runtime-services.d.ts +43 -75
  161. package/dist/contracts/runtime-services.js +29 -49
  162. package/dist/contracts/runtime-storage.d.ts +15 -14
  163. package/dist/contracts/runtime-storage.js +30 -14
  164. package/dist/contracts/sf-config-v1.d.ts +48 -14
  165. package/dist/contracts/slugs.js +13 -4
  166. package/dist/contracts/space-config.d.ts +283 -19
  167. package/dist/contracts/space-config.js +430 -80
  168. package/dist/contracts/spaces.d.ts +376 -290
  169. package/dist/contracts/spaces.js +200 -135
  170. package/dist/contracts/superadmin-activity.d.ts +3 -43
  171. package/dist/contracts/superadmin-activity.js +6 -30
  172. package/dist/contracts/superadmin-emails.d.ts +1 -0
  173. package/dist/contracts/superadmin-emails.js +17 -1
  174. package/dist/contracts/superadmin-runtime.d.ts +199 -0
  175. package/dist/contracts/superadmin-runtime.js +141 -0
  176. package/dist/contracts/superadmin-search.d.ts +22 -2
  177. package/dist/contracts/superadmin-search.js +14 -6
  178. package/dist/contracts/superadmin-spaces.d.ts +438 -189
  179. package/dist/contracts/superadmin-spaces.js +131 -25
  180. package/dist/contracts/superadmin-teams.d.ts +5 -2
  181. package/dist/contracts/superadmin-teams.js +1 -2
  182. package/dist/contracts/superadmin-tenants.d.ts +627 -12
  183. package/dist/contracts/superadmin-tenants.js +32 -13
  184. package/dist/contracts/superadmin.d.ts +232 -37
  185. package/dist/contracts/superadmin.js +106 -22
  186. package/dist/contracts/tags.d.ts +85 -58
  187. package/dist/contracts/tags.js +47 -37
  188. package/dist/contracts/teams.d.ts +86 -26
  189. package/dist/contracts/teams.js +90 -31
  190. package/dist/contracts/tenants.d.ts +135 -0
  191. package/dist/contracts/tenants.js +120 -0
  192. package/dist/contracts/test-triggers.d.ts +70 -0
  193. package/dist/contracts/test-triggers.js +116 -0
  194. package/dist/contracts/theme-json.js +3 -8
  195. package/dist/contracts/transfers.d.ts +1 -0
  196. package/dist/contracts/transfers.js +3 -2
  197. package/dist/contracts/usage.d.ts +209 -0
  198. package/dist/contracts/usage.js +124 -12
  199. package/dist/contracts/variables.d.ts +2 -2
  200. package/dist/contracts/variables.js +9 -13
  201. package/dist/contracts/webhooks.d.ts +13 -5
  202. package/dist/contracts/webhooks.js +3 -1
  203. package/dist/contracts/zero.d.ts +72 -81
  204. package/dist/contracts/zero.js +80 -78
  205. package/dist/dashboard-paths/index.d.ts +24 -21
  206. package/dist/dashboard-paths/index.js +35 -47
  207. package/dist/dashboard-paths/route-reservations.generated.d.ts +2 -0
  208. package/dist/dashboard-paths/route-reservations.generated.js +36 -0
  209. package/dist/docs/agent-arrival.d.ts +92 -0
  210. package/dist/docs/agent-arrival.js +227 -0
  211. package/dist/docs/agent-output-policy.d.ts +6 -0
  212. package/dist/docs/agent-output-policy.js +22 -0
  213. package/dist/docs/agent-prose.d.ts +12 -18
  214. package/dist/docs/agent-prose.js +73 -51
  215. package/dist/docs/agent-setup.d.ts +72 -41
  216. package/dist/docs/agent-setup.js +339 -436
  217. package/dist/docs/catalog.d.ts +153 -95
  218. package/dist/docs/catalog.js +163 -48
  219. package/dist/docs/error-docs.d.ts +2098 -1
  220. package/dist/docs/error-docs.js +421 -144
  221. package/dist/docs/index-build.d.ts +0 -1
  222. package/dist/docs/index-build.js +2 -3
  223. package/dist/docs/page-context-prompt.d.ts +77 -0
  224. package/dist/docs/page-context-prompt.js +131 -0
  225. package/dist/docs/reference-urls.d.ts +46 -0
  226. package/dist/docs/reference-urls.js +79 -0
  227. package/dist/docs/search.d.ts +6 -8
  228. package/dist/docs/search.js +10 -13
  229. package/dist/docs/skill-distribution.d.ts +4 -1
  230. package/dist/docs/skill-distribution.js +10 -5
  231. package/dist/docs/skills.d.ts +120 -120
  232. package/dist/docs/skills.js +121 -73
  233. package/dist/docs/start-prompts.d.ts +45 -0
  234. package/dist/docs/start-prompts.js +62 -0
  235. package/dist/domain-exploration.js +9 -13
  236. package/dist/og-template.d.ts +56 -0
  237. package/dist/og-template.js +56 -0
  238. package/dist/slug-policy/index.js +5 -11
  239. package/dist/test-helpers/fetch-stub.js +1 -0
  240. package/dist/utils/browser-credential.d.ts +13 -6
  241. package/dist/utils/browser-credential.js +14 -7
  242. package/dist/utils/build-settings.d.ts +21 -1
  243. package/dist/utils/build-settings.js +133 -15
  244. package/dist/utils/canonical-json.d.ts +3 -5
  245. package/dist/utils/canonical-json.js +4 -5
  246. package/dist/utils/cast-transport.d.ts +5 -17
  247. package/dist/utils/cast-transport.js +6 -19
  248. package/dist/utils/claim-token.js +1 -2
  249. package/dist/utils/comment-avatars.js +4 -6
  250. package/dist/utils/concurrency.js +3 -3
  251. package/dist/utils/content-type.d.ts +7 -6
  252. package/dist/utils/content-type.js +73 -51
  253. package/dist/utils/credential-policy.d.ts +50 -6
  254. package/dist/utils/credential-policy.js +126 -59
  255. package/dist/utils/dns-instructions.js +9 -9
  256. package/dist/utils/egress-policy.fixtures.json +1 -1
  257. package/dist/utils/error-code.js +1 -0
  258. package/dist/utils/generate-space-name.d.ts +3 -8
  259. package/dist/utils/generate-space-name.js +3 -8
  260. package/dist/utils/grant-decision.fixtures.json +2 -2
  261. package/dist/utils/grants.d.ts +0 -1
  262. package/dist/utils/grants.js +7 -8
  263. package/dist/utils/gravatar.d.ts +2 -4
  264. package/dist/utils/gravatar.js +6 -12
  265. package/dist/utils/id-hints.js +14 -23
  266. package/dist/utils/idempotency.d.ts +3 -3
  267. package/dist/utils/idempotency.js +6 -7
  268. package/dist/utils/local-space-state.d.ts +23 -26
  269. package/dist/utils/local-space-state.js +46 -46
  270. package/dist/utils/oauth-signed-query.d.ts +3 -5
  271. package/dist/utils/oauth-signed-query.js +6 -9
  272. package/dist/utils/one-shot-replay.d.ts +7 -6
  273. package/dist/utils/one-shot-replay.js +3 -5
  274. package/dist/utils/page-colors.d.ts +15 -19
  275. package/dist/utils/page-colors.js +23 -45
  276. package/dist/utils/page-fonts.d.ts +1 -1
  277. package/dist/utils/page-fonts.js +8 -20
  278. package/dist/utils/page-preview.d.ts +0 -1
  279. package/dist/utils/page-preview.js +0 -1
  280. package/dist/utils/pages.d.ts +33 -3
  281. package/dist/utils/pages.js +83 -30
  282. package/dist/utils/privacy-regions.d.ts +19 -0
  283. package/dist/utils/privacy-regions.js +91 -0
  284. package/dist/utils/publish-form-data.d.ts +4 -5
  285. package/dist/utils/publish-form-data.js +2 -3
  286. package/dist/utils/publish-policy.d.ts +11 -17
  287. package/dist/utils/publish-policy.fixtures.json +11 -5
  288. package/dist/utils/publish-policy.js +65 -110
  289. package/dist/utils/query-client.d.ts +2 -0
  290. package/dist/utils/query-client.js +10 -1
  291. package/dist/utils/runtime-paths.d.ts +4 -4
  292. package/dist/utils/runtime-paths.js +6 -8
  293. package/dist/utils/runtime-upload.d.ts +9 -0
  294. package/dist/utils/runtime-upload.js +12 -0
  295. package/dist/utils/secure-local-file.d.ts +3 -3
  296. package/dist/utils/secure-local-file.js +23 -40
  297. package/dist/utils/space-config.d.ts +12 -15
  298. package/dist/utils/space-config.js +13 -16
  299. package/dist/utils/static-runtime-policy.d.ts +10 -7
  300. package/dist/utils/static-runtime-policy.fixtures.json +38 -41
  301. package/dist/utils/static-runtime-policy.generated.d.ts +16 -0
  302. package/dist/utils/static-runtime-policy.generated.js +70 -0
  303. package/dist/utils/static-runtime-policy.js +31 -132
  304. package/dist/utils/storage-policy.js +1 -2
  305. package/dist/utils/upload-session.d.ts +4 -1
  306. package/dist/utils/upload-session.js +41 -19
  307. package/dist/utils/version-path.js +11 -19
  308. package/dist/utils/wpcom-auth-redirects.d.ts +5 -14
  309. package/dist/utils/wpcom-auth-redirects.js +1 -4
  310. package/dist/vocabulary.d.ts +13 -13
  311. package/dist/vocabulary.js +52 -27
  312. package/package.json +15 -18
  313. package/dist/agents/client-registry.d.ts +0 -22
  314. package/dist/agents/client-registry.js +0 -41
  315. package/dist/docs/agent-handoff-document.d.ts +0 -15
  316. package/dist/docs/agent-handoff-document.js +0 -180
  317. package/dist/docs/agent-solutions.d.ts +0 -110
  318. package/dist/docs/agent-solutions.js +0 -183
  319. package/dist/utils/query-keys.d.ts +0 -84
  320. package/dist/utils/query-keys.js +0 -108
@@ -27,8 +27,10 @@ function targetMatches(selector, target) {
27
27
  return target.kind === "version" && target.versionId === selector.versionId;
28
28
  case "branch":
29
29
  return target.kind === "branch" && target.branch === selector.branch;
30
+ // Immutable Version hosts only. The live host is its own target: sharing
31
+ // "every Version" does not thereby publish the live site.
30
32
  case "all_versions":
31
- return target.kind === "live" || target.kind === "version";
33
+ return target.kind === "version";
32
34
  }
33
35
  throw new Error("Unsupported Grant target.");
34
36
  }
@@ -71,12 +73,10 @@ export function grantResourcePatternMatches(pattern, resource, resourceKind = "r
71
73
  return matches(0, 0);
72
74
  }
73
75
  /**
74
- * Exclude patterns read wider than include patterns, and that asymmetry is the
75
- * rule, not an accident: the route lane collapses a terminal `index.html`
76
- * (normalizeAccessScopePath) while the artifact lane keeps it, so an exclude
77
- * naming an index artifact must also close the route that artifact serves.
78
- * Include never gets the same courtesy — granting the stripped route would hand
79
- * out access nobody wrote down. The serving engine compiles the identical pair
76
+ * Exclude reads wider than include, deliberately: the route lane collapses a
77
+ * terminal `index.html`, so an exclude naming an index artifact must also close
78
+ * the route it serves. Include must not, or it would grant a route nobody wrote
79
+ * down. The serving engine compiles the same pair
80
80
  * (access-rules.php _stattic_grant_exclude_pattern_variants).
81
81
  */
82
82
  function grantExcludePatternMatches(pattern, resource, resourceKind) {
@@ -88,7 +88,6 @@ function grantExcludePatternMatches(pattern, resource, resourceKind) {
88
88
  const stripped = canonical.slice(0, -"/index.html".length);
89
89
  return grantResourcePatternMatches(stripped === "" ? "/" : stripped, resource, resourceKind);
90
90
  }
91
- /** Does a Grant's resource set reach this path? Include, minus exclude. */
92
91
  export function grantResourceSetMatches(resources, resource, resourceKind = "route") {
93
92
  return (resources.include.some((pattern) => grantResourcePatternMatches(pattern, resource, resourceKind)) &&
94
93
  !resources.exclude.some((pattern) => grantExcludePatternMatches(pattern, resource, resourceKind)));
@@ -1,9 +1,7 @@
1
- /** Gravatar's canonical address form: trimmed and lowercased. */
2
1
  export declare function normalizeGravatarEmail(email: string | null | undefined): string | null;
3
- /** The canonical avatar URL for an already-computed SHA-256 hash. */
4
2
  export declare function gravatarUrlFromHash(hashHex: string): string;
5
3
  /**
6
- * SHA-256 hex of a normalized email — Gravatar's identifier. Uses WebCrypto so
7
- * a browser can derive it locally and never send the raw address anywhere.
4
+ * Gravatar's identifier, the SHA-256 hex of a normalized email. WebCrypto lets
5
+ * a browser derive it locally and never send the raw address anywhere.
8
6
  */
9
7
  export declare function gravatarEmailHash(email: string | null | undefined): Promise<string | null>;
@@ -1,26 +1,20 @@
1
1
  /**
2
- * The one Gravatar URL shape Spacefast emits. Every surface control-plane
3
- * profiles, the Comments SDK, Slack notifications derives the same address
4
- * for the same person, so an avatar is recognizable wherever it appears and
5
- * Cast can validate a guest avatar against a single pattern.
6
- *
7
- * `d=404` is deliberate: a person without a Gravatar gets no image at all, and
8
- * the consumer renders its own initials/palette fallback instead of a stock
9
- * silhouette. `s=160` covers the largest avatar we render, retina included.
2
+ * The one Gravatar URL shape Spacefast emits, so Cast can validate a guest
3
+ * avatar against a single pattern. `d=404` returns no image for a person
4
+ * without a Gravatar, leaving the consumer's own fallback to render; `s=160`
5
+ * covers the largest avatar we render, retina included.
10
6
  */
11
7
  const GRAVATAR_AVATAR_QUERY = "d=404&r=g&s=160";
12
- /** Gravatar's canonical address form: trimmed and lowercased. */
13
8
  export function normalizeGravatarEmail(email) {
14
9
  const normalized = email?.trim().toLowerCase();
15
10
  return normalized ? normalized : null;
16
11
  }
17
- /** The canonical avatar URL for an already-computed SHA-256 hash. */
18
12
  export function gravatarUrlFromHash(hashHex) {
19
13
  return `https://gravatar.com/avatar/${hashHex}?${GRAVATAR_AVATAR_QUERY}`;
20
14
  }
21
15
  /**
22
- * SHA-256 hex of a normalized email — Gravatar's identifier. Uses WebCrypto so
23
- * a browser can derive it locally and never send the raw address anywhere.
16
+ * Gravatar's identifier, the SHA-256 hex of a normalized email. WebCrypto lets
17
+ * a browser derive it locally and never send the raw address anywhere.
24
18
  */
25
19
  export async function gravatarEmailHash(email) {
26
20
  const normalized = normalizeGravatarEmail(email);
@@ -1,17 +1,12 @@
1
- // Shared not-found self-correction (W1). One source for the closest-candidate
2
- // ranking used by every resource's 404 hint builder (spaces, versions, teams,
3
- // domains). Resources differ only in which caller-scoped rows they feed in and
4
- // which keys they expose for matching; keeping the levenshtein/closeness/ranking
5
- // here prevents per-resource drift. Callers are responsible for scoping the rows
6
- // to the caller principal — this module never touches the DB or auth.
7
- // How many caller-scoped rows a hint builder will scan to rank candidates. Above
8
- // this the collection is treated as too large to rank for free, so the builder
9
- // returns only the recovery hint (no candidate ids).
1
+ // One closest-candidate ranking for every resource's 404 hint builder (spaces,
2
+ // versions, teams, domains). Callers scope the rows to the caller principal;
3
+ // this module never touches the DB or auth.
4
+ // Above this many rows the collection is too large to rank for free, and the
5
+ // builder returns the recovery hint without candidate ids.
10
6
  export const HINT_SCAN_CAP = 200;
11
7
  export const HINT_MAX_CANDIDATES = 5;
12
- // All supported hint keys (ids, slugs, hostnames, and numeric version refs) fit
13
- // within this ceiling. Rejecting larger values keeps best-effort 404 recovery
14
- // from turning attacker-controlled refs or stored labels into quadratic work.
8
+ // Every hint key (ids, slugs, hostnames, version refs) fits here. Rejecting
9
+ // larger values keeps attacker-controlled refs out of quadratic work.
15
10
  export const HINT_MAX_KEY_LENGTH = 256;
16
11
  function boundedLevenshtein(a, b, maxDistance) {
17
12
  if (Math.abs(a.length - b.length) > maxDistance)
@@ -48,9 +43,8 @@ export function levenshtein(a, b) {
48
43
  }
49
44
  return boundedLevenshtein(a, b, Math.max(a.length, b.length));
50
45
  }
51
- // Returns a small finite score the closer `candidate` is to `needle`, or
52
- // +Infinity when they are not genuinely close. Exact match = 0; substring
53
- // containment = 1; otherwise a typo within a length-bounded edit distance.
46
+ // Lower is closer, +Infinity when not close at all: exact = 0, substring
47
+ // containment = 1, otherwise 1 + a length-bounded edit distance.
54
48
  export function refCloseness(needle, candidate) {
55
49
  if (!candidate)
56
50
  return Number.POSITIVE_INFINITY;
@@ -61,22 +55,19 @@ export function refCloseness(needle, candidate) {
61
55
  return 0;
62
56
  if (candidate.includes(needle) || needle.includes(candidate))
63
57
  return 1;
64
- // Only surface genuinely close typos: bound the allowed distance by the shorter
65
- // string so short refs don't match everything.
58
+ // Bound the distance by the shorter string so short refs don't match everything.
66
59
  const tolerance = Math.max(2, Math.floor(Math.min(needle.length, candidate.length) / 3));
67
60
  const distance = boundedLevenshtein(needle, candidate, tolerance);
68
61
  return distance <= tolerance ? 1 + distance : Number.POSITIVE_INFINITY;
69
62
  }
70
- // Rank `rows` by how close any of their keys are to `ref`, returning at most
71
- // `max` closest rows. A row whose every key is far (or absent) is dropped, so
72
- // only genuine near-matches surface. Ties break by the optional comparator
73
- // (e.g. recency); keys are matched case-insensitively.
63
+ // Rank `rows` by their closest key to `ref`, at most `max` rows. Rows with no
64
+ // close key are dropped. Ties break by the optional comparator; keys match
65
+ // case-insensitively.
74
66
  export function rankCandidates(ref, rows, keysOf, options) {
75
67
  if (rows.length > HINT_SCAN_CAP || ref.length > HINT_MAX_KEY_LENGTH)
76
68
  return [];
77
69
  const needle = ref.toLowerCase();
78
- // Unicode case conversion can expand a string (for example, U+0130). Keep
79
- // that normalized representation under the same work ceiling too.
70
+ // Lowercasing can expand a string (U+0130), so re-check the ceiling.
80
71
  if (needle.length > HINT_MAX_KEY_LENGTH)
81
72
  return [];
82
73
  const max = options?.max ?? HINT_MAX_CANDIDATES;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Stable, secret-safe key for one exact logical mutation attempt. Shared by
3
- * every client surface: the same publish issued through the CLI and through
4
- * MCP must land on one key or the API stops deduplicating the retry.
2
+ * Stable, secret-safe key for one logical mutation attempt. The same publish
3
+ * from the CLI and from MCP must land on one key, or the API stops
4
+ * deduplicating the retry.
5
5
  */
6
6
  export declare function stableIdempotencyKey(prefix: string, parts: unknown): string;
@@ -1,9 +1,8 @@
1
1
  import { createHash } from "node:crypto";
2
2
  /**
3
- * Key-sorted JSON that treats an absent key and an `undefined` value as the
4
- * same thing. Deliberately *not* `canonicalJson`: a key the CLI omits and one
5
- * the MCP server sets to `undefined` describe the same mutation, so they have
6
- * to hash alike. Merging the two spellings would change every minted key.
3
+ * Key-sorted JSON that treats an absent key and an `undefined` value alike: a
4
+ * key the CLI omits and one MCP sets to `undefined` are the same mutation.
5
+ * Deliberately not `canonicalJson`; merging the two would change every key.
7
6
  */
8
7
  function keyJson(value) {
9
8
  if (Array.isArray(value)) {
@@ -19,9 +18,9 @@ function keyJson(value) {
19
18
  return JSON.stringify(value ?? null);
20
19
  }
21
20
  /**
22
- * Stable, secret-safe key for one exact logical mutation attempt. Shared by
23
- * every client surface: the same publish issued through the CLI and through
24
- * MCP must land on one key or the API stops deduplicating the retry.
21
+ * Stable, secret-safe key for one logical mutation attempt. The same publish
22
+ * from the CLI and from MCP must land on one key, or the API stops
23
+ * deduplicating the retry.
25
24
  */
26
25
  export function stableIdempotencyKey(prefix, parts) {
27
26
  return `${prefix}-${createHash("sha256").update(keyJson(parts)).digest("hex")}`;
@@ -5,16 +5,13 @@ export declare const LOCAL_SPACE_STATE_FILE_NAME = "state.json";
5
5
  /**
6
6
  * Local Spacefast checkout contract.
7
7
  *
8
- * `.spacefast/space.json` is the committable selection axis: it names which
9
- * space a checkout targets (`space`) and may carry non-secret provider/team
10
- * coordinates (`team`, `apiBaseUrl`). It must not carry credentials.
8
+ * `.spacefast/space.json` is the committable selection axis: which space a
9
+ * checkout targets, plus non-secret provider/team coordinates. Never credentials.
11
10
  *
12
- * `.spacefast/state.json` is the local credential/cache axis: it records the
13
- * resolved `spaceId`, provider `apiUrl`, anonymous `claimToken` before claim,
14
- * durable `accessToken` after continuation, and small publish caches such as
15
- * `lastVersionId`. It is secret, machine-written, gitignored, and merge-written.
16
- * The strict versioned schema fails closed instead of letting an older tool
17
- * reinterpret fields written under a contract it does not understand.
11
+ * `.spacefast/state.json` is the secret axis: credentials and small publish
12
+ * caches, machine-written, gitignored, merge-written. Its strict versioned
13
+ * schema fails closed rather than let an older tool reinterpret fields written
14
+ * under a contract it does not understand.
18
15
  */
19
16
  export declare const localSpaceLinkSchema: z.ZodObject<{
20
17
  team: z.ZodOptional<z.ZodString>;
@@ -22,6 +19,12 @@ export declare const localSpaceLinkSchema: z.ZodObject<{
22
19
  apiBaseUrl: z.ZodOptional<z.ZodString>;
23
20
  }, z.core.$loose>;
24
21
  export declare const LOCAL_SPACE_STATE_SCHEMA_VERSION = 1;
22
+ export declare const creationAttemptSchema: z.ZodObject<{
23
+ key: z.ZodString;
24
+ principal: z.ZodString;
25
+ kind: z.ZodLiteral<"authenticated">;
26
+ createdAt: z.ZodString;
27
+ }, z.core.$strict>;
25
28
  export declare const localSpaceStateSchema: z.ZodObject<{
26
29
  schemaVersion: z.ZodLiteral<1>;
27
30
  spaceId: z.ZodOptional<z.ZodString>;
@@ -41,22 +44,14 @@ export declare const localSpaceStateSchema: z.ZodObject<{
41
44
  pendingPublish: z.ZodOptional<z.ZodObject<{
42
45
  key: z.ZodString;
43
46
  principal: z.ZodString;
44
- kind: z.ZodEnum<{
45
- anonymous: "anonymous";
46
- authenticated: "authenticated";
47
- }>;
48
- intent: z.ZodOptional<z.ZodString>;
47
+ kind: z.ZodLiteral<"authenticated">;
49
48
  createdAt: z.ZodString;
50
49
  }, z.core.$strict>>;
51
50
  /** Settled creation receipt identity retained for invocations that began before its commit. */
52
51
  creationReplay: z.ZodOptional<z.ZodObject<{
53
52
  key: z.ZodString;
54
53
  principal: z.ZodString;
55
- kind: z.ZodEnum<{
56
- anonymous: "anonymous";
57
- authenticated: "authenticated";
58
- }>;
59
- intent: z.ZodOptional<z.ZodString>;
54
+ kind: z.ZodLiteral<"authenticated">;
60
55
  createdAt: z.ZodString;
61
56
  }, z.core.$strict>>;
62
57
  /** Random replay capability reserved before consuming a claim credential. */
@@ -126,17 +121,15 @@ export declare function localSpaceStateDir(root: string): string;
126
121
  export declare function localSpaceStatePath(root: string): string;
127
122
  export declare function localSpaceLinkPath(root: string): string;
128
123
  export declare function readLocalSpaceLink(root: string): Promise<LocalSpaceLink | null>;
129
- /** Like readLocalSpaceLink, but reports the file path alongside the link. */
130
124
  export declare function readLocalSpaceLinkWithPath(root: string): Promise<{
131
125
  link: LocalSpaceLink;
132
126
  path: string;
133
127
  } | null>;
134
128
  export declare function readLocalSpaceStateAt(root: string): Promise<DiscoveredLocalSpaceState | null>;
135
129
  /**
136
- * Walk up from `startDir` to the filesystem root (or `boundary`, when given),
137
- * returning the first non-null result of `probe`. Shared by every "nearest
138
- * checkout marker" lookup (state+link discovery here, the CLI's link-only
139
- * discovery) so the traversal rules live in one place.
130
+ * Walk up from `startDir` to the filesystem root (or `boundary`), returning the
131
+ * first non-null `probe` result. Every "nearest checkout marker" lookup shares
132
+ * it so the traversal rules live in one place.
140
133
  */
141
134
  export declare function findUpward<T>(probe: (dir: string) => Promise<T | null>, startDir?: string, boundary?: string): Promise<T | null>;
142
135
  export declare function discoverLocalSpaceState(startDir?: string, boundary?: string): Promise<DiscoveredLocalSpaceState | null>;
@@ -146,9 +139,9 @@ export declare function mutateLocalSpaceState(root: string, mutate: (current: Lo
146
139
  afterBackup?: (() => void | Promise<void>) | undefined;
147
140
  /** Fault-injection observer used to synchronize concurrency tests. */
148
141
  onConflict?: (() => void | Promise<void>) | undefined;
142
+ /** Reports whether this mutation changed `.gitignore`. */
143
+ onGitignoreResult?: ((changed: boolean) => void) | undefined;
149
144
  }): Promise<LocalSpaceStateFile>;
150
- export declare function writeLocalSpaceState(root: string, state: LocalSpaceStateWrite): Promise<string>;
151
- /** Reserve random replay custody before a claim token can be consumed. */
152
145
  export declare function reserveLocalCredentialReplay(root: string, input: {
153
146
  operation: LocalCredentialReplayOperation;
154
147
  claimToken: string;
@@ -158,4 +151,8 @@ export declare function saveLocalSpaceState(root: string, input: SaveLocalSpaceS
158
151
  statePath: string;
159
152
  linkPath: string;
160
153
  wroteLink: boolean;
154
+ gitignore: {
155
+ path: string;
156
+ changed: boolean;
157
+ };
161
158
  }>;
@@ -10,16 +10,13 @@ export const LOCAL_SPACE_STATE_FILE_NAME = "state.json";
10
10
  /**
11
11
  * Local Spacefast checkout contract.
12
12
  *
13
- * `.spacefast/space.json` is the committable selection axis: it names which
14
- * space a checkout targets (`space`) and may carry non-secret provider/team
15
- * coordinates (`team`, `apiBaseUrl`). It must not carry credentials.
13
+ * `.spacefast/space.json` is the committable selection axis: which space a
14
+ * checkout targets, plus non-secret provider/team coordinates. Never credentials.
16
15
  *
17
- * `.spacefast/state.json` is the local credential/cache axis: it records the
18
- * resolved `spaceId`, provider `apiUrl`, anonymous `claimToken` before claim,
19
- * durable `accessToken` after continuation, and small publish caches such as
20
- * `lastVersionId`. It is secret, machine-written, gitignored, and merge-written.
21
- * The strict versioned schema fails closed instead of letting an older tool
22
- * reinterpret fields written under a contract it does not understand.
16
+ * `.spacefast/state.json` is the secret axis: credentials and small publish
17
+ * caches, machine-written, gitignored, merge-written. Its strict versioned
18
+ * schema fails closed rather than let an older tool reinterpret fields written
19
+ * under a contract it does not understand.
23
20
  */
24
21
  export const localSpaceLinkSchema = z
25
22
  .object({
@@ -29,6 +26,17 @@ export const localSpaceLinkSchema = z
29
26
  })
30
27
  .loose();
31
28
  export const LOCAL_SPACE_STATE_SCHEMA_VERSION = 1;
29
+ // One reservation, two slots: it is written as `pendingPublish` and moved to
30
+ // `creationReplay` once its receipt commits. Space creation is the only
31
+ // mutation that reserves one. Credential-free publishes are not idempotent.
32
+ export const creationAttemptSchema = z
33
+ .object({
34
+ key: z.string().min(1),
35
+ principal: z.string().regex(/^[0-9a-f]{64}$/),
36
+ kind: z.literal("authenticated"),
37
+ createdAt: z.string().datetime(),
38
+ })
39
+ .strict();
32
40
  export const localSpaceStateSchema = z.strictObject({
33
41
  schemaVersion: z.literal(LOCAL_SPACE_STATE_SCHEMA_VERSION),
34
42
  spaceId: z.string().min(1).optional(),
@@ -45,27 +53,9 @@ export const localSpaceStateSchema = z.strictObject({
45
53
  /** Secret per-checkout entropy used only to namespace replay-safe first publishes. */
46
54
  anonymousPublishNonce: z.string().min(32).optional(),
47
55
  /** Unsettled first-publish mutation. Retries must reuse this exact key. */
48
- pendingPublish: z
49
- .object({
50
- key: z.string().min(1),
51
- principal: z.string().regex(/^[0-9a-f]{64}$/),
52
- kind: z.enum(["anonymous", "authenticated"]),
53
- intent: z.string().min(1).optional(),
54
- createdAt: z.string().datetime(),
55
- })
56
- .strict()
57
- .optional(),
56
+ pendingPublish: creationAttemptSchema.optional(),
58
57
  /** Settled creation receipt identity retained for invocations that began before its commit. */
59
- creationReplay: z
60
- .object({
61
- key: z.string().min(1),
62
- principal: z.string().regex(/^[0-9a-f]{64}$/),
63
- kind: z.enum(["anonymous", "authenticated"]),
64
- intent: z.string().min(1).optional(),
65
- createdAt: z.string().datetime(),
66
- })
67
- .strict()
68
- .optional(),
58
+ creationReplay: creationAttemptSchema.optional(),
69
59
  /** Random replay capability reserved before consuming a claim credential. */
70
60
  pendingCredentialReplay: z
71
61
  .object({
@@ -152,7 +142,6 @@ function linkSpaceId(link) {
152
142
  export async function readLocalSpaceLink(root) {
153
143
  return (await readLocalSpaceLinkWithPath(root))?.link ?? null;
154
144
  }
155
- /** Like readLocalSpaceLink, but reports the file path alongside the link. */
156
145
  export async function readLocalSpaceLinkWithPath(root) {
157
146
  const primary = parseLink(await readJsonFile(root, path.join(LOCAL_SPACE_STATE_DIR_NAME, LOCAL_SPACE_LINK_FILE_NAME)));
158
147
  return primary ? { link: primary, path: localSpaceLinkPath(root) } : null;
@@ -190,10 +179,9 @@ function isWithinBoundary(current, boundary) {
190
179
  return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
191
180
  }
192
181
  /**
193
- * Walk up from `startDir` to the filesystem root (or `boundary`, when given),
194
- * returning the first non-null result of `probe`. Shared by every "nearest
195
- * checkout marker" lookup (state+link discovery here, the CLI's link-only
196
- * discovery) so the traversal rules live in one place.
182
+ * Walk up from `startDir` to the filesystem root (or `boundary`), returning the
183
+ * first non-null `probe` result. Every "nearest checkout marker" lookup shares
184
+ * it so the traversal rules live in one place.
197
185
  */
198
186
  export async function findUpward(probe, startDir = process.cwd(), boundary) {
199
187
  let current = path.resolve(startDir);
@@ -258,7 +246,7 @@ async function ensureStateGitignored(root, onConflict) {
258
246
  const lines = raw.split(/\r?\n/);
259
247
  const missing = entries.filter((entry) => !lines.includes(entry));
260
248
  if (missing.length === 0)
261
- return;
249
+ return false;
262
250
  const prefix = raw.length > 0 && !raw.endsWith("\n") ? "\n" : "";
263
251
  await secureWriteFile({
264
252
  root,
@@ -268,7 +256,7 @@ async function ensureStateGitignored(root, onConflict) {
268
256
  mode: 0o644,
269
257
  expectedContent: existing,
270
258
  });
271
- return;
259
+ return true;
272
260
  }
273
261
  catch (error) {
274
262
  if (error instanceof SecureLocalFileConflictError)
@@ -281,6 +269,7 @@ async function ensureStateGitignored(root, onConflict) {
281
269
  }
282
270
  }
283
271
  /* eslint-enable no-await-in-loop */
272
+ throw new LocalSpaceStateConflictError("Local .gitignore stayed busy for too long.");
284
273
  }
285
274
  function assignDefined(target, input) {
286
275
  for (const [key, value] of Object.entries(input)) {
@@ -315,7 +304,8 @@ export async function writeLocalSpaceLink(root, link) {
315
304
  }
316
305
  export async function mutateLocalSpaceState(root, mutate, options = {}) {
317
306
  const stateRelativePath = path.join(LOCAL_SPACE_STATE_DIR_NAME, LOCAL_SPACE_STATE_FILE_NAME);
318
- await ensureStateGitignored(root, options.onConflict);
307
+ const gitignoreChanged = await ensureStateGitignored(root, options.onConflict);
308
+ options.onGitignoreResult?.(gitignoreChanged);
319
309
  /* eslint-disable no-await-in-loop -- compare-and-swap retries are intentionally serialized against the latest committed state. */
320
310
  for (let attempt = 1; attempt <= LOCAL_STATE_MUTATION_ATTEMPTS; attempt += 1) {
321
311
  try {
@@ -327,8 +317,8 @@ export async function mutateLocalSpaceState(root, mutate, options = {}) {
327
317
  const current = parsed?.success
328
318
  ? parsed.data
329
319
  : { schemaVersion: LOCAL_SPACE_STATE_SCHEMA_VERSION };
330
- // The callback may run again after a compare-and-swap collision. Keeping it
331
- // synchronous makes remote effects and other one-shot work impossible here.
320
+ // The callback may run again after a compare-and-swap collision; keeping
321
+ // it synchronous rules out one-shot work inside it.
332
322
  const payload = localSpaceStateSchema.parse({
333
323
  ...mutate(structuredClone(current)),
334
324
  schemaVersion: LOCAL_SPACE_STATE_SCHEMA_VERSION,
@@ -360,10 +350,6 @@ export async function mutateLocalSpaceState(root, mutate, options = {}) {
360
350
  /* eslint-enable no-await-in-loop */
361
351
  throw new LocalSpaceStateConflictError("Local Spacefast state stayed busy for too long.");
362
352
  }
363
- export async function writeLocalSpaceState(root, state) {
364
- await mutateLocalSpaceState(root, () => state);
365
- return localSpaceStatePath(root);
366
- }
367
353
  function credentialFingerprint(credential) {
368
354
  return createHash("sha256").update(credential).digest("hex");
369
355
  }
@@ -373,7 +359,6 @@ function sameCredentialReplay(left, right) {
373
359
  left.key === right.key &&
374
360
  left.principal === right.principal);
375
361
  }
376
- /** Reserve random replay custody before a claim token can be consumed. */
377
362
  export async function reserveLocalCredentialReplay(root, input) {
378
363
  const identity = createOneShotReplayIdentity(`sf-${input.operation}`);
379
364
  const candidate = {
@@ -407,6 +392,7 @@ function credentialMatches(state, expected) {
407
392
  return state.claimToken === expected.claimToken && state.accessToken === expected.accessToken;
408
393
  }
409
394
  export async function saveLocalSpaceState(root, input) {
395
+ let gitignoreChanged = false;
410
396
  await mutateLocalSpaceState(root, (existing) => {
411
397
  if (existing.spaceId && existing.spaceId !== input.spaceId && !input.replaceSpace) {
412
398
  throw new LocalSpaceStateConflictError(`Local Spacefast state changed from ${input.spaceId} to ${existing.spaceId}.`);
@@ -484,6 +470,10 @@ export async function saveLocalSpaceState(root, input) {
484
470
  delete next.pendingCredentialReplay;
485
471
  }
486
472
  return localSpaceStateSchema.parse(next);
473
+ }, {
474
+ onGitignoreResult: (changed) => {
475
+ gitignoreChanged = changed;
476
+ },
487
477
  });
488
478
  const statePath = localSpaceStatePath(root);
489
479
  const linkRelativePath = path.join(LOCAL_SPACE_STATE_DIR_NAME, LOCAL_SPACE_LINK_FILE_NAME);
@@ -506,7 +496,12 @@ export async function saveLocalSpaceState(root, input) {
506
496
  throw new LocalSpaceStateConflictError(`The committed checkout link selects ${inheritedLink.space}, not ${input.spaceId}.`);
507
497
  }
508
498
  if (inheritedLink) {
509
- return { statePath, linkPath: localSpaceLinkPath(root), wroteLink };
499
+ return {
500
+ statePath,
501
+ linkPath: localSpaceLinkPath(root),
502
+ wroteLink,
503
+ gitignore: { path: path.join(root, ".gitignore"), changed: gitignoreChanged },
504
+ };
510
505
  }
511
506
  }
512
507
  try {
@@ -530,5 +525,10 @@ export async function saveLocalSpaceState(root, input) {
530
525
  else if (primaryLink.space !== input.spaceId) {
531
526
  throw new LocalSpaceStateConflictError(`The committed checkout link selects ${primaryLink.space}, not ${input.spaceId}.`);
532
527
  }
533
- return { statePath, linkPath: localSpaceLinkPath(root), wroteLink };
528
+ return {
529
+ statePath,
530
+ linkPath: localSpaceLinkPath(root),
531
+ wroteLink,
532
+ gitignore: { path: path.join(root, ".gitignore"), changed: gitignoreChanged },
533
+ };
534
534
  }
@@ -1,8 +1,6 @@
1
1
  /**
2
- * The signed OAuth authorize continuation carried by a query string, or null
3
- * when there isn't one. Better Auth's signature covers every param it sent
4
- * (the set is self-declared in `ba_param`) anything extra that later joined
5
- * the URL (a returnTo, a tracking param) must be dropped before the query is
6
- * sent back, or verification fails.
2
+ * The signed authorize continuation in `query`, or null when there isn't one.
3
+ * The signature covers only the params `ba_param` names, so anything that
4
+ * joined the URL later must be dropped or verification fails.
7
5
  */
8
6
  export declare function signedOAuthQuerySubset(query: string): string | null;
@@ -1,13 +1,10 @@
1
- // Better Auth's OAuth authorize endpoint hands interaction prompts (login,
2
- // consent) to the dashboard by redirecting with the ENTIRE authorize query,
3
- // HMAC-signed by the auth server (`sig` + `exp` + `ba_*` bookkeeping params).
4
- // Verification hashes the query verbatim, so it must round-trip byte-exact.
1
+ // Better Auth redirects interaction prompts to the dashboard with the entire
2
+ // authorize query, HMAC-signed. Verification hashes it verbatim, so the query
3
+ // must round-trip byte-exact.
5
4
  /**
6
- * The signed OAuth authorize continuation carried by a query string, or null
7
- * when there isn't one. Better Auth's signature covers every param it sent
8
- * (the set is self-declared in `ba_param`) anything extra that later joined
9
- * the URL (a returnTo, a tracking param) must be dropped before the query is
10
- * sent back, or verification fails.
5
+ * The signed authorize continuation in `query`, or null when there isn't one.
6
+ * The signature covers only the params `ba_param` names, so anything that
7
+ * joined the URL later must be dropped or verification fails.
11
8
  */
12
9
  export function signedOAuthQuerySubset(query) {
13
10
  const params = new URLSearchParams(query);
@@ -3,12 +3,13 @@ export type OneShotReplayIdentity = {
3
3
  principal: string;
4
4
  };
5
5
  /**
6
- * Creates an unguessable capability for replaying one shown-once response.
7
- *
8
- * Neither value is derived from the credential consumed by the mutation. A
9
- * caller holding only that old credential therefore cannot locate the stored
10
- * response after the credential is revoked.
6
+ * An unguessable capability for replaying one shown-once response. Neither
7
+ * value derives from the credential the mutation consumes, so a caller holding
8
+ * only that revoked credential cannot locate the stored response.
11
9
  */
12
10
  export declare function createOneShotReplayIdentity(prefix: string): OneShotReplayIdentity;
13
11
  /** Production headers for one one-shot attempt (or one device-poll sequence). */
14
- export declare function oneShotReplayHeaders(identity: OneShotReplayIdentity, sequence?: number): Record<"idempotency-key" | "x-spacefast-idempotency-principal", string>;
12
+ export declare function oneShotReplayHeaders(identity: OneShotReplayIdentity, sequence?: number): {
13
+ "idempotency-key": string;
14
+ "x-spacefast-idempotency-principal": string;
15
+ };
@@ -1,10 +1,8 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  /**
3
- * Creates an unguessable capability for replaying one shown-once response.
4
- *
5
- * Neither value is derived from the credential consumed by the mutation. A
6
- * caller holding only that old credential therefore cannot locate the stored
7
- * response after the credential is revoked.
3
+ * An unguessable capability for replaying one shown-once response. Neither
4
+ * value derives from the credential the mutation consumes, so a caller holding
5
+ * only that revoked credential cannot locate the stored response.
8
6
  */
9
7
  export function createOneShotReplayIdentity(prefix) {
10
8
  return {
@@ -1,17 +1,17 @@
1
1
  import type { SpacePageTheme } from "../contracts/space-config.js";
2
- /** Default page palette (mirrored into the shared template CSS). */
2
+ /** Default page palette, mirrored into the shared template CSS. */
3
3
  export declare const PAGE_COLOR_DEFAULTS: {
4
- readonly accent: "#ff4217";
5
- readonly bg: "#f9f8f4";
6
- readonly fg: "#1a1913";
7
- readonly muted: "#6f6b62";
8
- readonly card: "#f9f8f4";
9
- readonly border: "#ddd9cf";
10
- readonly darkBg: "#141313";
11
- readonly darkFg: "#e9e7e2";
12
- readonly darkMuted: "#8f8b84";
13
- readonly darkCard: "#141313";
14
- readonly darkBorder: "#2b2a27";
4
+ readonly accent: "#d8f24b";
5
+ readonly bg: "#f7f5ef";
6
+ readonly fg: "#0c0c0c";
7
+ readonly muted: "#6e6a5e";
8
+ readonly card: "#f7f5ef";
9
+ readonly border: "#e5e1d4";
10
+ readonly darkBg: "#0c0c0c";
11
+ readonly darkFg: "#f0eee6";
12
+ readonly darkMuted: "#a6a193";
13
+ readonly darkCard: "#0c0c0c";
14
+ readonly darkBorder: "#2b2823";
15
15
  };
16
16
  export type PageSchemeColors = {
17
17
  bg: string;
@@ -26,7 +26,6 @@ export type DerivedPageColors = {
26
26
  scheme: "adaptive" | "light" | "dark";
27
27
  /** The accent exactly as pushed (fills keep the brand color verbatim). */
28
28
  accent: string;
29
- /** Label color on accent fills. */
30
29
  onAccent: string;
31
30
  /** Accent-derived link color, readable on the light (or pinned) surface. */
32
31
  link: string;
@@ -36,15 +35,12 @@ export type DerivedPageColors = {
36
35
  pinned?: PageSchemeColors;
37
36
  };
38
37
  /**
39
- * Return `color` unchanged when it already meets `target` on `surface`;
40
- * otherwise move its OKLCH lightness (hue/chroma preserved) just far enough
41
- * to meet it. Falls back to plain black/white when even full lightness range
42
- * cannot reach the target (e.g. a mid-gray surface).
38
+ * Moves `color`'s OKLCH lightness (hue and chroma preserved) just far enough
39
+ * to meet `target` on `surface`. Falls back to black or white when the full
40
+ * lightness range cannot reach it, as on a mid-gray surface.
43
41
  */
44
42
  export declare function readableOn(color: string, surface: string, target: number): string;
45
- /** Button-label color for an accent fill: white when it can carry, else ink. */
46
43
  export declare function onAccentColor(accent: string): string;
47
- /** The one entry point: raw theme in, everything the templates paint with out. */
48
44
  export declare function derivePageColors(theme: Pick<SpacePageTheme, "accent" | "background">): DerivedPageColors;
49
45
  /** Hex form of any schema-accepted color, for color-picker inputs. */
50
46
  export declare function pageColorToHex(value: string): string | null;