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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 1.0.3 - 2026-10-18

- Add `docs/maintenance.md`. It tells you who maintains the package, how CI
checks each change, how a release is published, what you keep if
maintenance stops, and how to become a maintainer. The README and the
comparison pages now link to this page. They and `docs/versioning.md` no
longer state a count of maintainers. A new test fails when a page states
one.

## 1.0.2 - 2026-10-15

- Add four comparison pages in `docs/compare/`: Restate virtual objects, DBOS
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ explains the model and when to use it.

**Status.** Version 1.0: the public API follows semantic versioning and does
not break before 2.0. [Versioning](docs/versioning.md) gives the limits of the
promise. First public release: August 13, 2026. One maintainer.
promise. First public release: August 13, 2026.

**Production use.** One first-party application with more than 100,000 users
runs it in production. That is a count of users, not a measure of load. No
Expand Down Expand Up @@ -294,6 +294,7 @@ then shows a tested Solid Objects version with its limits:
- [Operations and recovery](docs/operations.md)
- [Observability and diagnostics](docs/observability.md)
- [Detailed architecture](docs/architecture.md)
- [Maintenance and continuity](docs/maintenance.md)
- [Detailed documentation](docs/)

The benchmarks, parity ledger, dashboard, browser setup, and exhaustive API
Expand Down
2 changes: 1 addition & 1 deletion docs/compare/dbos.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ How it works:

- First public release of the npm package: August 13, 2026.
- Version 1.0.0: October 13, 2026. The public API follows [semantic versioning](../versioning.md).
- One maintainer.
- [Maintenance and continuity](../maintenance.md) tells you who maintains the project and how a release is made.
- One first-party application with more than 100,000 users runs it in production. That is a count of users, not a measure of load. No production use by other people is known.
- The [benchmarks](../benchmarks.md) are development measurements. Longer soak tests are open work.

Expand Down
2 changes: 1 addition & 1 deletion docs/compare/graphile-worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ How it works:

- First public release of the npm package: August 13, 2026.
- Version 1.0.0: October 13, 2026. The public API follows [semantic versioning](../versioning.md).
- One maintainer.
- [Maintenance and continuity](../maintenance.md) tells you who maintains the project and how a release is made.
- One first-party application with more than 100,000 users runs it in production. That is a count of users, not a measure of load. No production use by other people is known.
- The [benchmarks](../benchmarks.md) are development measurements. Longer soak tests are open work.

Expand Down
2 changes: 1 addition & 1 deletion docs/compare/restate.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ A model call can run again after a crash, because effects run at least once. If

- First public release of the npm package: August 13, 2026.
- Version 1.0.0: October 13, 2026. The public API follows [semantic versioning](../versioning.md).
- One maintainer.
- [Maintenance and continuity](../maintenance.md) tells you who maintains the project and how a release is made.
- One first-party application with more than 100,000 users runs it in production. That is a count of users, not a measure of load. No production use by other people is known.
- The [benchmarks](../benchmarks.md) are development measurements. Longer soak tests are open work.

Expand Down
2 changes: 1 addition & 1 deletion docs/compare/rivetkit.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ How it works:

- First public release of the npm package: August 13, 2026.
- Version 1.0.0: October 13, 2026. The public API follows [semantic versioning](../versioning.md).
- One maintainer.
- [Maintenance and continuity](../maintenance.md) tells you who maintains the project and how a release is made.
- One first-party application with more than 100,000 users runs it in production. That is a count of users, not a measure of load. No production use by other people is known.
- The [benchmarks](../benchmarks.md) are development measurements. Longer soak tests are open work.

Expand Down
70 changes: 70 additions & 0 deletions docs/maintenance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Maintenance and continuity

This page tells you who maintains Solid Objects, how a release is made, and
what you keep if maintenance stops. It also tells you how to help maintain the
project.

## Who maintains it

