gronod
bbe99c1358
chore: bump version to 1.7.38 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m4s
Docs Check / Markdown lint (push) Successful in 1m27s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m57s
CI / Swagger Validation & Coverage (push) Successful in 2m33s
CI / Security audit (push) Successful in 2m42s
Docs Check / Mermaid diagram parse check (push) Successful in 3m6s
CI / Tests & coverage (push) Successful in 6m11s
2026-05-29 14:53:15 +01:00
gronod
b2aa4f23fa
chore: bump version to 1.7.37 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m16s
Docs Check / Markdown lint (push) Successful in 1m36s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m14s
CI / Security audit (push) Successful in 2m42s
Docs Check / Mermaid diagram parse check (push) Successful in 3m3s
CI / Swagger Validation & Coverage (push) Successful in 3m20s
CI / Tests & coverage (push) Successful in 6m38s
2026-05-29 14:37:36 +01:00
gronod
6c4aedf60e
chore: bump version to 1.7.36 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m57s
Docs Check / Markdown lint (push) Failing after 2m21s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 3m11s
CI / Security audit (push) Successful in 3m44s
CI / Swagger Validation & Coverage (push) Successful in 4m4s
Docs Check / Mermaid diagram parse check (push) Successful in 4m37s
CI / Tests & coverage (push) Successful in 8m29s
2026-05-29 13:37:56 +01:00
gronod
53eb19ba0c
chore: bump version to 1.7.35 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m55s
Docs Check / Markdown lint (push) Successful in 2m35s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 3m12s
CI / Security audit (push) Successful in 3m43s
Docs Check / Mermaid diagram parse check (push) Successful in 4m12s
CI / Swagger Validation & Coverage (push) Successful in 4m31s
CI / Tests & coverage (push) Successful in 5m15s
2026-05-29 13:24:27 +01:00
gronod
df5328349b
chore: bump version to 1.7.34 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m46s
Docs Check / Markdown lint (push) Successful in 2m19s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m53s
CI / Security audit (push) Successful in 3m23s
Docs Check / Mermaid diagram parse check (push) Successful in 3m55s
CI / Swagger Validation & Coverage (push) Successful in 4m18s
CI / Tests & coverage (push) Successful in 4m36s
2026-05-28 18:15:27 +01:00
gronod
1dc8d8a26c
chore: bump version to 1.7.33 and update CHANGELOG and docs
Docs Check / Markdown lint (push) Successful in 2m4s
Build and Push Docker Image / build (push) Successful in 2m16s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m31s
CI / Security audit (push) Successful in 2m57s
Docs Check / Mermaid diagram parse check (push) Successful in 3m35s
CI / Swagger Validation & Coverage (push) Successful in 4m5s
CI / Tests & coverage (push) Successful in 4m6s
2026-05-28 17:42:43 +01:00
gronod
501a4c83bb
chore: bump version to 1.7.32 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m26s
Docs Check / Markdown lint (push) Failing after 1m12s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m23s
Docs Check / Mermaid diagram parse check (push) Successful in 2m58s
2026-05-28 16:24:24 +01:00
gronod
691d101e56
chore: bump version to 1.7.31 and update CHANGELOG and docs
2026-05-28 08:11:12 +01:00
gronod
d6907f42d3
chore: bump version to 1.7.30 and update CHANGELOG and docs
Docs Check / Markdown lint (push) Failing after 1m32s
Build and Push Docker Image / build (push) Successful in 1m40s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m59s
CI / Security audit (push) Successful in 2m30s
Docs Check / Mermaid diagram parse check (push) Successful in 3m10s
CI / Swagger Validation & Coverage (push) Successful in 3m18s
CI / Tests & coverage (push) Successful in 1m20s
2026-05-28 01:39:01 +01:00
gronod
f5315e5ceb
chore: bump version to 1.7.29 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m39s
Docs Check / Markdown lint (push) Failing after 1m49s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m11s
CI / Swagger Validation & Coverage (push) Successful in 2m51s
CI / Security audit (push) Successful in 3m9s
Docs Check / Mermaid diagram parse check (push) Successful in 3m21s
CI / Tests & coverage (push) Failing after 3m44s
2026-05-27 23:46:40 +01:00
gronod
a37874c553
chore: bump version to 1.7.28 and update CHANGELOG and docs
CI / Security audit (push) Successful in 1m27s
Build and Push Docker Image / build (push) Successful in 2m0s
Docs Check / Markdown lint (push) Failing after 2m0s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m29s
CI / Swagger Validation & Coverage (push) Successful in 3m3s
Docs Check / Mermaid diagram parse check (push) Successful in 3m24s
CI / Tests & coverage (push) Successful in 3m34s
2026-05-27 23:25:57 +01:00
gronod
1ee2a8044b
chore: bump version to 1.7.27 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m25s
Docs Check / Markdown lint (push) Failing after 1m24s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m53s
Docs Check / Mermaid diagram parse check (push) Successful in 2m46s
CI / Security audit (push) Successful in 3m14s
CI / Swagger Validation & Coverage (push) Successful in 3m32s
CI / Tests & coverage (push) Successful in 3m55s
2026-05-27 23:11:23 +01:00
gronod
865cf1f57a
chore: bump version to 1.7.26 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m25s
Docs Check / Markdown lint (push) Failing after 1m47s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m12s
CI / Security audit (push) Successful in 2m54s
CI / Swagger Validation & Coverage (push) Successful in 3m7s
Docs Check / Mermaid diagram parse check (push) Successful in 3m18s
CI / Tests & coverage (push) Successful in 3m28s
2026-05-27 22:50:29 +01:00
gronod
33b122d22b
fix(ombi): resolve TV request status, user, and date display (Issue #53 )
...
Build and Push Docker Image / build (push) Successful in 1m46s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m33s
CI / Security audit (push) Successful in 1m56s
CI / Swagger Validation & Coverage (push) Successful in 2m35s
CI / Tests & coverage (push) Successful in 2m51s
Ombi's TV API nests all request data (requestedUser, approved, available,
denied, requested, requestedDate) inside childRequests[] sub-objects.
The application previously only inspected top-level properties, causing
TV shows to consistently display 'unknown' status, 'unknown' user, and
no request date.
Changes:
- OmbiRetriever._hydrateRequest(): hydrate requestedUser on each
childRequests entry and promote requestedDate to top level
- getRequestStatus() (server + client): aggregate status flags from
childRequests[] when top-level properties are absent
- Client date display: fallback to childRequests[0].requestedDate
- Add 18 unit tests covering childRequests hydration, status
aggregation, and date promotion
Closes #53
2026-05-27 21:13:17 +01:00
gronod
35ff21a810
chore: bump version to 1.7.24 and update CHANGELOG and workflows
Build and Push Docker Image / build (push) Successful in 1m48s
Docs Check / Markdown lint (push) Successful in 1m36s
CI / Swagger Validation & Coverage (push) Successful in 2m9s
CI / Security audit (push) Successful in 2m10s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m23s
Docs Check / Mermaid diagram parse check (push) Successful in 3m2s
CI / Tests & coverage (push) Successful in 3m34s
2026-05-27 19:35:06 +01:00
gronod
5b3034e290
chore: bump version to 1.7.23 and update CHANGELOG and docs
Docs Check / Markdown lint (push) Successful in 46s
Build and Push Docker Image / build (push) Successful in 1m40s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m22s
CI / Security audit (push) Successful in 2m48s
CI / Swagger Validation & Coverage (push) Successful in 3m3s
Docs Check / Mermaid diagram parse check (push) Successful in 3m9s
CI / Tests & coverage (push) Successful in 3m36s
2026-05-27 19:16:12 +01:00
gronod
95bd703b26
chore: bump version to 1.7.22 and update CHANGELOG, tests and docs
Docs Check / Markdown lint (push) Successful in 1m14s
Build and Push Docker Image / build (push) Successful in 1m52s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m55s
CI / Security audit (push) Successful in 2m25s
Docs Check / Mermaid diagram parse check (push) Successful in 3m6s
CI / Swagger Validation & Coverage (push) Successful in 3m22s
CI / Tests & coverage (push) Successful in 3m45s
2026-05-27 17:42:41 +01:00
gronod
d2ac7731ca
chore: bump version to 1.7.21 and update CHANGELOG and docs
Build and Push Docker Image / build (push) Successful in 1m21s
CI / Security audit (push) Successful in 1m26s
Docs Check / Markdown lint (push) Successful in 1m27s
CI / Swagger Validation & Coverage (push) Successful in 2m25s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m30s
Docs Check / Mermaid diagram parse check (push) Successful in 3m17s
CI / Tests & coverage (push) Successful in 3m31s
2026-05-26 15:20:12 +01:00
gronod
5390bbf615
chore: bump version to 1.7.20 and resolve Ombi user hydration issue
Build and Push Docker Image / build (push) Successful in 2m6s
Docs Check / Markdown lint (push) Successful in 1m58s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m4s
Docs Check / Mermaid diagram parse check (push) Successful in 1m58s
CI / Security audit (push) Successful in 1m48s
CI / Tests & coverage (push) Successful in 1m59s
CI / Swagger Validation & Coverage (push) Successful in 1m47s
2026-05-26 11:30:49 +01:00
gronod
d87ad9f1c7
fix: mobile request card overflow ( #49 ) and admin arrLink active badges ( #50 ), bump version to 1.7.19
Build and Push Docker Image / build (push) Successful in 1m23s
Docs Check / Markdown lint (push) Successful in 1m42s
Licence Check / Licence compatibility and copyright header verification (push) Failing after 2m33s
Docs Check / Mermaid diagram parse check (push) Successful in 3m19s
CI / Security audit (push) Successful in 3m21s
CI / Swagger Validation & Coverage (push) Successful in 3m40s
CI / Tests & coverage (push) Successful in 4m57s
2026-05-25 08:28:16 +01:00
gronod
b8870ca6cf
chore: bump version to 1.7.18 and update CHANGELOG and docs
CI / Tests & coverage (push) Failing after 33s
Docs Check / Markdown lint (push) Successful in 1m57s
Docs Check / Mermaid diagram parse check (push) Successful in 2m59s
CI / Security audit (push) Successful in 3m32s
Licence Check / Licence compatibility and copyright header verification (push) Failing after 1m54s
Build and Push Docker Image / build (push) Successful in 1m32s
CI / Swagger Validation & Coverage (push) Successful in 2m34s
2026-05-24 23:26:27 +01:00
gronod
7690d959b3
fix: blocklist-search lookup against queue cache instead of downloadClientRegistry
...
CI / Security audit (push) Successful in 1m52s
Docs Check / Markdown lint (push) Successful in 1m37s
Build and Push Docker Image / build (push) Successful in 2m2s
Licence Check / Licence compatibility and copyright header verification (push) Failing after 2m33s
CI / Swagger Validation & Coverage (push) Successful in 3m17s
Docs Check / Mermaid diagram parse check (push) Successful in 3m31s
CI / Tests & coverage (push) Successful in 4m5s
Fixes the root cause of the regression from v1.7.16. The v1.7.16 fix
correctly cast arrQueueId to String, but the lookup was performed
against downloadClientRegistry.getAllDownloads() which returns raw
download client data (qBittorrent, SABnzbd, etc.) that never has
arrQueueId populated.
The fix now looks up the queue record directly from the Sonarr/Radarr
queue cache where record.id is the numeric queue ID, using String()
casting on both sides to handle the DOM-dataset (string) vs API
response (number) type difference.
Resolves Gitea Issue #48
Closes #48
2026-05-24 22:48:17 +01:00
gronod
83c9d4d164
fix: blocklist-search queue ID type mismatch and bump version to 1.7.16
...
Build and Push Docker Image / build (push) Successful in 2m14s
Docs Check / Markdown lint (push) Successful in 2m29s
CI / Security audit (push) Successful in 2m56s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 3m4s
CI / Swagger Validation & Coverage (push) Successful in 3m52s
Docs Check / Mermaid diagram parse check (push) Successful in 4m8s
CI / Tests & coverage (push) Successful in 4m38s
- Cast arrQueueId to String in both sides of the download lookup comparison
in /api/dashboard/blocklist-search to resolve false-negative match failure
caused by DOM dataset string vs Radarr/Sonarr API number type mismatch
- Add regression integration test for string-vs-number arrQueueId matching
- Bump version to 1.7.16, update CHANGELOG.md, openapi.yaml, and JSDoc examples
Resolves #48
2026-05-24 22:12:34 +01:00
gronod
7b9c895888
fix: support query parameter-based secret validation fallback to fix Ombi webhooks ( #47 )
Build and Push Docker Image / build (push) Successful in 2m4s
Docs Check / Markdown lint (push) Successful in 2m7s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 3m3s
CI / Security audit (push) Successful in 3m42s
Docs Check / Mermaid diagram parse check (push) Failing after 3m58s
CI / Tests & coverage (push) Successful in 4m21s
CI / Swagger Validation & Coverage (push) Successful in 4m33s
2026-05-24 21:25:38 +01:00
gronod
b5b4862e15
chore: bump version to 1.7.14 and update CHANGELOG for poller fix
Build and Push Docker Image / build (push) Successful in 1m42s
Docs Check / Markdown lint (push) Successful in 1m34s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m37s
CI / Security audit (push) Successful in 3m7s
Docs Check / Mermaid diagram parse check (push) Failing after 3m52s
CI / Swagger Validation & Coverage (push) Successful in 4m11s
CI / Tests & coverage (push) Successful in 4m41s
2026-05-24 19:36:53 +01:00
gronod
76631cd37e
chore: bump version to 1.7.13 and update CHANGELOG
Build and Push Docker Image / build (push) Successful in 2m2s
Docs Check / Markdown lint (push) Successful in 1m54s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m42s
CI / Tests & coverage (push) Successful in 3m7s
CI / Security audit (push) Successful in 3m35s
Docs Check / Mermaid diagram parse check (push) Failing after 3m53s
CI / Swagger Validation & Coverage (push) Successful in 4m26s
2026-05-24 19:24:01 +01:00
gronod
95e301ef56
chore: bump version to 1.7.12 and update CHANGELOG
Build and Push Docker Image / build (push) Successful in 1m37s
Docs Check / Markdown lint (push) Successful in 2m1s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m37s
CI / Security audit (push) Successful in 3m0s
Docs Check / Mermaid diagram parse check (push) Failing after 3m18s
CI / Swagger Validation & Coverage (push) Successful in 3m30s
CI / Tests & coverage (push) Successful in 3m55s
2026-05-24 18:50:30 +01:00
gronod
afc940aba7
chore: bump version to 1.7.11 and update CHANGELOG
Build and Push Docker Image / build (push) Successful in 2m2s
Docs Check / Markdown lint (push) Successful in 1m10s
Docs Check / Mermaid diagram parse check (push) Successful in 1m39s
CI / Security audit (push) Successful in 3m46s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m31s
CI / Swagger Validation & Coverage (push) Successful in 4m24s
CI / Tests & coverage (push) Successful in 4m39s
2026-05-24 10:48:52 +01:00
gronod
3f8970ea99
chore: bump version to 1.7.10 and update CHANGELOG
CI / Security audit (push) Has been cancelled
CI / Tests & coverage (push) Has been cancelled
CI / Swagger Validation & Coverage (push) Has been cancelled
Docs Check / Markdown lint (push) Successful in 50s
Build and Push Docker Image / build (push) Successful in 2m21s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m48s
Docs Check / Mermaid diagram parse check (push) Successful in 2m46s
2026-05-24 10:23:22 +01:00
gronod
64c872423f
chore: bump version to 1.7.9 and update CHANGELOG
Build and Push Docker Image / build (push) Successful in 2m12s
Docs Check / Markdown lint (push) Successful in 2m34s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 3m14s
CI / Security audit (push) Successful in 3m29s
Docs Check / Mermaid diagram parse check (push) Successful in 3m47s
CI / Swagger Validation & Coverage (push) Successful in 4m12s
CI / Tests & coverage (push) Successful in 4m57s
2026-05-23 20:58:09 +01:00
gronod
d1db3118f0
chore: bump version to 1.7.8 and update CHANGELOG
Build and Push Docker Image / build (push) Successful in 2m9s
CI / Security audit (push) Successful in 2m32s
Docs Check / Markdown lint (push) Successful in 2m34s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 3m4s
CI / Swagger Validation & Coverage (push) Successful in 3m55s
Docs Check / Mermaid diagram parse check (push) Successful in 4m18s
CI / Tests & coverage (push) Successful in 4m34s
2026-05-23 20:52:27 +01:00
gronod
82b3824658
chore: bump version to 1.7.7 and update CHANGELOG
Build and Push Docker Image / build (push) Successful in 2m17s
Docs Check / Markdown lint (push) Successful in 2m27s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m44s
CI / Security audit (push) Successful in 3m10s
Docs Check / Mermaid diagram parse check (push) Successful in 3m54s
CI / Tests & coverage (push) Successful in 4m6s
CI / Swagger Validation & Coverage (push) Successful in 4m23s
2026-05-23 20:38:05 +01:00
gronod
6ac0a8421e
fix: resolve rate-limiting and Ombi requests caching bugs ( fixes #42 , fixes #43 )
Build and Push Docker Image / build (push) Successful in 1m34s
Docs Check / Markdown lint (push) Successful in 2m14s
CI / Security audit (push) Successful in 2m30s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m40s
CI / Swagger Validation & Coverage (push) Successful in 3m22s
Docs Check / Mermaid diagram parse check (push) Successful in 3m43s
CI / Tests & coverage (push) Successful in 3m59s
2026-05-23 18:55:03 +01:00
gronod
f8c7e35f31
chore: bump version to 1.7.5 and update CHANGELOG
Docs Check / Markdown lint (push) Successful in 42s
Docs Check / Mermaid diagram parse check (push) Successful in 1m51s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m3s
CI / Security audit (push) Successful in 4m17s
Build and Push Docker Image / build (push) Successful in 5m5s
CI / Swagger Validation & Coverage (push) Successful in 5m19s
CI / Tests & coverage (push) Successful in 6m27s
2026-05-23 10:13:25 +01:00
gronod
1d571b066d
chore: bump version to 1.7.4 and update CHANGELOG
Docs Check / Markdown lint (push) Successful in 46s
Build and Push Docker Image / build (push) Successful in 1m44s
Docs Check / Mermaid diagram parse check (push) Successful in 1m42s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m28s
CI / Security audit (push) Successful in 2m37s
CI / Swagger Validation & Coverage (push) Successful in 3m9s
CI / Tests & coverage (push) Successful in 3m46s
2026-05-23 10:00:18 +01:00
gronod
f52a687a46
chore: bump version to 1.7.3 and update CHANGELOG
Docs Check / Markdown lint (push) Successful in 1m32s
Build and Push Docker Image / build (push) Successful in 1m57s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m28s
CI / Swagger Validation & Coverage (push) Successful in 3m21s
CI / Security audit (push) Successful in 3m23s
Docs Check / Mermaid diagram parse check (push) Successful in 3m36s
CI / Tests & coverage (push) Successful in 4m7s
2026-05-23 09:39:58 +01:00
gronod
1a4ff73067
feat(ci): add RAML 1.0 package generation pipeline
...
Build and Push Docker Image / build (push) Successful in 1m27s
CI / Security audit (push) Successful in 1m43s
CI / Swagger Validation & Coverage (push) Failing after 1m56s
CI / Tests & coverage (push) Failing after 1m56s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 53s
- Add generate:openapi, generate:raml, package:raml scripts to package.json
- Add archiver dependency for creating tar.gz archives
- Create scripts/generate-openapi.js to fetch merged OpenAPI spec from running server
- Create scripts/package-raml.js to build versioned RAML tar.gz archive
- Create .spectral.yml with minimal OpenAPI linting rules
- Add /api/swagger.json endpoint to server/app.js for serving merged spec
- Extend swagger job in ci.yml with RAML generation steps
- Upload raml-package artifact to CI with 14-day retention
2026-05-21 14:04:26 +01:00
gronod
7dadb849f6
ci(swagger): add OpenAPI validation job to CI
...
- Install @stoplight/spectral-cli as dev dependency
- Add "Swagger Validation & Coverage" job to .gitea/workflows/ci.yml
- Run spectral lint on server/openapi.yaml
- Run npm test to execute coverage tests
- Fail CI if spec is invalid or coverage is incomplete
- Runs on every push/PR alongside existing jobs
2026-05-21 12:39:13 +01:00
gronod
93a8c3fd2e
feat(swagger): create develop-swagger branch and install dependencies
...
- Install swagger-ui-express, swagger-jsdoc, yamljs
- Prepare for OpenAPI 3.1 spec integration
2026-05-21 12:28:52 +01:00
gronod
e39f15d3d8
fix: update package-lock.json after adding xmlrpc dependency
Build and Push Docker Image / build (push) Successful in 1m20s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m16s
CI / Security audit (push) Successful in 1m30s
CI / Tests & coverage (push) Failing after 1m38s
2026-05-19 12:02:23 +01:00
gronod
972b407956
chore: sync package-lock.json version to 1.3.0
2026-05-18 06:30:57 +01:00
gronod
c0dd93a1ab
feat: production hardening v1.2.0
...
Build and Push Docker Image / build (push) Successful in 59s
CI / Security audit (push) Successful in 1m5s
CI / Tests & coverage (push) Successful in 1m24s
Docs Check / Markdown lint (push) Failing after 45s
Docs Check / Mermaid diagram parse check (push) Successful in 1m27s
CI / Security audit (pull_request) Successful in 51s
CI / Tests & coverage (pull_request) Successful in 1m1s
Docs Check / Markdown lint (pull_request) Failing after 39s
Docs Check / Mermaid diagram parse check (pull_request) Successful in 1m12s
Phase 1 - Licensing & Compliance:
- Add MIT LICENSE file
- Add copyright headers to server/index.js, poller.js, config.js,
sanitizeError.js, and new loadSecrets.js
Phase 2 - Security Hardening:
- Add server/utils/loadSecrets.js: Docker secrets support via _FILE
env var pattern (COOKIE_SECRET_FILE, EMBY_API_KEY_FILE, etc.)
- Add SSRF/URL validation in config.js: validates all configured
service instance URLs for scheme and well-formedness at startup
- Add SIGTERM/SIGINT graceful shutdown: stops poller, drains HTTP
connections, 10s force-exit fallback
- Warn at startup if COOKIE_SECRET is shorter than 32 characters
- Validate EMBY_URL scheme at startup
- Improve sanitizeError: redact host:port from axios error URLs
while preserving path/query for other redaction patterns
Phase 3 - Config Robustness:
- Weak COOKIE_SECRET warning (< 32 chars)
- EMBY_URL validated via validateInstanceUrl on startup
Phase 4 - Docker & Deployment:
- .dockerignore: add tests/, coverage/, vitest.config.js,
CHANGELOG.md, SECURITY.md, LICENSE, .markdownlint.json
- docker-compose.yaml: add commented Option B (Docker secrets
_FILE pattern) alongside existing plain-env Option A
Phase 5 - Docs & Release Readiness:
- Add CHANGELOG.md with entries from v1.0.0 to v1.2.0
- Update SECURITY.md: supported versions table, fix Docker secrets
note to reflect _FILE support now implemented
- Add public/.well-known/security.txt for responsible disclosure
- Bump version to 1.2.0
2026-05-17 19:40:07 +01:00
gronod
5fd55b4e1a
test: add comprehensive test suite (115 tests, Vitest + supertest + nock)
...
Build and Push Docker Image / build (push) Successful in 49s
CI / Security audit (push) Successful in 1m23s
CI / Tests & coverage (push) Failing after 2m13s
Framework:
- Vitest v4 as test runner (fast ESM/CJS support, V8 coverage built-in)
- supertest for integration tests against createApp() factory
- nock for HTTP interception (works with CJS require('axios'), unlike vi.mock)
New files:
- vitest.config.js — test config: node env, isolate, V8 coverage, per-file thresholds
- tests/setup.js — isolated DATA_DIR per worker, SKIP_RATE_LIMIT, console suppression
- tests/README.md — approach, structure, design decisions
- server/app.js — testable Express factory (extracted from index.js side-effects)
Unit tests (91 tests):
- tests/unit/sanitizeError.test.js — secret redaction: apikey, token, bearer, basic-auth URLs
- tests/unit/config.test.js — JSON array + legacy single-instance config parsing
- tests/unit/requireAuth.test.js — valid/invalid/tampered cookies, schema validation
- tests/unit/verifyCsrf.test.js — double-submit pattern, timing-safe compare, safe methods
- tests/unit/qbittorrent.test.js — formatBytes, formatEta, mapTorrentToDownload state map
- tests/unit/tokenStore.test.js — store/get/clear lifecycle, TTL expiry, atomic disk write
Integration tests (24 tests):
- tests/integration/health.test.js — /health and /ready endpoints
- tests/integration/auth.test.js — full login/logout/me/csrf flows, input validation,
cookie attributes, no token leakage, Emby mock via nock
Production code changes (minimal, no behaviour change):
- server/routes/auth.js: EMBY_URL captured at request-time (not module load) for testability
- server/routes/auth.js: loginLimiter max → Number.MAX_SAFE_INTEGER when SKIP_RATE_LIMIT set
- server/utils/sanitizeError.js: fix HEADER_PATTERN to redact full line (not just first token)
CI:
- .gitea/workflows/ci.yml: add parallel 'test' job (npm run test:coverage, artifact upload)
- package.json: add test/test:watch/test:coverage/test:ui scripts
- .gitignore: add coverage/
2026-05-17 07:45:33 +01:00
gronod
37c1b64982
fix(docker): replace better-sqlite3 with pure-JS JSON token store
...
Build and Push Docker Image / build (push) Successful in 28s
CI / Security audit (push) Successful in 38s
better-sqlite3 is a native C++ addon that requires compilation on Alpine
(musl libc, no pre-built binaries exist) and fails on Debian slim too
because prebuild-install cannot detect the libc type correctly.
Replace with a pure-JS JSON file token store (server/utils/tokenStore.js):
- Atomic writes via temp file + rename (no corruption on crash)
- Same API: storeToken/getToken/clearToken
- TTL enforcement on read and hourly prune
- Zero native code, zero build tools required
Dockerfile:
- Revert to node:22-alpine (was node:22-slim)
- Remove build tools (python3/make/g++) — no longer needed
- Restore wget HEALTHCHECK (available in Alpine busybox)
docker-compose.yaml: restore wget healthcheck
package.json: remove better-sqlite3 dependency
2026-05-17 07:13:56 +01:00
gronod
2522bb3514
fix: rebuild package-lock for Node 22; upgrade dev environment
...
Build and Push Docker Image / build (push) Successful in 39s
CI / Security audit (push) Has been cancelled
- Deleted stale Node 12 node_modules and package-lock.json; reinstalled
with Node 22.22.2 (upgraded from system Node 12 via nodesource repo)
- better-sqlite3 native module rebuilt for Node 22
- All deps resolve cleanly: 0 vulnerabilities
2026-05-17 07:00:32 +01:00
gronod
bdbbcabfbc
feat(security): production hardening for external deployment
...
Build and Push Docker Image / build (push) Successful in 1m2s
CI / Security audit (push) Successful in 3m29s
Container (Dockerfile):
- Multi-stage build (deps + runtime) for minimal attack surface
- Upgrade base image from node:18-alpine to node:22-alpine
- Run as non-root 'node' user (UID 1000); source files owned by root
- /app/data directory owned by node for SQLite + logs
- Docker HEALTHCHECK: wget /health every 30s
docker-compose.yaml:
- Port bound to 127.0.0.1 only (expose via reverse proxy)
- read_only: true filesystem; /tmp tmpfs for Node.js
- no-new-privileges:true, cap_drop: ALL
- Named volume sofarr-data for persistent data
- TRUST_PROXY, COOKIE_SECRET, NODE_ENV added
Helmet v7 + CSP nonce:
- Upgrade helmet@4 → helmet@7, express-rate-limit@6 → @7
- CSP with per-request nonce injected into index.html script/link tags
(replaces blanket unsafe-inline; nonce changes every request)
- HSTS: max-age=1yr, includeSubDomains, preload
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy: camera/mic/geolocation/payment/usb all off
- index.html served dynamically with nonce injection; static assets
served normally via express.static({index:false})
Trust proxy:
- TRUST_PROXY env var configures app.set('trust proxy') so rate
limiting and secure cookies work correctly behind Nginx/Caddy
Session & auth:
- Token store migrated from in-memory Map to SQLite via better-sqlite3
(server/utils/tokenStore.js): survives restarts, WAL mode, 31-day TTL
- CSRF double-submit cookie pattern (server/middleware/verifyCsrf.js):
POST/PUT/PATCH/DELETE on /api/* require X-CSRF-Token header matching
the csrf_token cookie; timing-safe comparison
- CSRF token issued on login + GET /api/auth/csrf; cleared on logout
- Login input validation: username/password length + type checked before
hitting Emby
- skipSuccessfulRequests:true on login rate limiter (only count failures)
- express.json({ limit: '64kb' }) to reject oversized payloads
Rate limiting:
- General API limiter: 300 req/15min per IP on all /api/* routes
- Login limiter unchanged (10 failures/15min) but now only counts fails
Logging:
- Log file moved from /app/server.log to DATA_DIR/server.log (writable
by non-root node user in container)
- Size-based rotation: rotate at 10 MB, keep 3 files (server.log.1-3)
- DATA_DIR defaults to ./data locally, /app/data in container
Error handling:
- Global Express error handler: catches unhandled errors, logs message,
returns generic 500 (no stack traces to clients)
Health/readiness:
- GET /health: returns {status:'ok', uptime:N} — used by HEALTHCHECK
- GET /ready: returns 503 if EMBY_URL not configured
Error sanitization (sanitizeError.js):
- Added patterns for password= params, bearer tokens, Basic auth in URLs
Supply chain:
- Remove unused cors dependency
- add better-sqlite3@^9
- CI: upgrade to Node 22, raise audit level to --audit-level=high
- .gitignore: add data/, *.db, *.db-wal, *.db-shm
Docs:
- SECURITY.md: threat model, hardening checklist, proxy examples,
header table, rate limit table, Docker secrets guidance
- .env.example + .env.sample: TRUST_PROXY, DATA_DIR documented
2026-05-17 06:47:25 +01:00
gronod
031877e6a0
fix(ci): upgrade nodemon to ^3 to resolve semver ReDoS vulnerability
...
Build and Push Docker Image / build (push) Successful in 32s
CI / npm audit (push) Successful in 49s
nodemon@2 depends on simple-update-notifier which depends on a
vulnerable range of semver (7.0.0-7.5.1, GHSA-c2qf-rxjj-qqgw).
Upgrading to nodemon@3 pulls in a clean dependency tree.
npm audit now reports 0 vulnerabilities.
2026-05-16 17:11:24 +01:00
gronod
b608fa0337
fix(security #12 ): add helmet security response headers
...
Adds X-DNS-Prefetch-Control, X-Frame-Options, X-Content-Type-Options,
Referrer-Policy, X-XSS-Protection, HSTS (in prod) and others.
CSP disabled for now as the SPA uses inline scripts/styles; a
nonce/hash-based policy is a future hardening step.
2026-05-16 16:23:47 +01:00
gronod
1f41114482
fix(security #11 ): remove unused node-cron dependency
...
node-cron was listed in dependencies but never imported anywhere in
the codebase. Removed via npm uninstall.
2026-05-16 16:22:36 +01:00
gronod
1eadb30481
fix(security #6 ): add rate limiting to POST /api/auth/login
...
Uses express-rate-limit@6 (pinned for Node 12 dev compat; Node 18
in prod container is unaffected). Limits each IP to 10 attempts per
15-minute window. Returns 429 with a safe error message on breach.
2026-05-16 16:18:34 +01:00