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
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ jobs:
- run: bundle exec rake
- run: bundle exec rake at_least_once

quickstart:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1
with:
ruby-version: "3.3"
bundler-cache: true
- run: bundle exec rake quickstart

javascript:
runs-on: ubuntu-latest
timeout-minutes: 15
Expand Down Expand Up @@ -148,6 +159,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/v')
needs:
- sqlite
- quickstart
- postgresql
- mysql
- static
Expand Down
7 changes: 7 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ git push origin v0.5.0

CI validates the tag and publishes through RubyGems trusted publishing.

Before you tag, read `docs/virtual-actors.md` and `docs/agents.md` against the
release and correct any requirement, compatibility, or guarantee statement that
changed. After the tag publishes, refresh the solidobjects.dev documentation
snapshot from the tag and redeploy the site; its `check:release` step refuses a
snapshot that is not the latest published tag. Then trigger a Context7 refresh
for this repository.

## Security & Configuration

Preserve deny-by-default authorization. Never treat actor IDs, stream names, or signed tokens as authorization, and never commit secrets or unsafe deserialization paths.
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# Changelog

## 0.17.1 - 2026-10-08

- Name the category in the gem metadata and the README: Solid Objects is a
SQL-backed virtual actor library for Ruby on Rails. The gem homepage now
links to `https://solidobjects.dev/ruby` instead of the site root, which
redirects to the Node page.
- Add `docs/virtual-actors.md`, a category guide with the definition, a small
example, fit and poor-fit criteria, comparisons, and an Orleans concept map.
- Add `docs/agents.md`, a consumer guide for coding agents with setup,
authorization, effect idempotency, verification, and troubleshooting steps.
Both guides ship in the gem.
- Add `context7.json` so that Context7 indexes the consumer documentation and
skips maintainer files.
- Add a Rails quickstart in `examples/quickstart/` and a `rake quickstart`
check that runs it against the built gem. The check builds the gem, creates
a new SQLite Rails application, installs the gem from `vendor/cache` with
`bundle install --local`, and confirms by checksum and load path that the
application loads the built gem. It runs the install generator, the
migrations, and the doctor, and grants only the message and query policies.
It sends eight concurrent holds from separate processes to the README's
`TicketSale` actor and confirms that exactly one hold commits. It stops the
runtime, waits until a reminder is past due, confirms that the reminder did
not run, restarts the runtime, and confirms that the reminder released the
hold once. The check also fails when a `TicketSale` sample in the README or
in `docs/` differs from the actor that it runs. A new `quickstart` CI job runs
the check, and the release job waits for it.
- Correct the `json` 3.x note in `docs/operations.md`. The `json` gem 3.x works
only with Active Support 8.1.4 or newer. Active Support 7.1, 7.2, and 8.0
raise `unknown keyword: quirks_mode`, and Active Support 8.1.3.1 and earlier
8.1 releases fail to decode. Upgrade Rails to 8.1.4 or newer, or pin `json`
to 2.x. The compatibility CI matrix now pins `json` 2.x for Rails 7.1, 7.2,
and 8.0, the configuration that the guide prescribes.

## 0.17.0 - 2026-10-03

- Publish RBS types for portable events, metric samples, actor diagnostics, and
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ if rails_version
%w[actioncable actionpack actionview activerecord activesupport railties].each do |library|
gem library, constraint
end
gem "json", "~> 2" if Gem::Version.new(rails_version) < Gem::Version.new("8.1")
end

group :development, :test do
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
solid_objects (0.17.0)
solid_objects (0.17.1)
actioncable (>= 7.1)
actionpack (>= 7.1)
actionview (>= 7.1)
Expand Down Expand Up @@ -384,7 +384,7 @@ CHECKSUMS
rubocop-rails-omakase (1.1.0) sha256=2af73ac8ee5852de2919abbd2618af9c15c19b512c4cfc1f9a5d3b6ef009109d
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
solid_objects (0.17.0)
solid_objects (0.17.1)
sqlite3 (2.9.5-aarch64-linux-gnu) sha256=78075b6337d3d182c6d2b4691049ed45cd220826160c9ea18946bf6a1de200dc
sqlite3 (2.9.5-aarch64-linux-musl) sha256=18c801185deb4adc01ddb281e8f672a39e3d1729979ca91e39439cd3eac0402d
sqlite3 (2.9.5-arm-linux-gnu) sha256=1bdfca0c7d63998c60b0f4a8e3c8df2d33800ccc4abd2d612eddbbbc92a4c48b
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@

