From a6b9640738bbc30a84bb45aeb464521f20565cd1 Mon Sep 17 00:00:00 2001 From: Luis Erlacher Date: Sun, 16 Nov 2025 18:07:02 -0300 Subject: [PATCH] fix: Configure Vite to load environment variables from root directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes authentication environment variable loading by properly configuring Vite's envDir to read from the project root instead of the archon-ui-main directory. Changes: - Configure vite.config.ts with envDir pointing to parent directory - Add explicit VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY to .env - Create vite-env.d.ts for TypeScript environment variable types - Add debug logging to supabaseClient.ts for troubleshooting - Update .env.example with proper Vite variable configuration - Update AUTHENTICATION_SETUP.md with corrected setup instructions Technical details: - Vite's loadEnv() only loads vars for config use, not client injection - envDir config is required to tell Vite where to find .env for client code - Variables must be explicitly defined (Vite doesn't expand ${VAR} syntax) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .env.example | 16 ++++--- AUTHENTICATION_SETUP.md | 45 ++++++++++--------- archon-ui-main/package-lock.json | 26 ++++++++++- .../features/auth/config/supabaseClient.ts | 13 +++++- archon-ui-main/src/vite-env.d.ts | 14 ++++++ archon-ui-main/vite.config.ts | 7 ++- 6 files changed, 88 insertions(+), 33 deletions(-) create mode 100644 archon-ui-main/src/vite-env.d.ts diff --git a/.env.example b/.env.example index 4c2f646..b32dbb9 100644 --- a/.env.example +++ b/.env.example @@ -5,13 +5,6 @@ # https://supabase.com/dashboard/project//settings/api SUPABASE_URL= -# Frontend Supabase Configuration (for authentication) -# These are required for the frontend auth feature -VITE_SUPABASE_URL=${SUPABASE_URL} -# Get the ANON (public) key from Supabase Dashboard > Settings > API -# This is DIFFERENT from the SERVICE_ROLE key - frontend uses ANON key for client-side auth -VITE_SUPABASE_ANON_KEY= - # ⚠️ CRITICAL: You MUST use the SERVICE ROLE key, NOT the Anon key! ⚠️ # # COMMON MISTAKE: Using the anon (public) key will cause ALL saves to fail with "permission denied"! @@ -29,6 +22,15 @@ VITE_SUPABASE_ANON_KEY= # # On the Supabase dashboard, it's labeled as "service_role" under "Project API keys" SUPABASE_SERVICE_KEY= +SUPABASE_ANON_KEY= + +# Frontend Supabase Configuration (used by Vite) +# These variables are automatically picked up by the frontend build process +# Note: Vite doesn't expand ${VAR} syntax, so these need explicit values (same as above) +# Get the ANON (public) key from Supabase Dashboard > Settings > API +# This is DIFFERENT from the SERVICE_ROLE key - frontend uses ANON key for client-side auth +VITE_SUPABASE_URL= +VITE_SUPABASE_ANON_KEY= # Optional: Set log level for debugging LOGFIRE_TOKEN= diff --git a/AUTHENTICATION_SETUP.md b/AUTHENTICATION_SETUP.md index 2c02785..937c8d1 100644 --- a/AUTHENTICATION_SETUP.md +++ b/AUTHENTICATION_SETUP.md @@ -15,34 +15,37 @@ Archon now supports user authentication using Supabase Auth. This allows you to: 1. A Supabase project (create one at [supabase.com](https://supabase.com)) 2. Node.js and Python environment set up -## Step 1: Configure Environment Variables +## Step 1: Verify Environment Variables -### Backend Configuration - -In your `.env` file, ensure you have: +The authentication system uses the Supabase configuration already present in your root `.env` file: ```bash -# Supabase Configuration -SUPABASE_URL=https://your-project.supabase.co -SUPABASE_SERVICE_KEY=your-service-role-key-here +# Supabase Configuration (Backend) +SUPABASE_URL=https://supabase.automatizase.com.br +SUPABASE_SERVICE_KEY=eyJhbGc... # Your service role key +SUPABASE_ANON_KEY=eyJhbGc... # Your anon/public key -# Frontend Supabase Configuration +# Frontend Supabase Configuration (automatically configured) VITE_SUPABASE_URL=${SUPABASE_URL} -VITE_SUPABASE_ANON_KEY=your-anon-public-key-here +VITE_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY} ``` -### Getting Your Keys +**Important Notes:** +- The frontend uses `VITE_SUPABASE_ANON_KEY` (safe for client-side) +- The backend uses `SUPABASE_SERVICE_KEY` (server-side only) +- These variables are automatically loaded from the root `.env` file +- The Vite config has been updated to read from the root directory -1. Go to your Supabase Dashboard -2. Navigate to **Settings** > **API** -3. Copy the following: - - **Project URL** → `SUPABASE_URL` and `VITE_SUPABASE_URL` - - **anon (public)** key → `VITE_SUPABASE_ANON_KEY` (for frontend) - - **service_role (secret)** key → `SUPABASE_SERVICE_KEY` (for backend) +## Step 2: Install Frontend Dependencies -**Important:** The frontend uses the ANON key (safe for client-side), while the backend uses the SERVICE_ROLE key (server-side only). +```bash +cd archon-ui-main +npm install +``` -## Step 2: Enable Email Authentication in Supabase +This will install the `@supabase/supabase-js` package required for authentication. + +## Step 3: Enable Email Authentication in Supabase 1. Go to **Authentication** > **Providers** in your Supabase Dashboard 2. Enable **Email** provider @@ -51,7 +54,7 @@ VITE_SUPABASE_ANON_KEY=your-anon-public-key-here - Development: `http://localhost:3737/*` - Production: Your production URL -## Step 3: Enable Authentication Middleware (Optional) +## Step 4: Enable Authentication Middleware (Optional) By default, the authentication middleware is **disabled** to avoid breaking existing installations. To enable it: @@ -68,7 +71,7 @@ When enabled, all API routes will require authentication except: - `/docs`, `/redoc`, `/openapi.json` - API documentation - `/api/auth/*` - Authentication endpoints -## Step 4: Start the Application +## Step 5: Start the Application ```bash # Frontend @@ -80,7 +83,7 @@ cd python uv run python -m src.server.main ``` -## Step 5: Create Your First User +## Step 6: Create Your First User 1. Navigate to `http://localhost:3737/signup` 2. Enter your email and password diff --git a/archon-ui-main/package-lock.json b/archon-ui-main/package-lock.json index cae844f..bfea9aa 100644 --- a/archon-ui-main/package-lock.json +++ b/archon-ui-main/package-lock.json @@ -148,6 +148,7 @@ "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -881,6 +882,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.2.tgz", "integrity": "sha512-p44TsNArL4IVXDTbapUmEkAlvWs2CFQbcfc0ymDsis1kH2wh0gcY96AS29c/vp2d0y2Tquk1EDSaawpzilUiAw==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", @@ -969,6 +971,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", "license": "MIT", + "peer": true, "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } @@ -978,6 +981,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.1.tgz", "integrity": "sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", @@ -1152,6 +1156,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -1175,6 +1180,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -2162,6 +2168,7 @@ "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", "license": "MIT", + "peer": true, "dependencies": { "@lezer/common": "^1.0.0" } @@ -3840,6 +3847,7 @@ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.87.0.tgz", "integrity": "sha512-3uRCGHo7KWHl6h7ptzLd5CbrjTQP5Q/37aC1cueClkSN4t/OaNFmfGolgs1AoA0kFjP/OZxTY2ytQoifyJzpWQ==", "license": "MIT", + "peer": true, "dependencies": { "@tanstack/query-core": "5.87.0" }, @@ -4134,6 +4142,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.0.tgz", "integrity": "sha512-hfrc+1tud1xcdVTABC2JiomZJEklMcXYNTVtZLAeqTVWD+qL5jkHKT+1lOtqDdGxt+mB53DTtiz673vfjU8D1Q==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -4155,6 +4164,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -4166,6 +4176,7 @@ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -4234,6 +4245,7 @@ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", @@ -4599,6 +4611,7 @@ "integrity": "sha512-xa57bCPGuzEFqGjPs3vVLyqareG8DX0uMkr5U/v5vLv5/ZUrBrPL7gzxzTJedEyZxFMfsozwTIbbYfEQVo3kgg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/utils": "1.6.1", "fast-glob": "^3.3.2", @@ -4671,6 +4684,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5007,6 +5021,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001718", "electron-to-chromium": "^1.5.160", @@ -6026,6 +6041,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -7533,7 +7549,6 @@ "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", "license": "MIT", - "peer": true, "funding": { "type": "GitHub Sponsors ❤", "url": "https://github.com/sponsors/dmonad" @@ -7643,6 +7658,7 @@ "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cssstyle": "^4.0.1", "data-urls": "^5.0.0", @@ -7769,7 +7785,6 @@ "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.114.tgz", "integrity": "sha512-gcxmNFzA4hv8UYi8j43uPlQ7CGcyMJ2KQb5kZASw6SnAKAf10hK12i2fjrS3Cl/ugZa5Ui6WwIu1/6MIXiHttQ==", "license": "MIT", - "peer": true, "dependencies": { "isomorphic.js": "^0.2.4" }, @@ -9615,6 +9630,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -9894,6 +9910,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -9954,6 +9971,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -11212,6 +11230,7 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -11311,6 +11330,7 @@ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -11630,6 +11650,7 @@ "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -11713,6 +11734,7 @@ "integrity": "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "1.6.1", "@vitest/runner": "1.6.1", diff --git a/archon-ui-main/src/features/auth/config/supabaseClient.ts b/archon-ui-main/src/features/auth/config/supabaseClient.ts index 1667e0a..26baabf 100644 --- a/archon-ui-main/src/features/auth/config/supabaseClient.ts +++ b/archon-ui-main/src/features/auth/config/supabaseClient.ts @@ -3,9 +3,20 @@ import { createClient } from "@supabase/supabase-js"; const supabaseUrl = import.meta.env.VITE_SUPABASE_URL; const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY; +// Debug logging +console.log("🔍 Supabase Config Debug:", { + url: supabaseUrl ? `${supabaseUrl.substring(0, 30)}...` : "MISSING", + anonKey: supabaseAnonKey ? `${supabaseAnonKey.substring(0, 20)}...` : "MISSING", + allEnvVars: Object.keys(import.meta.env).filter(key => key.startsWith('VITE_')) +}); + if (!supabaseUrl || !supabaseAnonKey) { throw new Error( - "Missing Supabase environment variables. Please set VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY in your .env file.", + `Missing Supabase environment variables!\n` + + `VITE_SUPABASE_URL: ${supabaseUrl ? 'SET' : 'MISSING'}\n` + + `VITE_SUPABASE_ANON_KEY: ${supabaseAnonKey ? 'SET' : 'MISSING'}\n` + + `Available VITE_ vars: ${Object.keys(import.meta.env).filter(k => k.startsWith('VITE_')).join(', ')}\n` + + `Please ensure .env file is in the root directory (/home/luis/projetos/Archon/.env) and restart the Vite dev server.` ); } diff --git a/archon-ui-main/src/vite-env.d.ts b/archon-ui-main/src/vite-env.d.ts new file mode 100644 index 0000000..bc9b519 --- /dev/null +++ b/archon-ui-main/src/vite-env.d.ts @@ -0,0 +1,14 @@ +/// + +interface ImportMetaEnv { + readonly VITE_SUPABASE_URL: string + readonly VITE_SUPABASE_ANON_KEY: string + readonly VITE_HOST?: string + readonly VITE_PORT?: string + readonly VITE_ALLOWED_HOSTS?: string + readonly VITE_SHOW_DEVTOOLS?: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/archon-ui-main/vite.config.ts b/archon-ui-main/vite.config.ts index 464f3cf..8185739 100644 --- a/archon-ui-main/vite.config.ts +++ b/archon-ui-main/vite.config.ts @@ -9,8 +9,8 @@ import type { ConfigEnv, UserConfig } from 'vite'; // https://vitejs.dev/config/ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { - // Load environment variables - const env = loadEnv(mode, process.cwd(), ''); + // Load environment variables from root directory (parent of archon-ui-main) + const env = loadEnv(mode, path.resolve(__dirname, '..'), ''); // Get host and port from environment variables or use defaults // For internal Docker communication, use the service name @@ -24,6 +24,9 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { const port = process.env.ARCHON_SERVER_PORT || env.ARCHON_SERVER_PORT || '8181'; return { + // CRITICAL: Tell Vite where to find .env files (parent directory) + envDir: path.resolve(__dirname, '..'), + plugins: [ react(), // Custom plugin to add test endpoint