source_monitor 0.7.0 → 0.8.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.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/release.md +45 -22
  3. data/.claude/skills/sm-configure/SKILL.md +10 -1
  4. data/.claude/skills/sm-configure/reference/configuration-reference.md +44 -0
  5. data/.claude/skills/sm-host-setup/reference/initializer-template.md +17 -0
  6. data/.claude/skills/sm-host-setup/reference/setup-checklist.md +2 -0
  7. data/.claude/skills/sm-job/reference/job-conventions.md +26 -0
  8. data/.claude/skills/sm-upgrade/reference/version-history.md +22 -0
  9. data/.gitignore +10 -0
  10. data/AGENTS.md +1 -1
  11. data/CHANGELOG.md +56 -0
  12. data/CLAUDE.md +11 -5
  13. data/Gemfile.lock +1 -1
  14. data/README.md +6 -4
  15. data/VERSION +1 -1
  16. data/app/assets/builds/source_monitor/application.css +43 -0
  17. data/app/assets/builds/source_monitor/application.js +127 -0
  18. data/app/assets/builds/source_monitor/application.js.map +3 -3
  19. data/app/assets/javascripts/source_monitor/application.js +2 -0
  20. data/app/assets/javascripts/source_monitor/controllers/notification_container_controller.js +138 -0
  21. data/app/assets/javascripts/source_monitor/controllers/notification_controller.js +11 -0
  22. data/app/controllers/source_monitor/source_favicon_fetches_controller.rb +38 -0
  23. data/app/controllers/source_monitor/sources_controller.rb +11 -0
  24. data/app/helpers/source_monitor/application_helper.rb +51 -0
  25. data/app/jobs/source_monitor/favicon_fetch_job.rb +71 -0
  26. data/app/jobs/source_monitor/import_opml_job.rb +9 -0
  27. data/app/jobs/source_monitor/source_health_check_job.rb +10 -0
  28. data/app/models/source_monitor/source.rb +2 -0
  29. data/app/views/layouts/source_monitor/application.html.erb +23 -2
  30. data/app/views/source_monitor/shared/_toast.html.erb +1 -0
  31. data/app/views/source_monitor/sources/_details.html.erb +34 -5
  32. data/app/views/source_monitor/sources/_row.html.erb +11 -6
  33. data/config/routes.rb +1 -0
  34. data/docs/configuration.md +1 -1
  35. data/docs/upgrade.md +22 -0
  36. data/lib/generators/source_monitor/install/templates/source_monitor.rb.tt +15 -1
  37. data/lib/source_monitor/configuration/favicons_settings.rb +42 -0
  38. data/lib/source_monitor/configuration/http_settings.rb +1 -1
  39. data/lib/source_monitor/configuration/scraping_settings.rb +1 -1
  40. data/lib/source_monitor/configuration.rb +3 -1
  41. data/lib/source_monitor/favicons/discoverer.rb +196 -0
  42. data/lib/source_monitor/fetching/feed_fetcher/source_updater.rb +21 -0
  43. data/lib/source_monitor/fetching/feed_fetcher.rb +1 -0
  44. data/lib/source_monitor/http.rb +5 -3
  45. data/lib/source_monitor/version.rb +1 -1
  46. data/lib/source_monitor.rb +4 -0
  47. data/lib/tasks/test_fast.rake +11 -0
  48. data/source_monitor.gemspec +1 -1
  49. metadata +7 -93
  50. data/.vbw-planning/PROJECT.md +0 -51
  51. data/.vbw-planning/ROADMAP.md +0 -32
  52. data/.vbw-planning/SHIPPED.md +0 -63
  53. data/.vbw-planning/STATE.md +0 -27
  54. data/.vbw-planning/codebase/ARCHITECTURE.md +0 -147
  55. data/.vbw-planning/codebase/CONCERNS.md +0 -99
  56. data/.vbw-planning/codebase/CONVENTIONS.md +0 -97
  57. data/.vbw-planning/codebase/DEPENDENCIES.md +0 -100
  58. data/.vbw-planning/codebase/INDEX.md +0 -86
  59. data/.vbw-planning/codebase/META.md +0 -42
  60. data/.vbw-planning/codebase/PATTERNS.md +0 -262
  61. data/.vbw-planning/codebase/STACK.md +0 -101
  62. data/.vbw-planning/codebase/STRUCTURE.md +0 -324
  63. data/.vbw-planning/codebase/TESTING.md +0 -154
  64. data/.vbw-planning/config.json +0 -53
  65. data/.vbw-planning/discovery.json +0 -26
  66. data/.vbw-planning/milestones/default/ROADMAP.md +0 -115
  67. data/.vbw-planning/milestones/default/STATE.md +0 -82
  68. data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-01-SUMMARY.md +0 -56
  69. data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-01.md +0 -187
  70. data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-02-SUMMARY.md +0 -64
  71. data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-02.md +0 -137
  72. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-01-SUMMARY.md +0 -67
  73. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-01.md +0 -142
  74. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-02-SUMMARY.md +0 -64
  75. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-02.md +0 -138
  76. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-03-SUMMARY.md +0 -85
  77. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-03.md +0 -147
  78. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-04-SUMMARY.md +0 -63
  79. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-04.md +0 -129
  80. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-05-SUMMARY.md +0 -74
  81. data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-05.md +0 -154
  82. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/03-VERIFICATION-wave1.md +0 -303
  83. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/03-VERIFICATION.md +0 -510
  84. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-01-SUMMARY.md +0 -61
  85. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-01.md +0 -161
  86. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-02-SUMMARY.md +0 -66
  87. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-02.md +0 -132
  88. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-03-SUMMARY.md +0 -59
  89. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-03.md +0 -171
  90. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-04-SUMMARY.md +0 -56
  91. data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-04.md +0 -152
  92. data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/04-CONTEXT.md +0 -33
  93. data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-01-SUMMARY.md +0 -42
  94. data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-01.md +0 -119
  95. data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-02-SUMMARY.md +0 -52
  96. data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-02.md +0 -195
  97. data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-03-SUMMARY.md +0 -79
  98. data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-03.md +0 -130
  99. data/.vbw-planning/milestones/generator-enhancements/REQUIREMENTS.md +0 -72
  100. data/.vbw-planning/milestones/generator-enhancements/ROADMAP.md +0 -125
  101. data/.vbw-planning/milestones/generator-enhancements/SHIPPED.md +0 -40
  102. data/.vbw-planning/milestones/generator-enhancements/STATE.md +0 -43
  103. data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/01-CONTEXT.md +0 -33
  104. data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/01-VERIFICATION.md +0 -86
  105. data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/PLAN-01-SUMMARY.md +0 -61
  106. data/.vbw-planning/milestones/generator-enhancements/phases/01-generator-steps/PLAN-01.md +0 -380
  107. data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/02-VERIFICATION.md +0 -78
  108. data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/PLAN-01-SUMMARY.md +0 -46
  109. data/.vbw-planning/milestones/generator-enhancements/phases/02-verification/PLAN-01.md +0 -500
  110. data/.vbw-planning/milestones/generator-enhancements/phases/03-docs-alignment/03-VERIFICATION.md +0 -89
  111. data/.vbw-planning/milestones/generator-enhancements/phases/03-docs-alignment/PLAN-01-SUMMARY.md +0 -48
  112. data/.vbw-planning/milestones/generator-enhancements/phases/03-docs-alignment/PLAN-01.md +0 -456
  113. data/.vbw-planning/milestones/generator-enhancements/phases/04-dashboard-ux/04-VERIFICATION.md +0 -129
  114. data/.vbw-planning/milestones/generator-enhancements/phases/04-dashboard-ux/PLAN-01-SUMMARY.md +0 -70
  115. data/.vbw-planning/milestones/generator-enhancements/phases/04-dashboard-ux/PLAN-01.md +0 -747
  116. data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/05-VERIFICATION.md +0 -156
  117. data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-01-SUMMARY.md +0 -69
  118. data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-01.md +0 -455
  119. data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-02-SUMMARY.md +0 -39
  120. data/.vbw-planning/milestones/generator-enhancements/phases/05-active-storage-images/PLAN-02.md +0 -488
  121. data/.vbw-planning/milestones/generator-enhancements/phases/06-netflix-feed-fix/06-VERIFICATION.md +0 -100
  122. data/.vbw-planning/milestones/generator-enhancements/phases/06-netflix-feed-fix/PLAN-01-SUMMARY.md +0 -37
  123. data/.vbw-planning/milestones/generator-enhancements/phases/06-netflix-feed-fix/PLAN-01.md +0 -345
  124. data/.vbw-planning/milestones/upgrade-assurance/REQUIREMENTS.md +0 -80
  125. data/.vbw-planning/milestones/upgrade-assurance/ROADMAP.md +0 -75
  126. data/.vbw-planning/milestones/upgrade-assurance/STATE.md +0 -29
  127. data/.vbw-planning/milestones/upgrade-assurance/phases/01-upgrade-command/01-VERIFICATION.md +0 -144
  128. data/.vbw-planning/milestones/upgrade-assurance/phases/01-upgrade-command/PLAN-01-SUMMARY.md +0 -43
  129. data/.vbw-planning/milestones/upgrade-assurance/phases/01-upgrade-command/PLAN-01.md +0 -405
  130. data/.vbw-planning/milestones/upgrade-assurance/phases/02-config-deprecation/PLAN-01-SUMMARY.md +0 -27
  131. data/.vbw-planning/milestones/upgrade-assurance/phases/02-config-deprecation/PLAN-01.md +0 -303
  132. data/.vbw-planning/milestones/upgrade-assurance/phases/03-upgrade-skill-docs/03-VERIFICATION.md +0 -380
  133. data/.vbw-planning/milestones/upgrade-assurance/phases/03-upgrade-skill-docs/PLAN-01-SUMMARY.md +0 -36
  134. data/.vbw-planning/milestones/upgrade-assurance/phases/03-upgrade-skill-docs/PLAN-01.md +0 -652
  135. data/.vbw-planning/phases/01-aia-certificate-resolution/.context-dev.md +0 -17
  136. data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-01-SUMMARY.md +0 -26
  137. data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-01.md +0 -71
  138. data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-02-SUMMARY.md +0 -16
  139. data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-02.md +0 -56
  140. data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-03-SUMMARY.md +0 -17
  141. data/.vbw-planning/phases/01-aia-certificate-resolution/PLAN-03.md +0 -98
