Commit Graph

3139 Commits

Author SHA1 Message Date
clockwork-labs-bot 5404126aba CLI - Notify users if there's an update available (#4363)
## Summary

Adds a version update check to the `spacetimedb-update` proxy, so users
are notified when a newer version of SpacetimeDB is available.

## Changes

Adds `crates/update/src/update_notice.rs` — a lightweight update check
that runs in the proxy path before exec'ing the CLI:

- **Cache-based**: Stores the last check result in
`~/.spacetime/.update_check_cache`. Only hits the network once every 24
hours.
- **Non-blocking on cache hit**: If the cache is fresh, it's a single
file read — no network, no delay.
- **Short timeout**: When the cache is stale, makes a single HTTP
request to GitHub releases API with a 5-second timeout. Uses the same
`SPACETIME_UPDATE_RELEASES_URL` env var as `spacetime version upgrade`.
- **Best-effort**: Any failure (network, parse, file I/O) is silently
ignored. The update check never interferes with the user's command.
- **Uses semver**: Proper version comparison via the `semver` crate
(already a dependency).

## Output

When a newer version is available:
```
A new version of SpacetimeDB is available: v2.1.0 (current: v2.0.0)
Run `spacetime version upgrade` to update.
```

# Testing
- [x] I get a warning if my local version is less than 2.0.2
- [x] If I have a cached update check, I get the same error even if I
have no network connection
- [x] if the cache is old, the next command checks again
- [x] if I'm not connected and the cache is stale, I'm still able to use
the CLI

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
2026-03-05 22:20:57 +00:00
clockwork-labs-bot 36a948105e Overhaul README with up-to-date content (#4500)
The README was significantly out of date. This overhaul brings it in
line with the current docs and product state.

## What changed

**Content updates:**
- "What is SpacetimeDB" now mentions all 4 module languages (Rust, C#,
TypeScript, C++) instead of only Rust
- Removed the smart contracts comparison (outdated framing)
- Updated BitCraft description to match current docs wording
- Shortened the architecture description to be punchier

**New Quick Start section:**
- 5-step flow: install, login, init, dev, publish
- Introduces `spacetime dev` (the primary local development experience)
- Introduces `spacetime publish` to Maincloud
- Much more approachable than the old "Installation" wall of text

**New "How It Works" section:**
- Rust module code example showing tables and reducers
- TypeScript client code example showing `useTable` subscriptions
- Shows the core value prop in < 20 lines of code

**Language support:**
- Added TypeScript and C++ as server module languages
- Added Unreal Engine (C++) as a client SDK
- Listed all supported web frameworks (React, Next.js, Vue, Svelte,
Angular, Node.js, Bun, Deno)
- Fixed all doc links to current URL patterns (`/docs/quickstarts/...`)

**Build from source:**
- Collapsed into expandable `<details>` sections (macOS/Linux and
Windows)
- Removed duplicate Git for Windows instructions
- Still complete, just not the first thing you see

**Badges:**
- Added npm download count badge for the TypeScript SDK

**License:**
- Shortened to essentials with link to full license file

---------

Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
2026-03-05 21:52:16 +00:00
Zeke Foppa 9f691f3cd8 Fix stale --project-path flag in templates (#4564)
# Description of Changes

We apparently have stale usage of `--project-path` in a ton of our
templates. This was renamed to `module-path` a while ago, but it looks
like that was only partially fixed in templates.

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

I don't think it's _more_ broken 🤷

---------

Signed-off-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-03-05 21:23:36 +00:00
Shiven Garia af6d0df06c Fix typos in comments and doc comments across crates (#4560)
## Summary
- Fix `Deerialize` → `Deserialize` in doc comments for `ser.rs` and
`typespace.rs` (these are in developer-facing trait documentation)
- Fix `thier` → `their`, `reinintializes` → `reinitializes`, `occurence`
→ `occurrence`, `secion` → `section` across 4 other crates

## Details
Six typo fixes across 6 files, no logic changes:

| File | Typo | Fix |
|------|------|-----|
| `crates/sats/src/ser.rs:280` | `Deerialize` | `Deserialize` |
| `crates/sats/src/typespace.rs:303` | `Deerialize` | `Deserialize` |
| `crates/table/src/table.rs:460` | `thier` | `their` |
| `crates/schema/tests/ensure_same_schema.rs:21` | `reinintializes` |
`reinitializes` |
| `crates/lib/src/http.rs:131` | `occurence` | `occurrence` |
| `crates/bindings/src/lib.rs:763` | `secion` | `section` |

## Test plan
- [ ] No logic changes — comments and doc comments only
- [ ] CI should pass without issues

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 20:12:38 +00:00
joshua-spacetime c5743cfc8d Add implicit query builder conversions from bool to BoolExpr (#4547)
# Description of Changes

Adds implicit query builder conversions from `bool` to `BoolExpr` so
that you can write:
```rust
ctx.from.user().r#where(|u| u.online)
```

instead of
```rust
ctx.from.user().r#where(|u| u.online.eq(true))
```

Also removes `NullableCol` and `NullableIxCol` types from C# query
builder.

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

Unit and smoketests
2026-03-05 07:14:08 +00:00
Ben Snyder 292bda8eed docs: self-hosted prod/test/dev Azure VM guide with key rotation, Azure Key Vault workflows, and rsync data migration pattern (#4545)
## Summary

This PR creates a comprehensive self-hosted JWT key rotation how-to for
SpacetimeDB with reproducible defaults, identity-preserving rotation
guidance, and host-scoped data migration runbooks. It is written for
both operators and automation workflows, with explicit guardrails for
production-like VM environments.

## Key Changes

- Adds a top-level assumptions/risk section for a multi-host topology
(`prod`, `test`, `dev`, optional `local`) including backup prerequisites
before rotation or sync.
- Defines an opinionated, end-to-end path contract for keys:
  - host source: `./.generated/spacetimedb-keys`
  - runtime mount: `/etc/spacetimedb`
- startup args pinned to `/etc/spacetimedb/id_ecdsa` and
`/etc/spacetimedb/id_ecdsa.pub`
- Includes reproducible quickstart scaffolding:
  - OpenSSL commands for compatible ES256/P-256 key generation
  - non-container and Docker startup examples
  - rotation/verify command sequence and marker checks
- Documents one unified tooling surface around `spacetimedb-tooling.ts`
for:
  - rotate (`--dry-run`, `--yes`)
  - verify (`--verify-only`)
  - token continuity (`--resign-token-only`)
- explicit token/key path overrides (`--publisher-cli-toml-path`,
`--private-key-path`)
- Clarifies 401 vs 403 behavior and why identity drift causes publish
failures after rotation.
- Covers all rotation strategies in one place:
  - clean-slate rotation (stateless/dev)
  - identity-preserving rotation (stateful)
  - OIDC-backed identity model for production
- Adds host-scoped migration runbooks for staged sync (`prod -> test ->
dev`) with destination-side token re-signing semantics (run on
destination host context, including SSH examples).
- Explicitly separates conceptual topology guidance from currently
implemented sync primitives in reference tooling to avoid over-claiming.
- Adds operational guardrails for sync promotions:
  - `rsync --delete` is destructive
  - stop/start ordering around sync
- required acceptance gates: key parity, destination re-sign,
restart/redeploy, publish marker validation
- Expands verification and automation content:
  - PEM/parity/fingerprint/newline checks
- AI/automation contract with inputs, outputs, required command order,
and success/failure markers
- troubleshooting flow for `InvalidSignature` and ownership mismatch
errors

## Why This Matters

The most common failure mode in self-hosted fleets is identity drift:
signatures validate, but `spacetime publish` still fails with `403
Forbidden` because destination ownership no longer matches the
publishing identity after key rotation or data movement.

The updated how-to makes these operator requirements explicit:

1. preserve identity continuity across rotations and host promotions
2. re-sign destination tokens after `rsync` in destination host context
3. treat restart/redeploy and publish markers as promotion gates

Following this runbook prevents regressions where key material is
correct but publish still fails due to stale signatures or owner
mismatch state.

## Why JWT Key Rotation Is Essential for Self-Hosters

In self-hosted deployments, operators are the signing authority.
Rotation is both a security control and an operational correctness
requirement.

### Security value

- reduces exposure window for compromised private keys
- invalidates old/stolen tokens after rotation
- mitigates risk from snapshots, backups, clones, and long-lived VM
access

### Operational value

- keeps key material consistent across multi-VM environments
- reduces publish outages after promotion/sync operations
- prevents avoidable `401`/`403` failures in routine release workflows

## Scope

- docs-only change
- public-safe examples only (no internal org names, private vault IDs,
or private secret prefixes)
- includes non-container and Docker workflows, self-publish/versioning
guidance, and marker-based validation (`PUBLISH_SUCCESS`,
`PUBLISH_FAILED`)
- includes data migration workflow guidance (`rsync` + destination
re-sign + restart/redeploy + publish checks)

---------

Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
2026-03-05 02:55:57 +00:00
clockwork-labs-bot 476d15755e spacetime dev - Replace template selection with fuzzy-filterable menu (#4470)
This pull request updates the template system to support richer metadata
and improves the interactive CLI experience for selecting templates. The
main changes are the addition of a `client_framework` field to template
metadata, a refactor of the templates JSON generation and parsing, and a
redesign of the interactive template selection flow to group templates
by language/framework and use fuzzy search for easier navigation.

<img width="407" height="409" alt="image"
src="https://github.com/user-attachments/assets/d3548505-80e8-4778-8bfb-71d5e3fe31e9"
/>

**Template Metadata and Serialization Improvements:**

* Added a new `client_framework` field to all template metadata files
(e.g., `.template.json`) and updated the Rust structs (`TemplateInfo`,
`TemplateDefinition`, etc.) to support this field, enabling more
descriptive and flexible template selection.
[[1]](diffhunk://#diff-5438edbe7b41e3e0a1a62ce0ebde2a833a0441d76c6ffdf16093a3cff258f462R3)
[[2]](diffhunk://#diff-34a44755a07373e9c2872db87a64c3fd752cfee7d8d536045909daf861ea4728R3)
[[3]](diffhunk://#diff-a826c5a2eac977cff44022d72856ec4b1af176ffbb50697f22857e1e3d478aa1R3)
[[4]](diffhunk://#diff-7a21474fbc5bbbd989e89f32aa8dcc25fcc6fe4ac43d418c42b2b38603d21714R3)
[[5]](diffhunk://#diff-d8ee9fd0ef15ed23f0f7f38e556d789bdefc6c37dab67fbfccebc513b9da871cR3)
[[6]](diffhunk://#diff-7224fd4300f9c5af7834ff5989a76a399ce9117c28f5d7e2c1fbd6bdaf45be1bR3)
[[7]](diffhunk://#diff-8b015b0ce6339c444ef5ef4dc5e862275d98967e5c189da37b51bdaa58443606R3)
[[8]](diffhunk://#diff-89e32f7fc9fc42863998d7651bc7fa1fdfb352e8ac3ef45792e3f1374052c9ddR3)
[[9]](diffhunk://#diff-8259d300fda149c968a68989aec2bc2afa479aded649ac6b8d3c4b277f610542R3)
[[10]](diffhunk://#diff-bb8b9202e51fb7038efa2f2bb23872afa02caf71ab3a0fb7f513ca7822c1b8faR3)
[[11]](diffhunk://#diff-18497b72a2306fc2560475e2548cfe1b96b6206c395380437ba1fafefd66e126L199-R221)
[[12]](diffhunk://#diff-18497b72a2306fc2560475e2548cfe1b96b6206c395380437ba1fafefd66e126R279)
* Refactored the templates JSON generation to use `serde` for
serialization, replacing manual string building, and ensured that
optional string fields serialize as empty strings when not present.

**CLI Interactive Template Selection Redesign:**

* Removed the previous "highlights" concept and reworked the interactive
selection to group templates by language/framework combinations, showing
counts and using fuzzy search for easier filtering.
[[1]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL38-L48)
[[2]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL772-R833)
[[3]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL813-L850)
* Updated the selection menus to allow users to pick a
language/framework group, then choose from multiple templates if
available, or opt to clone from GitHub or select "None."
[[1]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL772-R833)
[[2]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL813-L850)
* Improved language label formatting for better user experience in the
CLI prompt.

**Codebase Cleanup and API Changes:**

* Removed unused highlight-related structs and logic from the CLI,
simplifying the template fetching API to return only templates.
[[1]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL38-L48)
[[2]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL198-R198)
* Updated all template selection logic to use the new API and data
structures.
[[1]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL683-R679)
[[2]](diffhunk://#diff-7fcfe09d0f54dde6b2fc0cb2b9ff02ab064add692f5602d6f627fe3840e282caL748-R744)

These changes make template selection more intuitive and scalable as
more templates and frameworks are added.

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-03-04 23:44:36 +00:00
Zeke Foppa 5e2dda9764 CI - Reduce when package job runs (#4539)
# Description of Changes

We run the "package CLI" job for every `master` commit, but I think we
basically never use those. Instead I added the work flow dispatch option
which can run as a one off if needed. (I didn't test it, but now that
it's added, we'll be able to fix it in a PR if needed).

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

None

---------

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-03-04 19:55:39 +00:00
clockwork-labs-bot e991421009 Wait for database to load before returning schema (#4551)
## Summary

When hitting `/v1/schema` while a database is still loading (replaying
the log, running init reducers, etc.), the endpoint returned a 500 error
because the module host was not yet available.

## Changes

- Add `Host::wait_for_module(timeout)` in `crates/client-api/src/lib.rs`
-- polls `get_module_host` with exponential backoff (100ms, 200ms,
400ms, 800ms, 1s, 1s, ...) up to the given timeout
- Update the `/v1/schema` route to use `wait_for_module(10s)` instead of
the immediate `module()` call

If the database finishes loading within 10 seconds, the schema is
returned normally. If it does not load in time, the existing 500 error
is returned (same behavior as before, just delayed).

No other routes are changed -- this is scoped to the schema endpoint per
the issue description. Other routes (SQL, call, etc.) could adopt the
same pattern if needed.

Fixes clockworklabs/SpacetimeDBPrivate#2748

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-03-04 16:55:48 +00:00
clockwork-labs-bot cacfd73865 docs: fix TS index definition nameaccessor (#4537)
The TypeScript table index definition uses `accessor` not `name` for the
index identifier. Fixes three instances:

- `docs/docs/.../indexes.md`: two occurrences (`idx_age`,
`by_player_and_level`)
- `docs/docs/.../constraints.md`: one occurrence (`by_user_item`)

```diff
-{ name: 'by_player_and_level', algorithm: 'btree', columns: ['player_id', 'level'] }
+{ accessor: 'by_player_and_level', algorithm: 'btree', columns: ['player_id', 'level'] }
```

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-03-04 11:06:17 +00:00
Zeke Foppa e8d829dd8f gitignore *.local files (#4544)
# Description of Changes

Just ignoring `*.local` so that I can commit e.g. custom shell configs.

# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk

1

# Testing

My `.fishrc.local` is no longer picked up 🤷

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-03-04 11:06:15 +00:00
Phoebe Goldman 018575d1f9 Expose RawModuleDefV10 via the HTTP schema route (#4540)
# Description of Changes

Add `?version=10` as an option to
`/v1/database/:name-or-identity/schema`, where previously only
`?version=9` was supported. This seems to have been forgotten when we
introduced `RawModuleDefV10`.

Also, in an unrelated minor fixup, fix a copy-paste error in a doc
comment in the V2 WebSocket format definition.

# API and ABI breaking changes

Additive extension to HTTP API.

# Expected complexity level and risk

1

# Testing

- [x] Did a local get against this route and got a JSON-ified
`RawModuleDefV10`:

```bash
$ curl http://localhost:3000/v1/database/chat-console-rs/schema?version=10
{"sections":[{"Typespace":{"types":[{"Product":{"elements":[{"name":{"some":"sender"},"algebraic_type":{"Product":{"elements":[{"name":{"some":"__identity__"},"algebraic_type":{"U256":[]}}]}}},{"name":{"some":"sent"},"algebraic_type":{"Product":{"elements":[{"name":{"some":"__timestamp_micros_since_unix_epoch__"},"algebraic_type":{"I64":[]}}]}}},{"name":{"some":"text"},"algebraic_type":{"String":[]}}]}},{"Product":{"elements":[{"name":{"some":"identity"},"algebraic_type":{"Product":{"elements":[{"name":{"some":"__identity__"},"algebraic_type":{"U256":[]}}]}}},{"name":{"some":"name"},"algebraic_type":{"Sum":{"variants":[{"name":{"some":"some"},"algebraic_type":{"String":[]}},{"name":{"some":"none"},"algebraic_type":{"Product":{"elements":[]}}}]}}},{"name":{"some":"online"},"algebraic_type":{"Bool":[]}}]}}]}},{"Types":[{"source_name":{"scope":[],"source_name":"Message"},"ty":0,"custom_ordering":true},{"source_name":{"scope":[],"source_name":"User"},"ty":1,"custom_ordering":true}]},{"Tables":[{"source_name":"message","product_type_ref":0,"primary_key":[],"indexes":[],"constraints":[],"sequences":[],"table_type":{"User":[]},"table_access":{"Public":[]},"default_values":[],"is_event":false},{"source_name":"user","product_type_ref":1,"primary_key":[0],"indexes":[{"source_name":{"some":"user_identity_idx_btree"},"accessor_name":{"some":"identity"},"algorithm":{"BTree":[0]}}],"constraints":[{"source_name":{"some":"user_identity_key"},"data":{"Unique":{"columns":[0]}}}],"sequences":[],"table_type":{"User":[]},"table_access":{"Public":[]},"default_values":[],"is_event":false}]},{"Reducers":[{"source_name":"identity_connected","params":{"elements":[]},"visibility":{"Private":[]},"ok_return_type":{"Product":{"elements":[]}},"err_return_type":{"String":[]}},{"source_name":"identity_disconnected","params":{"elements":[]},"visibility":{"Private":[]},"ok_return_type":{"Product":{"elements":[]}},"err_return_type":{"String":[]}},{"source_name":"init","params":{"elements":[]},"visibility":{"Private":[]},"ok_return_type":{"Product":{"elements":[]}},"err_return_type":{"String":[]}},{"source_name":"send_message","params":{"elements":[{"name":{"some":"text"},"algebraic_type":{"String":[]}}]},"visibility":{"ClientCallable":[]},"ok_return_type":{"Product":{"elements":[]}},"err_return_type":{"String":[]}},{"source_name":"set_name","params":{"elements":[{"name":{"some":"name"},"algebraic_type":{"String":[]}}]},"visibility":{"ClientCallable":[]},"ok_return_type":{"Product":{"elements":[]}},"err_return_type":{"String":[]}}]},{"LifeCycleReducers":[{"lifecycle_spec":{"Init":[]},"function_name":"init"},{"lifecycle_spec":{"OnConnect":[]},"function_name":"identity_connected"},{"lifecycle_spec":{"OnDisconnect":[]},"function_name":"identity_disconnected"}]},{"ExplicitNames":{"entries":[{"Table":{"source_name":"message","canonical_name":"message"}},{"Table":{"source_name":"user","canonical_name":"user"}},{"Function":{"source_name":"identity_connected","canonical_name":"identity_connected"}},{"Function":{"source_name":"identity_disconnected","canonical_name":"identity_disconnected"}},{"Function":{"source_name":"init","canonical_name":"init"}},{"Function":{"source_name":"send_message","canonical_name":"send_message"}},{"Function":{"source_name":"set_name","canonical_name":"set_name"}}]}}]}
```
2026-03-04 05:21:38 +00:00
Zeke Foppa bec1771c44 Update edition in .rustfmt.toml and pre-commit hook (#4543)
# Description of Changes

We've updated to 2024
(https://github.com/clockworklabs/SpacetimeDB/pull/3802).

I'm just adding `edition` to `.rustfmt.toml`, and removing the hardcoded
edition from the pre-commit hook. This fixes the pre-commit hook
complaining about us using Rust 2024 features.

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing
- [x] `rustfmt crates/auth/src/identity.rs` now succeeds for me

---------

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-03-04 05:20:08 +00:00
Phoebe Goldman dde8f989f2 Don't put invalid Cargo.toml files in our repo (#4536)
# Description of Changes

Our flake.nix relies on Crane, which begins by scanning the repo for
`Cargo.toml` files in order to pre-compute the full set of dependencies
in order to record them in the Nix store. A previous PR, #4413,
introduced a `Cargo.toml` which was intentionally invalid to our
repository, with a script that modified it as part of a test. This
`Cargo.toml` was excluded from our workspace, but unfortunately, Crane's
`buildDepsOnly` doesn't respect the workspace, and just searches the
whole repository. I consider this a bug in Crane, but in the interest of
doing useful work on SpacetimeDB in the near future rather than spending
hours hacking on my build script, this commit changes the `Cargo.toml`
in question to be valid at rest, so that Crane doesn't get angry due to
failing to parse it.

# API and ABI breaking changes

N/a

# Expected complexity level and risk

1

# Testing

- [x] `nix build` and `nix develop` work locally.
- [ ] @bradleyshep should please run `cargo llm run` to his satisfaction
to verify that I haven't broken it.
2026-03-04 01:21:10 +00:00
Ryan 9a1ea26e25 Adds code signing to tagged windows builds (#4473)
**Note**: This change requires the addition of new entries in the
secrets to work properly. These should be added prior to this merging.

# Description of Changes

* Add a tag-only Windows signing job that runs on a self-hosted signing
runner.
* This is an alternative/separate code-path just for the signing job.
See **Alternatives Considered** for details.
* Skip the unsigned Windows matrix build on tags so signed artifacts are
the only Windows release outputs.
* Sign `spacetimedb-update.exe`, `spacetimedb-cli.exe`, and
`spacetimedb-standalone.exe` before packaging, then upload the signed
artifacts as usual.

# Alternatives Considered
**Inline signing in the existing Windows packaging step**. This was
rejected because it would require all Windows builds (including non-tag
builds) to run on the signing-capable runner or to install/signing
tooling on GitHub-hosted runners. The chosen approach isolates signing
to tag releases, avoids exposing credentials in standard builds, and
keeps routine CI behavior unchanged.

# API and ABI breaking changes

None

# Expected complexity level and risk

2 – low risk. CI-only change that adds a new signing job and preserves
existing artifact layout.

# Testing

- [X] None (Not running, workflow change only)

---------

Signed-off-by: Ryan <r.ekhoff@clockworklabs.io>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
2026-03-03 23:21:09 +00:00
Noa 0b30b16c2d Bring typescript benchmark client to parity with rust (#4494)
# Description of Changes

* Enable pipelining by default
  * Set defaults for `MAX_INFLIGHT_PER_WORKER` for spacetime and convex
* Add a warmup period
* Reduce allocations in sdk (not that much of an effect but still
improved things)

This gives improved parity with the rust client on my machine.

# Expected complexity level and risk

1

# Testing

- [x] Yup:
```
══════════════════════════════════════════════════════════════════════
      RESULTS
══════════════════════════════════════════════════════════════════════

spacetimedb ████████████████████████████████████████ 80,617 TPS
convex █░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 235 TPS

      ╔════════════════════════════════════════════════════════════╗
      ║                                                            ║
      ║       🚀 spacetimedb is 343x FASTER than convex! 🚀        ║
      ║                                                            ║
      ╚════════════════════════════════════════════════════════════╝
    ```
2026-03-03 23:10:52 +00:00
joshua-spacetime 89fba42165 Make accessor required for table-level index defs in C# (#4541)
# Description of Changes

Make `Accessor` a required argument for table-level index defs in C# to
align with rust and typescript. The same change was done for typescript
in https://github.com/clockworklabs/SpacetimeDB/pull/4525.

# API and ABI breaking changes

Technically breaks the module api, although I believe this is the
behavior that is outlined in the spec, and so the current behavior
should really be considered a bug.

# Expected complexity level and risk

1

# Testing

Added negative compile tests
2026-03-03 23:06:19 +00:00
doug 8a82b6d5f6 Add AgentSkills.io integration for AI coding assistants (#4172)
## Summary

Add AgentSkills.io integration so developers can give their AI coding
assistants SpacetimeDB expertise.

## What is AgentSkills.io?

[AgentSkills.io](https://agentskills.io) is an open standard for
distributing domain knowledge to AI coding assistants. After this PR is
merged, developers can run:

```bash
npx skills add clockworklabs/SpacetimeDB
```

The skills are installed into whichever AI coding tools they use -
Claude Code, Cursor, Cline, GitHub Copilot, Windsurf, and 40+ others.
The AI then has access to SpacetimeDB-specific patterns, common mistakes
to avoid, and correct API usage.

### Test Now

You can test this PR before it's merged:

```bash
npx skills add douglance/SpacetimeDB
```

## Why This Matters

LLMs frequently hallucinate SpacetimeDB APIs that don't exist:
- `#[spacetimedb::table]` instead of `#[table]`
- `ctx.db.player` instead of `ctx.db.player()`
- `conn.reducers.foo("value")` instead of `conn.reducers.foo({ param:
"value" })`

These skills teach AI assistants the **correct** patterns and warn about
common mistakes, reducing debugging time for developers using AI tools.

## Skills Included

| Skill | Lines | What It Teaches |
|-------|-------|-----------------|
| `spacetimedb-rust` | 895 | Server modules, reducers, tables, RLS,
procedures |
| `spacetimedb-typescript` | 1004 | Client SDK, React hooks,
subscriptions, views |
| `spacetimedb-csharp` | 1463 | Unity integration, BSATN, sum types,
server modules |
| `spacetimedb-cli` | 562 | All CLI commands and workflows |
| `spacetimedb-concepts` | 518 | Architecture, when to use SpacetimeDB |

Each skill includes:
- **HALLUCINATED APIs** section - wrong patterns LLMs commonly generate
- **Common Mistakes Table** - server/client errors with fixes
- **Hard Requirements** - critical rules that must be followed
- **Code Examples** - correct usage patterns

## Directory Structure

```
skills/
├── spacetimedb-rust/SKILL.md
├── spacetimedb-typescript/SKILL.md
├── spacetimedb-csharp/SKILL.md
├── spacetimedb-cli/SKILL.md
└── spacetimedb-concepts/SKILL.md
```

## Usage (after merge)

```bash
# Install all SpacetimeDB skills
npx skills add clockworklabs/SpacetimeDB

# Install specific skill
npx skills add clockworklabs/SpacetimeDB -s spacetimedb-rust

# List available skills
npx skills add clockworklabs/SpacetimeDB --list
```

## Test Plan

- [x] `npx skills add . --list` shows 5 skills
- [x] `npx skills add . -s spacetimedb-rust --yes` installs to 28+
agents
- [x] YAML frontmatter validates against agentskills.io spec
- [x] Skills contain hallucinated APIs warnings
- [x] Skills contain common mistakes tables

---------

Co-authored-by: bradleyshep <148254416+bradleyshep@users.noreply.github.com>
2026-03-03 22:47:37 +00:00
Noa 8cb2038f85 Fix 'unsafe attr without unsafe' error (#4534)
# Description of Changes

Followup to #3802; was causing issues in modules in private. Rust 2024
now requires `unsafe()` around certain attributes, but the `settings`
macro was added after I first opened that PR, so I didn't wrap it.
Additionally, `settings` wasn't tested in this repo, so it wasn't
caught.

# Expected complexity level and risk

1

# Testing

- [x] Added use of `#[spacetimedb::settings]` in `module-test`
2026-03-03 19:58:44 +00:00
clockwork-tien af732f5ede feat(tanstack): add SSR prefetching for Tanstack Start (#4519)
# Description of Changes
- Add SSR prefetching for Tanstack Start

Closes https://github.com/clockworklabs/SpacetimeDB/issues/4438

<!-- Please describe your change, mention any related tickets, and so on
here. -->

# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk
1

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [x] SSR prefetch works from testing
2026-03-03 15:09:07 +00:00
joshua-spacetime 33f3ea18e2 Make accessor required for table-level index defs in typescript (#4525)
# Description of Changes

This patch contains two main changes:

1. It makes `accessor` a required argument for table-level index defs in
typescript to align with rust.

2. It removes unsound index typing in the TypeScript bindings by
splitting index data into two explicit representations:

- `indexes`: declarative user config (`IndexOpts`) used for type
inference
- `resolvedIndexes`: normalized runtime metadata (`UntypedIndex`)
derived from `RawTableDefV10`

`TableCacheImpl` now builds index accessors from `resolvedIndexes`
instead of re-casting `indexes` at runtime.

    This addressed the following comment:
    ```
// TODO: horrible horrible horrible. we smuggle this
`Array<UntypedIndex>`
// by casting it to an `Array<IndexOpts>` as `TableToSchema` expects.
// This is then used in `TableCacheImpl.constructor` and who knows where
else.
    // We should stop lying about our types.
    ```

    > Why?

    We were conflating two different concepts under `tableDef.indexes`:

      1. declared table-level index options authored by users
2. resolved runtime index definitions (including field-level inferred
indexes)

This required unsafe casts (`T['idxs']` / `UntypedIndex`) and made the
type model unsound.

Note, (2) was largely ai assisted.

# API and ABI breaking changes

Technically breaks the module api, although I believe this is the
behavior that is outlined in the spec, and so the current behavior
should really be considered a bug.

# Expected complexity level and risk

2

# Testing

Added unit tests covering the following:
1. Table-level explicit index without accessor throws.
2. Table-level duplicate accessor throws.
3. Table-level explicit accessor is accepted and used.
4. Field-level `.index(...)` derives accessor from the field name
(`displayName`).
2026-03-03 15:09:05 +00:00
Kim Altintop 17cc15ef4c Append commit instead of individual transactions to commitlog (#4404)
Re-open #4140 (reverted in #4292).


The original patch was merged a bit too eagerly.
It should go in _after_ 2.0 is released with some confidence.
2026-03-03 15:08:05 +00:00
Noa e3582131fe Migrate to Rust 2024 (#3802)
# Description of Changes

It'd be best to review this commit-by-commit, and using
[difftastic](https://difftastic.wilfred.me.uk) to easily tell when
changes are minor in terms of syntax but a line based diff doesn't show
that.

# Expected complexity level and risk

3 - edition2024 does bring changes to drop order, which could cause
issues with locks, but I looked through [all of the warnings that
weren't fixed
automatically](https://gistcdn.githack.com/coolreader18/80485ae5c5f82de1784229cce2febb26/raw/ba80f3fecda66ceb34f4f7ad73b98ea02d4893a2/warnings.html)
and couldn't find any issues.

# Testing

n/a; internal code change
2026-03-03 11:06:52 +00:00
clockwork-tien 5836c268a7 fix: fix useSpacetimeDBQuery returns untyped rows for TanStack Start (#4488)
# Description of Changes
- Fix useSpacetimeDBQuery returns untyped rows for TanStack Start

Closes https://github.com/clockworklabs/SpacetimeDB/issues/4441

<!-- Please describe your change, mention any related tickets, and so on
here. -->

# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
package-test-tag v2.0.3
2026-03-03 10:55:46 +00:00
clockwork-labs-bot 7470eb23d3 Add --level flag to spacetime logs for filtering by log level (#4362)
Fixes #1972

Adds client-side log level filtering to `spacetime logs`:

- `--level <LEVEL>` / `-l <LEVEL>`: Show only logs at the specified
severity or higher. Valid values: `trace`, `debug`, `info`, `warn`,
`error`, `panic`. Default: show all logs (no filtering).
- `--level-exact`: When combined with `--level`, show only logs at
exactly the specified level.

Severity order (most to least): panic > error > warn > info > debug >
trace.

Examples:
```
spacetime logs mydb --level warn                # Show only warn, error, and panic
spacetime logs mydb --level info                 # Show info and above
spacetime logs mydb --level error --level-exact  # Show only errors
```

Filtering is done client-side.

---------

Signed-off-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-03-03 07:02:46 +00:00
joshua-spacetime c98bdf90e3 Use prepared statements for postgres keynote benchmark (#4522)
# Description of Changes

Use prepared statements for postgres keynote benchmark.

# API and ABI breaking changes

None

# Expected complexity level and risk

2

# Testing

Manually ran inside of docker to verify
2026-03-03 05:57:46 +00:00
Zeke Foppa 923dfe28c6 Fix a misprint in the self-hosting docs (#4524)
# Description of Changes

Closes https://github.com/clockworklabs/SpacetimeDB/issues/4496.

The docs refer to a block mentioning `/v1/publish` but we don't have
such a block in our example config. What we actually have is:
```
    # Block all other routes explicitly. Only localhost can use these routes. If you want to open your
    # server up so that anyone can publish to it you should comment this section out.
    location / {
        allow 127.0.0.1;
        deny all;
    }
```

# API and ABI breaking changes

None.

# Expected complexity level and risk

1.

# Testing

None

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-03-02 21:23:04 +00:00
Noa 9eb0506056 [TS] Fix toCamelCase (#4523)
# Description of Changes

Previously, it didn't uncapitalize the first character. This makes the
runtime behavior match with the typed behavior.

# Expected complexity level and risk

1

# Testing

- [x] Added a test for `toCamelCase`
2026-03-02 20:31:59 +00:00
Ryan c323bdf0dc [docs] Corrected call case and updated out-dir to match part 3 (#4513)
# Description of Changes

Contains 2 changes to documentation:
* Updates Unity Client Blackholio tutorial, part 2, with a corrected
`call` command. `Debug` became `debug` to match the automatic case
conversion that now occurs. Originally found and reported by discord
user `chrispavs`
* Updates Unity Client Blackholio tutorial, part 2, with the `out-dir`
path to match the path given in the [Entering the
Game](https://spacetimedb.com/docs/tutorials/unity/part-3#entering-the-game)
of `step 3`.

# API and ABI breaking changes

None

# Expected complexity level and risk

1 - Docs correction

# Testing

- [X] Tested all `blackholio` tutorial steps using C# server and Unity
client
2026-03-02 19:06:28 +00:00
John Detter 033c181337 Upgrade prompt is skipped when -y is passed (#4511)
# Description of Changes

<!-- Please describe your change, mention any related tickets, and so on
here. -->

This prompt is now skipped when `-y` is passed:

<img width="1053" height="530" alt="image"
src="https://github.com/user-attachments/assets/7237df85-4a12-4ab7-b377-95abbd0084c2"
/>

# API and ABI breaking changes

None

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk

1 - this just skips a prompt in the CLI

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

- [x] publish a 1.0 database to maincloud, then upgrade it to 2.0 and
pass `-y`. You should no longer get the upgrade prompt.
- [x] publish a 1.0 database to maincloud, then upgrade it to 2.0
without passing `-y`. You should still get the upgrade prompt.
2026-03-02 18:28:29 +00:00
Shubham Mishra ab65b60fe4 fix index truncate edge cases (#4501)
# Description of Changes
Index offset `truncate` methods returns `IndexError::KeyNotFound` when
asked to truncate on empty index offset file or the key in input is
smaller than the first entry.

This was causing `commitlog::reset_to` method to return error, and stuck
replicas in re-spawn loop.

# API and ABI breaking changes
NA

# Expected complexity level and risk
1

# Testing
Added new tests to cover edge scenerios.
2026-03-02 07:31:14 +00:00
clockwork-labs-bot 0e0834a236 Fix useTable isReady stuck on false due to stale snapshot cache (#4499)
## Problem

`useTable` returns `[rows, isReady]` where `isReady` is always `false`,
even when data is present in `rows`.

## Root Cause

When subscription data arrives, `onInsert` events fire and call
`computeSnapshot()` while `subscribeApplied` is still `false`. This
caches `[rows, false]` in `lastSnapshotRef.current`.

When `onApplied` later fires and sets `subscribeApplied = true`,
`computeSnapshot` is recreated (it has `subscribeApplied` in its
dependency array), which recreates `getSnapshot`. However,
`getSnapshot()` checks `lastSnapshotRef.current` first -- since it is
non-null (cached from the earlier insert events), it returns the stale
`[rows, false]` tuple without recomputing.

If no further row changes happen after `onApplied` fires, `isReady`
stays `false` forever.

## Fix

Clear `lastSnapshotRef.current` whenever `computeSnapshot` changes, so
the next `getSnapshot()` call recomputes and returns `[rows, true]`.

Reported by a user in Discord.

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-03-02 03:06:07 +00:00
clockwork-labs-bot b322348f41 docs: document how to access module owner via init reducer (#4315)
In the `init` reducer, `ctx.sender` is the **module owner** — the
identity of the user who published the database. This is the only
lifecycle reducer where the owner identity is automatically provided.

Added a tip to the lifecycle docs showing:
- That `ctx.sender` in `init` is the owner
- How to store it in a table for later authorization checks
- Examples in TypeScript, C#, and Rust

Closes #3229

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-03-01 20:45:54 +00:00
clockwork-labs-bot 5d9eb7c705 Add missing TypeScript example in migration guide (#4508)
The 'Option 2: overwrite the name of individual tables' section of the
2.0 migration guide had an empty TypeScript tab. Adds a complete example
using `table()` with an explicit `name` property to preserve the
pre-conversion table name.

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-03-01 16:02:30 +00:00
bradleyshep efa6f382b1 LLM benchmark tool updates (#4413)
# Description of Changes

LLM benchmark updates for local development:

- **Local SDK paths**: Templates use relative paths to workspace crates
(`crates/bindings`, `crates/bindings-csharp`,
`crates/bindings-typescript`) instead of published packages, so the
bench runs against local SDK changes.
- **NODEJS_DIR support**: On Windows (e.g. nvm4w), if `pnpm` is not on
PATH, the bench uses `NODEJS_DIR` to locate `pnpm` and prepends it to
PATH for subprocesses.
- **Refactor**: Extracted `relative_to_workspace()` in `templates.rs`
and removed noisy `NODEJS_DIR` logging in `publishers.rs`.
- **Benchmark results**: Updated `docs/llms/llm-comparison-details.json`
and `docs/llms/llm-comparison-summary.json`.

# API and ABI breaking changes

None.

# Expected complexity level and risk

**2** — Local-only changes to the benchmark tool. Templates now require
local SDKs to be built (especially TypeScript: `pnpm build` in
`crates/bindings-typescript`). No impact on published SDKs or runtime.

# Testing

- [ ] Run `cargo llm run --lang rust --modes docs --providers openai`
from repo root
- [ ] Run TypeScript benchmarks with `pnpm build` in
`crates/bindings-typescript` first
- [ ] On Windows with nvm4w, set `NODEJS_DIR` if `pnpm` is not on PATH
and run TypeScript benchmarks

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-03-01 02:22:59 +00:00
Jason Larabie 14f79910ee Update C++ module bindings to RawModuleDefV10 (#4461)
# Description of Changes
- Migrated the C++ module-definition assembly path to V10-first
internals:
      - Added v10_builder and module_type_registration systems.
- Switched Module::__describe_module__ to serialize RawModuleDef with
V10 payload.
      - Updated macro registration pipeline to register through V10
- Added explicit naming support across macro surface (*_NAMED variants
for reducer/procedure/
        view and field/index macros).
- Reworked multi-column index macros (FIELD_MultiColumnIndex,
FIELD_MultiColumnIndex_NAMED) with
        migration alias.
- Added SPACETIMEDB_SETTING_CASE_CONVERSION(...) to support case
conversion policy
- Error-path hardening by adding explicit constraint-registration error
tracking and preinit validation
  - Codegen updates:
      - Updated C++ moduledef regen to V10 builder types.
- Adjusted C++ codegen duplicate-variant wrapper generation to emit
proper product-type
        wrappers.
  - Test/harness updates:
- type-isolation-test runner now defaults to focused V10 regression
checks; --v9 runs broader
        legacy/full suite.
      - Added focused modules for positive/negative V10 checks:
          - test_multicolumn_index_valid
          - error_multicolumn_missing_field
          - error_default_missing_field
- Re-enabled C++ paths in sdks/rust/tests/test.rs procedure/view/test
suites.

# API and ABI breaking changes

- Refactor of the underlying module definition
- New *_NAMED variant macros for explicit canonical naming
- FIELD_NamedMultiColumnIndex renamed to FIELD_MultiColumnIndex

# Expected complexity level and risk

3 - Large set of changes moving over to V10 with underlying changes to
make future updates a little easier

# Testing
- [x] Ran the type isolation test and expanded it
- [x] Ran the spacetimedb-sdk test framework to confirm no more drift
between C++ and other module languages
- [x] Ran Unreal test suite though not really applicable
- [x] New app creation with `spacetime init --template basic-cpp`
- [x] Ran describe module tests against Rust + C# matching with C++ on
the /modules/sdk-test* modules to find any possible mis-alignment

# Review
- [x] Another look at the new features with C++
- [x] Thoughts on *_NAMED macros, I couldn't come up with a better
solution with C++20
2026-02-28 07:05:50 +00:00
Mazdak Farrokhzad abbcec4ab3 keynote-2: alpha -> 1.5, withConfirmedReads(true), remove warmup (#4492)
# Description of Changes

This does 3 things to the keynote-2 benchmark:
- it changes the default alpha to 1.5, which we actually tested the
other services with
- it turns on confirmed reads (not the default for < 2.0)
- it removes warmup

This was tested on
https://github.com/clockworklabs/SpacetimeDB/pull/4404 to have no impact
on the TPS throughput of spacetimedb.
**This PR shouldn't be merged before #4404 has.**

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

This tweaks a bench test.
2026-02-28 03:06:11 +00:00
John Detter c29a44c50b Version upgrade 2.0.3 (#4489)
# Description of Changes

<!-- Please describe your change, mention any related tickets, and so on
here. -->

- Version upgrade 2.0.3

# API and ABI breaking changes

- None, this is a version bump

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk

- 1 - this is a version bump

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [x] License has been updated
- [x] Version number is correct (2.0.3)
2026-02-27 20:24:22 +00:00
clockwork-labs-bot 1aff83da93 Fix missing word 'time' in ScheduleAt tutorial docs (#4490)
Fixes a missing word in the Unity and Unreal tutorial part-3 docs.

**Before:** `specify a specific at which to call a reducer once`
**After:** `specify a specific **time** at which to call a reducer once`

Fixed in 4 files (current docs + v1.12.0 versioned docs), 6 occurrences
total.

Spotted by Tyler.

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-27 18:22:46 +00:00
bradleyshep a46c106deb Add PlanetScale configuration details to keynote README & DEVELOP (#4474)
# Description of Changes

- **keynote-2 docs:** Document PlanetScale benchmark configuration in
DEVELOP.md (env vars `PLANETSCALE_PG_URL`, `PLANETSCALE_RPC_URL`,
`SKIP_PLANETSCALE_PG`; short “create DB and set env” section; note that
we benchmarked using PS-2560, 32 vCPUs, 256 GB RAM).
- **README:** Add PlanetScale to cloud tier list (PS-2560, single node,
us-central1). Add region (us-central1) to Hardware Configuration for
Server Machine Variant B and Client Machine.

No code or config changes; documentation only.

# API and ABI breaking changes

None.

# Expected complexity level and risk

**Complexity: 1.** Doc-only updates to `templates/keynote-2/README.md`
and `templates/keynote-2/DEVELOP.md`. No behavioral or API impact.

# Testing

- [ ] Skim README and DEVELOP.md for accuracy and formatting.
2026-02-27 15:06:17 +00:00
Ryan d87e49487b [C#] Improve error messages for Views (#4435)
This is the implementation of a fix for #4425

# Description of Changes

* Clarified C# generator diagnostics for view return types:
1. Updated the comments around `IQuery<T>` handling to describe the
return value as `T?`, matching C# semantics.
2. Adjusted the validation comment to say views must return `List<T>` or
nullable `T` instead of “Vec/Option”.
* Synced the diagnostics fixture comments with the new terminology so
STDB0024 examples talk about `List<T>`/`T?`.
* Checked current documentation for anything C# related to “Vec/Option”
and confirmed everything now references `List<T>`/`T?`.
* Regenerated/verified tests and snapshots.

# API and ABI breaking changes

None

# Expected complexity level and risk

1 - Changes are documentation and diagnostic-comment only.

# Testing

- [X] CLI rebuilt, local `dotnet test` pass and error output tests
validated.

---------

Signed-off-by: Ryan <r.ekhoff@clockworklabs.io>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2026-02-27 01:46:39 +00:00
joshua-spacetime e8a2d33155 C# smoketest for IQuery views (#4391)
# Description of Changes

~~Updates Roslyn codegen to handle `IQuery` return type for views.~~

~~`IQuery` wasn't recognized before this change, which meant `.Build()`
was still required for query builder views.~~

~~Note, we currently support the old `Query` return type which means we
still support `.Build()`. I'm not sure if this was intended when
`IQuery` was originally introduced, so I'm maintaining support for it
until I can determine otherwise. cc @cloutiertyler.~~

This is now a test only change.

This patch introduces scaffolding for defining and running C# module
smoketests. It also adds a new C# smoketest for an`IQuery` view.

# API and ABI breaking changes

None

# Expected complexity level and risk

2

# Testing

A testing only change.
2026-02-26 23:06:33 +00:00
Tao Tien 824c993fae Remove security warning from 00500-schedule-tables.md (#4463)
Now that scheduled reducers are private, this warning is no longer
necessary.

# Description of Changes

- removed Security Considerations section from Schedule Tables
documentation

Signed-off-by: Tao Tien <29749622+taotien@users.noreply.github.com>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2026-02-26 21:57:22 +00:00
clockwork-labs-bot 9fbb322b0b CLI - preserve leading .. in --out-dir paths (#4431)
## Problem

`spacetime generate --out-dir ../frontend-ts-src/module-bindings` was
resolving the path incorrectly, stripping the leading `..` component.
Reported in #4429 via a [user report on
Discord](https://discord.com/channels/1037340874172014652/1475935288919462072/1475935288919462072).

## Root Cause

`normalize_path_lexical()` in `spacetime_config.rs` used
`PathBuf::pop()` to handle `..` components, but `pop()` is a no-op on an
empty `PathBuf`. This silently dropped leading `..` segments:

- Input: `../frontend-ts-src/module-bindings`
- Output: `frontend-ts-src/module-bindings` (wrong — `..` was eaten)

## Fix

Replace the `PathBuf`-based normalization with a `Vec<Component>` stack
approach. `..` only cancels a preceding `Normal` component; otherwise it
is preserved. This correctly handles:

- `../foo` → `../foo` (leading `..` preserved)
- `../../a/b` → `../../a/b` (multiple leading `..` preserved)
- `a/b/../c` → `a/c` (inner `..` still resolves)
- `/home/user/project/../foo` → `/home/user/foo` (absolute paths work)

## Testing

Added `test_normalize_path_preserves_leading_dotdot` covering all edge
cases.

Closes #4429

---------

Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-26 19:54:20 +00:00
Piotr Sarnacki ad26525880 Fix publishing in directories with spaces (#4453)
# Description of Changes

The publish subcommand calls the build subcommand internally. The
build's implementation used to split the arguments by space, which
breaks when a directory contains a space.

# API and ABI breaking changes

-

# Expected complexity level and risk

1

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [x] Tested locally
- [x] Added a test
2026-02-26 19:29:40 +00:00
clockwork-labs-bot 4375cb81a8 spacetime dev - Print feedback when client process exits (#4469)
The main event loop in `spacetime dev` blocked on file change events
with no periodic check on the client process. If the client exited
(e.g., user pressed Enter in the basic-rs template), `spacetime dev`
gave no feedback at all.

**Fix**: Switch from blocking `recv()` to `recv_timeout(1s)` and check
client process status every second. On exit, prints:

- `Client process exited. File watcher is still active.` (exit code 0)
- `Warning: Client process exited with code N. File watcher is still
active.` (non-zero)

The file watcher continues running so module changes are still detected
and published.

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
2026-02-26 18:31:01 +00:00
Zeke Foppa bc4fcec6f3 cargo bump-versions properly updates the smoketests lockfile (#4462)
# Description of Changes

Previously `bump-versions` would push a failing commit because the
smoketests had a diff. This fixes that by having `bump-versions` update
that lockfile.

# API and ABI breaking changes

None.

# Expected complexity level and risk

1

# Testing

- [x] Ran `cargo bump-versions --all 3.0.0` and confirmed that the
lockfile was updated

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
v2.0.2
2026-02-26 11:06:23 +00:00
clockwork-labs-bot 350066ab4c spacetime dev - Fix file watcher ignoring --module-path / spacetime.json module_path (#4464)
## Summary

Fixes #4443 — `spacetime dev` ignores both `--module-path` CLI flag and
`module-path` in `spacetime.json` for the file watcher, always watching
`<project-path>/spacetimedb/` instead.

## Root Cause

Two bugs:

1. **Config's `module-path` never applied to `spacetimedb_dir`**: When
`spacetime.json` contains `module-path`, the recovery prompt is
correctly skipped (the code checks for its existence), but the value is
never used to update `spacetimedb_dir`. It stays as
`project_dir/spacetimedb`.

2. **Hardcoded fallback in `determine_publish_configs()`**: When there
are no publish targets in config (no `database` key or `children`), the
fallback creates a publish config entry with `module-path:
"spacetimedb"` hardcoded. This propagates to `extract_watch_dirs()`
(file watcher) and the publish loop, overriding any CLI or config value.

## Fix

1. After loading config, resolve `spacetimedb_dir` from config's
`module-path` in `additional_fields` when CLI did not provide
`--module-path`.

2. Pass the resolved `spacetimedb_dir` to `determine_publish_configs()`
as `default_module_path` so the fallback uses the correct path instead
of hardcoding `"spacetimedb"`.

## Testing

- All 5 existing `determine_publish_configs` tests pass
- Added new test
`test_determine_publish_configs_fallback_uses_provided_module_path` that
verifies the fallback uses the provided path

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
2026-02-26 11:06:21 +00:00
joshua-spacetime 9f47647d0f Reduce fsync interval to 10ms (#4466)
# Description of Changes

Reduce fsync interval from 50ms -> 10ms

# API and ABI breaking changes

None

# Expected complexity level and risk

1

Should be fine based on p99 latencies

# Testing

N/A
2026-02-26 11:06:19 +00:00
clockwork-tien 5764ade224 fix(docs): Rename spacerace to referrals for nav item (#4477)
# Description of Changes
- Rename `Spacerace` to `Referrals` for docs nav item to align with
updated naming

<!-- Please describe your change, mention any related tickets, and so on
here. -->

# Screenshots
- After:
<img width="1510" height="49" alt="image"
src="https://github.com/user-attachments/assets/3bdbe6ec-8a51-4686-9292-28c38b6d14d9"
/>

- Before:
<img width="1460" height="47" alt="image"
src="https://github.com/user-attachments/assets/5c70b0ef-d5fc-42fa-9dc9-5fd4f034d415"
/>


# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk
1

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [x] Docs displays correctly
2026-02-26 11:06:16 +00:00