Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ permissions:
contents: read

jobs:
crate:
name: Crates.io dry run
runs-on: ubuntu-22.04
timeout-minutes: 35
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: ./.github/actions/setup-rust
with:
cache-key: crate
- run: just publish-dry-run

release:
name: Release binary
# Keep the build compatible with the container's glibc 2.36.
Expand Down
53 changes: 53 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Changelog

User-visible changes are recorded here.

## Unreleased

## 0.0.1 - 2026-09-15

### Added

- Serve database-backed HTTP APIs from SQL files with explicitly typed parameters
and validated response schemas. Use SQLRest as a standalone process or embed
its Rust library. See [Getting started](docs/getting-started.md).
- Use local Turso databases or remote/shared PostgreSQL databases through the
same publication and request interfaces.
- Publish database configuration, forward migrations and SQL interfaces with
one operation. Persist configuration and recovery state in a fixed TOML-based
workspace so healthy databases recover after restart without registration
replay. Unregister without deleting database or source files.
- Execute requests transactionally, validating result columns, values and JSON
before commit. Enforce execution deadlines and maximum final rows with errors,
not silent truncation; enforce read-only GET and HEAD requests.
- Export OpenAPI 3.1 from the published interface snapshot, including
self-contained recursive response schemas, for client generation.
- Recover edited or missing migration files from saved original SQL history.
Poll publication/unregistration operations and inspect per-database status
through the management API.
- Keep public errors sanitized while retaining private driver diagnostics for
runtime operators; drain accepted work during graceful shutdown.
- Start from working [Todolist](examples/todolist/README.md) and
[Ledger](examples/ledger/README.md) examples for both backends, generated
TypeScript client examples, and a distributable
[Agent runtime skill](skills/sqlrest-runtime/SKILL.md).

### Initial release boundaries

- Linux is the verified delivery platform. Turso dependencies are pinned to
`0.8.0-pre.10`; PostgreSQL connections are currently explicitly unencrypted.
- Authentication, TLS termination and exposure protection belong to the Agent
runtime/deployer. Protect both HTTP listeners; SQL is trusted configuration,
not a sandbox.
- MySQL, down migrations, filesystem watchers and persistent operation queues
are not implemented. Operation history does not survive process restart.
- Large JSON integers are not automatically stringified for JavaScript clients.
Database backups remain the deployer's responsibility.

### For contributors

- Run local verification through the Justfile. CI runs quality, backend and SDK
checks in parallel, then requires every lane and container verification to
succeed through the aggregate `delivery` check.
- Generate SDKs with the pinned openapi-nexus release binary, without compiling
the generator from source. See [delivery verification](docs/delivery.md).
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
[package]
name = "sqlrest"
version = "0.1.0"
version = "0.0.1"
edition = "2024"
rust-version = "1.98"
license = "MIT OR Apache-2.0"
description = "Typed SQL interfaces over HTTP"
repository = "https://github.com/rust-codegen-group/sqlrest"
readme = "README.md"
keywords = ["sql", "rest", "database", "agent", "turso"]
categories = ["database", "web-programming::http-server"]
publish = ["crates-io"]

[dependencies]
axum = "0.8"
Expand Down
8 changes: 8 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ sdk-schema:
release:
cargo build --release --locked

# Verify the actual crate archive without uploading anything.
publish-dry-run:
cargo publish --locked --registry crates-io --dry-run

# Upload the current crate to crates.io. Does not create or push Git tags.
publish:
cargo publish --locked --registry crates-io

# Package an existing release binary and exercise its container lifecycle.
container:
docker build --tag sqlrest:ci .
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ do not expose the management port to users. No auth, TLS or CORS is installed.
Includes restart, polling, history repair and checking behavior after publish.
- [Container and verification](docs/delivery.md): pinned inputs, local image,
complete test gates and CI.
- [Changelog](CHANGELOG.md): user-visible changes and release boundaries.

## Contracts

