source_monitor 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35e62d7d750d8d9fe1cff82806de1846d27fe505fad819551e48474f864b1499
4
- data.tar.gz: 2f6889306b930aa78caec52cc92c7c6919ba379955a6d0484cc8bf44f52dcf6f
3
+ metadata.gz: 55bf050a9f74f18ed354d7d751f868bc98dc8bc5da59c3da6ce5e0aa0cedc833
4
+ data.tar.gz: 37a5906b19541de00ef3b860f266a1c7a12e737da58d1a7b80cb806a191936d5
5
5
  SHA512:
6
- metadata.gz: 3ca0f0c0a9d6e1c2557c501a2a51bc9dee52e486b78cb78f1384232f5af704c209026e514f1dea2ea94c6962d502856add17c57b4afc79c462ed8fa39da8d236
7
- data.tar.gz: ed49ec4ce672c5850b2bc3f3a6d73e31f1d08d6c8f7b1a779258db69ac9cdb48d1aa6e8478784a0f89bf161ec81bad31b79485455373a702240a1580ad31f6dc
6
+ metadata.gz: 0c0109e46a1ec8691592fd304095c833d5d78b9091ffa216e72011040a8683be820016dd51b4a2185d17b9780761410918297f9f4fdeb2fd31d1e952575fbf99
7
+ data.tar.gz: 9016293bb6d6339026ed811689db2a4f1b87cd90fb60bb7f270113fc698c9714f9935f2aec704c1581b3ef6b61137b2df5c5b21e0ecd8b2bea69be987152057f
@@ -2,6 +2,20 @@
2
2
 
3
3
  Version-specific migration notes for each major/minor version transition. Agents should reference this file when guiding users through multi-version upgrades.
4
4
 
5
+ ## 0.14.0 to 0.15.0
6
+
7
+ **Key changes:**
8
+ - **Security:** Rails bumped to 8.1.3 (security release), picking up fixes for five CVEs including XSS in tag/DebugExceptions helpers, an Active Storage path-traversal, and a NumberConverter issue.
9
+ - **ViewComponent 4.x:** the `view_component` dependency widens from `>= 3.0, < 4.0` to `>= 3.0, < 5.0`, allowing host apps to resolve ViewComponent 4.x (engine lockfile resolves to 4.5.0). Engine components use only stable APIs unaffected by v4.
10
+ - **Solid Queue 1.4.0:** bumped from 1.3.1 with race-condition and supervisor stability fixes; dynamic recurring tasks are opt-in.
11
+ - **Documentation:** engine conventions consolidated into `AGENTS.md`; `CLAUDE.md` now points to it.
12
+
13
+ **Action items:**
14
+ 1. `bundle update source_monitor`
15
+ 2. `bin/rails source_monitor:upgrade`
16
+ 3. No migrations or breaking config/API changes.
17
+ 4. If the host app has ViewComponent 3.x customizations (custom components, previews), test after upgrading and consult ViewComponent v4 migration guides if needed.
18
+
5
19
  ## 0.13.1 to 0.14.0
6
20
 
7
21
  **Key changes:**
data/AGENTS.md CHANGED
@@ -1,47 +1,74 @@
1
1
  # Repository Guidelines
2
2
 
3
- Refer to `CLAUDE.md` for project conventions and skills catalog.
3
+ This file is the **canonical engine convention reference, shared across all AI coding agents** (Claude Code, Codex, etc.). It is the single source of truth for tech stack, architecture, testing, quality gates, CI, security, and commands.
4
+
5
+ `CLAUDE.md` holds only Claude Code-specific context (working-memory header, VBW commands, and the `.claude/` agent/skill catalogs) and references this file for conventions. When a convention changes, edit it **here**, not in `CLAUDE.md`.
4
6
 
5
7
  Use rbenv for all ruby and bundler/gem commands, not the system ruby.
6
8
 
7
- ## Contribution Workflow
9
+ ## Tech Stack
8
10
 
