Skip to content

Commit 7428f62

Browse files
committed
Merge remote-tracking branch 'origin/main' into garrytan/askuser-one-at-a-time
Resolved conflicts: - VERSION: take main's 0.11.16.1 (newer) - CHANGELOG.md: keep main's entries (0.11.15.0, 0.11.16.0, 0.11.16.1), drop our stale 0.11.14.1 entry (will get fresh entry at ship time)
2 parents 2e53139 + 2b85b1d commit 7428f62

20 files changed

Lines changed: 643 additions & 113 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ bun.lock
1515
.env.local
1616
.env.*
1717
!.env.example
18+
supabase/.temp/

CHANGELOG.md

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,43 @@
11
# Changelog
22

3-
## [0.11.14.1] - 2026-03-24
3+
## [0.11.16.1] - 2026-03-24 — Installation ID Privacy Fix
4+
5+
### Fixed
6+
7+
- **Installation IDs are now random UUIDs instead of hostname hashes.** The old `SHA-256(hostname+username)` approach meant anyone who knew your machine identity could compute your installation ID. Now uses a random UUID stored in `~/.gstack/installation-id` — not derivable from any public input, rotatable by deleting the file.
8+
- **RLS verification script handles edge cases.** `verify-rls.sh` now correctly treats INSERT success as expected (kept for old client compat), handles 409 conflicts and 204 no-ops.
9+
10+
## [0.11.16.0] - 2026-03-24 — Telemetry Security Hardening
11+
12+
### Fixed
13+
14+
- **Telemetry RLS policies tightened.** Row-level security policies on all telemetry tables now deny direct access via the anon key. All reads and writes go through validated edge functions with schema checks, event type allowlists, and field length limits.
15+
- **Community dashboard is faster and server-cached.** Dashboard stats are now served from a single edge function with 1-hour server-side caching, replacing multiple direct queries.
416

517
### Changed
618

7-
- **One decision per question — everywhere.** Every skill now presents decisions one at a time, each with its own focused question, recommendation, and options. No more wall-of-text questions that bundle unrelated choices together. This was already enforced in the three plan-review skills; now it's a universal rule across all 23+ skills.
19+
- **Telemetry sync uses `GSTACK_SUPABASE_URL` instead of `GSTACK_TELEMETRY_ENDPOINT`.** Edge functions need the base URL, not the REST API path. The old variable is removed from `config.sh`.
20+
- **Cursor advancement is now safe.** The sync script checks the edge function's `inserted` count before advancing — if zero events were inserted, the cursor holds and retries next run.
21+
22+
### For contributors
23+
24+
- New migration: `supabase/migrations/002_tighten_rls.sql`
25+
- New smoke test: `supabase/verify-rls.sh` (9 checks: 5 reads + 4 writes)
26+
- Extended `test/telemetry.test.ts` with field name verification
27+
- Untracked `browse/dist/` binaries from git (arm64-only, rebuilt by `./setup`)
28+
29+
## [0.11.15.0] - 2026-03-24 — E2E Test Coverage for Plan Reviews & Codex
30+
31+
### Added
32+
33+
- **E2E tests verify plan review reports appear at the bottom of plans.** The `/plan-eng-review` review report is now tested end-to-end — if it stops writing `## GSTACK REVIEW REPORT` to the plan file, the test catches it.
34+
- **E2E tests verify Codex is offered in every plan skill.** Four new lightweight tests confirm that `/office-hours`, `/plan-ceo-review`, `/plan-design-review`, and `/plan-eng-review` all check for Codex availability, prompt the user, and handle the fallback when Codex is unavailable.
35+
36+
### For contributors
37+
38+
- New E2E tests in `test/skill-e2e-plan.test.ts`: `plan-review-report`, `codex-offered-eng-review`, `codex-offered-ceo-review`, `codex-offered-office-hours`, `codex-offered-design-review`
39+
- Updated touchfile mappings and selection count assertions
40+
- Added `touchfiles` to the documented global touchfile list in CLAUDE.md
841

942
## [0.11.14.0] - 2026-03-24 — Windows Browse Fix
1043