Lucas Carlson ([@cardmagic](https://github.com/cardmagic)) is the lead
maintainer of the npm package `solid-objects` and of the Ruby gem
[`solid_objects`](https://github.com/cardmagic/solid-objects-ruby). The two
packages use the same model and the same correctness contract. A change to the
model goes into both packages, and the [parity ledger](parity.md) records each
difference between them.

The same maintainer sells [Solid Objects Pro](https://solidobjects.pro), a
commercial package that batches operations at scale. Pro depends on this
package. This package does not depend on Pro, and it needs no account, license
key, or service from the maintainer.

## How a change is checked

CI runs on each push and each pull request:

- Types, formatting, documentation links, the unit tests with coverage, and
the packaged artifact.
- The suite on the oldest supported Node.js version.
- The database suites on PostgreSQL and MySQL, and the Redis wake-up suite.
- The browser runtime in Chromium.

[Supported versions](support.md) lists the CI matrix. The
[correctness contract](correctness.md) lists the guarantees that the tests
check.

## How a release is made

1. The maintainer pushes a version tag, for example `v1.0.3`.
2. GitHub Actions runs all test jobs again on that tag.
3. If all test jobs pass, GitHub Actions publishes the package to npm with
trusted publishing. The repository keeps no npm token, and npm shows a
provenance attestation for each version.
4. The same job makes a GitHub release from the changelog.

[Releasing](releasing.md) gives the full procedure. [Versioning](versioning.md)
tells you what a release can change. [CHANGELOG.md](../CHANGELOG.md) lists each
release.

## What you keep if maintenance stops

- **Your data.** With the SQL runtime, actor state, mailboxes, reminders, and
effects are rows in your application's database. No service of the
maintainer holds your data.
- **The code.** The [MIT License](../MIT-LICENSE) lets anyone use, change,
fork, and publish the code.
- **The checks.** The tests and the CI configuration are in this repository. A
fork can check its changes with the same suite.

## Help maintain Solid Objects

The project wants more maintainers. Experience with TypeScript and Node.js,
with locks and transactions in PostgreSQL or MySQL, or with Rails helps.

1. Read [CONTRIBUTING.md](../CONTRIBUTING.md).
2. Send a small pull request: a fix, a test, or a correction to a guide.
3. After some of your pull requests are merged, open an
[issue](https://github.com/cardmagic/solid-objects-js/issues) to ask to
become a maintainer.

To report a vulnerability, use the private process in
[SECURITY.md](../SECURITY.md).
4 changes: 2 additions & 2 deletions docs/versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ change. A patch release does not raise a minimum version.

Version 1.0 is a promise about the API. It is not a claim of measured scale.
The [benchmarks](benchmarks.md) are development measurements and do not
guarantee capacity. Longer soak tests are open work. The project has one
maintainer, and no production use by other people is known.
guarantee capacity. Longer soak tests are open work. No production use by
other people is known.

## Releases before 1.0

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "solid-objects",
"version": "1.0.2",
"version": "1.0.3",
"description": "Fix race conditions across Node.js processes: ordered operations, expiring holds, and state that survives a restart, in your SQL database. A SQL-backed virtual actor library for TypeScript and Node.js.",
"type": "module",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const VERSION = "1.0.2"
export const VERSION = "1.0.3"
54 changes: 54 additions & 0 deletions test/maintenance-guide.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { existsSync, readdirSync, readFileSync } from "node:fs"
import { describe, expect, it } from "vitest"

const root = new URL("../", import.meta.url)
const maintainerCount =
/\b(?:\d+|one|two|three|four|five|six|seven|eight|nine|ten|only|sole|single)\s+maintainers?\b/i
const documentationPaths = [
"README.md",
"CONTRIBUTING.md",
"SECURITY.md",
...readdirSync(new URL("docs/", root), { encoding: "utf8", recursive: true })
.filter((path) => path.endsWith(".md"))
.sort()
.map((path) => `docs/${path}`),
]

function read(path: string): string {
return existsSync(new URL(path, root)) ? readFileSync(new URL(path, root), "utf8") : ""
}

describe("maintenance guide", () => {
it("is linked from the README", () => {
expect(read("README.md")).toContain("(docs/maintenance.md)")
})

it("names the lead maintainer", () => {
expect(read("docs/maintenance.md")).toMatch(
/Lucas Carlson \(\[@cardmagic\]\(https:\/\/github\.com\/cardmagic\)\) is the lead\s+maintainer/,
)
})

it("has a count pattern that finds a count of maintainers in each form", () => {
for (const text of [
"One maintainer.",
"1 maintainer",
"two maintainers",
"the only\nmaintainer",
]) {
expect(text).toMatch(maintainerCount)
}
for (const text of ["the lead maintainer", "wants more maintainers", "become a maintainer"]) {
expect(text).not.toMatch(maintainerCount)
}
})

it("has no page in the documentation that states a count of maintainers", () => {
const pages = documentationPaths.filter((path) => maintainerCount.test(read(path)))
expect(pages).toEqual([])
})

it("tells a contributor how to start", () => {
expect(read("docs/maintenance.md")).toContain("(../CONTRIBUTING.md)")
})
})
Loading