Repository navigation
security(#235): enforce ownership on recommendation_cache writes - #244
Merged
Merged
Conversation
…se JWT The POST /api/sporty-sync HTTP trigger was authenticated via a shared x-api-key checked against SPORTY_SYNC_API_KEY. While VITE_SPORTY_SYNC_API_KEY was not in CI secrets, the pattern was fragile and the key could leak if accidentally added. The /api/claude endpoint already handles this correctly with verifySupabaseJwt + X-Supabase-Token; this commit applies the same pattern to the sporty-sync trigger. The /api/sporty-health monitoring endpoint retains x-api-key — it is only called by external monitoring tools, never by the frontend. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a written_by column (DEFAULT auth.uid(), NOT NULL) so each cache entry is tied to the user who wrote it. The INSERT policy now requires written_by = auth.uid(), and the UPDATE policy restricts refreshes to the original writer — a different user's upsert on conflict is silently skipped rather than overwriting the entry. saveRecsCache in db.js requires no change: the DEFAULT column provides written_by on INSERT automatically, and the existing value is preserved on the conflict-UPDATE path. recsCacheCleanup uses service role and bypasses RLS, so cleanup is unaffected. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Updates to Preview Branch (security/235-rec-cache-ownership) ↗︎
Tasks are run on every commit but only new migration files are pushed.
❌ Branch Error • Fri, 15 May 2026 20:54:35 UTC View logs for this Workflow Run ↗︎. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
written_by uuid REFERENCES profiles(id) NOT NULL DEFAULT auth.uid()torecommendation_cachewritten_by = auth.uid()written_by = auth.uid()so no user can write on behalf of anothersaveRecsCacheindb.jsrequires no change:DEFAULT auth.uid()handles INSERT, and the conflict-UPDATE path preserves the existingwritten_byvaluerecsCacheCleanupAzure Function uses service role → bypasses RLS → unaffectedTradeoff: If user A wrote a cache entry, user B's "Oppdater anbefalinger" refresh will silently fail to update the cache (B sees fresh recs in-session from the Claude call, but the shared cache keeps A's entry until it expires in 7 days). This is intentional — preventing poisoning takes priority over cross-user cache refresh.
Test plan
written_byis populated on new cache entriesrecsCacheCleanupstill deletes expired + orphaned entries on SundayCloses #235
🤖 Generated with Claude Code