deepspace 0.17.0 → 0.19.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 CHANGED
@@ -1,5 +1,173 @@
1
1
  # deepspace
2
2
 
3
+ ## 0.19.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Block paid app checkout until the owner can accept charges and payouts; require
8
+ current app roles for direct job mutations and enabled production debug routes;
9
+ disconnect role-changed sockets; remove email/avatar data from ephemeral
10
+ presence; refresh ordered/limited live-query snapshots; and clean Yjs awareness
11
+ per subscribed document. Also retain the earlier claimable-ownership, room
12
+ identity, log-sanitization, generated-artifact, and first-run agent-DX fixes.
13
+
14
+ Existing beta apps must run `npx deepspace@latest app update` with this release
15
+ so the migration is run by the target CLI. It moves verified room identity from
16
+ URL parameters to internal headers and installs the stock job-role/debug-route
17
+ checks using the SDK's shared app-role lookup. Customized seams receive a
18
+ precise manual blocker; no legacy runtime compatibility branch is retained.
19
+
20
+ Generated apps also drop unused model-provider packages and the legacy
21
+ Documents editor migration. Record writes expose existing room readiness and
22
+ fail with a stable `not_ready` error before connection; Yjs rooms expose current
23
+ transport connectivity. Testing sign-in keeps safe server error codes,
24
+ workspace land returns the deterministic pull action when needed, and generated
25
+ Documents code is typechecked from the packed release artifact.
26
+
27
+ ## 0.18.0
28
+
29
+ ### Minor Changes
30
+
31
+ - **Deploy no longer reads `.dev.vars`. The secret store is the only source.**
32
+
33
+ Deploy used to compare hand-edited `.dev.vars` keys against the store and
34
+ refuse (`secrets_not_uploaded`) or warn when they differed — a guard that
35
+ inferred intent from a local file. It also broke its own escape hatch: the
36
+ refusal pointed at `secrets upload .dev.vars` while that same deploy had
37
+ already written the SDK-managed block into that file, whose keys the upload
38
+ then rejected, with no code and no action to recover from. An agent that hit
39
+ it had no way forward.
40
+
41
+ `.dev.vars` keeps its real job — deploy WRITES it so `deepspace dev` sees the
42
+ same values — and is never read back to decide anything.
43
+
44
+ **Removed:** the `--allow-missing-secrets` flag and the `secrets_not_uploaded`
45
+ refusal code, which only existed to escape that guard.
46
+
47
+ Deploy now distinguishes a missing config from an explicitly created empty
48
+ config. A missing config regenerates the local cache without app secrets and
49
+ refuses before build, Git push, or upload, with an executable
50
+ `secrets configs create` action. An existing empty config is explicit
51
+ delete-all intent. The deploy server independently preserves live bindings
52
+ when an older client omits secret authority, making the rollout safe in both
53
+ directions.
54
+
55
+ Authoritative deletion is part of release finalization, not a best-effort log.
56
+ The server retries Cloudflare reconciliation three times and retains the
57
+ per-app release fence on failure. Replaying the exact deploy retries deletion
58
+ without issuing a second Worker activation; a release is recorded only after
59
+ stale bindings, including `ALLOW_DEBUG_ROUTES`, are gone.
60
+
61
+ If the original CLI process exits after that partial result, a fresh deploy key
62
+ can resume only when the complete Worker, secret, attribution, and source
63
+ lineage hash matches the live operation. The server first proves that exact
64
+ operation is live at Cloudflare; different input stays fenced. Malformed
65
+ successful Cloudflare secret-list envelopes also fail closed.
66
+
67
+ The per-app release transaction is now reserved before route registration,
68
+ binding auto-provisioning, or rate-limit allocation. Losing concurrent deploys
69
+ therefore return without renaming the production app or creating provider
70
+ resources. An incomplete reservation cannot activate; an exact retry may
71
+ atomically take ownership and finish its resolved rollback metadata. Durable
72
+ key aliases keep displaced processes from reclaiming the operation and replay
73
+ the successor after finalization; a safe pre-activation abort removes the
74
+ aliases with the fence. A compare-and-set transition grants exactly one request
75
+ permission to issue the Worker PUT. That winner is bound to a request-scoped
76
+ claim nonce: it can clear its own committed-but-lost claim response before the
77
+ PUT begins, while an uncertain concurrent request cannot clear the winner's
78
+ activation fence.
79
+
80
+ - **`.dev.vars` is now fully generated. Hand edits do not survive.**
81
+
82
+ The file used to be three zones — an SDK section, a hand-edited section
83
+ preserved across runs, and a store cache — which required a divider grammar, a
84
+ dotenv parser to read the file back, and reconciliation between the two
85
+ sources. That made `.dev.vars` a second source of truth, and historically a
86
+ de-facto deploy input (docs/proposals/secrets-source-of-truth.md).
87
+
88
+ Now it is a materialization: rewritten whole on every `dev`, `test`, `deploy`,
89
+ and `secrets pull` run from platform values plus the app's secret store, with
90
+ a header saying so. Nothing reads it back.
91
+
92
+ **If you hand-edited `.dev.vars`, put required values in the store before
93
+ updating** (`deepspace secrets set KEY=value`). The next dev/test/pull run
94
+ overwrites the file. There is no legacy import or compatibility path; beta
95
+ consumers must update their configuration.
96
+
97
+ All Wrangler environments now share the one generated `.dev.vars`. Missing
98
+ configs materialize as empty, so a successful refresh cannot leave stale local
99
+ values behind.
100
+
101
+ Also removed: `secrets upload` no longer strips a generated block (there is no
102
+ block to strip — uploading the generated file is not a flow; use
103
+ `secrets download` for backups).
104
+
105
+ ### Patch Changes
106
+
107
+ - Remove stale lint suppressions from the Messaging and Documents feature
108
+ sources so an app containing every public feature builds without unused-rule
109
+ warnings.
110
+ - Support the maintained Node 22 (22.15+), 24, and 26 release lines. Reject
111
+ end-of-life odd-numbered releases explicitly instead of allowing installs that
112
+ can fail inside their frozen npm dependency resolver.
113
+
114
+ Because npm treats `engines` as a warning by default, `create-deepspace` also
115
+ checks the runtime before prompts, file copies, identity minting, or Git
116
+ initialization. Help and version remain available for diagnosis.
117
+
118
+ - `deepspace pull` no longer traps an agent when local work is simply unpushed.
119
+
120
+ Local-ahead — the ordinary state after `commit` — was classified as divergence.
121
+ `pull` exited 2 with `actionRequired: true` and handed back
122
+ `git merge refs/remotes/space/<branch>`, which answers "Already up to date" and
123
+ changes nothing. An agent honouring the exit-2 contract re-ran `pull` forever;
124
+ only `push` clears the state, and `push` was not the pinned action.
125
+
126
+ It is now `status: "local_ahead"` on a successful (exit 0) pull. Human output
127
+ names `deepspace push`, and JSON carries that same targeted push as its
128
+ executable success action. `deepspace status` has always classified this
129
+ correctly — the two now agree.
130
+
131
+ - Typo'd flags are now refused instead of silently ignored.
132
+
133
+ citty hardcodes its parser to `strict: false`, so an unknown flag was never
134
+ rejected — it was dropped and the command ran with the caller's intent
135
+ discarded. `deepspace releases --limitt 1` swallowed the flag _and_ its value
136
+ and returned every release with exit 0; `--jsonn` printed human prose to stdout
137
+ while the caller waited for JSON. Unknown subcommands and bad flag _values_
138
+ were already rejected; only flag names went unchecked.
139
+
140
+ One check at the shared command boundary now rejects them with
141
+ `code: "unknown_option"` before any side effect, naming the options that verb
142
+ accepts. Aliases, hyphenated names, and `--no-<flag>` are unaffected.
143
+
144
+ - Collaborative apps no longer show stale data as live when the connection dies
145
+ quietly.
146
+
147
+ A peer that stops answering without closing leaves the socket ESTABLISHED — no
148
+ packets are lost, so nothing retransmits, so no close event ever arrives.
149
+ Measured against a peer frozen mid-conversation, an unprobed connection stayed
150
+ open indefinitely. That is a hung Durable Object, a broken relay, or a
151
+ blackholed path; the browser's `offline` event fires for none of them, because
152
+ the machine's own network is fine.
153
+
154
+ Everything downstream already handled this correctly and was simply never
155
+ called: `useRecordContext().status` flips to `'disconnected'`, every live query
156
+ resets to loading while keeping its records on screen, and the socket
157
+ reconnects with backoff. The client now probes a connection once it has gone
158
+ quiet and closes it after 45s of silence, so those run when they should.
159
+
160
+ The probe costs nothing on the server: `BaseRoom` already registers a
161
+ `WebSocketRequestResponsePair('ping','pong')`, so the Cloudflare runtime
162
+ answers it while the Durable Object stays hibernated. An app already receiving
163
+ updates is never probed. Liveness is probe-based: a quiet socket sends a ping
164
+ after 15 seconds and closes only when that outstanding probe receives no
165
+ inbound answer for a further 30 seconds. A backgrounded timer's first resumed
166
+ callback therefore probes instead of falsely disconnecting a healthy socket.
167
+ If suspension occurs after a ping was sent, the first delayed callback also
168
+ discards that pre-suspension judgment and sends a fresh probe before applying
169
+ the normal deadline.
170
+
3
171
  ## 0.17.0
