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
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,27 @@ jobs:
bundler-cache: true
- run: bundle exec rubocop

docs:
name: Docs
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
fetch-depth: 0
- uses: ruby/setup-ruby@762794c140bbeda0f1224786aa33b4b46783a6c1 # v1.326.0
with:
ruby-version: "3.4"
bundler-cache: true
- run: bundle exec rake docs:check
# A warning on each page whose sources this pull request changed while the page did not.
- if: github.event_name == 'pull_request'
run: bundle exec rake docs:stale
env:
BASE: origin/${{ github.base_ref }}

# No converters installed here, on purpose. The three hotcell gems claim to be testable with no toolchain and
# no container, and a job that installed libvips would stop that claim from being checked.
hotcell:
Expand Down
43 changes: 35 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
# HotCell
# Hot Cell

This project includes a set of core gems used to isolate untrusted code or handling untrusted input:
hotcell-core, hotcell-server, and hotcell-client.
This repository holds the core gems that isolate untrusted code and untrusted input (`hotcell-core`,
`hotcell-server`, and `hotcell-client`), the Active Storage gems built on them
(`activestorage-hotcell-client` and `activestorage-hotcell-server`), and `yabeda-hotcell`.

It also includes a set of gems that build on the HotCell gems to provide drop-in replacement for
Active Storage analyzers, transformers, and previewers: activestorage-hotcell-client and
activestorage-hotcell-server.
## Find your way around

## How to develop this project.
The docs are in sibling sections, and each section's index lists its pages with a one-line description, so
you can pick the page you need without opening the others:

@CONTRIBUTING.md
- [`docs/index.md`](docs/index.md): the reference manual, which describes behavior.
- [`docs/design/index.md`](docs/design/index.md): the design rationale.
- [`docs/contributing/index.md`](docs/contributing/index.md): working on the gems.

Each page's frontmatter names the code it describes, under `sources`.

The numbered invariants in [`docs/design/invariants.md`](docs/design/invariants.md) and the numbered
experiments in [`docs/contributing/experiments.md`](docs/contributing/experiments.md) are cited by number from code,
tests, and docs. Never renumber them.

## Keep the docs current

@docs/contributing/docs.md

## Write the docs

- The README is the introduction for people: what Hot Cell is, and a quick start. Keep it short, and link
to a reference page for details instead of repeating them.
- The pages in `docs/` are a reference manual, written for agents first and readable by people. Write them
in [Google developer documentation style](https://developers.google.com/style): second person, present
tense, active voice, sentence-case headings, numbered lists for steps, and tables for settings.
- Keep one topic on each page, and keep each fact on one page. Link to it from everywhere else.
- The pages in `docs/design/` record rationale, not behavior. Change them when a decision changes. Record a
decision that was argued in [`adr/`](docs/contributing/decisions.md).

## Working on the gems

@docs/contributing/guide.md
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ This changelog covers these gems, which release together on the same version:
A `Tooling` section records changes to the checks and scripts in `bin/` and `examples/`, which ship in no
gem but are what an operator runs against their own image.

## next / unreleased

### Documentation

* The README is a short introduction and quick start, and the details are in a reference manual with one topic per page, starting at [docs/index.md](docs/index.md). `docs/DESIGN.md`, `docs/DEPLOYMENT.md`, `docs/TUNING.md` and `docs/LOGS.md` are gone. Their content is in [docs/design/](docs/design/index.md), [docs/container.md](docs/container.md), [docs/cell-settings.md](docs/cell-settings.md), [docs/client-api.md](docs/client-api.md), [docs/tuning.md](docs/tuning.md), [docs/scratch.md](docs/scratch.md) and [docs/observability.md](docs/observability.md).

## v0.6.0 / 2026-10-01

### Upgrading
Expand Down Expand Up @@ -113,7 +119,7 @@ Some actions that application developers should consider taking when upgrading f
Some actions that application developers should consider taking when upgrading from an earlier version:

* Log `stderr` from the `perform.hot_cell` event in the client Rails application. This improves observability and provides forensic evidence about cell crashes.
* Set `MAGICK_MEMORY_LIMIT`, `MAGICK_MAP_LIMIT` and `MAGICK_DISK_LIMIT` in a cell image that installs ImageMagick. See [docs/IMAGEMAGICK.md](docs/IMAGEMAGICK.md).
* Set `MAGICK_MEMORY_LIMIT`, `MAGICK_MAP_LIMIT` and `MAGICK_DISK_LIMIT` in a cell image that installs ImageMagick. See [docs/imagemagick.md](docs/imagemagick.md).

### HotCell::Client

Expand Down Expand Up @@ -192,7 +198,7 @@ Some actions that application developers should consider taking when upgrading f

#### Added

* `request`, `request.abandoned`, `worker.crashed`, `worker.killed` and `worker.undispatchable` carry `hotcell.op`, the operation the line is about. A cell runs several operations at once and they do not share limits, so `worker.killed cause=fsize` on a host serving three PDF operations named none of them, and no join was available elsewhere: the response carries no operation, and `hotcell_killed` is tagged `cell` and `cause` only. The worker parses the name out of the request; the supervisor, which never reads one, learns it from the worker's report and holds it, because a killed worker cannot write its own `worker.killed`. Where the name is not known the field is `null` rather than an earlier request's name. See [docs/LOGS.md](docs/LOGS.md).
* `request`, `request.abandoned`, `worker.crashed`, `worker.killed` and `worker.undispatchable` carry `hotcell.op`, the operation the line is about. A cell runs several operations at once and they do not share limits, so `worker.killed cause=fsize` on a host serving three PDF operations named none of them, and no join was available elsewhere: the response carries no operation, and `hotcell_killed` is tagged `cell` and `cause` only. The worker parses the name out of the request; the supervisor, which never reads one, learns it from the worker's report and holds it, because a killed worker cannot write its own `worker.killed`. Where the name is not known the field is `null` rather than an earlier request's name. See [docs/observability.md](docs/observability.md#cell-log).

* `worker.undispatchable` is the one line where the supervisor reads a request, since the worker died before the dispatch write and nothing else has read it. It peeks rather than reads, taking neither the bytes nor the caller's descriptors off the connection, and never waits for a request that has not arrived.

Expand Down
Loading
Loading