mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-07 22:16:52 +02:00
Merge branch 'main' into garrytan/team-supabase-store
Brings in 48 commits from main (v0.15.7–v0.15.16): deterministic slugs, TabSession refactor, pair-agent tunnel fix, content security layers, community security wave, team-friendly install, interactive snapshots. Conflict resolution: - .gitignore: merged both sides (kept .factory/ + added .kiro/.opencode/ .slate/.cursor/.openclaw/ from main) - open-gstack-browser/SKILL.md: accepted main (renamed from .factory/) - setup-team-sync/SKILL.md: regenerated via gen:skill-docs - test/fixtures/golden/*: updated golden baselines for ship SKILL.md - codex-ship-SKILL.md: accepted main (renamed from .factory/) - package.json version: synced to VERSION (0.15.16.0) - bin/gstack-uninstall: check settings file exists before claiming SessionStart hook removal (fixes false positive on clean systems) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -43,9 +43,15 @@ Deno.serve(async (req) => {
|
||||
return new Response(`Batch too large (max ${MAX_BATCH_SIZE})`, { status: 400 });
|
||||
}
|
||||
|
||||
// Use the anon key, not the service role key.
|
||||
// The service role key bypasses Row Level Security (RLS) and grants full
|
||||
// unrestricted database access — wildly over-privileged for a public
|
||||
// telemetry endpoint that only needs INSERT on two tables.
|
||||
// The anon key + properly configured RLS INSERT policies is correct.
|
||||
// See: https://supabase.com/docs/guides/database/postgres/row-level-security
|
||||
const supabase = createClient(
|
||||
Deno.env.get("SUPABASE_URL") ?? "",
|
||||
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
|
||||
Deno.env.get("SUPABASE_ANON_KEY") ?? ""
|
||||
);
|
||||
|
||||
// Validate and transform events
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
-- 003_installations_upsert_policy.sql
|
||||
-- Re-add a scoped UPDATE policy for installations so the telemetry-ingest
|
||||
-- edge function can upsert (update last_seen) using the caller's anon key
|
||||
-- instead of the service role key.
|
||||
--
|
||||
-- Migration 002 dropped the overly broad "anon_update_last_seen" policy
|
||||
-- (which allowed UPDATE on ALL columns). This replacement uses:
|
||||
-- 1. An RLS policy to allow UPDATE (required for any row access)
|
||||
-- 2. Column-level GRANT to restrict anon to only the tracking columns
|
||||
-- the edge function actually writes (last_seen, gstack_version, os)
|
||||
--
|
||||
-- This means anon callers cannot UPDATE first_seen or installation_id,
|
||||
-- closing the residual risk from the broad RLS-only approach.
|
||||
|
||||
-- RLS policy: allow UPDATE on rows (required for PostgREST/upsert)
|
||||
CREATE POLICY "anon_update_tracking" ON installations
|
||||
FOR UPDATE
|
||||
USING (true)
|
||||
WITH CHECK (true);
|
||||
|
||||
-- Column-level restriction: anon can only UPDATE these three columns.
|
||||
-- PostgreSQL GRANT UPDATE (col, ...) is enforced at the query level —
|
||||
-- any UPDATE touching other columns will be rejected with a permission error.
|
||||
REVOKE UPDATE ON installations FROM anon;
|
||||
GRANT UPDATE (last_seen, gstack_version, os) ON installations TO anon;
|
||||
Reference in New Issue
Block a user