From 8a3a33739fc85de45ee0258ef70dfd7e3425454d Mon Sep 17 00:00:00 2001 From: Renaud Laborbe <150821561+BluegReeno@users.noreply.github.com> Date: Sun, 26 Jul 2026 11:37:43 +0200 Subject: [PATCH 1/2] Fix: make deploy guards CLI version + token before deploying (#80) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit make deploy ran the deploy unconditionally: a missing SUPABASE_ACCESS_TOKEN (direnv doesn't fire non-interactively) failed with a misleading 403, and an outdated CLI that can't read deno.lock v5 died at bundling after auth succeeded. Both are now caught up front, as one guarded recipe line so the sourced token reaches the deploy in the same shell. Changes: - Makefile: add MIN_SUPABASE_CLI := 2.109.1; rewrite deploy as one logical recipe line — CLI-version guard (sort -V) then token guard (source .envrc only when the token is unset and .envrc exists) before the actual deploy - Makefile: an already-exported token is honoured as-is, a missing .envrc is not an error when the token is set, deno.lock is never touched - docs/operations.md §2: reconcile prose with the guards (#79) — Path A now guarded automatically, Path B still sources the token by hand Fixes #80 --- Makefile | 20 ++++++++++++++++++-- docs/operations.md | 17 ++++++++++++----- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 94036ef..971bda3 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,23 @@ +MIN_SUPABASE_CLI := 2.109.1 + .PHONY: deploy verify test -deploy: ## deploy hal-mcp + verify it answers - supabase functions deploy hal-mcp --no-verify-jwt +deploy: ## deploy hal-mcp + verify it answers (guards CLI version + token first) + set -e; \ + CLI_VERSION="$$(supabase --version)"; \ + LOWEST="$$(printf '%s\n%s\n' "$(MIN_SUPABASE_CLI)" "$$CLI_VERSION" | sort -V | head -1)"; \ + if [ "$$LOWEST" != "$(MIN_SUPABASE_CLI)" ]; then \ + echo "supabase CLI $$CLI_VERSION < required $(MIN_SUPABASE_CLI) (deno.lock is lockfile v5, needs a newer CLI) — run: brew trust --formula supabase/tap/supabase && brew upgrade supabase" >&2; \ + exit 1; \ + fi; \ + if [ -z "$$SUPABASE_ACCESS_TOKEN" ] && [ -f .envrc ]; then \ + . ./.envrc; \ + fi; \ + if [ -z "$$SUPABASE_ACCESS_TOKEN" ]; then \ + echo "SUPABASE_ACCESS_TOKEN unset and no .envrc to source — see docs/operations.md §2" >&2; \ + exit 1; \ + fi; \ + supabase functions deploy hal-mcp --no-verify-jwt && \ ./scripts/verify_deploy.sh verify: ## probe the live hal-mcp function (no redeploy) diff --git a/docs/operations.md b/docs/operations.md index 932ea2f..e2b7fa0 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -108,11 +108,14 @@ supabase projects list # the row shows ● in the LINKED column when authed + **direnv does not fire in a non-interactive shell.** An agent, a script, a CI runner or anything driving `make deploy` without an interactive `cd` gets **no token at all** and falls through to the personal account — which fails with a 403 that reads like a permissions problem rather than a -missing token. Source it explicitly first, exactly as Path B does: +missing token. -```bash -source /Users/renaud/Projects/hal/.envrc -``` +`make deploy` (Path A) guards this automatically: if `SUPABASE_ACCESS_TOKEN` is unset it sources +`.envrc` from the repo root when present, and fails with a named error otherwise (see the `deploy` +target in the root `Makefile`) — never a bare 403. An already-exported token is honoured as-is and +`.envrc` is not required to exist. This does **not** help **Path B**: worktree deploys bypass `make +deploy` entirely (they need `--workdir`/`--project-ref` flags the target doesn't pass), so there +you still source the token by hand — see Path B below. ### CLI version prerequisite @@ -126,7 +129,11 @@ Caused by: Unsupported lockfile version '5'. Try upgrading Deno or recreating th **Do not delete or regenerate `deno.lock` to work around this** — it pins the exact dependency versions that ship to production. Upgrade the CLI instead (2.72.7 → 2.109.1 fixed it on -2026-07-25): +2026-07-25). + +`make deploy` guards this too: it checks `supabase --version` against `MIN_SUPABASE_CLI` (kept in +the `Makefile`, currently `2.109.1`) and stops *before* bundling if the CLI is too old, printing +the exact remedy below. When you see it, run this and retry: ```bash brew trust --formula supabase/tap/supabase # Homebrew now refuses untrusted taps From 55de9fc08d67375d0d12e14ed520e06fdb50a8c9 Mon Sep 17 00:00:00 2001 From: Renaud Laborbe <150821561+BluegReeno@users.noreply.github.com> Date: Sun, 26 Jul 2026 11:47:32 +0200 Subject: [PATCH 2/2] docs: reconcile CLAUDE.md deploy summary with #80 guards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed: - CLAUDE.md's "Edge function deploy" bullet described the pre-#80 manual .envrc-sourcing model and made no mention of the automatic token/CLI- version guards this PR added to `make deploy`, contradicting the shipped behavior for any session that reads only the summary. Skipped: - README.md L279/L303 (LOW, optional per docs-impact-findings.md) — still technically true, not filed as a standalone finding. --- CLAUDE.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4094461..13e451d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -77,13 +77,16 @@ files → a **partial** set. The remote ledger is the source of truth, stamped a with the same SQL.** Never one without the other. Two files sharing a timestamp = a hand-written-timestamp bug; always use `migration new`. - **MCP `execute_sql` is read/debug only — never DDL.** -- **Edge function deploy**: `make deploy` (root `Makefile`) runs - `supabase functions deploy hal-mcp --no-verify-jwt` then `scripts/verify_deploy.sh`, which +- **Edge function deploy**: `make deploy` (root `Makefile`) guards `SUPABASE_ACCESS_TOKEN` and + the `supabase` CLI version before deploying — see below — then runs + `supabase functions deploy hal-mcp --no-verify-jwt` and `scripts/verify_deploy.sh`, which probes the live function and exits non-zero if it does not answer. `--no-verify-jwt` is - required so the function does its own auth. Requires the CLI authenticated as - **`renaud@bluegreen.ai`** (org BluegReeno, owner of the project) via the per-repo `.envrc` - `SUPABASE_ACCESS_TOKEN`. The personal account (SecondBrain org) has no access → 403. Verify - with `supabase projects list` (the project shows ● when linked + visible). Offline checks: + required so the function does its own auth. Deploy requires the CLI authenticated as + **`renaud@bluegreen.ai`** (org BluegReeno, owner of the project); the personal account + (SecondBrain org) has no access → 403. `make deploy` sources the per-repo `.envrc` + `SUPABASE_ACCESS_TOKEN` automatically when unset (falls back to a named error, never a bare + 403), and refuses to run below `MIN_SUPABASE_CLI` (kept in the `Makefile`). Verify auth with + `supabase projects list` (the project shows ● when linked + visible). Offline checks: `make test`. Full procedure (incl. deploying from an Archon worktree, and the OAuth vs `secret:hal_api_key`