Modernize to Rails 8 / Ruby 3.2, add tests, security fixes, and turnkey Docker#36
Modernize to Rails 8 / Ruby 3.2, add tests, security fixes, and turnkey Docker#36kltm wants to merge 7 commits into
Conversation
Upgrade rails 5.1.7 -> 8.0.3 and ruby 2.7.8 -> 3.2.9; move ontologies_api_client to its GitHub tag v2.9.0 (the modern, activesupport-8 line) and drop the faraday-v1 / dalli_store-era workarounds. Replace turbolinks/coffee/uglifier (uglifier -> terser; Sprockets retained via sprockets-rails), add config/storage.yml, use the positional enum syntax, set load_defaults 8.0, and regenerate schema.rb in the Rails 8 dump format. The license-key format is unchanged (verified byte-stable across OpenSSL 1.1 -> 3). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The app shipped without working tests. Add characterization + integration tests covering the license-key crypto contract, the License date / latest_licenses helpers, login + access control (anon/owner/admin), and the approve -> key -> email flow; the two BioPortal API calls are stubbed at the boundary. Fix the placeholder fixtures; load the per-env config and use an in-memory cache store in test so flash/session persist across redirects. (minitest is pinned to ~> 5.25 in the Gemfile -- Rails 8 is incompatible with minitest 6.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remove the blanket skip_before_action :verify_authenticity_token so CSRF is enforced again. Replace params[:license].permit! with explicit strong params; this also closes a privilege escalation where a non-admin could submit approval_status=approved and have a license key generated. Parameterize the user-scoped query in init_max_ids via Active Record rather than string-interpolated SQL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Dockerfile (Ruby 3.2.9, puma, asset precompile) plus docker-compose.yml wiring app + mysql + memcached, an ENV-driven config template, and an entrypoint that renders config, prepares the database, and launches puma. 'docker compose up --build' brings up a working instance (auto migrate/seed). No secrets are baked into the image; .dockerignore excludes local config, keys, and tmp/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@jvendetti I was wondering if I was on the right path here (developing on Ubuntu 24.04). I was wondering if you could take a quick look at this for me; running would look like:
|
|
Hi @kltm - sure, took a quick look and this seems like the right path. I was able to run the compose command you listed to bring up the license server and login with my BP account:
|
|
Great--thank you for taking a look at it. I'm going to poke at it a little more, but I think there may be enough there to me usable. I'll try and figure out a better way to test. |
GitHub Actions (.github/workflows/test.yml) runs the Minitest suite on push/PR against a MySQL service. Add a 'test' service to docker-compose (built with the test gem group, under the 'test' profile) so the suite runs with 'docker compose run --rm test'. Make the Dockerfile BUNDLE_WITHOUT an ARG so that image can include the test group. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
BioPortal accounts can have a nil firstName/lastName; LicensesController#new called nil.strip, raising a 500 on the Create License form. Coerce with to_s before stripping. Includes a regression test -- the first real bug caught by the new test suite / CI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
A note to clarify deployment, since this PR adds a Docker path alongside the existing Capistrano setup. Choosing between them is an NCBO decision — this PR deliberately doesn't settle it.
Two things to be aware of if you adopt Docker for production:
Happy to implement whichever direction you prefer. — Posted by Claude Code agent on behalf of @kltm. |
CLAUDE.md documents the app, its architecture, configuration, the Docker run/test workflow, and gotchas for future changes. docs/plans/ holds dated design notes and the record of the Rails 8 / Ruby 3.2 modernization (repo + issue survey, a behavioral characterization, approach/findings, and the upgrade plan). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@jvendetti I believe that this should cover the main target (update/refresh and dockerization), as well as #20 in order to test the tests added with the refresh. |

Status: WIP / draft — for evaluation, not yet ready to merge.
This modernizes the License Server end-to-end and packages it so it can be stood
up with a single command for evaluation. It is an in-place upgrade, so the
diff stays reviewable.
What's in this PR (4 commits)
ontologies_api_client→ itsGitHub tag
v2.9.0; puma instead of Passenger; the Sprockets pipeline isretained (
sprockets-rails);uglifier→terser; turbolinks/coffee dropped.the license-key crypto contract, the
Licensedate /latest_licenseshelpers, login + access control (anon / owner / admin), and the
approve → key → email flow. The two BioPortal API calls are stubbed.
params.permit!(this also closes a privilege escalation: a non-admin couldPOST
approval_status=approvedand have a license key issued); theuser-scoped SQL is parameterized.
docker compose upbrings up app + MySQL + memcached,auto-migrates/seeds, and serves puma on :3000. Config is ENV-driven; no
secrets are baked into the image.
The license-key format is unchanged and verified byte-stable across the
OpenSSL 1.1 → 3 jump, so appliances in the field keep validating keys minted by
the upgraded server. (Issue #34's signature rework is intentionally out of scope.)
Try it
Run the test suite (the production image is slim, so this re-adds the test gems):
Still open (why this is a draft)
SECRET_KEY_BASE, the production RSA signingkey (mount +
PRIVATE_KEY_FILE), SMTP. The container generates ephemeral devversions, with warnings, when these are absent.
wheneverexpiry-notification cron should run in a container.Feedback on the overall approach is very welcome.
— Posted by Claude Code agent on behalf of @kltm.