CLAUDE.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ against the previous run.
2929
**Diff-based test selection:** `test:evals` and `test:e2e` auto-select tests based
3030
on `git diff` against the base branch. Each test declares its file dependencies in
3131
`test/helpers/touchfiles.ts`. Changes to global touchfiles (session-runner, eval-store,
32-
llm-judge, gen-skill-docs) trigger all tests. Use `EVALS_ALL=1` or the `:all` script
32+
llm-judge, gen-skill-docs, touchfiles) trigger all tests. Use `EVALS_ALL=1` or the `:all` script
3333
variants to force all tests. Run `eval:select` to preview which tests would run.
3434

3535
## Testing
@@ -165,6 +165,19 @@ symlink or a real copy. If it's a symlink to your working directory, be aware th
165165
gen-skill-docs pipeline, consider whether the changes should be tested in isolation
166166
before going live (especially if the user is actively using gstack in other windows).
167167

168+
## Compiled binaries — NEVER commit browse/dist/
169+
170+
The `browse/dist/` directory contains compiled Bun binaries (`browse`, `find-browse`,
171+
~58MB each). These are Mach-O arm64 only — they do NOT work on Linux, Windows, or
172+
Intel Macs. The `./setup` script already builds from source for every platform, so
173+
the checked-in binaries are redundant. They are tracked by git due to a historical
174+
mistake and should eventually be removed with `git rm --cached`.
175+
176+
**NEVER stage or commit these files.** They show up as modified in `git status`
177+
because they're tracked despite `.gitignore` — ignore them. When staging files,
178+
always use specific filenames (`git add file1 file2`) — never `git add .` or
179+
`git add -A`, which will accidentally include the binaries.
180+
168181
## Commit style
169182

170183
**Always bisect commits.** Every commit should be a single logical change. When

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ gstack includes **opt-in** usage telemetry to help improve the project. Here's e
212212
- **What's never sent:** code, file paths, repo names, branch names, prompts, or any user-generated content.
213213
- **Change anytime:** `gstack-config set telemetry off` disables everything instantly.
214214

215-
Data is stored in [Supabase](https://supabase.com) (open source Firebase alternative). The schema is in [`supabase/migrations/001_telemetry.sql`](supabase/migrations/001_telemetry.sql) — you can verify exactly what's collected. The Supabase publishable key in the repo is a public key (like a Firebase API key) — row-level security policies restrict it to insert-only access.
215+
Data is stored in [Supabase](https://supabase.com) (open source Firebase alternative). The schema is in [`supabase/migrations/`](supabase/migrations/) — you can verify exactly what's collected. The Supabase publishable key in the repo is a public key (like a Firebase API key) — row-level security policies deny all direct access. Telemetry flows through validated edge functions that enforce schema checks, event type allowlists, and field length limits.
216216

217217
**Local analytics are always available.** Run `gstack-analytics` to see your personal usage dashboard from the local JSONL file — no remote data needed.
218218

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.11.14.1
1+
0.11.16.1

bin/gstack-community-dashboard

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
# gstack-community-dashboard — community usage stats from Supabase
33
#
4-
# Queries the Supabase REST API to show community-wide gstack usage:
4+
# Calls the community-pulse edge function for aggregated stats:
55
# skill popularity, crash clusters, version distribution, retention.
66
#
77
# Env overrides (for testing):
@@ -30,51 +30,40 @@ if [ -z "$SUPABASE_URL" ] || [ -z "$ANON_KEY" ]; then
3030
exit 0
3131
fi
3232

33-
# ─── Helper: query Supabase REST API ─────────────────────────
34-
query() {
35-
local table="$1"
36-
local params="${2:-}"
37-
curl -sf --max-time 10 \
38-
"${SUPABASE_URL}/rest/v1/${table}?${params}" \
39-
-H "apikey: ${ANON_KEY}" \
40-
-H "Authorization: Bearer ${ANON_KEY}" \
41-
2>/dev/null || echo "[]"
42-
}
33+
# ─── Fetch aggregated stats from edge function ────────────────
34+
DATA="$(curl -sf --max-time 15 \
35+
"${SUPABASE_URL}/functions/v1/community-pulse" \
36+
-H "apikey: ${ANON_KEY}" \
37+
2>/dev/null || echo "{}")"
4338

4439
echo "gstack community dashboard"
4540
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
4641
echo ""
4742

4843
# ─── Weekly active installs ──────────────────────────────────
49-
WEEK_AGO="$(date -u -v-7d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo "")"
50-
if [ -n "$WEEK_AGO" ]; then
51-
PULSE="$(curl -sf --max-time 10 \
52-
"${SUPABASE_URL}/functions/v1/community-pulse" \
53-
-H "Authorization: Bearer ${ANON_KEY}" \
54-
2>/dev/null || echo '{"weekly_active":0}')"
55-
56-
WEEKLY="$(echo "$PULSE" | grep -o '"weekly_active":[0-9]*' | grep -o '[0-9]*' || echo "0")"
57-
CHANGE="$(echo "$PULSE" | grep -o '"change_pct":[0-9-]*' | grep -o '[0-9-]*' || echo "0")"
58-
59-
echo "Weekly active installs: ${WEEKLY}"
60-
if [ "$CHANGE" -gt 0 ] 2>/dev/null; then
61-
echo " Change: +${CHANGE}%"
62-
elif [ "$CHANGE" -lt 0 ] 2>/dev/null; then
63-
echo " Change: ${CHANGE}%"
64-
fi
65-
echo ""
44+
WEEKLY="$(echo "$DATA" | grep -o '"weekly_active":[0-9]*' | grep -o '[0-9]*' || echo "0")"
45+
CHANGE="$(echo "$DATA" | grep -o '"change_pct":[0-9-]*' | grep -o '[0-9-]*' || echo "0")"
46+
47+
echo "Weekly active installs: ${WEEKLY}"
48+
if [ "$CHANGE" -gt 0 ] 2>/dev/null; then
49+
echo " Change: +${CHANGE}%"
50+
elif [ "$CHANGE" -lt 0 ] 2>/dev/null; then
51+
echo " Change: ${CHANGE}%"
6652
fi
53+
echo ""
6754

