diff --git a/CHANGELOG.md b/CHANGELOG.md index 95a2991..4b273fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index c948db9..855bf50 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 diff --git a/docs/compare/dbos.md b/docs/compare/dbos.md index 8b2f2b1..0d1b7c7 100644 --- a/docs/compare/dbos.md +++ b/docs/compare/dbos.md @@ -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. diff --git a/docs/compare/graphile-worker.md b/docs/compare/graphile-worker.md index 90a5b95..be8c181 100644 --- a/docs/compare/graphile-worker.md +++ b/docs/compare/graphile-worker.md @@ -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. diff --git a/docs/compare/restate.md b/docs/compare/restate.md index a36e3b8..6d2fb52 100644 --- a/docs/compare/restate.md +++ b/docs/compare/restate.md @@ -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. diff --git a/docs/compare/rivetkit.md b/docs/compare/rivetkit.md index b66cd4b..2dcb68e 100644 --- a/docs/compare/rivetkit.md +++ b/docs/compare/rivetkit.md @@ -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. diff --git a/docs/maintenance.md b/docs/maintenance.md new file mode 100644 index 0000000..d51b604 --- /dev/null +++ b/docs/maintenance.md @@ -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). diff --git a/docs/versioning.md b/docs/versioning.md index 1898a46..d0d3e07 100644 --- a/docs/versioning.md +++ b/docs/versioning.md @@ -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 diff --git a/package.json b/package.json index 6b045ea..a4e8edf 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/version.ts b/src/version.ts index d688532..44dcd98 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = "1.0.2" +export const VERSION = "1.0.3" diff --git a/test/maintenance-guide.test.ts b/test/maintenance-guide.test.ts new file mode 100644 index 0000000..9a2522f --- /dev/null +++ b/test/maintenance-guide.test.ts @@ -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)") + }) +})