**Open Source Durable Objects in your Rails app.**

Solid Objects is a SQL-backed virtual actor library for Ruby on Rails, with
durable state, ordered operations, and automatic activation. Each actor has a
stable identity, and its state lives in the SQL database that your app already
uses. [Virtual actors in Ruby on Rails](docs/virtual-actors.md) explains the
model and when to use it.

In a shopping cart, paying twice at the same time is a big problem. The payment provider might time out, and your Rails site could be restarting before recovery finishes.

To deal with this safely, you often need logic scattered between 7-10 files like database row locks, Redis locks, delayed jobs, retries, and cleanup code to keep that process straight. They are not all large, but they must agree about the same payment state and failure rules. That coordination is the difficult part.
Expand Down Expand Up @@ -160,6 +166,8 @@ Exactly once is not hiding in a more advanced configuration. Read the
## Read more

- [Five-minute Rails guide](https://solidobjects.dev/5min/rails)
- [Virtual actors in Ruby on Rails](docs/virtual-actors.md)
- [Guide for coding agents](docs/agents.md)
- [Choosing Solid Objects](docs/fit.md)
- [Operations and recovery](docs/operations.md)
- [Observability and diagnostics](docs/observability.md)
Expand Down
5 changes: 5 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ task :at_least_once do
sh "bundle exec ruby examples/at_least_once/demo.rb"
end

desc "Install the built gem into a new Rails app and prove ordering and restart recovery"
task :quickstart do
sh "bundle exec ruby examples/quickstart/smoke.rb"
end

desc "Scan the Rails engine for security warnings"
task :security do
sh "bundle exec brakeman --force --no-pager -q ."
Expand Down
29 changes: 29 additions & 0 deletions context7.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "https://context7.com/schema/context7.json",
"projectTitle": "Solid Objects for Rails (solid_objects)",
"description": "SQL-backed virtual actor library for Ruby on Rails. Actors have stable identities, durable JSON state in SQLite, PostgreSQL, or MySQL, ordered per-identity mailboxes, fenced activation, durable reminders, and transactional effects. Requires Ruby 3.3+ and Rails 7.1+.",
"folders": [
"docs",
"examples"
],
"excludeFolders": [
"./docs/adr",
"./docs/research"
],
"excludeFiles": [
"AGENTS.md",
"CLAUDE.md",
"CONTRIBUTING.md",
"implementation-plan.md"
],
"rules": [
"Solid Objects requires Rails 7.1 or newer and Ruby 3.3 or newer. It is a Rails engine, not a framework-independent Ruby library.",
"Install with bundle add solid_objects, bin/rails generate solid_objects:install, bin/rails db:migrate, and bin/rails solid_objects:doctor.",
"The json gem 3.x works only with Active Support 8.1.4 or newer. On Rails 7.1, 7.2, 8.0, or 8.1 before 8.1.4, pin gem \"json\", \"~> 2\".",
"The generated authorization policies deny every operation. Production policies must bind the actor type and ID to the authenticated user or tenant, and callers pass authorization_context:.",
"Run bundle exec solid_objects start for reminders, async calls, effects, and broadcasts. Direct synchronous calls do not need it.",
"Delivery is at least once. Effect handlers registered with SolidObjects.register_effect must use context.id as the idempotency key.",
"Actor handlers must not write Active Record models directly. Use commit_action for a short same-database write and emit for external I/O.",
"There are no transactions across actor identities. One hot identity is sequential."
]
}
Loading
Loading