6855
# ─── Skill popularity (top 10) ───────────────────────────────
6956
echo "Top skills (last 7 days)"
7057
echo "────────────────────────"
7158

72-
# Query telemetry_events, group by skill
73-
EVENTS="$(query "telemetry_events" "select=skill,gstack_version&event_type=eq.skill_run&event_timestamp=gte.${WEEK_AGO}&limit=1000" 2>/dev/null || echo "[]")"
74-
75-
if [ "$EVENTS" != "[]" ] && [ -n "$EVENTS" ]; then
76-
echo "$EVENTS" | grep -o '"skill":"[^"]*"' | awk -F'"' '{print $4}' | sort | uniq -c | sort -rn | head -10 | while read -r COUNT SKILL; do
77-
printf " /%-20s %d runs\n" "$SKILL" "$COUNT"
59+
# Parse top_skills array from JSON
60+
SKILLS="$(echo "$DATA" | grep -o '"top_skills":\[[^]]*\]' || echo "")"
61+
if [ -n "$SKILLS" ] && [ "$SKILLS" != '"top_skills":[]' ]; then
62+
# Parse each object — handle any key order (JSONB doesn't preserve order)
63+
echo "$SKILLS" | grep -o '{[^}]*}' | while read -r OBJ; do
64+
SKILL="$(echo "$OBJ" | grep -o '"skill":"[^"]*"' | awk -F'"' '{print $4}')"
65+
COUNT="$(echo "$OBJ" | grep -o '"count":[0-9]*' | grep -o '[0-9]*')"
66+
[ -n "$SKILL" ] && [ -n "$COUNT" ] && printf " /%-20s %s runs\n" "$SKILL" "$COUNT"
7867
done
7968
else
8069
echo " No data yet"
@@ -85,12 +74,12 @@ echo ""
8574
echo "Top crash clusters"
8675
echo "──────────────────"
8776

88-
CRASHES="$(query "crash_clusters" "select=error_class,gstack_version,total_occurrences,identified_users&limit=5" 2>/dev/null || echo "[]")"
89-
90-
if [ "$CRASHES" != "[]" ] && [ -n "$CRASHES" ]; then
91-
echo "$CRASHES" | grep -o '"error_class":"[^"]*"' | awk -F'"' '{print $4}' | head -5 | while read -r ERR; do
92-
C="$(echo "$CRASHES" | grep -o "\"error_class\":\"$ERR\"[^}]*\"total_occurrences\":[0-9]*" | grep -o '"total_occurrences":[0-9]*' | head -1 | grep -o '[0-9]*')"
93-
printf " %-30s %s occurrences\n" "$ERR" "${C:-?}"
77+
CRASHES="$(echo "$DATA" | grep -o '"crashes":\[[^]]*\]' || echo "")"
78+
if [ -n "$CRASHES" ] && [ "$CRASHES" != '"crashes":[]' ]; then
79+
echo "$CRASHES" | grep -o '{[^}]*}' | head -5 | while read -r OBJ; do
80+
ERR="$(echo "$OBJ" | grep -o '"error_class":"[^"]*"' | awk -F'"' '{print $4}')"
81+
C="$(echo "$OBJ" | grep -o '"total_occurrences":[0-9]*' | grep -o '[0-9]*')"
82+
[ -n "$ERR" ] && printf " %-30s %s occurrences\n" "$ERR" "${C:-?}"
9483
done
9584
else
9685
echo " No crashes reported"
@@ -101,9 +90,12 @@ echo ""
10190
echo "Version distribution (last 7 days)"
10291
echo "───────────────────────────────────"
10392

104-
if [ "$EVENTS" != "[]" ] && [ -n "$EVENTS" ]; then
105-
echo "$EVENTS" | grep -o '"gstack_version":"[^"]*"' | awk -F'"' '{print $4}' | sort | uniq -c | sort -rn | head -5 | while read -r COUNT VER; do
106-
printf " v%-15s %d events\n" "$VER" "$COUNT"
93+
VERSIONS="$(echo "$DATA" | grep -o '"versions":\[[^]]*\]' || echo "")"
94+
if [ -n "$VERSIONS" ] && [ "$VERSIONS" != '"versions":[]' ]; then
95+
echo "$VERSIONS" | grep -o '{[^}]*}' | head -5 | while read -r OBJ; do
96+
VER="$(echo "$OBJ" | grep -o '"version":"[^"]*"' | awk -F'"' '{print $4}')"
97+
COUNT="$(echo "$OBJ" | grep -o '"count":[0-9]*' | grep -o '[0-9]*')"
98+
[ -n "$VER" ] && [ -n "$COUNT" ] && printf " v%-15s %s events\n" "$VER" "$COUNT"
10799
done
108100
else
109101
echo " No data yet"

bin/gstack-telemetry-log

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,29 @@ if [ -d "$STATE_DIR/sessions" ]; then
106106
fi
107107

108108
# Generate installation_id for community tier
109+
# Uses a random UUID stored locally — not derived from hostname/user so it
110+
# can't be guessed or correlated by someone who knows your machine identity.
109111
INSTALL_ID=""
110112
if [ "$TIER" = "community" ]; then
111-
HOST="$(hostname 2>/dev/null || echo "unknown")"
112-
USER="$(whoami 2>/dev/null || echo "unknown")"
113-
if command -v shasum >/dev/null 2>&1; then
114-
INSTALL_ID="$(printf '%s-%s' "$HOST" "$USER" | shasum -a 256 | awk '{print $1}')"
115-
elif command -v sha256sum >/dev/null 2>&1; then
116-
INSTALL_ID="$(printf '%s-%s' "$HOST" "$USER" | sha256sum | awk '{print $1}')"
117-
elif command -v openssl >/dev/null 2>&1; then
118-
INSTALL_ID="$(printf '%s-%s' "$HOST" "$USER" | openssl dgst -sha256 | awk '{print $NF}')"
113+
ID_FILE="$HOME/.gstack/installation-id"
114+
if [ -f "$ID_FILE" ]; then
115+
INSTALL_ID="$(cat "$ID_FILE" 2>/dev/null)"
116+
fi
117+
if [ -z "$INSTALL_ID" ]; then
118+
# Generate a random UUID v4
119+
if command -v uuidgen >/dev/null 2>&1; then
120+
INSTALL_ID="$(uuidgen | tr '[:upper:]' '[:lower:]')"
121+
elif [ -r /proc/sys/kernel/random/uuid ]; then
122+
INSTALL_ID="$(cat /proc/sys/kernel/random/uuid)"
123+
else
124+
# Fallback: random hex from /dev/urandom
125+
INSTALL_ID="$(od -An -tx1 -N16 /dev/urandom 2>/dev/null | tr -d ' \n')"
126+
fi
127+
if [ -n "$INSTALL_ID" ]; then
128+
mkdir -p "$(dirname "$ID_FILE")" 2>/dev/null
129+
printf '%s' "$INSTALL_ID" > "$ID_FILE" 2>/dev/null
130+
fi
119131
fi
120-
# If no SHA-256 command available, install_id stays empty
121132
fi
122133

123134
# Local-only fields (never sent remotely)

bin/gstack-telemetry-sync

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
#
44
# Fire-and-forget, backgrounded, rate-limited to once per 5 minutes.
55
# Strips local-only fields before sending. Respects privacy tiers.
6+
# Posts to the telemetry-ingest edge function (not PostgREST directly).
67
#
78
# Env overrides (for testing):
89
# GSTACK_STATE_DIR — override ~/.gstack state directory
910
# GSTACK_DIR — override auto-detected gstack root
10-
# GSTACK_TELEMETRY_ENDPOINT — override Supabase endpoint URL
11+
# GSTACK_SUPABASE_URL — override Supabase project URL
1112
set -uo pipefail
1213

1314
GSTACK_DIR="${GSTACK_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"
@@ -19,15 +20,15 @@ RATE_FILE="$ANALYTICS_DIR/.last-sync-time"
1920
CONFIG_CMD="$GSTACK_DIR/bin/gstack-config"
2021

2122
# Source Supabase config if not overridden by env
22-
if [ -z "${GSTACK_TELEMETRY_ENDPOINT:-}" ] && [ -f "$GSTACK_DIR/supabase/config.sh" ]; then
23+
if [ -z "${GSTACK_SUPABASE_URL:-}" ] && [ -f "$GSTACK_DIR/supabase/config.sh" ]; then
2324
. "$GSTACK_DIR/supabase/config.sh"
2425
fi
25-
ENDPOINT="${GSTACK_TELEMETRY_ENDPOINT:-}"
26+
SUPABASE_URL="${GSTACK_SUPABASE_URL:-}"
2627
ANON_KEY="${GSTACK_SUPABASE_ANON_KEY:-}"
2728

2829
# ─── Pre-checks ──────────────────────────────────────────────
29-
# No endpoint configured yet → exit silently
30-
[ -z "$ENDPOINT" ] && exit 0
30+
# No Supabase URL configured yet → exit silently
31+
[ -z "$SUPABASE_URL" ] && exit 0
3132

3233
# No JSONL file → nothing to sync
3334
[ -f "$JSONL_FILE" ] || exit 0
@@ -66,6 +67,8 @@ UNSENT="$(tail -n "+$SKIP" "$JSONL_FILE" 2>/dev/null || true)"
6667
[ -z "$UNSENT" ] && exit 0
6768

6869
# ─── Strip local-only fields and build batch ─────────────────
70+
# Edge function expects raw JSONL field names (v, ts, sessions) —
71+
# no column renaming needed (the function maps them internally).
6972
BATCH="["
7073
FIRST=true
7174
COUNT=0
@@ -75,13 +78,10 @@ while IFS= read -r LINE; do
7578
[ -z "$LINE" ] && continue
7679
echo "$LINE" | grep -q '^{' || continue
7780

78-
# Strip local-only fields + map JSONL field names to Postgres column names
81+
# Strip local-only fields (keep v, ts, sessions as-is for edge function)
7982
CLEAN="$(echo "$LINE" | sed \
8083
-e 's/,"_repo_slug":"[^"]*"//g' \
8184
-e 's/,"_branch":"[^"]*"//g' \
82-
-e 's/"v":/"schema_version":/g' \
83-
-e 's/"ts":/"event_timestamp":/g' \
84-
-e 's/"sessions":/"concurrent_sessions":/g' \
8585
-e 's/,"repo":"[^"]*"//g')"
8686

8787
# If anonymous tier, strip installation_id
@@ -106,21 +106,31 @@ BATCH="$BATCH]"
106106
# Nothing to send after filtering
107107
[ "$COUNT" -eq 0 ] && exit 0
108108

109-
# ─── POST to Supabase ────────────────────────────────────────
110-
HTTP_CODE="$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 \
111-
-X POST "${ENDPOINT}/telemetry_events" \
109+
# ─── POST to edge function ───────────────────────────────────
110+
RESP_FILE="$(mktemp /tmp/gstack-sync-XXXXXX 2>/dev/null || echo "/tmp/gstack-sync-$$")"
111+
HTTP_CODE="$(curl -s -w '%{http_code}' --max-time 10 \
112+
-X POST "${SUPABASE_URL}/functions/v1/telemetry-ingest" \
112113
-H "Content-Type: application/json" \
113114
-H "apikey: ${ANON_KEY}" \
114-
-H "Authorization: Bearer ${ANON_KEY}" \
115-
-H "Prefer: return=minimal" \
115+
-o "$RESP_FILE" \
116116
-d "$BATCH" 2>/dev/null || echo "000")"
117117

