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
10 changes: 4 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,13 @@ jobs:
run: |
rustup toolchain install 1.98.0 --profile minimal --component rustfmt --component clippy
sudo apt-get update
sudo apt-get install -y clang libclang-dev pkg-config postgresql-client
sudo apt-get install -y clang libclang-dev pkg-config postgresql-client curl xz-utils
npm install --prefix "$RUNNER_TEMP/sqlrest-typescript" --ignore-scripts typescript@6.0.3
echo "$RUNNER_TEMP/sqlrest-typescript/node_modules/.bin" >> "$GITHUB_PATH"
- name: Build pinned openapi-nexus from source
- name: Download pinned openapi-nexus binary
run: |
git clone --no-checkout https://github.com/rust-codegen-group/openapi-nexus.git "$RUNNER_TEMP/openapi-nexus"
git -C "$RUNNER_TEMP/openapi-nexus" checkout --detach 1f8e1d8a3264d697c3aca8db7db01148d878115a
cargo +1.98.0 build --locked --manifest-path "$RUNNER_TEMP/openapi-nexus/Cargo.toml" --bin openapi-nexus
echo "OPENAPI_NEXUS_BIN=$RUNNER_TEMP/openapi-nexus/target/debug/openapi-nexus" >> "$GITHUB_ENV"
bash scripts/download-openapi-nexus.sh "$RUNNER_TEMP/openapi-nexus"
echo "OPENAPI_NEXUS_BIN=$RUNNER_TEMP/openapi-nexus/openapi-nexus" >> "$GITHUB_ENV"
- name: Create empty example database
env:
PGPASSWORD: sqlrest
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
*.db
*.db-wal
*.db-shm

