@spacefast/common 0.2.2 → 0.4.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 (226) hide show
  1. package/dist/agents/marketplace-prompts.d.ts +1 -0
  2. package/dist/agents/marketplace-prompts.js +6 -0
  3. package/dist/agents/registry/core.d.ts +4 -12
  4. package/dist/agents/registry/core.js +7 -28
  5. package/dist/config/domains.d.ts +10 -8
  6. package/dist/config/domains.js +4 -7
  7. package/dist/contracts/access-core.d.ts +135 -0
  8. package/dist/contracts/access-core.js +242 -0
  9. package/dist/contracts/access-profiles.d.ts +8 -8
  10. package/dist/contracts/access-profiles.js +8 -8
  11. package/dist/contracts/access.d.ts +14 -103
  12. package/dist/contracts/access.js +10 -210
  13. package/dist/contracts/activity.d.ts +54 -55
  14. package/dist/contracts/activity.js +38 -9
  15. package/dist/contracts/api-keys.d.ts +69 -26
  16. package/dist/contracts/api-keys.js +29 -2
  17. package/dist/contracts/application-journal.d.ts +197 -4
  18. package/dist/contracts/application-journal.js +97 -16
  19. package/dist/contracts/auth.d.ts +20 -0
  20. package/dist/contracts/auth.js +18 -0
  21. package/dist/contracts/beta.d.ts +13 -0
  22. package/dist/contracts/beta.js +28 -0
  23. package/dist/contracts/billing.d.ts +2 -2
  24. package/dist/contracts/bootstrap.d.ts +23 -6
  25. package/dist/contracts/builds.d.ts +18 -4
  26. package/dist/contracts/builds.js +7 -4
  27. package/dist/contracts/channels.d.ts +43 -0
  28. package/dist/contracts/channels.js +22 -6
  29. package/dist/contracts/comments.d.ts +49 -0
  30. package/dist/contracts/comments.js +61 -2
  31. package/dist/contracts/commerce.d.ts +19 -13
  32. package/dist/contracts/connector-access.d.ts +28 -0
  33. package/dist/contracts/connector-access.js +31 -0
  34. package/dist/contracts/connectors.d.ts +2382 -0
  35. package/dist/contracts/connectors.js +941 -0
  36. package/dist/contracts/content-contract-verification.d.ts +112 -58
  37. package/dist/contracts/content-contract-verification.js +42 -54
  38. package/dist/contracts/content-model-emit.d.ts +97 -0
  39. package/dist/contracts/content-model-emit.js +306 -0
  40. package/dist/contracts/content-model-sdk.d.ts +101 -0
  41. package/dist/contracts/content-model-sdk.js +232 -0
  42. package/dist/contracts/{content-program.d.ts → content-model.d.ts} +338 -82
  43. package/dist/contracts/{content-program.js → content-model.js} +291 -63
  44. package/dist/contracts/content-platform-fixture.d.ts +380 -110
  45. package/dist/contracts/content-platform-fixture.js +8 -8
  46. package/dist/contracts/content-sync.d.ts +197 -74
  47. package/dist/contracts/content-sync.js +98 -37
  48. package/dist/contracts/content.d.ts +30 -422
  49. package/dist/contracts/content.js +34 -294
  50. package/dist/contracts/dashboard-prefs.d.ts +10 -3
  51. package/dist/contracts/dashboard-prefs.js +6 -3
  52. package/dist/contracts/data-location.d.ts +9 -0
  53. package/dist/contracts/data-location.js +7 -0
  54. package/dist/contracts/deployment-comparison.d.ts +67 -0
  55. package/dist/contracts/deployment-comparison.js +68 -0
  56. package/dist/contracts/device-auth.d.ts +55 -11
  57. package/dist/contracts/domains.d.ts +40 -16
  58. package/dist/contracts/domains.js +23 -0
  59. package/dist/contracts/enums.d.ts +1 -10
  60. package/dist/contracts/enums.js +0 -15
  61. package/dist/contracts/error-code-meta.d.ts +384 -20
  62. package/dist/contracts/error-code-meta.js +200 -5
  63. package/dist/contracts/error-codes.d.ts +17 -4
  64. package/dist/contracts/error-codes.js +108 -10
  65. package/dist/contracts/events.d.ts +5 -0
  66. package/dist/contracts/events.js +12 -3
  67. package/dist/contracts/execution.d.ts +5 -1
  68. package/dist/contracts/execution.js +4 -0
  69. package/dist/contracts/feature-lifecycle.d.ts +53 -20
  70. package/dist/contracts/feature-lifecycle.js +65 -23
  71. package/dist/contracts/features.d.ts +57 -31
  72. package/dist/contracts/features.js +0 -1
  73. package/dist/contracts/feedback.d.ts +124 -0
  74. package/dist/contracts/feedback.js +64 -0
  75. package/dist/contracts/fixtures/content-model-sdk-v1.generated.d.ts +129 -0
  76. package/dist/contracts/fixtures/content-model-sdk-v1.generated.js +48 -0
  77. package/dist/contracts/fixtures/content-platform-v1.json +101 -49
  78. package/dist/contracts/frame-session.d.ts +60 -10
  79. package/dist/contracts/frame-session.js +52 -12
  80. package/dist/contracts/functions.d.ts +28 -2
  81. package/dist/contracts/functions.js +25 -2
  82. package/dist/contracts/grant-copy.d.ts +2 -0
  83. package/dist/contracts/grant-copy.js +2 -0
  84. package/dist/contracts/grants-core.d.ts +95 -0
  85. package/dist/contracts/grants-core.js +435 -0
  86. package/dist/contracts/grants.d.ts +13 -84
  87. package/dist/contracts/grants.js +21 -369
  88. package/dist/contracts/ids-core.d.ts +11 -0
  89. package/dist/contracts/ids-core.js +14 -0
  90. package/dist/contracts/ids.d.ts +7 -4
  91. package/dist/contracts/ids.js +12 -4
  92. package/dist/contracts/internal.d.ts +18 -0
  93. package/dist/contracts/internal.js +19 -0
  94. package/dist/contracts/mcp.d.ts +8 -18
  95. package/dist/contracts/mcp.js +2 -23
  96. package/dist/contracts/notifications.d.ts +4 -1
  97. package/dist/contracts/notifications.js +1 -0
  98. package/dist/contracts/oauth-resources.d.ts +46 -9
  99. package/dist/contracts/oauth-resources.js +50 -1
  100. package/dist/contracts/oauth-scope-actions.d.ts +27 -3
  101. package/dist/contracts/oauth-scope-actions.js +18 -8
  102. package/dist/contracts/operations.d.ts +1 -1
  103. package/dist/contracts/partner-account.d.ts +629 -0
  104. package/dist/contracts/partner-account.js +18 -0
  105. package/dist/contracts/principal-assertion.d.ts +74 -1
  106. package/dist/contracts/principal-assertion.js +67 -3
  107. package/dist/contracts/publish-archive.d.ts +22 -1
  108. package/dist/contracts/push-new.d.ts +3 -3
  109. package/dist/contracts/push-new.js +1 -1
  110. package/dist/contracts/quotas.js +2 -1
  111. package/dist/contracts/repository-connections.d.ts +10 -6
  112. package/dist/contracts/repository-connections.js +15 -0
  113. package/dist/contracts/resources.d.ts +6 -5
  114. package/dist/contracts/resources.js +7 -0
  115. package/dist/contracts/route-inventory.d.ts +74 -19
  116. package/dist/contracts/route-inventory.js +20 -6
  117. package/dist/contracts/runtime-api.d.ts +415 -4
  118. package/dist/contracts/runtime-api.js +60 -15
  119. package/dist/contracts/runtime-app.d.ts +6 -1
  120. package/dist/contracts/runtime-components.d.ts +646 -18
  121. package/dist/contracts/runtime-components.js +304 -188
  122. package/dist/contracts/runtime-services.d.ts +15 -0
  123. package/dist/contracts/runtime-services.js +25 -0
  124. package/dist/contracts/runtime-storage.d.ts +32 -0
  125. package/dist/contracts/runtime-storage.js +37 -0
  126. package/dist/contracts/source-workspaces.d.ts +511 -0
  127. package/dist/contracts/source-workspaces.js +276 -0
  128. package/dist/contracts/space-config-spacefast.d.ts +394 -0
  129. package/dist/contracts/space-config-spacefast.js +70 -0
  130. package/dist/contracts/space-config.d.ts +177 -90
  131. package/dist/contracts/space-config.js +77 -92
  132. package/dist/contracts/spaces.d.ts +132 -24
  133. package/dist/contracts/spaces.js +77 -13
  134. package/dist/contracts/superadmin-connectors.d.ts +371 -0
  135. package/dist/contracts/superadmin-connectors.js +61 -0
  136. package/dist/contracts/superadmin-emails.d.ts +1 -1
  137. package/dist/contracts/superadmin-emails.js +1 -1
  138. package/dist/contracts/superadmin-entities.d.ts +105 -0
  139. package/dist/contracts/superadmin-entities.js +64 -0
  140. package/dist/contracts/superadmin-runtime.d.ts +35 -116
  141. package/dist/contracts/superadmin-runtime.js +13 -69
  142. package/dist/contracts/superadmin-search.d.ts +12 -14
  143. package/dist/contracts/superadmin-search.js +2 -2
  144. package/dist/contracts/superadmin-spaces.d.ts +15 -72
  145. package/dist/contracts/superadmin-spaces.js +2 -7
  146. package/dist/contracts/superadmin-teams.d.ts +12 -0
  147. package/dist/contracts/superadmin-teams.js +7 -1
  148. package/dist/contracts/superadmin-tenants.d.ts +44 -16
  149. package/dist/contracts/superadmin.d.ts +2 -2
  150. package/dist/contracts/tags.d.ts +12 -12
  151. package/dist/contracts/teams.d.ts +29 -1
  152. package/dist/contracts/teams.js +24 -2
  153. package/dist/contracts/tenants.d.ts +98 -0
  154. package/dist/contracts/tenants.js +20 -0
  155. package/dist/contracts/transfers.d.ts +92 -0
  156. package/dist/contracts/transfers.js +37 -0
  157. package/dist/contracts/usage.d.ts +9 -1
  158. package/dist/contracts/usage.js +2 -0
  159. package/dist/contracts/visual-review.d.ts +448 -0
  160. package/dist/contracts/visual-review.js +156 -0
  161. package/dist/contracts/wordpress-php-toolkit.json +9 -0
  162. package/dist/contracts/work-mode.d.ts +24 -0
  163. package/dist/contracts/work-mode.js +17 -0
  164. package/dist/contracts/wp-cli.d.ts +66 -0
  165. package/dist/contracts/wp-cli.js +68 -0
  166. package/dist/contracts/zero-catalog.d.ts +29 -0
  167. package/dist/contracts/zero-catalog.js +55 -0
  168. package/dist/contracts/zero-platform-abilities.generated.d.ts +31 -0
  169. package/dist/contracts/zero-platform-abilities.generated.js +373 -0
  170. package/dist/contracts/zero-spacefast.d.ts +444 -0
  171. package/dist/contracts/zero-spacefast.js +149 -0
  172. package/dist/contracts/zero-types.d.ts +47 -0
  173. package/dist/contracts/zero-types.js +263 -0
  174. package/dist/contracts/zero.d.ts +781 -14
  175. package/dist/contracts/zero.js +204 -10
  176. package/dist/dashboard-paths/index.d.ts +2 -2
  177. package/dist/dashboard-paths/route-reservations.generated.d.ts +2 -2
  178. package/dist/dashboard-paths/route-reservations.generated.js +5 -0
  179. package/dist/docs/agent-prose.d.ts +1 -1
  180. package/dist/docs/agent-prose.js +15 -18
  181. package/dist/docs/agent-setup.d.ts +1 -1
  182. package/dist/docs/agent-setup.js +5 -13
  183. package/dist/docs/catalog.d.ts +64 -28
  184. package/dist/docs/catalog.js +155 -28
  185. package/dist/docs/error-docs.d.ts +361 -17
  186. package/dist/docs/error-docs.js +365 -21
  187. package/dist/docs/reference-urls.js +1 -1
  188. package/dist/docs/skills.d.ts +84 -84
  189. package/dist/docs/skills.js +66 -47
  190. package/dist/docs/start-prompts.d.ts +14 -0
  191. package/dist/docs/start-prompts.js +20 -0
  192. package/dist/utils/account-labels.d.ts +7 -0
  193. package/dist/utils/account-labels.js +15 -0
  194. package/dist/utils/auth.d.ts +1 -0
  195. package/dist/utils/auth.js +1 -0
  196. package/dist/utils/credential-policy.d.ts +22 -1
  197. package/dist/utils/credential-policy.js +55 -6
  198. package/dist/utils/local-space-state.d.ts +7 -0
  199. package/dist/utils/local-space-state.js +7 -0
  200. package/dist/utils/logger.d.ts +34 -0
  201. package/dist/utils/logger.js +144 -0
  202. package/dist/utils/page-routes.d.ts +9 -0
  203. package/dist/utils/page-routes.js +82 -0
  204. package/dist/utils/pages.d.ts +2 -0
  205. package/dist/utils/pages.js +7 -0
  206. package/dist/utils/publish-form-data.d.ts +2 -0
  207. package/dist/utils/publish-form-data.js +2 -0
  208. package/dist/utils/publish-policy-spacefast.d.ts +13 -0
  209. package/dist/utils/publish-policy-spacefast.js +117 -0
  210. package/dist/utils/publish-policy.d.ts +22 -16
  211. package/dist/utils/publish-policy.fixtures.json +15 -0
  212. package/dist/utils/publish-policy.js +62 -139
  213. package/dist/utils/query-client.js +9 -1
  214. package/dist/utils/runtime-upload.d.ts +4 -0
  215. package/dist/utils/runtime-upload.js +5 -0
  216. package/dist/utils/space-config.d.ts +2 -3
  217. package/dist/utils/space-config.js +1 -1
  218. package/dist/utils/uploaded-source.d.ts +4 -0
  219. package/dist/utils/uploaded-source.js +12 -0
  220. package/dist/visual-review.d.ts +4 -0
  221. package/dist/visual-review.js +208 -0
  222. package/dist/vocabulary.d.ts +38 -0
  223. package/dist/vocabulary.js +55 -0
  224. package/package.json +7 -2
  225. package/dist/agents/registry/deeplink-probes.d.ts +0 -23
  226. package/dist/agents/registry/deeplink-probes.js +0 -18