118118
# ─── Update cursor on success (2xx) ─────────────────────────
119119
case "$HTTP_CODE" in
120-
2*) NEW_CURSOR=$(( CURSOR + COUNT ))
121-
echo "$NEW_CURSOR" > "$CURSOR_FILE" 2>/dev/null || true ;;
120+
2*)
121+
# Parse inserted count from response — only advance if events were actually inserted.
122+
# Advance by SENT count (not inserted count) because we can't map inserted back to
123+
# source lines. If inserted==0, something is systemically wrong — don't advance.
124+
INSERTED="$(grep -o '"inserted":[0-9]*' "$RESP_FILE" 2>/dev/null | grep -o '[0-9]*' || echo "0")"
125+
if [ "${INSERTED:-0}" -gt 0 ] 2>/dev/null; then
126+
NEW_CURSOR=$(( CURSOR + COUNT ))
127+
echo "$NEW_CURSOR" > "$CURSOR_FILE" 2>/dev/null || true
128+
fi
129+
;;
122130
esac
123131

132+
rm -f "$RESP_FILE" 2>/dev/null || true
133+
124134
# Update rate limit marker
125135
touch "$RATE_FILE" 2>/dev/null || true
126136

bin/gstack-update-check

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -160,25 +160,22 @@ fi
160160
mkdir -p "$STATE_DIR"
161161

