From c8fe311a4b562886bd95f75cf27531cd96f2b07c Mon Sep 17 00:00:00 2001 From: Christopher Rotnes Date: Fri, 15 May 2026 23:47:26 +0200 Subject: [PATCH] security(#239 #240): retry jitter + GitHub Actions hardening Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 2 +- .github/workflows/cleanup-staging.yml | 2 +- CHANGELOG.md | 9 +++++++++ app/api/claude.js | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3acf06e..594b1d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,7 +86,7 @@ jobs: run: npm run build env: VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }} - VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }} + VITE_SUPABASE_ANON_KEY: ${{ vars.VITE_SUPABASE_ANON_KEY }} - name: Deploy to Azure Static Web Apps id: builddeploy uses: Azure/static-web-apps-deploy@v1 diff --git a/.github/workflows/cleanup-staging.yml b/.github/workflows/cleanup-staging.yml index b336023..38014b8 100644 --- a/.github/workflows/cleanup-staging.yml +++ b/.github/workflows/cleanup-staging.yml @@ -1,5 +1,5 @@ name: Cleanup staging environment -run-name: "Cleanup staging env — ${{ github.event.pull_request.title }}" +run-name: "Cleanup staging environment" on: pull_request: diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b9ca16..c370d7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to Workout Lens are documented here. +## [1.5.10] — 2026-05-15 + +### Security +- **`VITE_SUPABASE_ANON_KEY` moved from GitHub secret to repository variable (issue #240)** — the Supabase anon key is intentionally public (it ships in the frontend bundle). Storing it as an encrypted secret masked its value in CI logs for no security benefit and added unnecessary surface area to the secrets inventory. Moved to `vars.VITE_SUPABASE_ANON_KEY` — requires adding it as a repository variable in GitHub Settings → Secrets and variables → Variables and removing the old secret. +- **Cleanup-staging workflow no longer interpolates PR title (issue #240)** — `run-name` previously embedded `github.event.pull_request.title` directly. PR titles are user-controlled input; removed the interpolation to prevent any future hygiene risk if script steps are added to the workflow. + +### Developer / Infrastructure +- **Retry jitter added to Anthropic 529 backoff (issue #239)** — the retry loop in `claude.js` used plain exponential backoff (`2^attempt * 1000ms`). During an Anthropic overload, all concurrent clients would retry at the same intervals. Now uses `min(2^attempt * 1000 + random(0–500ms), 32s)` to spread load. + ## [1.5.9] — 2026-05-15 ### Security diff --git a/app/api/claude.js b/app/api/claude.js index 359ee61..1bc7deb 100644 --- a/app/api/claude.js +++ b/app/api/claude.js @@ -59,7 +59,7 @@ app.http('claude', { const requestBody = JSON.stringify(body); let upstream; for (let attempt = 0; attempt < 5; attempt++) { - if (attempt > 0) await new Promise(r => setTimeout(r, 2 ** attempt * 1000)); + if (attempt > 0) await new Promise(r => setTimeout(r, Math.min(2 ** attempt * 1000 + Math.random() * 500, 32_000))); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 25_000); try {