deepspace 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +247 -1
- package/README.md +18 -41
- package/dist/cli.js +1499 -1327
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -157
- package/dist/index.js +248 -326
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +4 -137
- package/dist/server.js +3 -412
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +5 -210
- package/dist/worker.js +3 -419
- package/dist/worker.js.map +1 -1
- package/features/documents/src/LibrarySidebar.tsx +6 -8
- package/features/documents/src/editor/useDocEditor.ts +3 -8
- package/features/landing/feature.json +1 -1
- package/features/messaging/src/components/chat/MessageItem.tsx +83 -34
- package/features/messaging/src/hooks/useChatChannel.ts +2 -8
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,251 @@
|
|
|
1
1
|
# deepspace
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- **Deploy no longer reads `.dev.vars`. The secret store is the only source.**
|
|
8
|
+
|
|
9
|
+
Deploy used to compare hand-edited `.dev.vars` keys against the store and
|
|
10
|
+
refuse (`secrets_not_uploaded`) or warn when they differed — a guard that
|
|
11
|
+
inferred intent from a local file. It also broke its own escape hatch: the
|
|
12
|
+
refusal pointed at `secrets upload .dev.vars` while that same deploy had
|
|
13
|
+
already written the SDK-managed block into that file, whose keys the upload
|
|
14
|
+
then rejected, with no code and no action to recover from. An agent that hit
|
|
15
|
+
it had no way forward.
|
|
16
|
+
|
|
17
|
+
`.dev.vars` keeps its real job — deploy WRITES it so `deepspace dev` sees the
|
|
18
|
+
same values — and is never read back to decide anything.
|
|
19
|
+
|
|
20
|
+
**Removed:** the `--allow-missing-secrets` flag and the `secrets_not_uploaded`
|
|
21
|
+
refusal code, which only existed to escape that guard.
|
|
22
|
+
|
|
23
|
+
Deploy now distinguishes a missing config from an explicitly created empty
|
|
24
|
+
config. A missing config regenerates the local cache without app secrets and
|
|
25
|
+
refuses before build, Git push, or upload, with an executable
|
|
26
|
+
`secrets configs create` action. An existing empty config is explicit
|
|
27
|
+
delete-all intent. The deploy server independently preserves live bindings
|
|
28
|
+
when an older client omits secret authority, making the rollout safe in both
|
|
29
|
+
directions.
|
|
30
|
+
|
|
31
|
+
Authoritative deletion is part of release finalization, not a best-effort log.
|
|
32
|
+
The server retries Cloudflare reconciliation three times and retains the
|
|
33
|
+
per-app release fence on failure. Replaying the exact deploy retries deletion
|
|
34
|
+
without issuing a second Worker activation; a release is recorded only after
|
|
35
|
+
stale bindings, including `ALLOW_DEBUG_ROUTES`, are gone.
|
|
36
|
+
|
|
37
|
+
If the original CLI process exits after that partial result, a fresh deploy key
|
|
38
|
+
can resume only when the complete Worker, secret, attribution, and source
|
|
39
|
+
lineage hash matches the live operation. The server first proves that exact
|
|
40
|
+
operation is live at Cloudflare; different input stays fenced. Malformed
|
|
41
|
+
successful Cloudflare secret-list envelopes also fail closed.
|
|
42
|
+
|
|
43
|
+
The per-app release transaction is now reserved before route registration,
|
|
44
|
+
binding auto-provisioning, or rate-limit allocation. Losing concurrent deploys
|
|
45
|
+
therefore return without renaming the production app or creating provider
|
|
46
|
+
resources. An incomplete reservation cannot activate; an exact retry may
|
|
47
|
+
atomically take ownership and finish its resolved rollback metadata. Durable
|
|
48
|
+
key aliases keep displaced processes from reclaiming the operation and replay
|
|
49
|
+
the successor after finalization; a safe pre-activation abort removes the
|
|
50
|
+
aliases with the fence. A compare-and-set transition grants exactly one request
|
|
51
|
+
permission to issue the Worker PUT. That winner is bound to a request-scoped
|
|
52
|
+
claim nonce: it can clear its own committed-but-lost claim response before the
|
|
53
|
+
PUT begins, while an uncertain concurrent request cannot clear the winner's
|
|
54
|
+
activation fence.
|
|
55
|
+
|
|
56
|
+
- **`.dev.vars` is now fully generated. Hand edits do not survive.**
|
|
57
|
+
|
|
58
|
+
The file used to be three zones — an SDK section, a hand-edited section
|
|
59
|
+
preserved across runs, and a store cache — which required a divider grammar, a
|
|
60
|
+
dotenv parser to read the file back, and reconciliation between the two
|
|
61
|
+
sources. That made `.dev.vars` a second source of truth, and historically a
|
|
62
|
+
de-facto deploy input (docs/proposals/secrets-source-of-truth.md).
|
|
63
|
+
|
|
64
|
+
Now it is a materialization: rewritten whole on every `dev`, `test`, `deploy`,
|
|
65
|
+
and `secrets pull` run from platform values plus the app's secret store, with
|
|
66
|
+
a header saying so. Nothing reads it back.
|
|
67
|
+
|
|
68
|
+
**If you hand-edited `.dev.vars`, put required values in the store before
|
|
69
|
+
updating** (`deepspace secrets set KEY=value`). The next dev/test/pull run
|
|
70
|
+
overwrites the file. There is no legacy import or compatibility path; beta
|
|
71
|
+
consumers must update their configuration.
|
|
72
|
+
|
|
73
|
+
All Wrangler environments now share the one generated `.dev.vars`. Missing
|
|
74
|
+
configs materialize as empty, so a successful refresh cannot leave stale local
|
|
75
|
+
values behind.
|
|
76
|
+
|
|
77
|
+
Also removed: `secrets upload` no longer strips a generated block (there is no
|
|
78
|
+
block to strip — uploading the generated file is not a flow; use
|
|
79
|
+
`secrets download` for backups).
|
|
80
|
+
|
|
81
|
+
### Patch Changes
|
|
82
|
+
|
|
83
|
+
- Remove stale lint suppressions from the Messaging and Documents feature
|
|
84
|
+
sources so an app containing every public feature builds without unused-rule
|
|
85
|
+
warnings.
|
|
86
|
+
- Support the maintained Node 22 (22.15+), 24, and 26 release lines. Reject
|
|
87
|
+
end-of-life odd-numbered releases explicitly instead of allowing installs that
|
|
88
|
+
can fail inside their frozen npm dependency resolver.
|
|
89
|
+
|
|
90
|
+
Because npm treats `engines` as a warning by default, `create-deepspace` also
|
|
91
|
+
checks the runtime before prompts, file copies, identity minting, or Git
|
|
92
|
+
initialization. Help and version remain available for diagnosis.
|
|
93
|
+
|
|
94
|
+
- `deepspace pull` no longer traps an agent when local work is simply unpushed.
|
|
95
|
+
|
|
96
|
+
Local-ahead — the ordinary state after `commit` — was classified as divergence.
|
|
97
|
+
`pull` exited 2 with `actionRequired: true` and handed back
|
|
98
|
+
`git merge refs/remotes/space/<branch>`, which answers "Already up to date" and
|
|
99
|
+
changes nothing. An agent honouring the exit-2 contract re-ran `pull` forever;
|
|
100
|
+
only `push` clears the state, and `push` was not the pinned action.
|
|
101
|
+
|
|
102
|
+
It is now `status: "local_ahead"` on a successful (exit 0) pull. Human output
|
|
103
|
+
names `deepspace push`, and JSON carries that same targeted push as its
|
|
104
|
+
executable success action. `deepspace status` has always classified this
|
|
105
|
+
correctly — the two now agree.
|
|
106
|
+
|
|
107
|
+
- Typo'd flags are now refused instead of silently ignored.
|
|
108
|
+
|
|
109
|
+
citty hardcodes its parser to `strict: false`, so an unknown flag was never
|
|
110
|
+
rejected — it was dropped and the command ran with the caller's intent
|
|
111
|
+
discarded. `deepspace releases --limitt 1` swallowed the flag _and_ its value
|
|
112
|
+
and returned every release with exit 0; `--jsonn` printed human prose to stdout
|
|
113
|
+
while the caller waited for JSON. Unknown subcommands and bad flag _values_
|
|
114
|
+
were already rejected; only flag names went unchecked.
|
|
115
|
+
|
|
116
|
+
One check at the shared command boundary now rejects them with
|
|
117
|
+
`code: "unknown_option"` before any side effect, naming the options that verb
|
|
118
|
+
accepts. Aliases, hyphenated names, and `--no-<flag>` are unaffected.
|
|
119
|
+
|
|
120
|
+
- Collaborative apps no longer show stale data as live when the connection dies
|
|
121
|
+
quietly.
|
|
122
|
+
|
|
123
|
+
A peer that stops answering without closing leaves the socket ESTABLISHED — no
|
|
124
|
+
packets are lost, so nothing retransmits, so no close event ever arrives.
|
|
125
|
+
Measured against a peer frozen mid-conversation, an unprobed connection stayed
|
|
126
|
+
open indefinitely. That is a hung Durable Object, a broken relay, or a
|
|
127
|
+
blackholed path; the browser's `offline` event fires for none of them, because
|
|
128
|
+
the machine's own network is fine.
|
|
129
|
+
|
|
130
|
+
Everything downstream already handled this correctly and was simply never
|
|
131
|
+
called: `useRecordContext().status` flips to `'disconnected'`, every live query
|
|
132
|
+
resets to loading while keeping its records on screen, and the socket
|
|
133
|
+
reconnects with backoff. The client now probes a connection once it has gone
|
|
134
|
+
quiet and closes it after 45s of silence, so those run when they should.
|
|
135
|
+
|
|
136
|
+
The probe costs nothing on the server: `BaseRoom` already registers a
|
|
137
|
+
`WebSocketRequestResponsePair('ping','pong')`, so the Cloudflare runtime
|
|
138
|
+
answers it while the Durable Object stays hibernated. An app already receiving
|
|
139
|
+
updates is never probed. Liveness is probe-based: a quiet socket sends a ping
|
|
140
|
+
after 15 seconds and closes only when that outstanding probe receives no
|
|
141
|
+
inbound answer for a further 30 seconds. A backgrounded timer's first resumed
|
|
142
|
+
callback therefore probes instead of falsely disconnecting a healthy socket.
|
|
143
|
+
If suspension occurs after a ping was sent, the first delayed callback also
|
|
144
|
+
discards that pre-suspension judgment and sends a fresh probe before applying
|
|
145
|
+
the normal deadline.
|
|
146
|
+
|
|
147
|
+
## 0.17.0
|
|
148
|
+
|
|
149
|
+
### Minor Changes
|
|
150
|
+
|
|
151
|
+
- **`deepspace deploy --claim-released` lets a platform admin take a name still inside its 30-day cooldown.** Undeploying releases a hostname into a hold reserved for its previous owner, and `released_by` records the app's **owner** — not whoever ran the undeploy. So an admin taking down an abandoned or abusive app could not then put anything on that name for a month: the reservation belongs to the absent owner, and the admin's own app matches neither the releasing-owner nor the releasing-app leg that normally allows a reclaim. The name was stranded by the mechanism meant to protect it.
|
|
152
|
+
|
|
153
|
+
The flag is explicit rather than an implicit admin bypass. The override is absolute — it beats a release made seconds ago and permanently discards the reservation rather than pausing it — so a routine admin deploy must not be able to seize a held name by accident. This is the same reasoning that makes a rename require `--rename`. Non-admin accounts are refused with `admin_required`, and because the tier lookup fails closed, a billing outage refuses rather than grants.
|
|
154
|
+
|
|
155
|
+
Two records are written, because neither side knows the whole story: the deploy worker logs the acting admin (it cannot name the displaced owner, since only released rows carry `released_by` and no by-host lookup returns them), and the registry logs the displaced owner and the app that lost the name at the moment the row is replaced.
|
|
156
|
+
|
|
157
|
+
- **Removed: GameRoom, document mode, and the identity-migration wire.** These
|
|
158
|
+
landed in #240 and #241 without a changeset, so this declares them rather than
|
|
159
|
+
letting a release drop public exports silently.
|
|
160
|
+
|
|
161
|
+
Gone from the public surface:
|
|
162
|
+
- `useGameRoom`, and the `GameRoom` durable object with `GameRoomConfig`,
|
|
163
|
+
`GamePlayer`, `UseGameRoomResult`, `Player`, and `GameInput`. No in-repo app
|
|
164
|
+
used it, and it failed the authorization, hibernation, and scheduling
|
|
165
|
+
invariants every other room holds. Use `RecordRoom` for shared state.
|
|
166
|
+
- `CANONICAL_APP_IDENTITY_MIGRATION_ID` and the `MSG.GAME_*` protocol
|
|
167
|
+
constants, which had no producer or consumer once the room went.
|
|
168
|
+
- The RecordRoom document-mode migrations, verified unused across every repo
|
|
169
|
+
in the org before deletion.
|
|
170
|
+
|
|
171
|
+
An app that imported any of these will fail to build. Nothing in the templates
|
|
172
|
+
or the feature catalog referenced them.
|
|
173
|
+
|
|
174
|
+
### Patch Changes
|
|
175
|
+
|
|
176
|
+
- Fix a set of version-control lifecycle and honesty defects found by
|
|
177
|
+
black-box agent live-testing of multi-checkout collaboration — cases where
|
|
178
|
+
a verb prescribed recovery that deterministically failed, reported work it
|
|
179
|
+
did not do, or handed out a command that could not run where it pointed.
|
|
180
|
+
- **Recovery actions execute verbatim.** Every `action.argv` that re-invokes
|
|
181
|
+
this CLI is pinned to the running interpreter and entry (resolved through
|
|
182
|
+
the `node_modules/.bin` symlink) instead of the bare word `deepspace`,
|
|
183
|
+
which is not on PATH in a linked worktree, a bare clone, or an `npx`
|
|
184
|
+
invocation. One door (`executableAction`) applies it to refusal actions,
|
|
185
|
+
success-path actions, the unknown-command suggestion, and `deploy`'s own
|
|
186
|
+
exit envelope; consumers must not assume `argv[0] === 'deepspace'`.
|
|
187
|
+
- **A checkout can follow its own advice.** `deepspace clone`, `workspace
|
|
188
|
+
new`, `workspace attach`, `workspace sync`, and `workspace land` fill
|
|
189
|
+
whichever half of the checkout's repo-local git identity is missing from
|
|
190
|
+
the session token — previously the `git pull` a divergence refusal handed
|
|
191
|
+
back (and any first commit) died on `unable to auto-detect email address`
|
|
192
|
+
in a container with no global git config, or with a half-configured one.
|
|
193
|
+
The divergence recovery also pins `git pull --no-rebase` (a fresh clone
|
|
194
|
+
has no reconcile config) and exits 2 from workspace publishes exactly as
|
|
195
|
+
it does from `push`.
|
|
196
|
+
- **A second checkout of a landed workspace is no longer a dead end.**
|
|
197
|
+
`workspace drop` cleans up the stale local worktree and branch of a
|
|
198
|
+
workspace another clone landed or dropped — proving publication against a
|
|
199
|
+
freshly fetched trunk tip when the landed ref is gone — and reports
|
|
200
|
+
whether the remote drop actually happened (`json.remoteDropped`) instead
|
|
201
|
+
of claiming a fresh drop on a replay. `workspace status` states the right
|
|
202
|
+
fact per state (landed/dropped → drop cleans up; behind → fast-forward;
|
|
203
|
+
diverged → integrate first) instead of prescribing a `workspace sync` that
|
|
204
|
+
would refuse, and `--json` gains `syncRelation` so machine callers see the
|
|
205
|
+
same distinction. `workspace land` and `workspace sync` on a finished
|
|
206
|
+
workspace report `workspace_not_active` (with the `workspace drop` cleanup
|
|
207
|
+
action) ahead of a checkout mismatch whose attach advice could not
|
|
208
|
+
succeed; drop's own unsynced refusal stops prescribing the publish path
|
|
209
|
+
once the workspace is finished — nothing can publish those commits, and
|
|
210
|
+
the message says so. The server returns `workspace_not_active` (over the
|
|
211
|
+
generic `conflict`) for sync/land/drop against a finished workspace — a
|
|
212
|
+
worker-side change that reaches existing CLIs on deploy; no released CLI
|
|
213
|
+
branches on the old slug, and this CLI tolerates both.
|
|
214
|
+
- **`workspace attach` is idempotent.** Attaching an already-attached
|
|
215
|
+
workspace points at the existing worktree instead of refusing
|
|
216
|
+
`branch_exists` — reporting the LOCAL tip and, when it differs from the
|
|
217
|
+
published tip, the recovery that relation actually admits (`workspace
|
|
218
|
+
sync` when ahead; `git pull --no-rebase` first when behind or diverged,
|
|
219
|
+
since sync would refuse) — and re-materializes a worktree that `git
|
|
220
|
+
worktree remove` or a failed cleanup deleted.
|
|
221
|
+
- **Land refusals carry their resume action, and a recorded merge is never
|
|
222
|
+
reported as a bare failure.** `merge_conflict`, `conflict_markers` (now
|
|
223
|
+
naming the offending files), `validation_failed`, and
|
|
224
|
+
`validation_mutated_tree` carry the exact re-run action; when the trunk
|
|
225
|
+
push succeeded and only recording the land failed, `land_unrecorded`
|
|
226
|
+
states that the merge IS on trunk and resumes by re-running instead of
|
|
227
|
+
implying nothing happened. When a concurrent land or drop finished the
|
|
228
|
+
workspace mid-merge, land answers `workspace_not_active` at exit 2 with
|
|
229
|
+
`pushed: true` and the `workspace drop` cleanup action — the merge is on
|
|
230
|
+
trunk, and re-running could never record it.
|
|
231
|
+
- **`status` stops labeling a feature branch's sync line "Trunk".** A
|
|
232
|
+
non-default branch renders as `Branch sync`, and `json.trunk` gains
|
|
233
|
+
`branch`/`isTrunk` (`isTrunk: null` when the default branch is unknown —
|
|
234
|
+
GitHub-owned source or an unborn cloud repo — never a guess), so
|
|
235
|
+
`trunk.state: "in_sync"` on a feature branch can no longer read as "local
|
|
236
|
+
trunk matches cloud trunk". `activity` (CLI and dashboard) stops printing
|
|
237
|
+
a fabricated "(0 files vs base)" changed-file count on workspace syncs —
|
|
238
|
+
the event never carried one.
|
|
239
|
+
|
|
240
|
+
- `deepspace workspace drop` and `land` no longer treat the generic `conflict`
|
|
241
|
+
error as "already finished".
|
|
242
|
+
|
|
243
|
+
The server refuses a finished workspace with `workspace_not_active`; `conflict`
|
|
244
|
+
was the pre-rename slug, and the CLI accepted both. Platform workers deploy
|
|
245
|
+
ahead of the CLI release, so nothing still answers with the old slug — and
|
|
246
|
+
`conflict` remains live for workspace-id clashes, which were being re-read as
|
|
247
|
+
"already finished" instead of surfacing. An id clash now raises immediately.
|
|
248
|
+
|
|
3
249
|
## 0.16.0
|
|
4
250
|
|
|
5
251
|
### Minor Changes
|
|
@@ -20,7 +266,7 @@
|
|
|
20
266
|
|
|
21
267
|
### Minor Changes
|
|
22
268
|
|
|
23
|
-
- **`deepspace app migrate` is removed**, replaced by `deepspace app update` (below). It existed for one historical cutover — moving an app from a name-shaped id to a canonical one
|
|
269
|
+
- **`deepspace app migrate` is removed**, replaced by `deepspace app update` (below). It existed for one historical cutover — moving an app from a name-shaped id to a canonical one. The platform migration endpoints were subsequently removed too; an unexpected legacy-id app now requires operator-owned recovery. Do not downgrade to run the old command.
|
|
24
270
|
|
|
25
271
|
A file that no longer exists now answers `404`, not the app's HTML. Deploys configured the asset layer with `not_found_handling: "single-page-application"`, so it answered EVERY unmatched path with `index.html` at 200 — correct for a client route, wrong for a file. A deploy replaces the hashed build chunks, so a tab still holding the previous `index.html` requested one and got HTML where JavaScript belonged: the script tag parsed it, failed, and the page went white with no error in any log, monitor, or network panel. The same answer went to agents probing `/llms.txt` and `/.well-known/mcp`, telling them the app publishes a manifest it does not have.
|
|
26
272
|
|
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
The DeepSpace SDK — build real-time collaborative apps on Cloudflare Workers.
|
|
8
8
|
Bundles auth, real-time data subscriptions, RBAC, messaging, file storage,
|
|
9
|
-
collaborative editing (Yjs), and zero-config deployment
|
|
9
|
+
collaborative editing (Yjs), and zero-config deployment through focused public
|
|
10
|
+
entry points.
|
|
10
11
|
|
|
11
12
|
The fastest way to start is to scaffold a full app rather than wire the SDK up
|
|
12
13
|
by hand:
|
|
@@ -27,15 +28,18 @@ npm install deepspace
|
|
|
27
28
|
|
|
28
29
|
## Entry points
|
|
29
30
|
|
|
30
|
-
The package has
|
|
31
|
+
The package has seven supported import paths:
|
|
31
32
|
|
|
32
33
|
- **`deepspace`** — the React client SDK (hooks, providers, auth, storage,
|
|
33
34
|
messaging, theme). Runs in the browser.
|
|
35
|
+
- **`deepspace/schema`** — schema builders and shared schema types.
|
|
34
36
|
- **`deepspace/worker`** — the Cloudflare Worker runtime (`RecordRoom`, schemas,
|
|
35
37
|
JWT verification, HMAC auth). Runs in your app's Worker.
|
|
36
38
|
- **`deepspace/server`** — app-server helpers for actions, billing, and room
|
|
37
39
|
handlers.
|
|
38
40
|
- **`deepspace/testing`** — Playwright fixtures for multi-user tests.
|
|
41
|
+
- **`deepspace/documentation`** — documentation compiler and runtime helpers.
|
|
42
|
+
- **`deepspace/documentation/react`** — documentation React components.
|
|
39
43
|
|
|
40
44
|
## Minimal usage
|
|
41
45
|
|
|
@@ -89,11 +93,10 @@ npx deepspace dev start # run locally
|
|
|
89
93
|
npx deepspace deploy # deploy to *.app.space
|
|
90
94
|
```
|
|
91
95
|
|
|
92
|
-
The
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
`deepspace app migrate`; there is no top-level `deepspace migrate` alias.
|
|
96
|
+
The hierarchy shown by `deepspace --help` keeps durable app lifecycle under
|
|
97
|
+
`deepspace app`, while checkout-oriented Git, workspace, release, and deploy
|
|
98
|
+
operations stay top-level. The historical `deepspace app migrate` command was
|
|
99
|
+
removed in 0.15.0; it is not an upgrade or recovery path.
|
|
97
100
|
|
|
98
101
|
Every app has one authoritative Git repository. DeepSpace source is the packaged
|
|
99
102
|
default: the first normal deploy claims it and publishes automatically.
|
|
@@ -114,40 +117,14 @@ DeepSpace verifies GitHub but never writes it. Inspect or transfer authority wit
|
|
|
114
117
|
`deepspace app source`, `deepspace app source github`, or
|
|
115
118
|
`deepspace app source deepspace`. Transfers mirror branches and tags before one
|
|
116
119
|
atomic authority change; switching back uses the same commands. Commands support
|
|
117
|
-
`--json` for agents.
|
|
118
|
-
[
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
npx deepspace app migrate --dry-run
|
|
127
|
-
npx deepspace app migrate
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
The dry-run lists pending source migrations without changing files. For a
|
|
131
|
-
legacy GitHub app whose `DEEPSPACE_APP_ID` is still name-shaped, it also lists
|
|
132
|
-
the exact registry rows that will be re-keyed and the physical stores that
|
|
133
|
-
remain at the existing resource id. The command applies only transformations
|
|
134
|
-
it recognizes safely, pauses for normal commit/push, and finishes with one
|
|
135
|
-
deploy. Applied steps live in the checked-in `deepspace.migrations.json`
|
|
136
|
-
manifest. Normal deploy bundles record that manifest in the release, so the
|
|
137
|
-
next run can determine whether the migration is live without depending on Git
|
|
138
|
-
commit lineage. Rerun after each returned action; when nothing is pending it
|
|
139
|
-
reports `up_to_date`. This is the same workflow for GitHub and DeepSpace
|
|
140
|
-
source; only their normal push behavior differs. `APP_NAME`-based
|
|
141
|
-
legacy room and storage addresses are retained; canonical `DEEPSPACE_APP_ID`
|
|
142
|
-
is used only for logical identity and platform authentication.
|
|
143
|
-
|
|
144
|
-
Keep deploy, release rollback, and undeploy idle from the mutating command until
|
|
145
|
-
that returned deploy begins; normal app traffic continues throughout.
|
|
146
|
-
Before the registry cutover commits, `--cancel` reverses a prepared migration
|
|
147
|
-
after the restored legacy configuration is committed and pushed. After the
|
|
148
|
-
cutover, recovery is deliberately forward-only: deploy the canonical app and
|
|
149
|
-
rerun `deepspace app migrate` to verify the live release. DeepSpace never
|
|
150
|
-
writes the GitHub repository.
|
|
120
|
+
`--json` for agents. Use `deepspace --help`, command-specific `--help`, and the
|
|
121
|
+
[public manual](https://documentation.deep.space) for workspaces, releases, and
|
|
122
|
+
rollback.
|
|
123
|
+
|
|
124
|
+
Use the current command-specific release notes for supported upgrade steps. If
|
|
125
|
+
an app or checkout still carries a name-shaped legacy id, stop and contact the
|
|
126
|
+
DeepSpace operator; do not downgrade the SDK or run migration commands copied
|
|
127
|
+
from historical changelogs and proposals.
|
|
151
128
|
|
|
152
129
|
## Debugging
|
|
153
130
|
|