@@ -1,63 +0,0 @@
1
- # Shipped Milestones
2
-
3
- ## default (2026-02-09 to 2026-02-10)
4
-
5
- **Core value:** Drop-in Rails engine for feed monitoring, content scraping, and operational dashboards.
6
-
7
- ### Metrics
8
-
9
- | Metric | Value |
10
- |--------|-------|
11
- | Phases | 4 |
12
- | Plans completed | 14 |
13
- | Commits | 18 |
14
- | Requirements satisfied | 15/15 |
15
- | Test runs | 841 (up from 473) |
16
- | Coverage | 86.97% line (510 uncovered, down from 2117) |
17
-
18
- ### Phases
19
-
20
- 1. Coverage Analysis & Quick Wins (2 plans)
21
- 2. Critical Path Test Coverage (5 plans)
22
- 3. Large File Refactoring (4 plans)
23
- 4. Code Quality & Conventions Cleanup (3 plans)
24
-
25
- ### Archive
26
-
27
- Location: `.vbw-planning/milestones/default/`
28
- Tag: `milestone/default`
29
-
30
- ---
31
-
32
- ## upgrade-assurance (2026-02-12 to 2026-02-13)
33
-
34
- **Goal:** Give host app developers confidence that gem updates go smoothly -- automated migration detection, upgrade command, config validation, and AI-assisted upgrade guidance.
35
-
36
- ### Metrics
37
-
38
- | Metric | Value |
39
- |--------|-------|
40
- | Phases | 3 |
41
- | Plans completed | 3 |
42
- | Tasks completed | 14 |
43
- | Commits | 12 |
44
- | Requirements satisfied | 5/5 (REQ-26 through REQ-30) |
45
- | Tests | 1003 (up from 973) |
46
-
47
- ### Phases
48
-
49
- 1. Upgrade Command & Migration Verifier (1 plan, 5 tasks)
50
- 2. Configuration Deprecation Framework (1 plan, 4 tasks)
51
- 3. Upgrade Skill & Documentation (1 plan, 5 tasks)
52
-
53
- ### Key Decisions
54
-
55
- - 3 phases: command, config, skill -- each independently valuable
56
- - `.source_monitor_version` marker file for version tracking
57
- - Deprecation registry with :warning and :error severities
58
- - sm-upgrade as a consumer skill (installed by default)
59
-
60
- ### Archive
61
-
62
- Location: `.vbw-planning/milestones/upgrade-assurance/`
63
- Tag: `milestone/upgrade-assurance`
@@ -1,27 +0,0 @@
1
- # State
2
-
3
- ## Current Position
4
-
5
- - **Milestone:** aia-ssl-fix
6
- - **Phase:** 1 -- AIA Certificate Resolution
7
- - **Status:** Complete
8
- - **Progress:** 100%
9
-
10
- ## Decisions
11
-
12
- | Decision | Date | Context |
13
- |----------|------|---------|
14
- | Single-phase milestone for AIA fix | 2026-02-17 | Complete plan already validated; no scoping needed |
15
- | 3 plans with wave parallelism | 2026-02-17 | Plans 01+02 (wave 1, disjoint files), Plan 03 (wave 2, integration) |
16
-
17
- ## Todos
18
-
19
- ## Metrics
20
-
21
- - **Started:** 2026-02-17
22
- - **Phases:** 1
23
- - **Plans:** 3
24
- - **Tests at start:** 1003
25
- - **Tests at end:** 1025
26
- - **Commits:** 4 (f60e9bf, 4c9568a, 9c38bc3, e68a6b0)
27
- - **Plans completed:** 3/3
@@ -1,147 +0,0 @@
1
- # Architecture
2
-
3
- ## System Overview
4
-
5
- SourceMonitor is a mountable Rails 8 engine that ingests RSS, Atom, and JSON feeds, scrapes full article content, and surfaces Solid Queue-powered dashboards for monitoring and remediation. It is packaged as a RubyGem and mounted into a host Rails application.
6
-
7
- ## Architecture Pattern
8
-
9
- **Mountable Rails Engine** with `isolate_namespace SourceMonitor`. The engine:
10
- - Provides its own models, controllers, views, jobs, and frontend assets
11
- - Uses its own `ApplicationRecord`, `ApplicationController`, and `ApplicationJob` base classes
12
- - Namespaces all database tables under a configurable prefix (default: `sourcemon_`)
13
- - Registers its own routes, asset paths, and initializers
14
-
15
- ## Core Domain Modules
16
-
17
- ### 1. Feed Fetching (`lib/source_monitor/fetching/`)
18
- The primary data ingestion pipeline:
19
- - `FeedFetcher` -- Orchestrates HTTP request, feed parsing via Feedjira, item creation, adaptive interval scheduling, and retry policies
20
- - `FetchRunner` -- Entry point for enqueuing fetch jobs; handles concurrency control
21
- - `FetchError` hierarchy -- Typed error classes (TimeoutError, ConnectionError, HTTPError, ParsingError)
22
- - `RetryPolicy` -- Exponential backoff with circuit breaker pattern
23
- - `StalledFetchReconciler` -- Recovers stalled fetch jobs
24
-
25
- ### 2. Content Scraping (`lib/source_monitor/scraping/` + `lib/source_monitor/scrapers/`)
26
- Pluggable content extraction system:
27
- - `Scrapers::Base` -- Abstract adapter contract; subclasses implement `#call` returning a `Result` struct
28
- - `Scrapers::Readability` -- Default adapter using ruby-readability
29
- - `Scraping::ItemScraper` -- Orchestrator that resolves adapter, executes scrape, persists results
30
- - `Scraping::BulkSourceScraper` -- Batch scraping across all items for a source
31
- - `Scraping::Enqueuer` -- Manages scrape job queuing with in-flight throttling
32
- - `Scraping::State` -- Tracks in-flight scrape state via cache/memory
33
-
34
- ### 3. Health Monitoring (`lib/source_monitor/health/`)
35
- Source health tracking system:
36
- - `SourceHealthMonitor` -- Computes health status from recent fetch history (sliding window)
37
- - `SourceHealthCheck` -- One-off health probe for a source URL
38
- - `ImportSourceHealthCheck` -- Variant for import wizard health checks
39
- - `SourceHealthReset` -- Resets health status for a source
40
- - Configurable thresholds: healthy (0.8), warning (0.5), auto-pause (0.2)
41
-
42
- ### 4. Scheduling (`lib/source_monitor/scheduler.rb`)
43
- - `Scheduler` -- Periodic job that finds sources due for fetch using `FOR UPDATE SKIP LOCKED`
44
- - Adaptive fetch interval algorithm (increase/decrease factors, jitter)
45
- - Integrates with `StalledFetchReconciler` for recovery
46
-
47
- ### 5. Event System (`lib/source_monitor/events.rb`)
48
- - Typed event structs: `ItemCreatedEvent`, `ItemScrapedEvent`, `FetchCompletedEvent`
49
- - Callback-based dispatch with error isolation per handler
50
- - Item processor pipeline for custom host-app processing
51
- - Registration via `SourceMonitor.config.events.after_*` DSL
52
-
53
- ### 6. Configuration (`lib/source_monitor/configuration.rb`)
54
- Rich nested configuration object with sub-configs:
55
- - `HTTPSettings` -- timeout, retries, user agent, proxy, headers
56
- - `ScraperRegistry` -- pluggable adapter registration
57
- - `RetentionSettings` -- item retention days, max items, strategy (destroy/soft_delete)
58
- - `RealtimeSettings` -- adapter selection (solid_cable/redis/async)
59
- - `FetchingSettings` -- adaptive interval tuning
60
- - `HealthSettings` -- health window and threshold configuration
61
- - `AuthenticationSettings` -- pluggable authentication/authorization handlers
62
- - `ScrapingSettings` -- concurrency limits
63
- - `Events` -- callback registration
64
- - `Models` -- concern injection and custom validation registration
65
-
66
- ### 7. Model Extensions (`lib/source_monitor/model_extensions.rb`)
67
- Dynamic model customization system:
68
- - Host apps can inject concerns and validations into engine models at configuration time
69
- - `ModelExtensions.register(model_class, key)` -- called in each model class body
70
- - `ModelExtensions.reload!` -- re-applies all extensions (called on configuration change)
71
- - Manages table name assignment from configurable prefix
72
-
73
- ### 8. Real-time Broadcasting (`lib/source_monitor/realtime/`)
74
- - `Realtime::Adapter` -- Configures Action Cable based on selected adapter
75
- - `Realtime::Broadcaster` -- Broadcasts source/item updates and toast notifications
76
- - `Dashboard::TurboBroadcaster` -- Wires dashboard stat updates to Turbo Streams
77
-
78
- ### 9. Setup/Installation System (`lib/source_monitor/setup/`)
79
- Comprehensive host-app installation workflow:
80
- - `Setup::CLI` -- Command-line interface for setup
81
- - `Setup::Workflow` -- Orchestrates multi-step installation
82
- - `Setup::Requirements` / `Setup::Detectors` -- System requirement checks
83
- - `Setup::GemfileEditor` / `Setup::BundleInstaller` / `Setup::NodeInstaller` -- Dependency installation
84
- - `Setup::InstallGenerator` -- Rails generator for migrations, routes, initializer
85
- - `Setup::Verification::Runner` -- Post-install verification (Solid Queue, Action Cable)
86
-
87
- ### 10. OPML Import Wizard (`app/controllers/source_monitor/import_sessions_controller.rb`)
88
- Multi-step wizard for bulk feed import:
89
- - 5-step flow: upload -> preview -> health_check -> configure -> confirm
90
- - State persisted in `ImportSession` model with JSONB columns
91
- - Health check jobs run asynchronously with Turbo Stream progress updates
92
- - Bulk settings applied to all imported sources
93
-
94
- ## Data Model
95
-
96
- ```
97
- Source (sourcemon_sources)
98
- |-- has_many Item (sourcemon_items)
99
- | |-- has_one ItemContent (sourcemon_item_contents) [separate table for large content]
100
- | |-- has_many ScrapeLog (sourcemon_scrape_logs)
101
- | +-- has_many LogEntry (sourcemon_log_entries) [polymorphic]
102
- |-- has_many FetchLog (sourcemon_fetch_logs)
103
- |-- has_many HealthCheckLog (sourcemon_health_check_logs)
104
- +-- has_many LogEntry (sourcemon_log_entries)
105
-
106
- LogEntry (sourcemon_log_entries)
107
- |-- delegated_type :loggable -> FetchLog | ScrapeLog | HealthCheckLog
108
-
109
- ImportSession (sourcemon_import_sessions)
110
- +-- JSONB columns for wizard state
111
-
112
- ImportHistory (sourcemon_import_histories)
113
- +-- Records completed imports
114
- ```
115
-
116
- ## Job Architecture
117
-
118
- All jobs inherit from `SourceMonitor::ApplicationJob` which inherits from the host app's `ApplicationJob` (or `ActiveJob::Base`).
119
-
120
- | Job | Queue | Purpose |
121
- |-----|-------|---------|
122
- | `ScheduleFetchesJob` | fetch | Recurring: triggers Scheduler to find and enqueue due sources |
123
- | `FetchFeedJob` | fetch | Fetches a single source's feed, creates items |
124
- | `ScrapeItemJob` | scrape | Scrapes content for a single item |
125
- | `SourceHealthCheckJob` | fetch | Runs health check for a source |
126
- | `ImportSessionHealthCheckJob` | fetch | Health checks during OPML import wizard |
127
- | `ImportOpmlJob` | fetch | Bulk-creates sources from OPML import |
128
- | `LogCleanupJob` | fetch | Recurring: prunes old log entries |
129
- | `ItemCleanupJob` | fetch | Recurring: prunes old items per retention policy |
130
-
131
- Queue names are configurable via `config.fetch_queue_name` and `config.scrape_queue_name`.
132
-
133
- ## Security Architecture
134
-
135
- - `Security::Authentication` -- Pluggable authentication via handler callbacks (symbol method names or callables)
136
- - `Security::ParameterSanitizer` -- HTML sanitization of all user inputs via `ActionView::Base.full_sanitizer`
137
- - `Models::Sanitizable` -- Concern that sanitizes string and hash model attributes before validation
138
- - `Models::UrlNormalizable` -- URL normalization and validation concern
139
- - `SanitizesSearchParams` -- Controller concern for search parameter sanitization
140
- - CSRF protection enabled (`protect_from_forgery with: :exception`)
141
- - No built-in user model -- delegates to host app
142
-
143
- ## Instrumentation & Metrics
144
-
145
- - `Instrumentation` -- Emits `ActiveSupport::Notifications` events for fetch lifecycle
146
- - `Metrics` -- In-memory counters and gauges, populated via notification subscribers
147
- - Events: `source_monitor.fetch.start`, `source_monitor.fetch.finish`, `source_monitor.scheduler.run`, `source_monitor.items.duplicate`, `source_monitor.items.retention`
@@ -1,99 +0,0 @@
1
- # Concerns
2
-
3
- ## Technical Debt
4
-
5
- ### 1. Large Files
6
- - `lib/source_monitor/fetching/feed_fetcher.rb` (627 lines) -- The core fetch pipeline handles HTTP, parsing, item creation, adaptive intervals, retry strategies, and source updates all in one class. This is the largest single-responsibility violation.
7
- - `lib/source_monitor/configuration.rb` (655 lines) -- Contains ~12 nested configuration classes in a single file. Each settings class could be extracted.
8
- - `app/controllers/source_monitor/import_sessions_controller.rb` (792 lines) -- The OPML import wizard controller handles all 5 wizard steps, file parsing, health checks, selection management, and bulk operations.
9
- - `lib/source_monitor/items/item_creator.rb` -- Large item creation file (based on coverage baseline entry count).
10
- - `config/coverage_baseline.json` (2329 lines) -- This file itself is very large, indicating significant uncovered code.
11
-
12
- ### 2. Coverage Baseline Gaps
13
- The `config/coverage_baseline.json` catalogs uncovered lines. Particularly notable gaps:
14
- - `lib/source_monitor/items/item_creator.rb` -- Hundreds of uncovered branch lines
15
- - `lib/source_monitor/fetching/feed_fetcher.rb` -- Extensive uncovered branches
16
- - `lib/source_monitor/configuration.rb` -- Many configuration edge cases untested
17
- - `lib/source_monitor/dashboard/queries.rb` -- Dashboard query logic largely uncovered
18
- - `lib/source_monitor/realtime/broadcaster.rb` -- Broadcasting logic has gaps
19
- - `lib/source_monitor/scraping/bulk_source_scraper.rb` -- Bulk scraping coverage gaps
20
- - `lib/source_monitor/analytics/sources_index_metrics.rb` -- Analytics largely uncovered
21
-
22
- ### 3. LogEntry Hard-coded Table Name
23
- In `app/models/source_monitor/log_entry.rb` line 6: `self.table_name = "sourcemon_log_entries"` -- This bypasses the configurable table name prefix system that all other models use via `ModelExtensions.register`. The table name is hard-coded despite the engine supporting custom prefixes.
24
-
25
- ### 4. `lib/source_monitor.rb` Entry Point Complexity
26
- The main entry point has 102+ require statements loaded eagerly. This means all engine code is loaded at boot regardless of what features the host app uses. No autoloading or lazy-loading strategy.
27
-
28
- ## Architectural Risks
29
-
30
- ### 1. PostgreSQL Lock-in
31
- The `Scheduler` uses `FOR UPDATE SKIP LOCKED` (PostgreSQL-specific locking), and queries use `NULLS FIRST`/`NULLS LAST` ordering. The engine will not work with MySQL or SQLite. This is documented nowhere in the gemspec constraints.
32
-
33
- ### 2. In-Memory Metrics Without Persistence
34
- `SourceMonitor::Metrics` stores counters and gauges in module-level instance variables (`@counters`, `@gauges`). These are:
35
- - Lost on process restart
36
- - Not shared across workers/processes
37
- - Not suitable for production monitoring
38
-
39
- ### 3. Scraping State Management
40
- `SourceMonitor::Scraping::State` tracks in-flight scrapes but the mechanism (cache/memory) is fragile. In multi-process deployments, this could lead to over-enqueuing or under-enqueuing of scrape jobs.
41
-
42
- ### 4. Optional Dependency Loading
43
- Solid Queue, Solid Cable, Turbo, and Ransack are loaded with `rescue LoadError`. This means the engine could silently fail to load core functionality without clear error messages to the host app developer.
44
-
45
- ### 5. No Database Index Verification
46
- 24 migration files create the schema incrementally. There is no single-schema check to verify all expected indexes exist after migration.
47
-
48
- ## Security Considerations
49
-
50
- ### 1. No Built-in Authentication
51
- The engine relies entirely on the host app for authentication. The `Security::Authentication` module provides hooks but no default protection. An unconfigured engine is accessible to anyone who can reach the mount path.
52
-
53
- ### 2. Fallback User Creation in Import Controller
54
- `ImportSessionsController#create_guest_user` (lines 416-429) can create a `User` record in the host app's database when no authentication is configured. This is a defensive fallback but could be unexpected behavior.
55
-
56
- ### 3. Parameter Sanitization Scope
57
- `Security::ParameterSanitizer` uses `ActionView::Base.full_sanitizer` which strips all HTML. This is broad but may not catch all injection vectors (e.g., URL-based attacks, header injection via custom_headers).
58
-
59
- ### 4. Custom Headers Passthrough
60
- Source `custom_headers` are stored as JSONB and passed to HTTP requests (`FeedFetcher#request_headers`). Malicious header values could potentially be used for SSRF or header injection if not properly validated.
61
-
62
- ## Performance Considerations
63
-
64
- ### 1. N+1 Query Risk in Dashboard
65
- `Dashboard::Queries` performs multiple database queries for stats, recent activity, quick actions, job metrics, and fetch schedules. The controller assembles all of these synchronously.
66
-
67
- ### 2. Large OPML File Handling
68
- The OPML import parses entire files in memory (`Nokogiri::XML(content)`). Large OPML files with thousands of entries could cause memory pressure.
69
-
70
- ### 3. Bulk Scrape Operations
71
- `BulkSourceScraper` enqueues individual `ScrapeItemJob` for each item. For sources with thousands of items, this could flood the job queue.
72
-
73
- ### 4. Coverage Baseline File
74
- The `config/coverage_baseline.json` at 2329 lines is parsed at test time and represents significant technical debt in test coverage.
75
-
76
- ## Operational Risks
77
-
78
- ### 1. No Health Check Endpoint Documentation
79
- The `/health` endpoint exists but its response format and behavior are not documented.
80
-
81
- ### 2. Stalled Fetch Recovery
82
- The `StalledFetchReconciler` runs within the `Scheduler`, but if the scheduler itself stalls, there is no external recovery mechanism.
83
-
84
- ### 3. Circuit Breaker State in Database
85
- Fetch circuit breaker state (`fetch_circuit_opened_at`, `fetch_circuit_until`) is stored on the `Source` model. This means circuit breaker resets require database writes, and a failing database connection prevents circuit recovery.
86
-
87
- ## Dependency Risks
88
-
89
- ### 1. ruby-readability (~> 0.7)
90
- This gem appears to be minimally maintained. The `0.7.x` line is old. It depends on Nokogiri which receives frequent security updates, creating a transitive dependency management burden.
91
-
92
- ### 2. Nokolexbor (~> 0.5)
93
- Native extension gem with C bindings to the Lexbor HTML parser. Platform-specific builds could cause deployment issues, especially on less common architectures.
94
-
95
- ### 3. Feedjira Wide Version Range
96
- `>= 3.2, < 5.0` allows major version bumps that could introduce breaking API changes.
97
-
98
- ### 4. Ruby >= 3.4.0 Minimum
99
- This is an aggressive minimum that excludes many production Ruby installations still on 3.2.x or 3.3.x.
@@ -1,97 +0,0 @@
1
- # Conventions
2
-
3
- ## Ruby Code Style
4
-
5
- - **Style Guide**: Rails Omakase via `rubocop-rails-omakase` gem
6
- - **Frozen String Literals**: Consistently used across all app/ and lib/ Ruby files (`# frozen_string_literal: true`)
7
- - **No frozen_string_literal**: Absent from some test files and the main `lib/source_monitor.rb` entry point
8
-
9
- ## Naming Conventions
10
-
11
- ### Module/Class Naming
12
- - All engine code namespaced under `SourceMonitor::`
13
- - Sub-modules use descriptive domain names: `Fetching`, `Scraping`, `Health`, `Security`, `Dashboard`, `Realtime`
14
- - Service objects named as nouns (e.g., `FeedFetcher`, `ItemScraper`, `Scheduler`, `RetentionPruner`)
15
- - Presenters suffixed with `Presenter` (e.g., `BulkResultPresenter`, `RecentActivityPresenter`, `TurboStreamPresenter`)
16
- - Query objects in `analytics/` and `dashboard/` (e.g., `Queries`, `SourcesIndexMetrics`)
17
-
18
- ### File Organization
19
- - One class per file, file path mirrors class namespace
20
- - Nested classes extracted to sub-directories (e.g., `item_scraper/adapter_resolver.rb`, `item_scraper/persistence.rb`)
21
- - Concerns placed in `concerns/` subdirectories
22
-
23
- ### Database Naming
24
- - Table prefix: `sourcemon_` (configurable via `config.models.table_name_prefix`)
25
- - Tables: `sourcemon_sources`, `sourcemon_items`, `sourcemon_fetch_logs`, etc.
26
- - Foreign keys follow Rails conventions: `source_id`, `item_id`
27
- - Timestamps use `started_at`/`completed_at` pattern for log records
28
-
29
- ### Method Naming
30
- - Bang methods (`!`) for operations that raise on failure: `soft_delete!`, `mark_processing!`
31
- - Predicate methods: `fetch_circuit_open?`, `auto_paused?`, `deleted?`, `success?`
32
- - `call` method pattern for service objects and scraper adapters
33
- - Private `set_*` for controller before_actions: `set_source`, `set_import_session`
34
-
35
- ### Job Naming
36
- - Jobs suffixed with `Job`: `FetchFeedJob`, `ScrapeItemJob`, `ScheduleFetchesJob`
37
- - Queue assignment via `source_monitor_queue :fetch` class method
38
-
39
- ### Controller Naming
40
- - Resource controllers follow Rails conventions: `SourcesController`, `ItemsController`
41
- - Singular nested resource controllers: `SourceFetchesController`, `SourceRetriesController`
42
- - Action-specific controllers for non-RESTful actions: `SourceBulkScrapesController`, `SourceHealthChecksController`
43
-
44
- ## Configuration Patterns
45
-
46
- - Configuration via `SourceMonitor.configure { |config| ... }` block DSL
47
- - Nested configuration objects with `reset!` methods for testing
48
- - Settings classes with explicit defaults defined as constants
49
- - Callable values supported (procs/lambdas) for dynamic configuration
50
-
51
- ## Error Handling
52
-
53
- - Custom error hierarchy: `FetchError` base with typed subclasses (`TimeoutError`, `ConnectionError`, `HTTPError`, `ParsingError`)
54
- - Errors carry structured data: `http_status`, `response`, `original_error`
55
- - Defensive `rescue StandardError` wrappers around logging calls
56
- - `Rails.logger` usage guarded with `defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger`
57
-
58
- ## Struct Usage
59
-
60
- - `Struct.new(..., keyword_init: true)` extensively used for result/event objects
61
- - Named structs: `Result`, `ResponseWrapper`, `EntryProcessingResult`
62
- - Event structs: `ItemCreatedEvent`, `ItemScrapedEvent`, `FetchCompletedEvent`
63
-
64
- ## Frontend Conventions
65
-
66
- - CSS scoped under `.fm-admin` class with Tailwind `important` selector
67
- - Stimulus controllers registered on `window.SourceMonitorStimulus`
68
- - Controller naming: kebab-case in HTML (`async-submit`, `confirm-navigation`)
69
- - ERB partials prefixed with underscore, organized per resource
70
- - Turbo Stream responses via `SourceMonitor::TurboStreams::StreamResponder`
71
-
72
- ## View Conventions
73
-
74
- - Layouts: Engine uses host app layout; views are ERB
75
- - Partials extensively used: `_row.html.erb`, `_details.html.erb`, `_form_fields.html.erb`
76
- - Wizard steps as separate partials: `steps/_upload.html.erb`, `steps/_preview.html.erb`
77
- - Toast notifications broadcast via realtime system
78
-
79
- ## Test Conventions
80
-
81
- - Minitest with Rails test helpers (not RSpec)
82
- - Test files mirror source structure: `test/lib/source_monitor/scraping/item_scraper_test.rb`
83
- - Test helper methods: `create_source!` factory method in `ActiveSupport::TestCase`
84
- - Parallel test execution by default
85
- - Configuration reset in `setup` block: `SourceMonitor.reset_configuration!`
86
- - WebMock disables external connections
87
- - VCR for HTTP interaction recording
88
- - test-prof `before_all` for expensive shared setup
89
- - `with_inline_jobs` and `with_queue_adapter` helpers for job testing
90
-
91
- ## Documentation Conventions
92
-
93
- - YARD-style comments in some service classes
94
- - Inline comments explain "why" not "what"
95
- - `# :nocov:` markers for untestable/defensive code paths
96
- - CHANGELOG maintained in conventional format
97
- - CONTRIBUTING.md present
@@ -1,100 +0,0 @@
1
- # Dependencies
2
-
3
- ## Runtime Dependencies (gemspec)
4
-
5
- These are declared in `source_monitor.gemspec` and required by any host app using the engine.
6
-
7
- | Gem | Constraint | Purpose | Risk |
8
- |-----|-----------|---------|------|
9
- | rails | >= 8.0.3, < 9.0 | Core framework | Major version lock |
10
- | cssbundling-rails | ~> 1.4 | CSS asset bundling bridge | Low |
11
- | jsbundling-rails | ~> 1.3 | JS asset bundling bridge | Low |
12
- | turbo-rails | ~> 2.0 | Hotwire Turbo for real-time updates | Medium - optional but recommended |
13
- | feedjira | >= 3.2, < 5.0 | Feed parsing (RSS/Atom) | Core functionality |
14
- | faraday | ~> 2.9 | HTTP client | Core functionality |
15
- | faraday-retry | ~> 2.2 | Retry middleware | Low |
16
- | faraday-follow_redirects | ~> 0.4 | Redirect handling | Low |
17
- | faraday-gzip | ~> 3.0 | Compression support | Low |
18
- | nokolexbor | ~> 0.5 | Fast HTML parsing (lexbor engine) | Medium - native extension |
19
- | ruby-readability | ~> 0.7 | Article content extraction | Medium - older gem |
20
- | solid_queue | >= 0.3, < 3.0 | Background job processing | Core functionality |
21
- | solid_cable | >= 3.0, < 4.0 | Action Cable adapter | Real-time features |
22
- | ransack | ~> 4.2 | Search/filter form builder | Medium |
23
-
24
- ## Optional Runtime Dependencies
25
-
26
- Loaded with rescue from LoadError in `lib/source_monitor.rb`:
27
- - `solid_queue` -- optional if host uses different Active Job backend
28
- - `solid_cable` -- optional if host uses Redis or another Action Cable adapter
29
- - `turbo-rails` -- optional but recommended for real-time updates
30
- - `ransack` -- powers search forms when available
31
-
32
- ## Development Dependencies (Gemfile)
33
-
34
- | Gem | Purpose |
35
- |-----|---------|
36
- | puma | Development web server |
37
- | pg | PostgreSQL adapter |
38
- | propshaft | Asset pipeline |
39
- | rubocop-rails-omakase | Linting (Rails omakase style) |
40
- | brakeman | Security scanning |
41
-
42
- ## Test Dependencies (Gemfile)
43
-
44
- | Gem | Purpose |
45
- |-----|---------|
46
- | simplecov | Code coverage reporting |
47
- | test-prof | Test profiling toolkit |
48
- | stackprof | Stack sampling profiler |
49
- | capybara | System test framework |
50
- | webmock | HTTP stubbing |
51
- | vcr | HTTP recording/playback |
52
- | selenium-webdriver | Browser driver for system tests |
53
-
54
- ## JavaScript Dependencies (package.json)
55
-
56
- ### Runtime
57
-
58
- | Package | Version | Purpose |
59
- |---------|---------|---------|
60
- | @hotwired/stimulus | ^3.2.2 | Stimulus JS framework |
61
- | stimulus-use | ^0.52.0 | Composable Stimulus behaviors |
62
-
63
- ### Development
64
-
65
- | Package | Version | Purpose |
66
- |---------|---------|---------|
67
- | esbuild | ^0.23.0 | JS bundling |
68
- | tailwindcss | ^3.4.10 | CSS framework |
69
- | postcss | ^8.4.45 | CSS transformation |
70
- | autoprefixer | ^10.4.20 | CSS vendor prefixes |
71
- | eslint | ^9.11.0 | JS linting |
72
- | @eslint/js | ^9.11.0 | ESLint core config |
73
- | stylelint | ^16.8.0 | CSS linting |
74
- | stylelint-config-standard | ^36.0.0 | Stylelint standard config |
75
-
76
- ## Dependency Coupling Analysis
77
-
78
- ### Tight Coupling (hard to replace)
79
- - **Rails 8.x** -- entire engine is built on Rails conventions
80
- - **Feedjira** -- core feed parsing logic, deeply integrated in `Fetching::FeedFetcher`
81
- - **Faraday** -- HTTP client used throughout `SourceMonitor::HTTP`, configurable via middleware stack
82
- - **Solid Queue** -- integrated in engine initializer, scheduler, and job visibility system
83
- - **PostgreSQL** -- uses `FOR UPDATE SKIP LOCKED`, `NULLS FIRST/LAST` SQL syntax
84
-
85
- ### Moderate Coupling (replaceable with effort)
86
- - **Nokolexbor/Nokogiri** -- HTML parsing in scrapers and OPML import
87
- - **Ransack** -- used in model `ransackable_attributes` declarations and search forms
88
- - **Tailwind CSS** -- all views use Tailwind utility classes scoped under `.fm-admin`
89
-
90
- ### Loose Coupling (easily replaceable)
91
- - **Solid Cable** -- configurable via `config.realtime.adapter`, supports `:solid_cable`, `:redis`, `:async`
92
- - **ruby-readability** -- wrapped in `Scrapers::Readability` adapter behind pluggable adapter interface
93
- - **Turbo Rails** -- optional, loaded conditionally
94
-
95
- ## Version Constraints of Note
96
-
97
- - Ruby >= 3.4.0 is a relatively aggressive minimum requirement
98
- - Rails >= 8.0.3 pins to the latest major, narrowing host app compatibility
99
- - Solid Queue has a wide range (0.3 to 3.0), suggesting early adoption with forward-looking flexibility
100
- - PostgreSQL is the only supported database (uses PG-specific SQL features)
@@ -1,86 +0,0 @@
1
- # Index
2
-
3
- Cross-referenced index of key findings across all mapping documents.
4
-
5
- ## Quick Reference
6
-
7
- | Document | Focus | Key Finding |
8
- |----------|-------|-------------|
9
- | [STACK.md](STACK.md) | Technology choices | Rails 8.1.1 engine, Ruby 3.4+, PostgreSQL, Solid Queue, Tailwind 3 |
10
- | [DEPENDENCIES.md](DEPENDENCIES.md) | Dependency analysis | 14 runtime gems, PG-only, optional deps loaded silently |
11
- | [ARCHITECTURE.md](ARCHITECTURE.md) | System design | 10 domain modules, event-driven, pluggable scrapers |
12
- | [STRUCTURE.md](STRUCTURE.md) | Directory layout | ~324 Ruby files, 124 tests, 24 migrations |
13
- | [CONVENTIONS.md](CONVENTIONS.md) | Code style | Rails omakase, frozen strings, Struct-based results |
14
- | [TESTING.md](TESTING.md) | Test infrastructure | Minitest, parallel, SimpleCov branch coverage, nightly profiling |
15
- | [CONCERNS.md](CONCERNS.md) | Risks & debt | Large files, PG lock-in, coverage gaps, no default auth |
16
- | [PATTERNS.md](PATTERNS.md) | Recurring patterns | Service objects, adapter pattern, event callbacks, Turbo Streams |
17
-
18
- ## Key Entry Points
19
-
20
- | Purpose | File | Notes |
21
- |---------|------|-------|
22
- | Gem entry point | `lib/source_monitor.rb` | 102+ require statements, module definition |
23
- | Engine definition | `lib/source_monitor/engine.rb` | Initializers, asset registration |
24
- | Configuration DSL | `lib/source_monitor/configuration.rb` | 12 nested settings classes |
25
- | Routes | `config/routes.rb` | 24 lines, RESTful resources |
26
- | Main model | `app/models/source_monitor/source.rb` | Core domain entity |
27
- | Dashboard | `app/controllers/source_monitor/dashboard_controller.rb` | Landing page |
28
- | Fetch pipeline | `lib/source_monitor/fetching/feed_fetcher.rb` | Core data ingestion |
29
- | Scrape pipeline | `lib/source_monitor/scraping/item_scraper.rb` | Content extraction orchestrator |
30
- | Scheduler | `lib/source_monitor/scheduler.rb` | Periodic fetch scheduling |
31
- | JS entry | `app/assets/javascripts/source_monitor/application.js` | Stimulus app setup |
32
- | CSS entry | `app/assets/stylesheets/source_monitor/application.tailwind.css` | Tailwind input |
33
- | Test entry | `test/test_helper.rb` | Test infrastructure setup |
34
-
35
- ## Data Model Reference
36
-
37
- | Model | Table | Key Relationships |
38
- |-------|-------|-------------------|
39
- | `Source` | `sourcemon_sources` | has_many: items, fetch_logs, scrape_logs, health_check_logs, log_entries |
40
- | `Item` | `sourcemon_items` | belongs_to: source; has_one: item_content; has_many: scrape_logs, log_entries |
41
- | `ItemContent` | `sourcemon_item_contents` | belongs_to: item (separate table for large scraped content) |
42
- | `FetchLog` | `sourcemon_fetch_logs` | belongs_to: source; has_one: log_entry (polymorphic) |
43
- | `ScrapeLog` | `sourcemon_scrape_logs` | belongs_to: item, source; has_one: log_entry (polymorphic) |
44
- | `HealthCheckLog` | `sourcemon_health_check_logs` | belongs_to: source; has_one: log_entry (polymorphic) |
45
- | `LogEntry` | `sourcemon_log_entries` | delegated_type: loggable (FetchLog/ScrapeLog/HealthCheckLog) |
46
- | `ImportSession` | `sourcemon_import_sessions` | JSONB state for wizard flow |
47
- | `ImportHistory` | `sourcemon_import_histories` | Records completed imports |
48
-
49
- ## Job Reference
50
-
51
- | Job Class | Queue | Schedule | Purpose |
52
- |-----------|-------|----------|---------|
53
- | `ScheduleFetchesJob` | fetch | Recurring | Triggers scheduler to find due sources |
54
- | `FetchFeedJob` | fetch | On-demand | Fetches one source's feed |
55
- | `ScrapeItemJob` | scrape | On-demand | Scrapes one item's content |
56
- | `SourceHealthCheckJob` | fetch | On-demand | Health check for one source |
57
- | `ImportSessionHealthCheckJob` | fetch | On-demand | Health check during OPML import |
58
- | `ImportOpmlJob` | fetch | On-demand | Bulk creates sources from OPML |
59
- | `LogCleanupJob` | fetch | Recurring | Prunes old log entries |
60
- | `ItemCleanupJob` | fetch | Recurring | Prunes items per retention policy |
61
-
62
- ## Configuration Surface Area
63
-
64
- | Section | Key Settings | Defaults |
65
- |---------|-------------|----------|
66
- | Queues | `fetch_queue_name`, `scrape_queue_name`, concurrency | `source_monitor_fetch`, `source_monitor_scrape`, 2 each |
67
- | HTTP | timeout, retries, user agent, proxy, headers | 15s/5s timeout, 4 retries |
68
- | Fetching | adaptive interval params, jitter | 5min-24hr, 1.25x increase, 0.75x decrease |
69
- | Health | window size, thresholds, auto-pause | 20 window, 0.8/0.5/0.2 thresholds |
70
- | Scraping | max_in_flight, max_bulk_batch | 25, 100 |
71
- | Retention | days, max_items, strategy | nil (no auto-cleanup), :destroy |
72
- | Realtime | adapter (solid_cable/redis/async) | solid_cable |
73
- | Authentication | handlers, current_user_method | nil (no auth by default) |
74
- | Models | table_name_prefix, concerns, validations | `sourcemon_` |
75
-
76
- ## Critical Cross-Cutting Concerns
77
-
78
- 1. **PG-only** (ARCHITECTURE + CONCERNS): `FOR UPDATE SKIP LOCKED` and `NULLS FIRST/LAST` SQL are PostgreSQL-specific. No other DB supported.
79
-
80
- 2. **No default auth** (ARCHITECTURE + CONCERNS): Engine mounts without authentication unless host app configures it. Import wizard has a `create_guest_user` fallback.
81
-
82
- 3. **Eager loading** (STRUCTURE + CONCERNS): All 102+ require statements in `lib/source_monitor.rb` load at boot time.
83
-
84
- 4. **Coverage debt** (TESTING + CONCERNS): `config/coverage_baseline.json` lists 2329 lines of known uncovered code, particularly in `FeedFetcher`, `ItemCreator`, `Configuration`, and `Dashboard::Queries`.
85
-
86
- 5. **Large files** (STRUCTURE + CONCERNS): `FeedFetcher` (627 lines), `Configuration` (655 lines), and `ImportSessionsController` (792 lines) are candidates for extraction.
@@ -1,42 +0,0 @@
1
- # META
2
-
3
- ## Mapping Metadata
4
-
5
- | Field | Value |
6
- |-------|-------|
7
- | mapped_at | 2026-02-09T00:00:00Z |
8
- | git_hash | 1fb781a35575c2d46bfb8cd96f90c64ddf6ed210 |
9
- | file_count | 530 |
10
- | mode | full |
11
- | monorepo | false |
12
- | mapping_tier | solo (inline) |
13
-
14
- ## Documents
15
-
16
- | File | Domain | Description |
17
- |------|--------|-------------|
18
- | `STACK.md` | Tech Stack | Technology choices, framework versions, build pipeline |
19
- | `DEPENDENCIES.md` | Tech Stack | Runtime, dev, and test dependency analysis with coupling assessment |
20
- | `ARCHITECTURE.md` | Architecture | System overview, domain modules, data model, job architecture |
21
- | `STRUCTURE.md` | Architecture | Full directory tree with file counts and organization |
22
- | `CONVENTIONS.md` | Quality | Naming conventions, code style, frontend patterns |
23
- | `TESTING.md` | Quality | Test framework, CI pipeline, coverage strategy, profiling |
24
- | `CONCERNS.md` | Concerns | Technical debt, security risks, performance, operational risks |
25
- | `INDEX.md` | Synthesis | Cross-referenced index with key findings and quick references |
26
- | `PATTERNS.md` | Synthesis | 14 recurring patterns across the codebase |
27
- | `META.md` | Meta | This file -- mapping metadata and document inventory |
28
-
29
- ## Language Breakdown
30
-
31
- | Language | File Count | Notes |
32
- |----------|-----------|-------|
33
- | Ruby (.rb) | ~324 | Models, controllers, jobs, lib modules, tests |
34
- | ERB (.erb) | ~48 | View templates |
35
- | Markdown (.md) | ~45 | Documentation |
36
- | YAML (.yml) | ~16 | Configuration files |
37
- | JavaScript (.js) | ~14 | Stimulus controllers, build entry points |
38
- | CSS (.css) | ~2 | Tailwind input and build output |
39
-
40
- ## Project Summary
41
-
42
- SourceMonitor is a mountable Rails 8 engine (v0.2.1) that ingests RSS/Atom/JSON feeds, scrapes full article content via pluggable adapters, and provides Solid Queue-powered dashboards for monitoring and remediation. It is distributed as a RubyGem, requires PostgreSQL and Ruby >= 3.4.0, and integrates with host Rails applications via the standard engine mounting pattern with an isolated namespace.