4
172
 
5
173
  ### Minor Changes
@@ -122,7 +290,7 @@ worktree remove` or a failed cleanup deleted.
122
290
 
123
291
  ### Minor Changes
124
292
 
125
- - **`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 — and the platform endpoints behind it are unchanged, so an app still on a legacy id migrates with `npx deepspace@0.13.0 app migrate` and then upgrades normally.
293
+ - **`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.
126
294
 
127
295
  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.
128
296
 
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 behind four imports.
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 four supported import paths:
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
 
@@ -71,6 +75,12 @@ function Tasks() {
71
75
  }
72
76
  ```
73
77
 
78
+ `useMutations(collection)` exposes the existing RecordRoom `ready` state.
79
+ Writes attempted before it is true reject with `RecordRoomNotReadyError`
80
+ (`code: "not_ready"`) instead of disappearing into a closed socket. For direct
81
+ Yjs rooms, `connected` describes the current WebSocket and `synced` describes
82
+ completion of the current connection's initial document sync.
83
+
74
84
  Worker — expose a `RecordRoom` Durable Object:
75
85
 
76
86
  ```ts
@@ -89,11 +99,20 @@ npx deepspace dev start # run locally
89
99
  npx deepspace deploy # deploy to *.app.space
90
100
  ```
91
101
 