@@ -1,11 +1,27 @@
1
1
  import { DOCS_BASE_URL } from "../config/domains.js";
2
2
  const BOTH_RUNTIMES = ["local", "hosted"];
3
3
  const PUBLISH_CONTINUATION_INSTRUCTIONS = [
4
- "If `publish.result.status` is `publishing`, call `operation_status` with `publish.result.job.poll.operationId`.",
4
+ "For authenticated `publish`, set a unique `requestId` before the first call. Reuse it only with the same input after uncertainty.",
5
+ "If `publish.result.status` is `publishing`, call `operation_status`. Use `publish.result.job.poll.url` when present. Otherwise, use `publish.result.job.poll.operationId`.",
5
6
  "Call `operation_status` again only while `operation_status.result.done` is false.",
7
+ "Wait two seconds between publish status reads.",
6
8
  "Continue only when `operation_status.result.status` is `succeeded`.",
7
9
  "Report `failed` or `canceled` and stop.",
8
10
  ];
11
+ const UNCLAIMED_PUBLISH_VERIFICATION = "If `publish.result.receipt.claim` is present, use the completed publish receipt as verification. Do not call `show_space`. The user must claim the Space before you open a detailed view.";
12
+ const EXECUTE_CONTINUATION_INSTRUCTIONS = [
13
+ "Before editing an existing Space, read `get_work_mode`. If mode is null, open `show_work_mode` and wait for the user's choice.",
14
+ "In vibe mode, handle routine source steps internally. Disable configured automatic deployment before committing. Build with `{preview:false,channel:null}`.",
15
+ "Show the exact ready version as a visual preview. Request publishing approval separately. Do not show code or diff Apps unless asked.",
16
+ "In code mode, show the existing files, diffs, commit history, and build logs for review. Reuse the saved mode on later requests.",
17
+ "Describe each selected path with `tools.describe.tool({ path: item.path })`. Read `inputTypeScript` and `outputTypeScript` before calling it.",
18
+ "Check `result.ok`. The HTTP body is `result.data`; a Spacefast JSON success envelope contains its payload at `result.data.data`.",
19
+ "If `execute` pauses, follow its `resumePrompt`.",
20
+ "For an MCP App approval, call `resume_execution` with only the same `executionId` to open the card.",
21
+ "Wait for the card's user message before calling it again. Browser approval also resumes with only `executionId` after the user acts.",
22
+ "For an On-Device form approval, send the requested action and content only after the user approves.",
23
+ "Do not start another program. `resume_execution` continues the saved program.",
24
+ ];
9
25
  /** Canonical agent workflows shared by MCP tools, prompts, resources, and recipe docs. */