9
- - Treat the engine like any external contributor would: no direct commits to `main`.
10
- - Before writing code, branch off the latest `origin/main` (use a descriptive `feature/` or `bugfix/` prefix) and open a draft PR on `github.com/dchuk/source_monitor`.
11
- - Push early and often to that branch so history stays visible; keep commits scoped and rebases local to your branch only.
12
- - Move the PR out of draft once tests pass and the slice is ready for review; request at least one review and wait for all CI jobs (lint, security, Rails tests + diff coverage) to succeed before merging.
13
- - The `test` job enforces diff coverage via `bin/check-diff-coverage`; if legitimate gaps remain after new code paths, refresh `config/coverage_baseline.json` by running `bin/test-coverage` followed by `bin/update-coverage-baseline` on the updated branch and commit the regenerated baseline.
14
- - Merge via the PR UI (squash or rebase as agreed) after approval; avoid rewriting shared history post-push.
15
- - Tag releases only after the release PR merges, then follow the checklist in `CHANGELOG.md`.
11
+ | Layer | Technology |
12
+ |-------|------------|
13
+ | Ruby | 4.0+ |
14
+ | Rails | 8.x |
15
+ | Testing | Minitest (no fixtures -- uses factory helpers + WebMock/VCR) |
16
+ | Authorization | Host app responsibility (mountable engine); **fail-closed by default** (#129) |
17
+ | Jobs | Solid Queue |
18
+ | Frontend | Hotwire (Turbo + Stimulus) + Tailwind CSS |
19
+ | Linting | RuboCop (omakase) + Brakeman |
20
+ | Database | PostgreSQL only |
16
21
 
17
- ## Library Documentation
22
+ ## Project Structure & Module Organization
18
23
 
19
- - Use Context7 MCP constantly to look up fresh documentation for any task you're looking to complete, especially tasks that rely on using libraries or gems
24
+ The engine follows the Rails mountable layout generated by `rails plugin new source_monitor --mountable`. Runtime code lives under `app/` (controllers, jobs, views) and is namespaced as `SourceMonitor`. Long-lived services, adapters, and instrumentation helpers belong in `lib/source_monitor/`. Generator templates and install scripts reside in `lib/generators/source_monitor/`. Tests sit in `test/`, with fixtures under `test/fixtures/feeds/`, and the dummy host app in `test/dummy/` for integration coverage. Keep shared UI assets under `app/assets/` and engine configuration in `config/initializers/`.
20
25
 
21
- ### Project Dependencies & context7 links
26
+ ## Architecture Conventions
22
27
 
23
- - Feedjirra - https://context7.com/feedjira/feedjira
28
+ ### Models First
29
+ - Business logic lives in models. Use concerns for horizontal sharing.
30
+ - Service objects ONLY for operations spanning 3+ models or external integrations.
31
+ - Query objects for complex queries that don't fit a single scope.
32
+ - Presenters (SimpleDelegator) for view-specific formatting.
24
33
 
25
- ## Project Structure & Module Organization
34
+ ### Everything-is-CRUD Routing
35
+ - Prefer creating a new resource over adding custom actions.
36
+ - `POST /posts/:id/publications` over `POST /posts/:id/publish`.
37
+ - RESTful routes only; no `member` or `collection` blocks with custom verbs.
26
38
 
27
- The engine follows the Rails mountable layout generated by `rails plugin new source_monitor --mountable`. Runtime code lives under `app/` (controllers, jobs, views) and is namespaced as `SourceMonitor`. Long-lived services, adapters, and instrumentation helpers belong in `lib/source_monitor/`. Generator templates and install scripts reside in `lib/generators/source_monitor/`. Tests sit in `test/`, with fixtures under `test/fixtures/feeds/`, and the dummy host app in `test/dummy/` for integration coverage. Keep shared UI assets under `app/assets/` and engine configuration in `config/initializers/`.
39
+ ### State as Records
40
+ - Track business state transitions as separate records (who/when/why).
41
+ - Boolean columns ONLY for technical flags (e.g., `email_verified`, `open_access`).
28
42
 
29
- ## Build, Test, and Development Commands
43
+ ### Jobs
44
+ - Shallow jobs: call `_later` or `_now` methods on models/services.
45
+ - Jobs contain only deserialization + delegation. No business logic.
46
+ - Use Solid Queue recurring jobs for scheduled work.
30
47
 
31
- Run `bin/setup` to install gems, prepare the dummy database, and compile Tailwind. Use `bin/rails test` (or `bundle exec rake test`) for the full MiniTest suite, including system tests through the dummy app. During feature work, `bin/dev` starts the dummy app with Solid Queue workers and Tailwind watcher. Trigger a feed ingest locally with `bin/rails runner 'SourceMonitor::FetchFeeds.call'` once the fetcher service lands.
48
+ ### Frontend
49
+ - Turbo Frames for partial page updates.
50
+ - Turbo Streams for real-time broadcasts.
51
+ - Stimulus controllers: small, focused, one behavior each.
52
+ - Tailwind CSS utility classes; extract components for repeated patterns.
32
53
 
33
- ## Background Job Defaults
54
+ ## Coding Style & Naming Conventions
34
55
 
35
- - SourceMonitor ensures Solid Queue is the default adapter when the host app is still using the async adapter, but respects any explicit `ActiveJob` configuration already in place. Override queues/concurrency via `SourceMonitor.configure`.
36
- - Queue names are namespaced (`source_monitor_fetch`/`source_monitor_scrape` by default) and automatically honor host `queue_name_prefix`. Use `SourceMonitor.queue_name(:fetch)` helpers inside jobs.
37
- - Dashboard queue metrics read directly from Solid Queue tables via `SourceMonitor::Jobs::SolidQueueMetrics`. Host apps must install the Solid Queue migrations (reuse the engine's `20251009140000_create_solid_queue_tables.rb` or run `rails solid_queue:install`) for the card to surface ready/scheduled/failed counts; otherwise the UI falls back to an availability warning. Mission Control remains optional for deeper drill-downs.
38
- - The dummy host keeps Solid Queue tables in the primary database via `20251009140000_create_solid_queue_tables.rb`. Real apps can either reuse that migration or run `rails solid_queue:install` to manage a dedicated queue database—Mission Control expects one of those setups before it can surface data.
39
- - Recurring schedules live in `config/recurring.yml`, scheduling `SourceMonitor::ScheduleFetchesJob` each minute plus the scraping scheduler every two minutes. Override the schedule path with `bin/jobs --recurring_schedule_file=...` (or `SOLID_QUEUE_RECURRING_SCHEDULE_FILE`) and disable recurring runners with `SOLID_QUEUE_SKIP_RECURRING=true` or `bin/jobs --skip-recurring`.
40
- - Hosts that need to wrap Solid Queue command execution can set `config.recurring_command_job_class` in the generated initializer to point at their custom job class.
56
+ Use two-space indentation and Ruby 4.0+ syntax. Keep engine classes under the `SourceMonitor::` namespace; new modules should mirror their directory, e.g., `lib/source_monitor/fetching/pipeline.rb`. Favor service objects ending in `Service`, jobs ending in `Job`, and background channels ending in `Channel`. Rails defaults handle formatting, but run `bin/rubocop` (configured via `.rubocop.yml`) before opening a PR. For views, stick with ERB and Tailwind utility classes.
57
+
58
+ Sub-module extraction pattern: create `module/submodule.rb` with `require_relative`, lazy accessors, and forwarding methods for backward compatibility. The project uses Ruby autoload for `lib/` modules (not Zeitwerk).
59
+
60
+ ## Clean Coding Principles
61
+
62
+ - **SRP**: Classes and methods should have a single responsibility.
63
+ - **DRY**: Avoid duplication; changes should only need one edit.
64
+ - **Depend on behaviour, not data**: Wrap instance variables in methods (`attr_reader`); use Struct for data structures.
65
+ - **Minimise dependencies**: Use dependency injection, encapsulate external messages, prefer hash arguments.
66
+ - **Depend on things that change less often than you do.**
41
67
 
42
68
  ## Configuration DSL
43
69
 
44
- - `SourceMonitor.configure` now exposes structured namespaces:
70
+ - `SourceMonitor.configure` exposes structured namespaces:
71
+ - `config.authentication` gates the engine. With no `authenticate_with`/`authorize_with` handler configured, the engine is **fail-closed** and returns `403`. Set `config.authentication.open_access = true` (default `false`) only for local demos/sandboxes — never production.
45
72
  - `config.http` for Faraday timeouts, retry policy, proxy, and default headers. Per the [Faraday retry docs](https://github.com/lostisland/faraday/blob/main/docs/middleware/index.md), middleware options map 1:1 to the settings we surface (max retries, interval, backoff, statuses).
46
73
  - `config.scrapers` registers/overrides adapters by name; adapters must inherit from `SourceMonitor::Scrapers::Base` and are discovered before constant lookup.
47
74
  - `config.retention` supplies global defaults for `items_retention_days`, `max_items`, and the pruning strategy (`:destroy` or `:soft_delete`). Runtimes treat blank source fields as “inherit from config”.
@@ -57,29 +84,109 @@ Run `bin/setup` to install gems, prepare the dummy database, and compile Tailwin
57
84
  - `SourceMonitor::ItemCleanupJob` batches retention pruning across sources and can soft delete records (`rake source_monitor:cleanup:items` honours `SOFT_DELETE=true`, `SOURCE_IDS=1,2`). `SourceMonitor::LogCleanupJob` prunes old fetch/scrape logs (`rake source_monitor:cleanup:logs`, override `FETCH_LOG_DAYS` / `SCRAPE_LOG_DAYS`).
58
85
  - Nightly recurring entries in `config/recurring.yml` enqueue both cleanup jobs by default; adjust schedules or disable via Solid Queue overrides as needed.
59
86
 
60
- ## Coding Style & Naming Conventions
87
+ ## Background Job Defaults
61
88
 
62
- Use two-space indentation and Ruby 4.0+ syntax. Keep engine classes under the `SourceMonitor::` namespace; new modules should mirror their directory, e.g., `lib/source_monitor/fetching/pipeline.rb`. Favor service objects ending in `Service`, jobs ending in `Job`, and background channels ending in `Channel`. Rails defaults handle formatting, but run `bundle exec rubocop` (configured via `.rubocop.yml`) before opening a PR. For views, stick with ERB and Tailwind utility classes.
89
+ - SourceMonitor ensures Solid Queue is the default adapter when the host app is still using the async adapter, but respects any explicit `ActiveJob` configuration already in place. Override queues/concurrency via `SourceMonitor.configure`.
90
+ - Queue names are namespaced (`source_monitor_fetch`/`source_monitor_scrape` by default) and automatically honor host `queue_name_prefix`. Use `SourceMonitor.queue_name(:fetch)` helpers inside jobs.
91
+ - Dashboard queue metrics read directly from Solid Queue tables via `SourceMonitor::Jobs::SolidQueueMetrics`. Host apps must install the Solid Queue migrations (reuse the engine's `20251009140000_create_solid_queue_tables.rb` or run `rails solid_queue:install`) for the card to surface ready/scheduled/failed counts; otherwise the UI falls back to an availability warning. Mission Control remains optional for deeper drill-downs.
92
+ - The dummy host keeps Solid Queue tables in the primary database via `20251009140000_create_solid_queue_tables.rb`. Real apps can either reuse that migration or run `rails solid_queue:install` to manage a dedicated queue database—Mission Control expects one of those setups before it can surface data.
93
+ - Recurring schedules live in `config/recurring.yml`, scheduling `SourceMonitor::ScheduleFetchesJob` each minute plus the scraping scheduler every two minutes. Override the schedule path with `bin/jobs --recurring_schedule_file=...` (or `SOLID_QUEUE_RECURRING_SCHEDULE_FILE`) and disable recurring runners with `SOLID_QUEUE_SKIP_RECURRING=true` or `bin/jobs --skip-recurring`.
94
+ - Hosts that need to wrap Solid Queue command execution can set `config.recurring_command_job_class` in the generated initializer to point at their custom job class.
95
+
96
+ ## Build, Test, and Development Commands
97
+
98
+ Run `bin/setup` to install gems, prepare the dummy database, and compile Tailwind. During feature work, `bin/dev` starts the dummy app with Solid Queue workers and Tailwind watcher.
99
+
100
+ ```bash
101
+ bin/dev # Start dev server
102
+ bin/rails test # Run the MiniTest suite (NOT a substitute for CI -- see below)
103
+ bin/rubocop # Check style
104
+ bin/rubocop -a # Auto-fix style
105
+ bin/brakeman --no-pager # Security scan
106
+ bin/rails db:migrate # Run migrations
107
+ ```
108
+
109
+ The dummy host app runs on **port 3002** (`cd test/dummy && bin/rails server -p 3002`).
110
+
111
+ ## Testing
63
112
 
64
- ## Testing Guidelines
113
+ - **Framework:** Minitest. NEVER use RSpec or FactoryBot. Name files with `_test.rb` and wrap suites in `module SourceMonitor`. Tests live in `test/models`, `test/controllers`, `test/system`, `test/lib`, `test/integration`.
114
+ - **Helpers:** `create_source!` factory, `with_inline_jobs`, `with_queue_adapter`.
115
+ - **HTTP:** WebMock disables external HTTP; VCR for recorded cassettes under `test/vcr_cassettes/` (record new fixtures with descriptive names like `source_fetch_success.yml`).
116
+ - **Config isolation:** `test/test_helper.rb` calls `SourceMonitor.reset_configuration!` in every test's setup (rebuilding a fresh `Configuration`), so any config a test relies on must be set in setup, not the dummy initializer.
117
+ - **Coverage:** Target >90% for new services; cover every model validation, scope, public method, and controller action, plus regression tests for bug fixes.
118
+ - **Parallelism:** Coverage runs need `COVERAGE=1 PARALLEL_WORKERS=1` with **threads** (not forks) to avoid a PG segfault and SimpleCov data loss. Scope queries to a specific source/item to prevent cross-test contamination in parallel runs.
119
+ - **Automate what you can:** Anything verifiable programmatically (config defaults, job enqueue behavior, controller responses) should be a test, not a manual checkpoint.
120
+
121
+ ## Quality Gates
122
+
123
+ - `bin/rubocop` — zero offenses before commit (omakase: only ~45/775 cops enabled, all Metrics cops disabled — no file-size enforcement).
124
+ - `bin/brakeman --no-pager` — zero warnings before merge.
125
+ - `bin/rails test` — all tests pass.
126
+ - `yarn build` — rebuild JS assets if any `.js` files changed (ESLint runs in CI).
127
+ - No N+1 queries (use `includes`/`preload`).
128
+ - No hardcoded credentials (use Rails credentials or ENV).
129
+
130
+ ### Pre-Push CI Checklist (run ALL before pushing to GitHub)
131
+
132
+ Before pushing any branch (especially release branches), run the full CI equivalent locally:
133
+
134
+ 1. `bin/rubocop` — catches Ruby lint issues.
135
+ 2. `bin/test-coverage` — **this is what CI's `test` job actually runs.** Do NOT rely on `bin/rails test` to predict CI: `bin/rails test` uses a different harness/seed and does NOT run the diff-coverage gate, so it can be green (e.g. 1741/0) while CI fails. `bin/test-coverage` runs the real seed, the second `health_suite` pass, and the host-app-template test that **changes the process CWD mid-suite** (see gemspec note below).
136
+ 3. `bundle exec ruby bin/check-diff-coverage` — run AFTER `bin/test-coverage` (it reads `coverage/.resultset.json`). Reproduces the CI diff-coverage gate locally (threshold 90% on changed `app/`/`lib/` lines vs `origin/main`). This is the only way to know the gate passes before pushing.
137
+ 4. `bin/brakeman --no-pager` — catches security issues.
138
+ 5. `yarn build` — rebuilds JS and catches ESLint issues (CI runs ESLint separately).
139
+
140
+ If legitimate coverage gaps remain after new code paths, refresh the baseline: `bin/test-coverage` then `bin/update-coverage-baseline`, and commit the regenerated `config/coverage_baseline.json`.
141
+
142
+ **Why:** CI failures cost ~5 min per round-trip. Hard-won lessons:
143
+ - **CI runs `bin/test-coverage`, not `bin/rails test`** — replicate the gate locally with steps 2 + 3. (v0.14.0: a green local `bin/rails test` masked a CI `bin/test-coverage` failure.)
144
+ - **Diff coverage covers EVERY changed `app/`/`lib/` line**, including defensive/edge branches with no natural caller. If a branch can't be reached through a normal engine route (e.g. the `#130` turbo_stream flash-append, which only fires when a turbo_stream request carries a Rails flash), add a **test-only probe controller in the dummy app** (pattern: `test/dummy/app/controllers/test_support_controller.rb` + a route in `test/dummy/config/routes.rb`); subclass `SourceMonitor::ApplicationController` if the branch lives in the engine's filter chain.
145
+ - Every `rescue`/fallback/error path in new source code needs test coverage.
146
+ - **Gemspec packaging must be CWD-independent.** Do NOT use a bare `Dir[...]` glob in `source_monitor.gemspec` for file selection — it resolves against the process CWD, and during `bin/test-coverage` a sibling test chdir's into a generated host app, so the glob returns nothing and files silently drop from the package (v0.14.0 `#131`). Drive packaging from `git ls-files` inside the existing `Dir.chdir(File.expand_path(__dir__))` block.
147
+ - JS files need `/* global */` declarations for browser APIs (MutationObserver, requestAnimationFrame, etc.); ESLint `no-undef` rejects them otherwise. Run `yarn build` after JS changes to sync sourcemaps.
148
+
149
+ ## Contribution Workflow
65
150
 
66
- MiniTest drives coverage (`test/models`, `test/controllers`, `test/system`). Name files with `_test.rb` and wrap suites in `module SourceMonitor`. Add VCR cassettes under `test/vcr_cassettes/` when touching HTTP clients, and record new fixtures with descriptive names like `source_fetch_success.yml`. Target >90% coverage for new services and include regression tests for bug fixes. Use `bin/rails test test/system` before changing UI flows.
151
+ - Treat the engine like any external contributor would: no direct commits to `main`.
152
+ - Before writing code, branch off the latest `origin/main` (use a descriptive `feature/` or `bugfix/` prefix) and open a draft PR on `github.com/dchuk/source_monitor`.
153
+ - Push early and often to that branch so history stays visible; keep commits scoped and rebases local to your branch only.
154
+ - Move the PR out of draft once tests pass and the slice is ready for review; request at least one review and wait for all CI jobs (lint, security, test + diff coverage, release_verification) to succeed before merging.
155
+ - Merge via the PR UI (squash or rebase as agreed) after approval; avoid rewriting shared history post-push.
156
+ - Tag releases only after the release PR merges, then follow the checklist in `CHANGELOG.md`. There are TWO version files — `lib/source_monitor/version.rb` AND the top-level `VERSION` — and both must match; run `bundle install` after a bump so `Gemfile.lock` stays in sync (CI runs `--frozen`).
67
157
 
68
158
  ## Commit & Pull Request Guidelines
69
159
 
70
- Adopt imperative commit messages in the format `scope: action`, e.g., `sources: enforce URL normalization`. Group unrelated work into separate commits. PRs should describe context, summarise the slice delivered, and list validation steps (`bin/rails test`, manual fetch run). Include screenshots or console output when altering UI or background jobs. Request at least one review and ensure CI completes before merge.
160
+ Use Conventional Commit subjects in the format `type(scope): description`, e.g., `fix(fetch): resolve advisory lock contention`. Group unrelated work into separate commits. PRs should describe context, summarise the slice delivered, and list validation steps (`bin/test-coverage`, manual fetch run). Include screenshots or console output when altering UI or background jobs. Request at least one review and ensure CI completes before merge.
161
+
162
+ ## Security
71
163
 
72
- ## Security & Configuration Tips
164
+ ### Protected files (NEVER read or output)
165
+ - `.env`, `.env.*`
166
+ - `config/master.key`, `config/credentials.yml.enc`
167
+ - `.kamal/secrets`
168
+ - Any `*.pem` / `*.key` files
73
169
 
170
+ ### Forbidden operations
171
+ - `git push --force` to main/master/production
172
+ - `git reset --hard` without explicit user confirmation
173
+ - `rm -rf` on root, home, or parent directories
174
+ - `chmod 777`
175
+
176
+ ### General
74
177
  Store secrets (API keys, webhook tokens) in `config/credentials/` and never commit plain-text values. When adding HTTP endpoints or webhooks, default to Solid Queue middleware for retries and respect the allowlist in `config/source_monitor.yml`. Document new environment variables in `config/application.yml.sample` and call out any migrations that impact host apps.
75
178
 
76
- ## Clean Coding Principles
179
+ ## Maintenance: Skills & Docs Alignment
77
180
 
78
- - **SRP**: Classes and methods should have a single responsibility.
79
- - **DRY**: Avoid duplication; changes should only need one edit.
80
- - **Depend on behaviour, not data**: Wrap instance variables in methods (`attr_reader`); use Struct for data structures.
81
- - **Minimise dependencies**: Use dependency injection, encapsulate external messages, prefer hash arguments.
82
- - **Depend on things that change less often than you do.**
181
+ Whenever engine code changes (models, configuration, pipeline, jobs, migrations, scrapers, events, health rules, or dashboard), the corresponding `sm-*` skill and its `reference/` files MUST be updated **in the same PR** so skills always reflect current engine behavior. Releases must also audit `README.md`, `docs/` (especially `docs/upgrade.md`), and the install initializer template against the source code.
182
+
183
+ ## Library Documentation
184
+
185
+ - Use Context7 MCP constantly to look up fresh documentation for any task, especially tasks that rely on libraries or gems.
186
+
187
+ ### Project Dependencies & context7 links
188
+
189
+ - Feedjira - https://context7.com/feedjira/feedjira
83
190
 
84
191
  ## Claude Code Skills
85
192
 
@@ -92,4 +199,4 @@ bin/rails source_monitor:skills:all # All skills
92
199
  bin/rails source_monitor:skills:remove # Remove all sm-* skills
93
200
  ```
94
201
 
95
- See `CLAUDE.md` for the full skills catalog and usage details.
202
+ See `CLAUDE.md` for the full skills catalog (consumer vs. contributor) and the `.claude/` agent catalog.
data/CHANGELOG.md CHANGED
@@ -15,6 +15,20 @@ All notable changes to this project are documented below. The format follows [Ke
15
15
 
16
16
  - No unreleased changes yet.
17
17
 
18
+ ## [0.15.0] - 2026-06-18
19
+
20
+ ### Security
21
+ - Bump Rails to 8.1.3 via the 8.1.2.1 security release (#104), picking up fixes for five CVEs including XSS in tag/DebugExceptions helpers, an Active Storage path-traversal, and a NumberConverter issue.
22
+
23
+ ### Changed
24
+ - **Allow ViewComponent 4.x** (#96). The `view_component` dependency constraint widens from `>= 3.0, < 4.0` to `>= 3.0, < 5.0`, so host apps can now resolve ViewComponent 4.x (the engine's lockfile moves to 4.5.0). The engine's components use only stable ViewComponent APIs and are unaffected by the v4 upgrade — but a host app on its own ViewComponent 3.x customizations should review the v4 upgrade notes before running `bundle update`.
25
+ - Bump Solid Queue to 1.4.0 (#102) — race-condition and supervisor stability fixes; the new dynamic recurring-tasks feature is opt-in and off by default.
26
+ - Bump nokolexbor to 0.6.4 (#103) and json to 2.19.2 (#99).
27
+ - Development/CI dependency bumps: test-prof 1.6.0 (#101), webmock 3.26.2 (#100), brakeman 8.0.4 (#88), selenium-webdriver 4.41.0 (#78), stackprof 0.2.28 (#71), and the GitHub Actions artifact actions (#87, #86).
28
+
29
+ ### Documentation
30
+ - Consolidate engine conventions into `AGENTS.md` as the canonical, cross-agent reference; `CLAUDE.md` now points to it instead of duplicating content (#134).
31
+
18
32
  ## [0.14.0] - 2026-05-28
19
33
 
20
34
  ### Security (BREAKING)
data/CLAUDE.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  **Core value:** Drop-in Rails engine for feed monitoring, content scraping, and operational dashboards.
4
4
 
5
+ > **Engine conventions live in [`AGENTS.md`](AGENTS.md)** — the canonical, cross-agent reference for tech stack, architecture, testing, quality gates, the pre-push CI checklist, security rules, configuration DSL, and commands. This file holds only Claude Code-specific context: working memory, VBW commands, and the `.claude/` agent/skill catalogs. When a convention changes, edit `AGENTS.md`, not here.
6
+
5
7
  ## Active Context
6
8
 
7
9
  **Last shipped:** rails-audit-and-refactoring (7 phases, 30 plans)
@@ -10,7 +12,7 @@
10
12
  ## Key Decisions
11
13
 
12
14
  - Keep PostgreSQL-only for now
13
- - Keep host-app auth model
15
+ - Keep host-app auth model (fail-closed by default since #129)
14
16
  - Ruby autoload for lib/ modules (not Zeitwerk)
15
17
  - PG parallel fork segfault resolved: switched to thread-based parallelism in aia-ssl-fix milestone
16
18
 
@@ -23,13 +25,6 @@
23
25
  - vastai (global)
24
26
  - find-skills (global)
25
27
 
26
- ## Learned Patterns
27
-
28
- - Sub-module extraction: create `module/submodule.rb` with `require_relative`, lazy accessors, forwarding methods for backward compat
29
- - Coverage runs need `COVERAGE=1 PARALLEL_WORKERS=1` with threads (not forks) to avoid PG segfault and SimpleCov data loss
30
- - Test isolation: scope queries to specific source/item to prevent cross-test contamination in parallel runs
31
- - RuboCop omakase: only 45/775 cops enabled, all Metrics cops disabled -- no file size enforcement
32
-
33
28
  ## VBW Commands
34
29
 
35
30
  This project uses VBW (Vibe Better with Claude Code).
@@ -38,111 +33,10 @@ Run /vbw:help for all commands.
38
33
 
39
34
  ---
40
35
 
41
- # Rails Development Conventions
42
-
43
- ## Tech Stack
44
-
45
- | Layer | Technology |
46
- |-------|------------|
47
- | Ruby | 4.0+ |
48
- | Rails | 8.x |
49
- | Testing | Minitest (no fixtures -- uses factory helpers + WebMock/VCR) |
50
- | Authorization | Host app responsibility (mountable engine) |
51
- | Jobs | Solid Queue |
52
- | Frontend | Hotwire (Turbo + Stimulus) + Tailwind CSS |
53
- | Linting | RuboCop (omakase) + Brakeman |
54
- | Database | PostgreSQL only |
55
-
56
- ## Architecture Conventions
57
-
58
- ### Models First
59
- - Business logic lives in models. Use concerns for horizontal sharing.
60
- - Service objects ONLY for operations spanning 3+ models or external integrations.
61
- - Query objects for complex queries that don't fit a single scope.
62
- - Presenters (SimpleDelegator) for view-specific formatting.
63
-
64
- ### Everything-is-CRUD Routing
65
- - Prefer creating a new resource over adding custom actions.
66
- - `POST /posts/:id/publications` over `POST /posts/:id/publish`.
67
- - RESTful routes only; no `member` or `collection` blocks with custom verbs.
68
-
69
- ### State as Records
70
- - Track business state transitions as separate records (who/when/why).
71
- - Boolean columns ONLY for technical flags (e.g., `email_verified`).
72
-
73
- ### Jobs
74
- - Shallow jobs: call `_later` or `_now` methods on models/services.
75
- - Jobs contain only deserialization + delegation. No business logic.
76
- - Use Solid Queue recurring jobs for scheduled work.
77
-
78
- ### Frontend
79
- - Turbo Frames for partial page updates.
80
- - Turbo Streams for real-time broadcasts.
81
- - Stimulus controllers: small, focused, one behavior each.
82
- - Tailwind CSS utility classes; extract components for repeated patterns.
83
-
84
- ## Testing Conventions
85
-
86
- - **Framework:** Minitest. NEVER use RSpec or FactoryBot.
87
- - **Helpers:** `create_source!` factory, `with_inline_jobs`, `with_queue_adapter`.
88
- - **HTTP:** WebMock disables external HTTP; VCR for recorded cassettes.
89
- - **Config:** Reset every test with `SourceMonitor.reset_configuration!`.
90
- - **TDD workflow:** Red (failing test) -> Green (minimal pass) -> Refactor.
91
- - **Coverage:** Every model validation, scope, and public method. Every controller action.
92
-
93
- ## Quality Gates
94
-
95
- - `bin/rubocop` -- zero offenses before commit.
96
- - `bin/brakeman --no-pager` -- zero warnings before merge.
97
- - `bin/rails test` -- all tests pass.
98
- - `yarn build` -- rebuild JS assets if any `.js` files changed (ESLint runs in CI).
99
- - No N+1 queries (use `includes`/`preload`).
100
- - No hardcoded credentials (use Rails credentials or ENV).
101
-
102
- ### Pre-Push CI Checklist (run ALL before pushing to GitHub)
103
-
104
- Before pushing any branch (especially release branches), run the full CI equivalent locally:
105
-
106
- 1. `bin/rubocop` -- catches Ruby lint issues
107
- 2. `PARALLEL_WORKERS=1 bin/rails test` -- catches test failures AND diff coverage gaps
108
- 3. `bin/brakeman --no-pager` -- catches security issues
109
- 4. `yarn build` -- rebuilds JS and catches ESLint issues (CI runs ESLint separately)
110
-
111
- **Why:** CI failures cost ~5 min per round-trip. In v0.8.0, skipping ESLint and diff coverage checks locally caused 2 wasted CI cycles. Common blind spots:
112
- - JS files need `/* global */` declarations for browser APIs (MutationObserver, requestAnimationFrame, etc.)
113
- - Every `rescue` / fallback / error path in new source code needs test coverage (CI diff coverage gate rejects uncovered lines)
114
- - `yarn build` must run after JS changes to sync sourcemaps
115
-
116
- ## QA and UAT Rules
36
+ ## QA and UAT Rules (Claude Code)
117
37
 
118
38
  - **Browser-first verification:** During VBW QA (`/vbw:qa`) and UAT (`/vbw:verify`), ALWAYS start by using `agent-browser` to test UI scenarios yourself before presenting checkpoints to the user. Navigate to the dummy app (port 3002), take snapshots/screenshots, and verify visual and functional behavior with agents first.
119
- - **Automate what you can:** Any test that can be verified programmatically (config defaults, job enqueue behavior, controller responses) should be automated -- only present truly visual/interactive tests to the user.
120
- - **Dummy app port:** The SourceMonitor dummy app runs on port 3002 (`cd test/dummy && bin/rails server -p 3002`).
121
-
122
- ## Security Rules
123
-
124
- ### Protected Files (NEVER read or output)
125
- - `.env`, `.env.*`
126
- - `config/master.key`, `config/credentials.yml.enc`
127
- - `.kamal/secrets`
128
- - Any `*.pem`, `*.key` files
129
-
130
- ### Forbidden Operations
131
- - `git push --force` to main/master/production
132
- - `git reset --hard` without explicit user confirmation
133
- - `rm -rf` on root, home, or parent directories
134
- - `chmod 777`
135
-
136
- ## Development Commands
137
-
138
- ```bash
139
- bin/dev # Start dev server
140
- bin/rails test # Run all tests
141
- bin/rubocop # Check style
142
- bin/rubocop -a # Auto-fix style
143
- bin/brakeman --no-pager # Security scan
144
- bin/rails db:migrate # Run migrations
145
- ```
39
+ - **Automate what you can:** anything verifiable programmatically should be a test see the Testing section in [`AGENTS.md`](AGENTS.md) and only present truly visual/interactive checks to the user.
146
40
 
147
41
  ## Agent Catalog
148
42
 
@@ -200,7 +94,7 @@ These skills are available in `.claude/skills/`:
200
94
 
201
95
  ## Source Monitor Skills
202
96
 
203
- Engine-specific skills (`sm-*` prefix). Consumer skills install by default; contributor skills are opt-in.
97
+ Engine-specific skills (`sm-*` prefix). Consumer skills install by default; contributor skills are opt-in. The **Skills & Docs Alignment** maintenance rule lives in [`AGENTS.md`](AGENTS.md).
204
98
 
205
99
  ### Consumer Skills (default install)
206
100
 
@@ -237,7 +131,3 @@ bin/rails source_monitor:skills:contributor # Contributor skills
237
131
  bin/rails source_monitor:skills:all # All skills
238
132
  bin/rails source_monitor:skills:remove # Remove all sm-* skills
239
133
  ```
240
-
241
- ## Maintenance Rules
242
-
243
- - **Skills & docs alignment**: Whenever engine code changes (models, configuration, pipeline, jobs, migrations, scrapers, events, health rules, or dashboard), the corresponding `sm-*` skill and its `reference/` files MUST be updated in the same PR to ensure skills always reflect current engine behavior.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- source_monitor (0.14.0)
4
+ source_monitor (0.15.0)
5
5
  cssbundling-rails (~> 1.4)
6
6
  faraday (~> 2.9)
7
7
  faraday-follow_redirects (~> 0.4)
@@ -16,36 +16,36 @@ PATH
16
16
  solid_cable (>= 3.0, < 4.0)
17
17
  solid_queue (>= 0.3, < 3.0)
18
18
  turbo-rails (~> 2.0)
19
- view_component (>= 3.0, < 4.0)
19
+ view_component (>= 3.0, < 5.0)
20
20
 
21
21
  GEM
22
22
  remote: https://rubygems.org/
23
23
  specs:
24
- action_text-trix (2.1.16)
24
+ action_text-trix (2.1.17)
25
25
  railties
26
- actioncable (8.1.2)
27
- actionpack (= 8.1.2)
28
- activesupport (= 8.1.2)
26
+ actioncable (8.1.3)
27
+ actionpack (= 8.1.3)
28
+ activesupport (= 8.1.3)
29
29
  nio4r (~> 2.0)
30
30
  websocket-driver (>= 0.6.1)
31
31
  zeitwerk (~> 2.6)
32
- actionmailbox (8.1.2)
33
- actionpack (= 8.1.2)
34
- activejob (= 8.1.2)
35
- activerecord (= 8.1.2)
36
- activestorage (= 8.1.2)
37
- activesupport (= 8.1.2)
32
+ actionmailbox (8.1.3)
33
+ actionpack (= 8.1.3)
34
+ activejob (= 8.1.3)
35
+ activerecord (= 8.1.3)
36
+ activestorage (= 8.1.3)
37
+ activesupport (= 8.1.3)
38
38
  mail (>= 2.8.0)
39
- actionmailer (8.1.2)
40
- actionpack (= 8.1.2)
41
- actionview (= 8.1.2)
42
- activejob (= 8.1.2)
43
- activesupport (= 8.1.2)
39
+ actionmailer (8.1.3)
40
+ actionpack (= 8.1.3)
41
+ actionview (= 8.1.3)
42
+ activejob (= 8.1.3)
43
+ activesupport (= 8.1.3)
44
44
  mail (>= 2.8.0)
45
45
  rails-dom-testing (~> 2.2)
46
- actionpack (8.1.2)
47
- actionview (= 8.1.2)
48
- activesupport (= 8.1.2)
46
+ actionpack (8.1.3)
47
+ actionview (= 8.1.3)
48
+ activesupport (= 8.1.3)
49
49
  nokogiri (>= 1.8.5)
50
50
  rack (>= 2.2.4)
51
51
  rack-session (>= 1.0.1)
@@ -53,36 +53,36 @@ GEM
53
53
  rails-dom-testing (~> 2.2)
54
54
  rails-html-sanitizer (~> 1.6)
55
55
  useragent (~> 0.16)
56
- actiontext (8.1.2)
56
+ actiontext (8.1.3)
57
57
  action_text-trix (~> 2.1.15)
58
- actionpack (= 8.1.2)
59
- activerecord (= 8.1.2)
60
- activestorage (= 8.1.2)
61
- activesupport (= 8.1.2)
58
+ actionpack (= 8.1.3)
59
+ activerecord (= 8.1.3)
60
+ activestorage (= 8.1.3)
61
+ activesupport (= 8.1.3)
62
62
  globalid (>= 0.6.0)
63
63
  nokogiri (>= 1.8.5)
64
- actionview (8.1.2)
65
- activesupport (= 8.1.2)
64
+ actionview (8.1.3)
65
+ activesupport (= 8.1.3)
66
66
  builder (~> 3.1)
67
67
  erubi (~> 1.11)
68
68
  rails-dom-testing (~> 2.2)
69
69
  rails-html-sanitizer (~> 1.6)
70
- activejob (8.1.2)
71
- activesupport (= 8.1.2)
70
+ activejob (8.1.3)
71
+ activesupport (= 8.1.3)
72
72
  globalid (>= 0.3.6)
73
- activemodel (8.1.2)
74
- activesupport (= 8.1.2)
75
- activerecord (8.1.2)
76
- activemodel (= 8.1.2)
77
- activesupport (= 8.1.2)
73
+ activemodel (8.1.3)
74
+ activesupport (= 8.1.3)
75
+ activerecord (8.1.3)
76
+ activemodel (= 8.1.3)
77
+ activesupport (= 8.1.3)
78
78
  timeout (>= 0.4.0)
79
- activestorage (8.1.2)
80
- actionpack (= 8.1.2)
81
- activejob (= 8.1.2)
82
- activerecord (= 8.1.2)
83
- activesupport (= 8.1.2)
79
+ activestorage (8.1.3)
80
+ actionpack (= 8.1.3)
81
+ activejob (= 8.1.3)
82
+ activerecord (= 8.1.3)
83
+ activesupport (= 8.1.3)
84
84
  marcel (~> 1.0)
85
- activesupport (8.1.2)
85
+ activesupport (8.1.3)
86
86
  base64
87
87
  bigdecimal
88
88
  concurrent-ruby (~> 1.0, >= 1.3.1)
@@ -95,12 +95,12 @@ GEM
95
95
  securerandom (>= 0.3)
96
96
  tzinfo (~> 2.0, >= 2.0.5)
97
97
  uri (>= 0.13.1)
98
- addressable (2.8.7)
99
- public_suffix (>= 2.0.2, < 7.0)
98
+ addressable (2.9.0)
99
+ public_suffix (>= 2.0.2, < 8.0)
100
100
  ast (2.4.3)
101
101
  base64 (0.3.0)
102
- bigdecimal (4.0.1)
103
- brakeman (8.0.2)
102
+ bigdecimal (4.1.2)
103
+ brakeman (8.0.4)
104
104
  racc
105
105
  builder (3.3.0)
106
106
  capybara (3.40.0)
@@ -125,7 +125,7 @@ GEM
125
125
  digest (3.2.1)
126
126
  docile (1.4.1)
127
127
  drb (2.2.3)
128
- erb (6.0.1)
128
+ erb (6.0.2)
129
129
  erubi (1.13.1)
130
130
  et-orbi (1.4.0)
131
131
  tzinfo
@@ -163,11 +163,11 @@ GEM
163
163
  reline (>= 0.4.2)
164
164
  jsbundling-rails (1.3.1)
165
165
  railties (>= 6.0.0)
166
- json (2.18.1)
166
+ json (2.19.2)
167
167
  language_server-protocol (3.17.0.5)
168
168
  lint_roller (1.1.0)
169
169
  logger (1.7.0)
170
- loofah (2.25.0)
170
+ loofah (2.25.1)
171
171
  crass (~> 1.0.2)
172
172
  nokogiri (>= 1.12.0)
173
173
  mail (2.9.0)
@@ -178,17 +178,17 @@ GEM
178
178
  net-smtp
179
179
  marcel (1.1.0)
180
180
  matrix (0.4.3)
181
- method_source (1.1.0)
182
181
  mini_magick (5.3.1)
183
182
  logger
184
183
  mini_mime (1.1.5)
185
184
  mini_portile2 (2.8.9)
186
- minitest (6.0.1)
185
+ minitest (6.0.2)
186
+ drb (~> 2.0)
187
187
  prism (~> 1.5)
188
188
  minitest-mock (5.27.0)
189
189
  net-http (0.9.1)
190
190
  uri (>= 0.11.1)
191
- net-imap (0.6.2)
191
+ net-imap (0.6.3)
192
192
  date
193
193
  net-protocol
194
194
  net-pop (0.1.2)
@@ -198,18 +198,18 @@ GEM
198
198
  net-smtp (0.5.1)
199
199
  net-protocol
200
200
  nio4r (2.7.5)
201
- nokogiri (1.19.0)
201
+ nokogiri (1.19.2)
202
202
  mini_portile2 (~> 2.8.2)
203
203
  racc (~> 1.4)
204
- nokogiri (1.19.0-aarch64-linux-gnu)
204
+ nokogiri (1.19.2-aarch64-linux-gnu)
205
205
  racc (~> 1.4)
206
- nokogiri (1.19.0-aarch64-linux-musl)
206
+ nokogiri (1.19.2-aarch64-linux-musl)
207
207
  racc (~> 1.4)
208
- nokogiri (1.19.0-arm-linux-gnu)
208
+ nokogiri (1.19.2-arm-linux-gnu)
209
209
  racc (~> 1.4)
210
- nokogiri (1.19.0-arm-linux-musl)
210
+ nokogiri (1.19.2-arm-linux-musl)
211
211
  racc (~> 1.4)
212
- nokolexbor (0.6.2)
212
+ nokolexbor (0.6.4)
213
213
  ostruct (0.6.3)
214
214
  parallel (1.27.0)
215
215
  parser (3.3.10.1)
@@ -229,12 +229,12 @@ GEM
229
229
  psych (5.3.1)
230
230
  date
231
231
  stringio
232
- public_suffix (6.0.2)
232
+ public_suffix (7.0.5)
233
233
  puma (7.2.0)
234
234
  nio4r (~> 2.0)
235
235
  raabro (1.4.0)
236
236
  racc (1.8.1)
237
- rack (3.2.4)
237
+ rack (3.2.5)
238
238
  rack-session (2.1.1)
239
239
  base64 (>= 0.1.0)
240
240
  rack (>= 3.0.0)
@@ -242,30 +242,30 @@ GEM
242
242
  rack (>= 1.3)
243
243
  rackup (2.3.1)
244
244
  rack (>= 3)
245
- rails (8.1.2)
246
- actioncable (= 8.1.2)
247
- actionmailbox (= 8.1.2)
248
- actionmailer (= 8.1.2)
249
- actionpack (= 8.1.2)
250
- actiontext (= 8.1.2)
251
- actionview (= 8.1.2)
252
- activejob (= 8.1.2)
253
- activemodel (= 8.1.2)
254
- activerecord (= 8.1.2)
255
- activestorage (= 8.1.2)
256
- activesupport (= 8.1.2)
245
+ rails (8.1.3)
246
+ actioncable (= 8.1.3)
247
+ actionmailbox (= 8.1.3)
248
+ actionmailer (= 8.1.3)
249
+ actionpack (= 8.1.3)
250
+ actiontext (= 8.1.3)
251
+ actionview (= 8.1.3)
252
+ activejob (= 8.1.3)
253
+ activemodel (= 8.1.3)
254
+ activerecord (= 8.1.3)
255
+ activestorage (= 8.1.3)
256
+ activesupport (= 8.1.3)
257
257
  bundler (>= 1.15.0)
258
- railties (= 8.1.2)
258
+ railties (= 8.1.3)
259
259
  rails-dom-testing (2.3.0)
260
260
  activesupport (>= 5.0.0)
261
261
  minitest
262
262
  nokogiri (>= 1.6)
263
- rails-html-sanitizer (1.6.2)
264
- loofah (~> 2.21)
263
+ rails-html-sanitizer (1.7.0)
264
+ loofah (~> 2.25)
265
265
  nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
266
- railties (8.1.2)
267
- actionpack (= 8.1.2)
268
- activesupport (= 8.1.2)
266
+ railties (8.1.3)
267
+ actionpack (= 8.1.3)
268
+ activesupport (= 8.1.3)
269
269
  irb (~> 1.13)
270
270
  rackup (>= 1.0.0)
271
271
  rake (>= 12.2)
@@ -321,7 +321,7 @@ GEM
321
321
  rubyzip (3.2.2)
322
322
  sax-machine (1.3.2)
323
323
  securerandom (0.4.1)
324
- selenium-webdriver (4.40.0)
324
+ selenium-webdriver (4.41.0)
325
325
  base64 (~> 0.2)
326
326
  logger (~> 1.4)
327
327
  rexml (~> 3.2, >= 3.2.5)
@@ -338,18 +338,18 @@ GEM
338
338
  activejob (>= 7.2)
339
339
  activerecord (>= 7.2)
340
340
  railties (>= 7.2)
341
- solid_queue (1.3.1)
341
+ solid_queue (1.4.0)
342
342
  activejob (>= 7.1)
343
343
  activerecord (>= 7.1)
344
344
  concurrent-ruby (>= 1.3.1)
345
345
  fugit (~> 1.11)
346
346
  railties (>= 7.1)
347
347
  thor (>= 1.3.1)
348
- stackprof (0.2.27)
348
+ stackprof (0.2.28)
349
349
  stringio (3.2.0)
350
- test-prof (1.5.2)
350
+ test-prof (1.6.0)
351
351
  thor (1.5.0)
352
- timeout (0.6.0)
352
+ timeout (0.6.1)
353
353
  tsort (0.2.0)
354
354
  turbo-rails (2.0.23)
355
355
  actionpack (>= 7.1.0)
@@ -362,11 +362,11 @@ GEM
362
362
  uri (1.1.1)
363
363
  useragent (0.16.11)
364
364
  vcr (6.4.0)
365
- view_component (3.24.0)
366
- activesupport (>= 5.2.0, < 8.2)
365
+ view_component (4.5.0)
366
+ actionview (>= 7.1.0)
367
+ activesupport (>= 7.1.0)
367
368
  concurrent-ruby (~> 1)
368
- method_source (~> 1.0)
369
- webmock (3.26.1)
369
+ webmock (3.26.2)
370
370
  addressable (>= 2.8.0)
371
371
  crack (>= 0.3.2)
372
372
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -377,7 +377,7 @@ GEM
377
377
  websocket-extensions (0.1.5)
378
378
  xpath (3.2.0)
379
379
  nokogiri (~> 1.8)
380
- zeitwerk (2.7.4)
380
+ zeitwerk (2.7.5)
381
381
  zlib (3.2.2)
382
382
 
383
383
  PLATFORMS
data/README.md CHANGED
@@ -9,8 +9,8 @@ SourceMonitor is a production-ready Rails 8 mountable engine for ingesting, norm
9
9
  In your host Rails app:
10
10
 
11
11
  ```bash
12
- bundle add source_monitor --version "~> 0.14.0"
13
- # or add `gem "source_monitor", "~> 0.14.0"` manually, then run:
12
+ bundle add source_monitor --version "~> 0.15.0"
13
+ # or add `gem "source_monitor", "~> 0.15.0"` manually, then run:
14
14
  bundle install
15
15
  ```
16
16
 
@@ -46,7 +46,7 @@ This exposes `bin/source_monitor` (via Bundler binstubs) so you can run the guid
46
46
  Before running any SourceMonitor commands inside your host app, add the gem and install dependencies:
47
47
 
48
48
  ```bash
49
- bundle add source_monitor --version "~> 0.14.0"
49
+ bundle add source_monitor --version "~> 0.15.0"
50
50
  # or edit your Gemfile, then run
51
51
  bundle install
52
52
  ```
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.14.0
1
+ 0.15.0
data/docs/setup.md CHANGED
@@ -7,7 +7,7 @@ This guide consolidates the new guided installer, verification commands, and rol
7
7
  | Requirement | Minimum | Notes |
8
8
  | --- | --- | --- |
9
9
  | Ruby | 4.0.1 | Use rbenv and match the engine's `.ruby-version`. |
10
- | Rails | 8.1.2 | Run `bin/rails about` inside the host to confirm. |
10
+ | Rails | 8.1.3 | Run `bin/rails about` inside the host to confirm. |
11
11
  | PostgreSQL | 14+ | Required for Solid Queue tables and item storage. |
12
12
  | Node.js | 18+ | Needed for Tailwind/esbuild assets when the host owns node tooling. |
13
13
  | Background jobs | Solid Queue (>= 0.3, < 3.0) | Add `solid_queue` to the host Gemfile if not present. |
@@ -18,8 +18,8 @@ This guide consolidates the new guided installer, verification commands, and rol
18
18
  Run these commands inside your host Rails application before invoking the guided workflow:
19
19
 
20
20
  ```bash
21
- bundle add source_monitor --version "~> 0.14.0"
22
- # or add gem "source_monitor", "~> 0.14.0" to Gemfile manually
21
+ bundle add source_monitor --version "~> 0.15.0"
22
+ # or add gem "source_monitor", "~> 0.15.0" to Gemfile manually
23
23
  bundle install
24
24
  ```
25
25
 
data/docs/upgrade.md CHANGED
@@ -46,6 +46,20 @@ If a removed option raises an error (`SourceMonitor::DeprecatedOptionError`), yo
46
46
 
47
47
  ## Version-Specific Notes
48
48
 
49
+ ### Upgrading to 0.15.0
50
+
51
+ **What changed:**
52
+ - **Security:** Rails bumped to 8.1.3 (security release), fixing five CVEs including XSS in tag/DebugExceptions helpers, an Active Storage path-traversal, and a NumberConverter issue.
53
+ - **ViewComponent 4.x compatibility:** The `view_component` dependency constraint widens from `>= 3.0, < 4.0` to `>= 3.0, < 5.0`, so host apps can now resolve ViewComponent 4.x (the engine's lockfile moves to 4.5.0). The engine's components use only stable ViewComponent APIs unaffected by the v4 upgrade, but host apps with their own ViewComponent 3.x customizations should review the [ViewComponent v4 release notes](https://github.com/ViewComponent/view_component/releases) before running `bundle update`.
54
+ - **Solid Queue 1.4.0:** Bumped from 1.3.1 with race-condition and supervisor stability fixes. The new dynamic recurring-tasks feature is opt-in and off by default.
55
+ - **Documentation:** Engine conventions consolidated into `AGENTS.md` as the canonical cross-agent reference; `CLAUDE.md` now points to it.
56
+
57
+ **Action items:**
58
+ 1. `bundle update source_monitor`
59
+ 2. `bin/rails source_monitor:upgrade`
60
+ 3. No database migrations and no breaking API or configuration changes.
61
+ 4. If your host app has its own ViewComponent 3.x customizations, test after upgrading and consult the ViewComponent v4 migration guide if issues arise.
62
+
49
63
  ### Upgrading to 0.14.0
50
64
 
51
65
  **What changed:**
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SourceMonitor
4
- VERSION = "0.14.0"
4
+ VERSION = "0.15.0"
5
5
  end
@@ -51,5 +51,5 @@ Gem::Specification.new do |spec|
51
51
  spec.add_dependency "solid_queue", ">= 0.3", "< 3.0"
52
52
  spec.add_dependency "solid_cable", ">= 3.0", "< 4.0"
53
53
  spec.add_dependency "ransack", "~> 4.2"
54
- spec.add_dependency "view_component", ">= 3.0", "< 4.0"
54
+ spec.add_dependency "view_component", ">= 3.0", "< 5.0"
55
55
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: source_monitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dchuk
@@ -238,7 +238,7 @@ dependencies:
238
238
  version: '3.0'
239
239
  - - "<"
240
240
  - !ruby/object:Gem::Version
241
- version: '4.0'
241
+ version: '5.0'
242
242
  type: :runtime
243
243
  prerelease: false
244
244
  version_requirements: !ruby/object:Gem::Requirement
@@ -248,7 +248,7 @@ dependencies:
248
248
  version: '3.0'
249
249
  - - "<"
250
250
  - !ruby/object:Gem::Version
251
- version: '4.0'
251
+ version: '5.0'
252
252
  description: SourceMonitor is a mountable Rails 8 engine that ingests RSS, Atom, and
253
253
  JSON feeds, scrapes full article content, and surfaces Solid Queue powered dashboards
254
254
  for monitoring and remediation.