Expand Down
38 changes: 36 additions & 2 deletions docs/delivery.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,14 @@ runs its lifecycle tests. These two remain separate from the default `all` group
| `quality.yml` | Format, Clippy | Rust; native tools/cache only for Clippy |
| `tests.yml` | Turso/default contracts, PostgreSQL contracts | PostgreSQL service only for its matrix entry |
| `sdk.yml` | Turso SDK, PostgreSQL SDK, recursive schema | SDK tools; separate empty PostgreSQL service only for PG |
| `package.yml` | Release binary, then container lifecycle | Container downloads the binary built in the same run |
| `package.yml` | Crates.io dry run; release binary, then container lifecycle | Container downloads the binary built in the same run |

The four workflows start independently. Database and SDK matrices use
`fail-fast: false` so a failure does not cancel other diagnostic results.
Composite actions in `.github/actions/` share Rust/native/cache setup and SDK
tool installation. Rust comes from `rust-toolchain.toml`; Clippy, tests and release
use separate cache partitions. SDK jobs share the tests partition.
use separate cache partitions. SDK jobs share the tests partition; crate
verification has its own partition.
The artifact is a candidate until the complete CI run succeeds; it is not a
published release.

Expand All @@ -151,6 +152,39 @@ push and pull-request runs for the same feature branch.
No remote CI run or release is implied by checking in a workflow; local validation
and hosted CI are distinct evidence.

## Publishing to crates.io

`Cargo.toml` is the version source for the crate, CLI and exported OpenAPI.
Prepare a release PR updating its version, the root package in `Cargo.lock`
and `CHANGELOG.md`. Merge only after the complete `delivery` check passes,
including the crate dry run.

From a clean checkout of that exact release commit, verify the crate archive:

```sh
just publish-dry-run
```

This runs Cargo's packaging and build verification without uploading. It is
separate from the full backend/SDK tests and does not prove crates.io ownership
or token permissions. Authenticate with `cargo login --registry crates-io` or
provide `CARGO_REGISTRY_TOKEN` through your secret manager, then:

```sh
just publish
```

This uploads the library and binary crate to crates.io. Cargo's clean-tree and
package-verification checks remain enabled. A published version cannot be
overwritten; inspect crates.io before retrying an upload with an uncertain result.
The maintainer creates and pushes the matching `v0.0.1` tag on the same commit.
Neither recipe creates tags, GitHub Releases or container releases, and CI never
uploads to crates.io automatically.

After publication, consumers can install the CLI with
`cargo install sqlrest --version 0.0.1 --locked` or depend on
`sqlrest = "0.0.1"`. The native build prerequisites above still apply.

## Embedding, backups and trust

`Registry` and `http::Server` are public Rust entrypoints. Keep Tokio alive until
Expand Down
4 changes: 2 additions & 2 deletions examples/sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Verified inputs:
- Node.js 24.15.0 and TypeScript 6.0.3

Download the pinned release binary, not the generator source. The shared CI/local
script downloads and extracts the Linux x86_64 musl archive. It requires Bash,
curl, tar and xz. Install TypeScript in a disposable tools directory or
Justfile recipe downloads and extracts the Linux x86_64 musl archive. It requires
Just 1.58.0, Bash, curl, tar and xz. Install TypeScript in a disposable tools directory or
use an existing matching installation; put its `tsc` on PATH.

```sh
Expand Down
2 changes: 1 addition & 1 deletion src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ fn insert_body(schema: &mut Value, path: &[String], leaf: Value) {
fn build_openapi(endpoints: &[Arc<Endpoint>]) -> Result<Value, SqlrestError> {
let mut document = json!({
"openapi": "3.1.0",
"info": {"title": "SQLRest", "version": "0.1.0"},
"info": {"title": "SQLRest", "version": env!("CARGO_PKG_VERSION")},
"paths": {},
"components": {"schemas": {}}
});
Expand Down
1 change: 1 addition & 0 deletions tests/loading_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ fn snapshot_routes_body_and_openapi_are_one_contract() {
405
);
let openapi = snapshot.openapi("/db/personal");
assert_eq!(openapi["info"]["version"], env!("CARGO_PKG_VERSION"));
assert_eq!(
openapi["components"]["schemas"]["PatchTodosByIdInput"]["properties"]["input"]["properties"]
["completed"]["type"],
Expand Down
Loading