10
26
  export const SPACEFAST_SKILLS = [
11
27
  {
@@ -15,7 +31,7 @@ export const SPACEFAST_SKILLS = [
15
31
  whenToUse: "Use when the user wants a new website built, improved, or launched.",
16
32
  keywords: ["create", "website", "design", "build", "responsive", "launch", "publish"],
17
33
  runtimes: BOTH_RUNTIMES,
18
- tools: ["publish", "operation_status", "show_space_deployments"],
34
+ tools: ["publish", "operation_status", "show_space"],
19
35
  docs: ["quickstart", "publishing"],
20
36
  instructions: [
21
37
  "Use the user's brief. Infer optional design choices from the content and workspace.",
@@ -28,12 +44,13 @@ export const SPACEFAST_SKILLS = [
28
44
  ...PUBLISH_CONTINUATION_INSTRUCTIONS,
29
45
  ],
30
46
  verification: [
31
- "Call `show_space_deployments` with `space: publish.result.receipt.space.id`. Confirm that the intended version is ready and current.",
47
+ UNCLAIMED_PUBLISH_VERIFICATION,
48
+ 'If `publish.result.receipt.claim` is absent, call `show_space` with `request.view: "deployments"` and `request.input.space: publish.result.receipt.space.id`. Confirm that the intended version is ready and current.',
32
49
  "If the deployment failed or stalled, report its stable error code and actionable diagnostics.",
33
- "Open the live URL. Verify the main page, navigation, assets, responsive layout, and primary call to action.",
50
+ "For a claimed Space, open its access URL. Verify the main page, navigation, assets, responsive layout, and primary call to action.",
34
51
  ],
35
52
  runtimeNotes: {
36
- local: "On-Device can work directly inside the configured local workspace root and publish a local build path.",
53
+ local: "On Linux, On-Device can publish a build path relative to the configured workspace root. On other systems, publish new artifacts inline or use a permitted CLI or HTTP upload.",
37
54
  hosted: "Hosted has no filesystem. Generate small files in the client and publish them inline, or use catalog manifest and import operations for larger artifacts.",
38
55
  },
39
56
  prompt: true,
@@ -50,7 +67,7 @@ export const SPACEFAST_SKILLS = [
50
67
  whenToUse: "Use when the artifact already exists and the user wants it published or updated.",
51
68
  keywords: ["publish", "deploy", "live", "verify", "version", "claim"],
52
69
  runtimes: BOTH_RUNTIMES,
53
- tools: ["publish", "operation_status", "show_space_deployments"],
70
+ tools: ["publish", "operation_status", "show_space"],
54
71
  docs: ["publishing", "workflow/publish-receipt", "workflow/secret-handling"],
55
72
  instructions: [
56
73
  "Identify the actual publish root or build output. Run the real build first when the source tree is not the artifact.",
@@ -60,9 +77,10 @@ export const SPACEFAST_SKILLS = [
60
77
  "Never expose a raw claim credential. Never ask the user to paste one.",
61
78
  ],
62
79
  verification: [
63
- "Call `show_space_deployments` with `space: publish.result.receipt.space.id`. Confirm that the intended version is ready and current.",
80
+ UNCLAIMED_PUBLISH_VERIFICATION,
81
+ 'If `publish.result.receipt.claim` is absent, call `show_space` with `request.view: "deployments"` and `request.input.space: publish.result.receipt.space.id`. Confirm that the intended version is ready and current.',
64
82
  "Report the stable error code and actionable diagnostics when the deployment failed or stalled.",
65
- "Open the live URL. Verify representative content and assets before reporting success.",
83
+ "For a claimed Space, open its access URL. Verify representative content and assets before reporting success.",
66
84
  ],
67
85
  runtimeNotes: {
68
86
  local: "Publish a bounded local path; locally custodied claim credentials are reused automatically.",
@@ -114,20 +132,24 @@ export const SPACEFAST_SKILLS = [
114
132
  whenToUse: "Use when reviewers need a realistic preview before a change goes live.",
115
133
  keywords: ["preview", "channel", "branch", "pull request", "review", "private"],
116
134
  runtimes: BOTH_RUNTIMES,
117
- tools: ["publish", "operation_status", "show_space_deployments", "execute", "resume_execution"],
135
+ tools: ["publish", "operation_status", "show_space", "execute", "resume_execution"],
118
136
  docs: ["builds", "access-control"],
119
137
  instructions: [
120
- "Call `publish` once for an explicit non-production space or channel. Do not change the production target.",
138
+ "Use `publish` for a separate preview Space. Pass its `spaceId`, or set `createNew: true` when the user requests a new Space.",
139
+ "For a source preview in an existing Space, describe `createSpaceBuild` through `execute`. Use a repository input pinned to the saved commit.",
140
+ "Set `body.target` to `{ preview: true, channel: null }`. Set the described `Idempotency-Key` header and keep `wait` false.",
141
+ "Poll `getBuild` until it succeeds or fails. A build response does not prove that a version is live.",
142
+ "Direct `publish` has no channel input. Keep the production target unchanged.",
121
143
  ...PUBLISH_CONTINUATION_INSTRUCTIONS,
122
144
  "Keep the preview private unless the user requests sharing.",
123
145
  "For reviewer access, use one bounded `execute` program. Read current access, create the narrowest Link, then read it again.",
124
- "If `execute` pauses, follow its `resumePrompt`. Then call `resume_execution` with the returned `executionId`.",
125
- "Do not start another `execute` program.",
146
+ ...EXECUTE_CONTINUATION_INSTRUCTIONS,
126
147
  "Label the preview with its branch, change, or pull request. Report what is out of scope.",
127
148
  ],
128
149
  verification: [
129
- "Call `show_space_deployments` for each affected Space. Confirm that the preview changed. Confirm that production did not change.",
130
- "Test the reviewer Link in a signed-out context. Report its scope and expiry.",
150
+ UNCLAIMED_PUBLISH_VERIFICATION,
151
+ 'If `publish.result.receipt.claim` is absent, call `show_space` with `request.view: "deployments"` and `request.input.space` set to each affected Space. Confirm that the preview changed. Confirm that production did not change.',
152
+ "If `publish.result.receipt.claim` is absent, test the reviewer Link in a signed-out context. Report its scope and expiry.",
131
153
  ],
132
154
  recipe: {
133
155
  slug: "recipes/preview-channels",
@@ -146,18 +168,17 @@ export const SPACEFAST_SKILLS = [
146
168
  docs: ["anonymous-publish", "workflow/continue-after-claim", "workflow/secret-handling"],
147
169
  instructions: [
148
170
  "Point the user to the claim action in the publish card and state its expiry. Never copy the claim credential into model text.",
149
- "When account credentials are available, use one bounded `execute` program. Search and describe the claim operation before calling it.",
150
- "Pass only the required team ID and expected space ID.",
151
- "After the claim resumes, read the space in the same program. Return its owner and claim state.",
152
- "If `execute` pauses, follow its `resumePrompt`. Then call `resume_execution` with the returned `executionId`.",
153
- "Do not start another `execute` program.",
154
- "Otherwise, ask the user to use the claim action in the publish card.",
155
- "After a browser claim, call `publish` again from On-Device. It exchanges the locally held credential without exposing it.",
171
+ "Let the user complete the claim through the publish card. The card keeps the claim credential outside model text.",
172
+ "After the claim, use one bounded `execute` program with the connected account to read the Space by its known ID.",
173
+ "Return its owner and claim state. Do not extract the saved claim key or call its exchange through `execute`.",
174
+ ...EXECUTE_CONTINUATION_INSTRUCTIONS,
175
+ "If account access is unavailable, reconnect Spacefast in the client.",
176
+ "The next requested On-Device publish exchanges the locally held credential automatically without exposing it.",
156
177
  ...PUBLISH_CONTINUATION_INSTRUCTIONS,
157
178
  ],
158
179
  verification: [
159
180
  "Confirm that the space has no claim expiry. Confirm that it belongs to the intended account or team.",
160
- "Confirm that the republish uses durable access without a raw credential.",
181
+ "When the user next requests a publish, confirm that it succeeds through the saved credential without exposing it.",
161
182
  ],
162
183
  prompt: true,
163
184
  },
@@ -168,17 +189,16 @@ export const SPACEFAST_SKILLS = [
168
189
  whenToUse: "Use when the current live version is broken and a prior healthy version is known or discoverable.",
169
190
  keywords: ["rollback", "revert", "version", "incident", "restore"],
170
191
  runtimes: BOTH_RUNTIMES,
171
- tools: ["show_space_deployments", "execute", "resume_execution"],
192
+ tools: ["show_space", "execute", "resume_execution"],
172
193
  docs: ["versions-and-rollback"],
173
194
  instructions: [
174
- "Call `show_space_deployments`. Select a known-good ready version that is older than the current version.",
195
+ 'Call `show_space` with `request.view: "deployments"` and `request.input.space` set to the affected Space. Select a known-good ready version that is older than the current version.',
175
196
  "Use one bounded `execute` program. Search and describe the version promotion operation before calling it.",
176
197
  "Read the live pointer, promote the selected version, then read the pointer again in the same program.",
177
- "If `execute` pauses, follow its `resumePrompt`. Then call `resume_execution` with the returned `executionId`.",
178
- "Do not start another `execute` program.",
198
+ ...EXECUTE_CONTINUATION_INSTRUCTIONS,
179
199
  ],
180
200
  verification: [
181
- "Call `show_space_deployments`. Confirm that the selected version is current and ready.",
201
+ 'Call `show_space` with `request.view: "deployments"` and `request.input.space` set to the affected Space. Confirm that the selected version is current and ready.',
182
202
  "Open the live URL. Verify that the failing path or behavior works again.",
183
203
  ],
184
204
  prompt: true,
@@ -190,19 +210,18 @@ export const SPACEFAST_SKILLS = [
190
210
  whenToUse: "Use when the user owns a domain they want a Spacefast space to serve.",
191
211
  keywords: ["domain", "dns", "tls", "https", "cname", "custom"],
192
212
  runtimes: BOTH_RUNTIMES,
193
- tools: ["show_space_domains", "execute", "resume_execution"],
213
+ tools: ["show_space", "execute", "resume_execution"],
194
214
  docs: ["custom-domains", "recipes/migrate-dns"],
195
215
  instructions: [
196
- "Call `show_space_domains`. Read the current domain, DNS, and certificate state.",
216
+ 'Call `show_space` with `request.view: "domains"` and `request.input.space` set to the affected Space. Read the current domain, DNS, and certificate state.',
197
217
  "If setup is required, use one bounded `execute` program. Search and describe the add or assign operation before calling it.",
198
218
  "Read the domain again in the same program after the mutation resumes.",
199
- "If `execute` pauses, follow its `resumePrompt`. Then call `resume_execution` with the returned `executionId`.",
200
- "Do not start another `execute` program.",
219
+ ...EXECUTE_CONTINUATION_INSTRUCTIONS,
201
220
  "Return the exact DNS records from Spacefast. Do not claim that Spacefast changed third-party DNS.",
202
221
  "Keep the existing production hostname until the custom domain is ready.",
203
222
  ],
204
223
  verification: [
205
- "After the external DNS change, call `show_space_domains`. Report the current verification state.",
224
+ 'After the external DNS change, call `show_space` with `request.view: "domains"` and `request.input.space` set to the affected Space. Report the current verification state.',
206
225
  "Open the HTTPS URL only after DNS and certificate states are ready. Verify representative content.",
207
226
  ],
208
227
  prompt: true,
@@ -219,7 +238,7 @@ export const SPACEFAST_SKILLS = [
219
238
  whenToUse: "Use for moved pages, canonical host paths, and intentional permanent or temporary redirects.",
220
239
  keywords: ["redirect", "rewrite", "routing", "301", "302", "path"],
221
240
  runtimes: BOTH_RUNTIMES,
222
- tools: ["publish", "operation_status", "show_space_deployments"],
241
+ tools: ["publish", "operation_status", "show_space"],
223
242
  docs: ["redirects"],
224
243
  instructions: [
225
244
  "Inspect existing routing rules, then add the smallest non-conflicting rules to `_redirects` at the publish root.",
@@ -229,9 +248,10 @@ export const SPACEFAST_SKILLS = [
229
248
  ...PUBLISH_CONTINUATION_INSTRUCTIONS,
230
249
  ],
231
250
  verification: [
232
- "Call `show_space_deployments` with `space: publish.result.receipt.space.id`. Confirm that the new version is current and ready.",
233
- "Request representative old and new paths and confirm the exact status and Location header.",
234
- "Verify the final target serves successfully and unrelated assets are not redirected.",
251
+ UNCLAIMED_PUBLISH_VERIFICATION,
252
+ 'If `publish.result.receipt.claim` is absent, call `show_space` with `request.view: "deployments"` and `request.input.space: publish.result.receipt.space.id`. Confirm that the new version is current and ready.',
253
+ "If `publish.result.receipt.claim` is absent, request representative old and new paths and confirm the exact status and Location header.",
254
+ "If `publish.result.receipt.claim` is absent, verify the final target serves successfully and unrelated assets are not redirected.",
235
255
  ],
236
256
  recipe: {
237
257
  slug: "recipes/redirects",
@@ -246,20 +266,19 @@ export const SPACEFAST_SKILLS = [
246
266
  whenToUse: "Use when an existing production domain must move to Spacefast.",
247
267
  keywords: ["dns", "migrate", "cutover", "domain", "downtime", "certificate"],
248
268
  runtimes: BOTH_RUNTIMES,
249
- tools: ["show_space_domains", "execute", "resume_execution"],
269
+ tools: ["show_space", "execute", "resume_execution"],
250
270
  docs: ["custom-domains"],
251
271
  instructions: [
252
272
  "Inventory the current authoritative DNS records. Lower the TTL before cutover when the provider and timing permit it.",
253
- "Call `show_space_domains`. Read the current DNS and certificate state.",
273
+ 'Call `show_space` with `request.view: "domains"` and `request.input.space` set to the affected Space. Read the current DNS and certificate state.',
254
274
  "If setup is required, use one bounded `execute` program. Search and describe the add or assign operation before calling it.",
255
275
  "Read the domain again in the same program after the mutation resumes.",
256
- "If `execute` pauses, follow its `resumePrompt`. Then call `resume_execution` with the returned `executionId`.",
257
- "Do not start another `execute` program.",
276
+ ...EXECUTE_CONTINUATION_INSTRUCTIONS,
258
277
  "Create the returned DNS records at the provider. Keep the previous origin available during propagation.",
259
278
  "Cut over only after the expected content and TLS state are ready.",
260
279
  ],
261
280
  verification: [
262
- "Call `show_space_domains`. Confirm that DNS and certificate states are ready.",
281
+ 'Call `show_space` with `request.view: "domains"` and `request.input.space` set to the affected Space. Confirm that DNS and certificate states are ready.',
263
282
  "Check more than one resolver. Confirm that the certificate matches the final hostname.",
264
283
  "Open the public HTTPS URL. Verify representative content before removing rollback records.",
265
284
  ],
@@ -276,18 +295,19 @@ export const SPACEFAST_SKILLS = [
276
295
  whenToUse: "Use when a build, finalize, activation, or live serving step fails or stalls.",
277
296
  keywords: ["debug", "failed", "build", "logs", "diagnose", "stalled"],
278
297
  runtimes: BOTH_RUNTIMES,
279
- tools: ["show_space_deployments", "execute", "publish", "operation_status"],
298
+ tools: ["show_space", "execute", "resume_execution", "publish", "operation_status"],
280
299
  docs: ["troubleshooting"],
281
300
  instructions: [
282
- "Call `show_space_deployments`. Read the failed version, build state, stable error code, and diagnostics.",
301
+ 'Call `show_space` with `request.view: "deployments"` and `request.input.space` set to the affected Space. Read the failed version, build state, stable error code, and diagnostics.',
283
302
  "If more detail is required, use one bounded `execute` program. Read only the required build logs or version data.",
284
303
  "Apply the smallest fix supported by the evidence. Run the real build.",
285
304
  "Call `publish` once with the fixed output.",
286
305
  ...PUBLISH_CONTINUATION_INSTRUCTIONS,
287
306
  ],
288
307
  verification: [
289
- "Call `show_space_deployments` with `space: publish.result.receipt.space.id`. Confirm that the new version is current and ready.",
290
- "Open the affected live path. Verify that the concrete failure does not occur.",
308
+ UNCLAIMED_PUBLISH_VERIFICATION,
309
+ 'If `publish.result.receipt.claim` is absent, call `show_space` with `request.view: "deployments"` and `request.input.space: publish.result.receipt.space.id`. Confirm that the new version is current and ready.',
310
+ "If `publish.result.receipt.claim` is absent, open the affected live path. Verify that the concrete failure does not occur.",
291
311
  ],
292
312
  prompt: true,
293
313
  },
@@ -304,8 +324,7 @@ export const SPACEFAST_SKILLS = [
304
324
  "Use one bounded `execute` program. Search and describe the access operations before calling them.",
305
325
  "Read current access. Apply the narrowest change for one explicit access intent. Read the resulting access state.",
306
326
  "Run the matching access check in the same program after the mutation resumes.",
307
- "If `execute` pauses, follow its `resumePrompt`. Then call `resume_execution` with the returned `executionId`.",
308
- "Do not start another `execute` program.",
327
+ ...EXECUTE_CONTINUATION_INSTRUCTIONS,
309
328
  "Show new Link or machine secrets only to the requesting user. Never store them in logs or committed files.",
310
329
  ],
311
330
  verification: [
@@ -22,6 +22,12 @@ export type StartShippingIntent = keyof typeof START_SHIPPING_INTENTS;
22
22
  * private handoff link.
23
23
  */
24
24
  export declare function teamContextLine(teamName: string): string;
25
+ /**
26
+ * The existing space a copied prompt targets. The hostname is the identifier
27
+ * an agent can act on directly — the CLI and MCP tools both resolve a space
28
+ * from the domain it serves.
29
+ */
30
+ export declare function spaceContextLine(host: string): string;
25
31
  /**
26
32
  * How a /start handoff prompt ends. The private-prompt builder's default
27
33
  * closing points back at "the page task" and "the references above", which is
@@ -37,6 +43,14 @@ export declare const START_HANDOFF_CLOSING = "Then ask me what to publish, and w
37
43
  */
38
44
  export declare function terminalLoginCommand(handoffUrl: string): string;
39
45
  export declare const TERMINAL_LOGIN_COMMAND_DISPLAY: string;
46
+ /**
47
+ * The same paste-to-login, chained into the command the visitor actually came
48
+ * for. One paste signs the CLI in with the one-use link and then runs the
49
+ * follow-on — a surface offering "set up my git remote" should not make
50
+ * signing in a separate errand.
51
+ */
52
+ export declare function terminalLoginThenCommand(handoffUrl: string, command: string): string;
53
+ export declare function terminalLoginThenCommandDisplay(command: string): string;
40
54
  /**
41
55
  * Joins a base prompt with a shipping intent. An empty base means the copy
42
56
  * carries a handoff link that serves the setup itself, so the intent stands
@@ -32,6 +32,14 @@ export const START_SHIPPING_INTENTS = {
32
32
  export function teamContextLine(teamName) {
33
33
  return `Use my Spacefast team: ${teamName}.`;
34
34
  }
35
+ /**
36
+ * The existing space a copied prompt targets. The hostname is the identifier
37
+ * an agent can act on directly — the CLI and MCP tools both resolve a space
38
+ * from the domain it serves.
39
+ */
40
+ export function spaceContextLine(host) {
41
+ return `Publish to my existing space: ${host}.`;
42
+ }
35
43
  /**
36
44
  * How a /start handoff prompt ends. The private-prompt builder's default
37
45
  * closing points back at "the page task" and "the references above", which is
@@ -49,6 +57,18 @@ export function terminalLoginCommand(handoffUrl) {
49
57
  return `printf '%s\\n' '${handoffUrl}' | sf login --handoff`;
50
58
  }
51
59
  export const TERMINAL_LOGIN_COMMAND_DISPLAY = terminalLoginCommand("<one-use link>");
60
+ /**
61
+ * The same paste-to-login, chained into the command the visitor actually came
62
+ * for. One paste signs the CLI in with the one-use link and then runs the
63
+ * follow-on — a surface offering "set up my git remote" should not make
64
+ * signing in a separate errand.
65
+ */
66
+ export function terminalLoginThenCommand(handoffUrl, command) {
67
+ return `${terminalLoginCommand(handoffUrl)} && ${command}`;
68
+ }
69
+ export function terminalLoginThenCommandDisplay(command) {
70
+ return terminalLoginThenCommand("<one-use link>", command);
71
+ }
52
72
  /**
53
73
  * Joins a base prompt with a shipping intent. An empty base means the copy
54
74
  * carries a handoff link that serves the setup itself, so the intent stands
@@ -0,0 +1,7 @@
1
+ type AccountIdentity = {
2
+ name?: string | null;
3
+ email: string;
4
+ };
5
+ export declare function getAccountDisplayName(account: AccountIdentity): string;
6
+ export declare function getAccountSecondaryLabel(account: AccountIdentity): string;
7
+ export {};
@@ -0,0 +1,15 @@
1
+ // Accounts carry a name and an email, no handle. The display name is the name
2
+ // with a presentable email-derived fallback; the secondary line is the email,
3
+ // shown only when it adds information the display name does not already carry.
4
+ export function getAccountDisplayName(account) {
5
+ const name = account.name?.trim();
6
+ if (name)
7
+ return name;
8
+ const email = account.email.trim();
9
+ const at = email.indexOf("@");
10
+ return at > 0 ? email.slice(0, at) : email;
11
+ }
12
+ export function getAccountSecondaryLabel(account) {
13
+ const email = account.email.trim();
14
+ return email === getAccountDisplayName(account) ? "" : email;
15
+ }
@@ -1,5 +1,6 @@
1
1
  export declare const SPACEFAST_TENANT_HEADER = "x-spacefast-tenant-id";
2
2
  export declare const SPACEFAST_CLIENT_HEADER = "x-spacefast-client";
3
3
  export declare const SPACEFAST_CLI_DEVICE_CLIENT_ID = "spacefast-cli";
4
+ export declare const SPACEFAST_MCP_DEVICE_CLIENT_ID = "spacefast-mcp";
4
5
  export declare function normalizeDeviceUserCode(value: string): string;
5
6
  export declare function formatDeviceUserCode(value: string): string;
@@ -1,6 +1,7 @@
1
1
  export const SPACEFAST_TENANT_HEADER = "x-spacefast-tenant-id";
2
2
  export const SPACEFAST_CLIENT_HEADER = "x-spacefast-client";
3
3
  export const SPACEFAST_CLI_DEVICE_CLIENT_ID = "spacefast-cli";
4
+ export const SPACEFAST_MCP_DEVICE_CLIENT_ID = "spacefast-mcp";
4
5
  export function normalizeDeviceUserCode(value) {
5
6
  return value.replace(/[^a-z0-9]/gi, "").toUpperCase();
6
7
  }
@@ -21,9 +21,15 @@ export type PolicyAuthorizeInput = {
21
21
  * scope grants, derived from the one scope⇄action table so an API-key preset
22
22
  * and an OAuth client of the same tier can never drift apart.
23
23
  */
24
- export declare const publishActions: ("teams:read" | "teams:create" | "spaces:read" | "spaces:write" | "spaces:rename" | "domains:read" | "spaces:publish" | "builds:trigger" | "*" | "spaces:create" | "spaces:delete" | "spaces:transfer" | "spaces:export" | "spaces:import" | "spaces:policy.write" | "versions:read" | "versions:promote" | "versions:delete" | "versions:download" | "domains:create" | "domains:verify" | "domains:assign" | "domains:bind" | "domains:delete" | "domains:dns.write" | "domains:dns.credentials.write" | "domains:purchase" | "webhooks:read" | "webhooks:write" | "builds:read" | "builds:create" | "variables:read" | "variables:write" | "tenants:read" | "tenants:write" | "principals:read" | "principals:write" | "infrastructure:read" | "teams:write" | "teams:members.write" | "billing:read" | "billing:write" | "tokens:read" | "tokens:create" | "tokens:revoke" | "runtime:manage")[];
24
+ export declare const publishActions: ("teams:read" | "teams:create" | "teams:members.write" | "spaces:read" | "spaces:write" | "spaces:rename" | "spaces:delete" | "versions:download" | "domains:read" | "connectors:read" | "connectors:write" | "connectors:execute" | "spaces:publish" | "builds:trigger" | "*" | "spaces:create" | "spaces:transfer" | "spaces:export" | "spaces:import" | "spaces:policy.write" | "versions:read" | "versions:promote" | "versions:delete" | "domains:create" | "domains:verify" | "domains:assign" | "domains:bind" | "domains:delete" | "domains:dns.write" | "domains:dns.credentials.write" | "domains:purchase" | "webhooks:read" | "webhooks:write" | "builds:read" | "builds:create" | "variables:read" | "variables:write" | "tenants:read" | "tenants:write" | "principals:read" | "principals:write" | "infrastructure:read" | "teams:write" | "billing:read" | "billing:write" | "tokens:read" | "tokens:create" | "tokens:revoke" | "runtime:manage")[];
25
25
  /** The canonical policy resource for a team principal's subtree. */
26
26
  export declare function teamResource(input: PolicyCompileInput): string;
27
+ /** The customer-resource collection managed by one marked partner team. */
28
+ export declare function partnerResource(input: PolicyCompileInput): string;
29
+ /** One external customer inside a marked partner team's managed collection. */
30
+ export declare function partnerPrincipalResource(input: PolicyCompileInput & {
31
+ principalId: string;
32
+ }): string;
27
33
  export declare function compileApiKeyPreset(preset: ApiKeyPreset, input: PolicyCompileInput): ApiCredentialPolicy;
28
34
  /**
29
35
  * Expand a named API-key preset into the finite permissions sent on the public
@@ -38,6 +44,7 @@ export declare function compileTenantRootedPolicy(input: {
38
44
  }): ApiCredentialPolicy;
39
45
  export declare function compilePartnerPrincipalPolicy(input: {
40
46
  tenantId: string;
47
+ teamId?: string | undefined;
41
48
  normalizedPrincipalId: string;
42
49
  }): ApiCredentialPolicy;
43
50
  export declare function compileTeamRolePolicy(input: PolicyCompileInput & {
@@ -99,5 +106,19 @@ export declare function grantedPrincipalsFromPolicy(policy: ApiCredentialPolicy,
99
106
  spaceId: string;
100
107
  })[];
101
108
  };
109
+ /**
110
+ * Partner-managed customer collections reached by a policy in one tenant.
111
+ * A collection grant covers every customer under that team; a principal grant
112
+ * covers only the named customer. Actions are evaluated separately.
113
+ */
114
+ export declare function grantedPartnerCollectionsFromPolicy(policy: ApiCredentialPolicy, input: {
115
+ tenantId: string;
116
+ }): {
117
+ teamIds: string[];
118
+ principals: {
119
+ teamId: string;
120
+ principalId: string;
121
+ }[];
122
+ };
102
123
  export declare function policyReaches(policy: ApiCredentialPolicy, resourceBase: string): boolean;
103
124
  export {};
@@ -24,6 +24,17 @@ const domainActions = oauthScopeActionsFor("domains:write");
24
24
  export function teamResource(input) {
25
25
  return `stt://tenant/${input.tenantId}/principal/team/${input.teamId}/*`;
26
26
  }
27
+ /** The customer-resource collection managed by one marked partner team. */
28
+ export function partnerResource(input) {
29
+ return `stt://tenant/${input.tenantId}/partner/${input.teamId}/*`;
30
+ }
31
+ /** One external customer inside a marked partner team's managed collection. */
32
+ export function partnerPrincipalResource(input) {
33
+ if (input.principalId.includes("*") || input.principalId.includes("/")) {
34
+ throw new Error("Partner principal id contains a reserved policy character.");
35
+ }
36
+ return `stt://tenant/${input.tenantId}/partner/${input.teamId}/principal/${input.principalId}/*`;
37
+ }
27
38
  function spaceResource(input) {
28
39
  return `stt://tenant/${input.tenantId}/space/${input.spaceId}`;
29
40
  }
@@ -65,8 +76,8 @@ function presetActions(preset) {
65
76
  case "team_admin":
66
77
  return ["*"];
67
78
  // The partner tier: everything a partner needs to run its own customers'
68
- // spaces on our infrastructure, and nothing that mints credentials, edits
69
- // team membership, or moves money.
79
+ // spaces on our infrastructure, including tenant credentials. Billing and
80
+ // team membership remain outside partner administration.
70
81
  case "partner_admin":
71
82
  return [
72
83
  "tenants:read",
@@ -75,12 +86,15 @@ function presetActions(preset) {
75
86
  "principals:write",
76
87
  "infrastructure:read",
77
88
  "spaces:policy.write",
78
- ...spaceAdminActions,
89
+ ...spaceAdminActions.filter((action) => action !== "teams:read"),
79
90
  ...domainActions,
80
91
  "webhooks:read",
81
92
  "webhooks:write",
82
- "teams:read",
83
- "billing:read",
93
+ "variables:read",
94
+ "variables:write",
95
+ "tokens:read",
96
+ "tokens:create",
97
+ "tokens:revoke",
84
98
  ];
85
99
  }
86
100
  throw new Error("Unsupported API key preset.");
@@ -96,6 +110,13 @@ export function compilePartnerPrincipalPolicy(input) {
96
110
  if (input.normalizedPrincipalId.includes("*") || input.normalizedPrincipalId.includes("/")) {
97
111
  throw new Error("Partner principal id contains a reserved policy character.");
98
112
  }
113
+ const resource = input.teamId
114
+ ? partnerPrincipalResource({
115
+ tenantId: input.tenantId,
116
+ teamId: input.teamId,
117
+ principalId: input.normalizedPrincipalId,
118
+ })
119
+ : `stt://tenant/${input.tenantId}/principal/external/${input.normalizedPrincipalId}/*`;
99
120
  return allowPolicy([
100
121
  "spaces:read",
101
122
  "spaces:create",
@@ -110,7 +131,7 @@ export function compilePartnerPrincipalPolicy(input) {
110
131
  "builds:create",
111
132
  "variables:read",
112
133
  "variables:write",
113
- ], [`stt://tenant/${input.tenantId}/principal/external/${input.normalizedPrincipalId}/*`]);
134
+ ], [resource]);
114
135
  }
115
136
  export function compileTeamRolePolicy(input) {
116
137
  switch (input.role) {
@@ -296,6 +317,34 @@ export function grantedPrincipalsFromPolicy(policy, input) {
296
317
  ],
297
318
  };
298
319
  }
320
+ /**
321
+ * Partner-managed customer collections reached by a policy in one tenant.
322
+ * A collection grant covers every customer under that team; a principal grant
323
+ * covers only the named customer. Actions are evaluated separately.
324
+ */
325
+ export function grantedPartnerCollectionsFromPolicy(policy, input) {
326
+ const teamIds = new Set();
327
+ const principals = new Map();
328
+ for (const statement of policy.statements) {
329
+ if (statement.effect !== "allow")
330
+ continue;
331
+ for (const resource of statement.resources) {
332
+ const parsed = parseStatticResource(resource);
333
+ if (!parsed || (parsed.tenantId !== input.tenantId && parsed.tenantId !== "*"))
334
+ continue;
335
+ if (parsed.kind === "partner") {
336
+ teamIds.add(parsed.teamId);
337
+ }
338
+ else if (parsed.kind === "partner-principal") {
339
+ principals.set(`${parsed.teamId}\0${parsed.principalId}`, {
340
+ teamId: parsed.teamId,
341
+ principalId: parsed.principalId,
342
+ });
343
+ }
344
+ }
345
+ }
346
+ return { teamIds: [...teamIds], principals: [...principals.values()] };
347
+ }
299
348
  // Whether the policy's allow statements reach a resource subtree at all. This
300
349
  // is a visibility/scoping check (404 vs 403), never an action grant.
301
350
  export function policyReaches(policy, resourceBase) {
@@ -38,6 +38,13 @@ export declare const localSpaceStateSchema: z.ZodObject<{
38
38
  pendingOperationId: z.ZodOptional<z.ZodString>;
39
39
  lastVersionUrl: z.ZodOptional<z.ZodString>;
40
40
  lastSpaceUrl: z.ZodOptional<z.ZodString>;
41
+ /**
42
+ * The directory this machine-written link was recorded for, relative (POSIX)
43
+ * to the checkout root holding it; "." for the root itself. A publish of a
44
+ * different directory under the same checkout gets its own Space rather than
45
+ * silently overwriting the one this receipt names.
46
+ */
47
+ publishRoot: z.ZodOptional<z.ZodString>;
41
48
  /** Secret per-checkout entropy used only to namespace replay-safe first publishes. */
42
49
  anonymousPublishNonce: z.ZodOptional<z.ZodString>;
43
50
  /** Unsettled first-publish mutation. Retries must reuse this exact key. */
@@ -50,6 +50,13 @@ export const localSpaceStateSchema = z.strictObject({
50
50
  pendingOperationId: z.string().min(1).optional(),
51
51
  lastVersionUrl: z.string().min(1).optional(),
52
52
  lastSpaceUrl: z.string().min(1).optional(),
53
+ /**
54
+ * The directory this machine-written link was recorded for, relative (POSIX)
55
+ * to the checkout root holding it; "." for the root itself. A publish of a
56
+ * different directory under the same checkout gets its own Space rather than
57
+ * silently overwriting the one this receipt names.
58
+ */
59
+ publishRoot: z.string().min(1).optional(),
53
60
  /** Secret per-checkout entropy used only to namespace replay-safe first publishes. */
54
61
  anonymousPublishNonce: z.string().min(32).optional(),
55
62
  /** Unsettled first-publish mutation. Retries must reuse this exact key. */
@@ -0,0 +1,34 @@
1
+ export type LogLevel = "debug" | "info" | "warn" | "error";
2
+ export type LogFields = Record<string, unknown>;
3
+ export type Logger = {
4
+ debug: (message: string, fields?: LogFields) => void;
5
+ info: (message: string, fields?: LogFields) => void;
6
+ warn: (message: string, fields?: LogFields) => void;
7
+ error: (message: string, fields?: LogFields) => void;
8
+ child: (bindings: LogFields) => Logger;
9
+ };
10
+ export type LogEmitListener = (level: LogLevel, message: string, fields?: LogFields) => void;
11
+ export type CreateLoggerOptions = {
12
+ /**
13
+ * Minimum level to emit; "silent" emits nothing. Defaults to LOG_LEVEL, else
14
+ * info in production and debug elsewhere.
15
+ */
16
+ level?: LogLevel | "silent";
17
+ /** Output shape. Defaults to json in production (or LOG_FORMAT=json), pretty elsewhere. */
18
+ format?: "json" | "pretty";
19
+ /**
20
+ * Where lines go. "auto" sends debug/info to stdout and warn/error to stderr;
21
+ * "stderr" sends everything to stderr, for processes whose stdout is a
22
+ * protocol channel (MCP stdio, CLI --json receipts).
23
+ */
24
+ stream?: "auto" | "stderr";
25
+ /** Bindings merged into every record, as with child(). */
26
+ bindings?: LogFields;
27
+ /** Observes every emitted record (e.g. Sentry fan-out). Failures are swallowed. */
28
+ onEmit?: LogEmitListener;
29
+ /** Replaces sensitive errors before console output and listener fan-out. */
30
+ projectError?: (error: Error) => LogFields | undefined;
31
+ };
32
+ export declare function createLogger(options?: CreateLoggerOptions): Logger;
33
+ /** Env-configured logger for processes that own their stdout. */
34
+ export declare const logger: Logger;