92
- The [normative CLI hierarchy](../../docs/platform/cli-contract.md#public-command-hierarchy)
93
- keeps durable app lifecycle and version migrations under `deepspace app`,
94
- while checkout-oriented Git, workspace, release, and deploy operations stay
95
- top-level. In particular, app migration is
96
- `deepspace app migrate`; there is no top-level `deepspace migrate` alias.
102
+ When updating an existing app, run the target CLI rather than the app's old
103
+ installed binary:
104
+
105
+ ```bash
106
+ npx deepspace@latest app update
107
+ ```
108
+
109
+ The target CLI owns the source migrations required by the SDK version it
110
+ installs. Review and commit its source changes before deploying.
111
+
112
+ The hierarchy shown by `deepspace --help` keeps durable app lifecycle under
113
+ `deepspace app`, while checkout-oriented Git, workspace, release, and deploy
114
+ operations stay top-level. The historical `deepspace app migrate` command was
115
+ removed in 0.15.0; it is not an upgrade or recovery path.
97
116
 
98
117
  Every app has one authoritative Git repository. DeepSpace source is the packaged
99
118
  default: the first normal deploy claims it and publishes automatically.
@@ -114,40 +133,19 @@ DeepSpace verifies GitHub but never writes it. Inspect or transfer authority wit
114
133
  `deepspace app source`, `deepspace app source github`, or
115
134
  `deepspace app source deepspace`. Transfers mirror branches and tags before one
116
135
  atomic authority change; switching back uses the same commands. Commands support
117
- `--json` for agents. See the
118
- [repository guide](https://github.com/deepdotspace/deepspace/blob/main/docs/platform/repo-store-git.md)
119
- for workspaces, releases, and rollback.
120
-
121
- `deepspace app migrate` is the permanent upgrade runner for breaking app
122
- changes. It contains an ordered set of structural, idempotent migrations, so
123
- agents and developers keep using the same command across releases:
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.
136
+ `--json` for agents. Use `deepspace --help`, command-specific `--help`, and the
137
+ [public manual](https://documentation.deep.space) for workspaces, releases, and
138
+ rollback.
139
+
140
+ In a container, give Git its own credentials before a private-repository
141
+ verification. Forward an SSH agent, or configure an ephemeral Git credential
142
+ helper in the container. Never embed a token in the remote URL: URLs can appear
143
+ in process listings, logs, and copied configuration.
144
+
145
+ Use the current command-specific release notes for supported upgrade steps. If
146
+ an app or checkout still carries a name-shaped legacy id, stop and contact the
147
+ DeepSpace operator; do not downgrade the SDK or run migration commands copied
148
+ from historical changelogs and proposals.
151
149
 
152
150
  ## Debugging
153
151