.sqlrest.lock
.database-*.tmp
**/databases/*/database.toml
62 changes: 62 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ heck = "0.5"
futures-util = "0.3"
tokio-util = { version = "0.7", features = ["rt"] }
same-file = "1"
toml = "0.9"
uuid = { version = "1", features = ["v4"] }

[dev-dependencies]
tempfile = "3"
Expand Down
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
Typed SQL files → database-backed HTTP APIs for agent runtimes.

SQLRest is a Rust library and a standalone HTTP service. An agent writes SQL and
response schemas; the runtime registers a database and publishes its interfaces.
response schemas in a fixed workspace; one publish call registers the database,
applies pending migrations and publishes its interfaces.
Turso is the default local backend; PostgreSQL supports remote/shared databases.
There is no site or user model, authentication, UI renderer, or runtime SDK dependency.

Expand All @@ -28,7 +29,7 @@ properties:

Success is always `{"records":[...]}`. SQL values are bound parameters. Requests
are transactional; result validation and serialization happen before commit.
Reload is explicit and atomic, and the published OpenAPI comes from the same snapshot.
Publication is explicit and atomic, and OpenAPI comes from the same snapshot.

## Try it

Expand All @@ -42,15 +43,16 @@ python3 scripts/e2e.py

This executable tutorial starts a real service with fresh temporary files, runs
both Todolist and Ledger examples, verifies CRUD, retry keys, ID arrays and migration
history repair, restarts the process, re-registers and verifies persistence. It
history repair, restarts the process and verifies automatic recovery without replay. It
then removes **only its temporary data**. It does not start a browser or retain
an application for continued use.

For a persistent application, follow [Getting started](docs/getting-started.md).
Run the service with explicit addresses, for example:

```sh
target/debug/sqlrest --data-listen 127.0.0.1:8080 --management-listen 127.0.0.1:8081
target/debug/sqlrest --workspace /data/sqlrest \
--data-listen 127.0.0.1:8080 --management-listen 127.0.0.1:8081
```

Any bindable address is allowed. The addresses above are examples, not enforced
Expand All @@ -65,7 +67,7 @@ do not expose the management port to users. No auth, TLS or CORS is installed.
strict compilation and real requests, without adding a service dependency.
- [Runtime skill](skills/sqlrest-runtime/SKILL.md): copy the entire
`skills/sqlrest-runtime` directory into your runtime's skill distribution.
Includes restart, polling, history repair and checking behavior after auto-resume.
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.

Expand All @@ -87,8 +89,9 @@ Important boundaries:
stringification is implemented. Use deliberate application constraints/encoding.
- A lost response or `commit_outcome_unknown` is not proof of rollback.
Check stable business IDs before retrying.
- The runtime persists registration configs, appoints one migrator per real PG
database, and prevents multiple processes opening the same Turso file.
- SQLRest persists configuration and recovery state in its workspace. The runtime
appoints one migrator per real PG database and avoids sharing Turso files across
different workspaces. One Registry owns a workspace at a time.
- Migration source history is for recovery, **not a database backup**. Arrange
independent backups and test restoration before destructive changes.
- MySQL, TLS-enabled PostgreSQL connections, down migrations, background watchers
Expand Down
24 changes: 16 additions & 8 deletions docs/delivery.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ claim or automatic upgrade.
Linux is the verified delivery platform. CI runs Ubuntu 22.04, tests against
PostgreSQL **18.3** from pinned `postgres:18-alpine` digest
`sha256:54451ecb8ab38c24c3ec123f2fd501303a3a1856a5c66e98cecf2460d5e1e9d7`,
and uses Node **24.15.0**, TypeScript **6.0.3**, and openapi-nexus revision
`1f8e1d8a3264d697c3aca8db7db01148d878115a`.
and uses Node **24.15.0**, TypeScript **6.0.3**, and the openapi-nexus **0.2.3**
release binary. CI and local SDK verification use
`scripts/download-openapi-nexus.sh` to download and extract the Linux x86_64 musl
archive. No generator source is cloned or compiled; download or extraction
errors fail the setup.

On Ubuntu 22.04:

```sh
sudo apt-get update
sudo apt-get install -y build-essential clang libclang-dev pkg-config python3 curl jq
sudo apt-get install -y build-essential clang libclang-dev pkg-config python3 curl jq xz-utils
cargo build --locked
cargo test --locked
```
Expand Down Expand Up @@ -57,11 +60,13 @@ docker run --name sqlrest-demo \
--user "$(id -u):$(id -g)" \
--mount "type=bind,src=$SQLREST_DEMO,dst=/workspace" \
-p 127.0.0.1:8080:8080 -p 127.0.0.1:8081:8081 \
sqlrest:local --data-listen 0.0.0.0:8080 --management-listen 0.0.0.0:8081
sqlrest:local --workspace /workspace \
--data-listen 0.0.0.0:8080 --management-listen 0.0.0.0:8081
```

`SQLREST_DEMO` is the absolute persistent directory from the getting-started guide.
Adjust registration paths to `/workspace/todolist/...` **inside the container**.
The fixed layout is `/workspace/databases/todolist/...` inside the container;
publish requests do not carry paths.
Default image user is numeric 65532; the example uses the caller's UID/GID for
bind-mount access. This does not restrict socket addresses. Proxy authorization
and exposure policy still belong to the runtime/deployer.
Expand All @@ -81,9 +86,12 @@ Provision two disposable PG databases: a core-test database and a separate
new for another run. Then:

```sh
SQLREST_TOOLS=$(mktemp -d)
bash scripts/download-openapi-nexus.sh "$SQLREST_TOOLS/openapi-nexus"

SQLREST_TEST_POSTGRES='postgresql://user:password@host/core_test' \
SQLREST_EXAMPLES_POSTGRES='postgresql://user:password@host/examples_test' \
OPENAPI_NEXUS_BIN=/absolute/path/to/openapi-nexus \
OPENAPI_NEXUS_BIN="$SQLREST_TOOLS/openapi-nexus/openapi-nexus" \
bash scripts/check.sh
```

Expand All @@ -107,13 +115,13 @@ by checking in a workflow; local verification and hosted CI are distinct evidenc
`Registry::shutdown().await` or graceful `Server::serve` completion. A forcibly
stopped runtime cannot attest rollback or commit state.

Keep runtime configuration and database backups independently. Recovering original
Keep workspace configuration and database backups independently. Recovering original
migration source repairs history mismatch; it cannot recover deleted business
data. Designate one migrator for each PG database and one process owner for a
Turso file. Shared DB aliases do not create isolation or separate migration history.

The bundled skill is self-contained: distribute `skills/sqlrest-runtime` as a
directory. It directs the agent to check actual behavior after automatic resume,
directory. It directs the agent to check actual behavior after publish,
preserve edited historical files before restoration, poll asynchronous operations
and avoid blind retries after an unknown commit. It is guidance, not a security
boundary or a substitute for runtime authorization.
Loading
Loading