162162
# Fire Supabase install ping in background (parallel, non-blocking)
163-
# This logs an update check event for community health metrics.
164-
# If the endpoint isn't configured or Supabase is down, this is a no-op.
165-
# Source Supabase config for install ping
166-
if [ -z "${GSTACK_TELEMETRY_ENDPOINT:-}" ] && [ -f "$GSTACK_DIR/supabase/config.sh" ]; then
163+
# This logs an update check event for community health metrics via edge function.
164+
# If Supabase is not configured or telemetry is off, this is a no-op.
165+
if [ -z "${GSTACK_SUPABASE_URL:-}" ] && [ -f "$GSTACK_DIR/supabase/config.sh" ]; then
167166
. "$GSTACK_DIR/supabase/config.sh"
168167
fi
169-
_SUPA_ENDPOINT="${GSTACK_TELEMETRY_ENDPOINT:-}"
168+
_SUPA_URL="${GSTACK_SUPABASE_URL:-}"
170169
_SUPA_KEY="${GSTACK_SUPABASE_ANON_KEY:-}"
171170
# Respect telemetry opt-out — don't ping Supabase if user set telemetry: off
172171
_TEL_TIER="$("$GSTACK_DIR/bin/gstack-config" get telemetry 2>/dev/null || true)"
173-
if [ -n "$_SUPA_ENDPOINT" ] && [ -n "$_SUPA_KEY" ] && [ "${_TEL_TIER:-off}" != "off" ]; then
172+
if [ -n "$_SUPA_URL" ] && [ -n "$_SUPA_KEY" ] && [ "${_TEL_TIER:-off}" != "off" ]; then
174173
_OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
175174
curl -sf --max-time 5 \
176-
-X POST "${_SUPA_ENDPOINT}/update_checks" \
175+
-X POST "${_SUPA_URL}/functions/v1/update-check" \
177176
-H "Content-Type: application/json" \
178177
-H "apikey: ${_SUPA_KEY}" \
179-
-H "Authorization: Bearer ${_SUPA_KEY}" \
180-
-H "Prefer: return=minimal" \
181-
-d "{\"gstack_version\":\"$LOCAL\",\"os\":\"$_OS\"}" \
178+
-d "{\"version\":\"$LOCAL\",\"os\":\"$_OS\"}" \
182179
>/dev/null 2>&1 &
183180
fi
184181

browse/dist/browse

-58.1 MB
Binary file not shown.

0 commit comments

Comments
 (0)