Skip to content

Commit dfca027

Browse files
authored
feat: simplify feed creation contract & backend error handling (#962)
## Summary - simplify feed creation around auto-source and remove strategy from create payload/result - add structured backend error metadata and feed empty-extraction handling - clean token/access internals, Sentry breadcrumbs, OpenAPI/types, and related docs ## Validation - make setup && make ready inside devcontainer image - make ready inside devcontainer image - make openapi-verify && make openapi-lint inside devcontainer image with host gitdir mounted ## Slice notes - Source branch: preact-router @ 3b1e647 - Backup branch: backup/preact-router-3b1e647 - Excludes frontend routed workflow and result UX/tooling polish for later slices
1 parent 5c25458 commit dfca027

63 files changed

Lines changed: 1583 additions & 599 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Gemfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ source 'https://rubygems.org'
44

55
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
66

7-
gem 'html2rss', '~> 0.18'
8-
# gem 'html2rss', github: 'html2rss/html2rss', branch: :master
7+
# gem 'html2rss', '~> 0.18'
8+
gem 'html2rss', github: 'html2rss/html2rss', branch: 'codex-pr-auto-fallback-pipeline'
99
gem 'html2rss-configs', github: 'html2rss/html2rss-configs'
1010

1111
# Use these instead of the two above (uncomment them) when developing locally:
1212
# gem 'html2rss', path: '../html2rss'
1313
# gem 'html2rss-configs', path: '../html2rss-configs'
1414

15+
gem 'concurrent-ruby'
1516
gem 'parallel'
1617
gem 'rack-cache'
1718
gem 'rack-timeout'
@@ -21,7 +22,6 @@ gem 'zeitwerk'
2122
gem 'puma', require: false
2223

2324
group :development do
24-
gem 'byebug'
2525
gem 'irb', require: false
2626
gem 'rake', require: false
2727
gem 'rubocop', require: false

Gemfile.lock

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
GIT
2+
remote: https://github.com/html2rss/html2rss
3+
revision: 54f6f53482352932b69621f1df989f83cd285c72
4+
branch: codex-pr-auto-fallback-pipeline
5+
specs:
6+
html2rss (0.18.0)
7+
addressable (~> 2.7)
8+
brotli
9+
dry-validation
10+
faraday (> 2.0.1, < 3.0)
11+
faraday-follow_redirects
12+
faraday-gzip (~> 3)
13+
kramdown
14+
mime-types (> 3.0)
15+
nokogiri (>= 1.10, < 2.0)
16+
parallel
17+
puppeteer-ruby
18+
regexp_parser
19+
reverse_markdown (~> 3.0)
20+
rss
21+
sanitize
22+
thor
23+
tzinfo
24+
zeitwerk
25+
126
GIT
227
remote: https://github.com/html2rss/html2rss-configs
328
revision: 71981aff28d88e4553c206d78bf54d5633bcdd19
@@ -68,8 +93,6 @@ GEM
6893
bigdecimal (4.1.2)
6994
brotli (0.8.0)
7095
builder (3.3.0)
71-
byebug (13.0.0)
72-
reline (>= 0.6.0)
7396
climate_control (1.2.0)
7497
concurrent-ruby (1.3.6)
7598
connection_pool (3.0.2)
@@ -138,25 +161,6 @@ GEM
138161
fiber-storage
139162
fiber-storage (1.0.1)
140163
hashdiff (1.2.1)
141-
html2rss (0.18.0)
142-
addressable (~> 2.7)
143-
brotli
144-
dry-validation
145-
faraday (> 2.0.1, < 3.0)
146-
faraday-follow_redirects
147-
faraday-gzip (~> 3)
148-
kramdown
149-
mime-types (> 3.0)
150-
nokogiri (>= 1.10, < 2.0)
151-
parallel
152-
puppeteer-ruby
153-
regexp_parser
154-
reverse_markdown (~> 3.0)
155-
rss
156-
sanitize
157-
thor
158-
tzinfo
159-
zeitwerk
160164
i18n (1.14.8)
161165
concurrent-ruby (~> 1.0)
162166
io-console (0.8.2)
@@ -371,9 +375,9 @@ PLATFORMS
371375
x86_64-linux-musl
372376

373377
DEPENDENCIES
374-
byebug
375378
climate_control
376-
html2rss (~> 0.18)
379+
concurrent-ruby
380+
html2rss!
377381
html2rss-configs!
378382
irb
379383
parallel
@@ -413,7 +417,6 @@ CHECKSUMS
413417
bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
414418
brotli (0.8.0) sha256=0c5a42046b3b603fb109656881147fd76064c034b7d19c1b4fcc32a093a4d55d
415419
builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
416-
byebug (13.0.0) sha256=d2263efe751941ca520fa29744b71972d39cbc41839496706f5d9b22e92ae05d
417420
climate_control (1.2.0) sha256=36b21896193fa8c8536fa1cd843a07cf8ddbd03aaba43665e26c53ec1bd70aa5
418421
concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
419422
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
@@ -442,7 +445,7 @@ CHECKSUMS
442445
fiber-local (1.1.0) sha256=c885f94f210fb9b05737de65d511136ea602e00c5105953748aa0f8793489f06
443446
fiber-storage (1.0.1) sha256=f48e5b6d8b0be96dac486332b55cee82240057065dc761c1ea692b2e719240e1
444447
hashdiff (1.2.1) sha256=9c079dbc513dfc8833ab59c0c2d8f230fa28499cc5efb4b8dd276cf931457cd1
445-
html2rss (0.18.0) sha256=83e9dd0388d65f1992df4afc9d345cbfd84e8c740be3756815b5e840ac71cf54
448+
html2rss (0.18.0)
446449
html2rss-configs (0.2.0)
447450
i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5
448451
io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc

app.rb

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@
1313

1414
module Html2rss
1515
module Web
16+
DEFAULT_HEADERS = {
17+
'X-Content-Type-Options' => 'nosniff',
18+
'X-XSS-Protection' => '1; mode=block',
19+
'X-Frame-Options' => 'SAMEORIGIN',
20+
'X-Permitted-Cross-Domain-Policies' => 'none',
21+
'Referrer-Policy' => 'strict-origin-when-cross-origin',
22+
'Permissions-Policy' => 'geolocation=(), microphone=(), camera=()',
23+
'Strict-Transport-Security' => 'max-age=31536000; includeSubDomains; preload',
24+
'Cross-Origin-Embedder-Policy' => 'require-corp',
25+
'Cross-Origin-Opener-Policy' => 'same-origin',
26+
'Cross-Origin-Resource-Policy' => 'same-origin',
27+
'X-DNS-Prefetch-Control' => 'off',
28+
'X-Download-Options' => 'noopen'
29+
}.freeze
30+
1631
##
1732
# Roda app serving RSS feeds via html2rss
1833
class App < Roda
@@ -32,7 +47,8 @@ class App < Roda
3247
</html>
3348
HTML
3449
FRONTEND_DIST_PATH = 'frontend/dist'
35-
FRONTEND_INDEX_PATH = File.join(FRONTEND_DIST_PATH, 'index.html')
50+
FRONTEND_DIST_INDEX_PATH = File.join(FRONTEND_DIST_PATH, 'index.html')
51+
FRONTEND_SOURCE_INDEX_PATH = 'frontend/index.html'
3652
def self.development? = EnvironmentValidator.development?
3753

3854
def development? = self.class.development?
@@ -43,7 +59,7 @@ def development? = self.class.development?
4359

4460
plugin :content_security_policy do |csp|
4561
csp.default_src :none
46-
csp.style_src :self, "'unsafe-inline'"
62+
csp.style_src :self
4763
csp.script_src :self
4864
csp.connect_src :self
4965
csp.img_src :self
@@ -65,21 +81,7 @@ def development? = self.class.development?
6581
csp.block_all_mixed_content
6682
csp.upgrade_insecure_requests
6783
end
68-
69-
plugin :default_headers, {
70-
'X-Content-Type-Options' => 'nosniff',
71-
'X-XSS-Protection' => '1; mode=block',
72-
'X-Frame-Options' => 'SAMEORIGIN',
73-
'X-Permitted-Cross-Domain-Policies' => 'none',
74-
'Referrer-Policy' => 'strict-origin-when-cross-origin',
75-
'Permissions-Policy' => 'geolocation=(), microphone=(), camera=()',
76-
'Strict-Transport-Security' => 'max-age=31536000; includeSubDomains; preload',
77-
'Cross-Origin-Embedder-Policy' => 'require-corp',
78-
'Cross-Origin-Opener-Policy' => 'same-origin',
79-
'Cross-Origin-Resource-Policy' => 'same-origin',
80-
'X-DNS-Prefetch-Control' => 'off',
81-
'X-Download-Options' => 'noopen'
82-
}
84+
plugin :default_headers, DEFAULT_HEADERS
8385

8486
plugin :json_parser
8587
plugin :static,
@@ -91,7 +93,7 @@ def development? = self.class.development?
9193
plugin :not_allowed
9294
plugin :exception_page
9395
plugin :error_handler do |error|
94-
next exception_page(error) if development?
96+
next exception_page(error) if development? && !error.is_a?(HttpError)
9597

9698
ErrorResponder.respond(request: request, response: response, error: error)
9799
end
@@ -107,7 +109,16 @@ def development? = self.class.development?
107109

108110
def render_index_page(router)
109111
router.response['Content-Type'] = 'text/html'
110-
File.exist?(FRONTEND_INDEX_PATH) ? File.read(FRONTEND_INDEX_PATH) : FALLBACK_HTML
112+
index_path = index_page_path
113+
return File.read(index_path) if index_path
114+
115+
FALLBACK_HTML
116+
end
117+
118+
def index_page_path
119+
return FRONTEND_DIST_INDEX_PATH if File.exist?(FRONTEND_DIST_INDEX_PATH)
120+
121+
FRONTEND_SOURCE_INDEX_PATH if development? && File.exist?(FRONTEND_SOURCE_INDEX_PATH)
111122
end
112123
end
113124
end

app/web/api/v1/contract.rb

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)