diff --git a/Dockerfile b/Dockerfile index 7cf32b3..45b9491 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,9 +9,13 @@ WORKDIR /app ARG NEXT_PUBLIC_SUPABASE_URL ARG NEXT_PUBLIC_SUPABASE_ANON_KEY +ARG SUPABASE_URL +ARG NEXT_PUBLIC_APP_URL ARG BUILD_CACHE_BUSTER ENV NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL} ENV NEXT_PUBLIC_SUPABASE_ANON_KEY=${NEXT_PUBLIC_SUPABASE_ANON_KEY} +ENV SUPABASE_URL=${SUPABASE_URL} +ENV NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} ENV BUILD_CACHE_BUSTER=${BUILD_CACHE_BUSTER} COPY --from=deps /app/node_modules ./node_modules @@ -28,6 +32,12 @@ FROM node:20-bookworm-slim AS runner WORKDIR /app ENV NODE_ENV=production +ARG NEXT_PUBLIC_SUPABASE_URL +ARG SUPABASE_URL +ARG NEXT_PUBLIC_APP_URL +ENV NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL} +ENV SUPABASE_URL=${SUPABASE_URL} +ENV NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} COPY --from=prod-deps /app/node_modules ./node_modules COPY --from=builder /app/package.json ./package.json diff --git a/Jenkinsfile b/Jenkinsfile index aa1a5d9..fb8d661 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -12,7 +12,8 @@ pipeline { APP_HOST = "${env.APP_HOST ?: '192.168.68.89'}" APP_USER = "${env.APP_USER ?: 'deploy'}" DEPLOY_PATH = "${env.DEPLOY_PATH ?: '/opt/plesk-agency-portal'}" - APP_BASE_URL = "${env.APP_BASE_URL ?: 'http://192.168.68.89:3000'}" + APP_BASE_URL = "${env.APP_BASE_URL ?: 'https://portal.rdbcloud.co.uk'}" + NEXT_PUBLIC_APP_URL = "${env.NEXT_PUBLIC_APP_URL ?: 'https://portal.rdbcloud.co.uk'}" } @@ -64,10 +65,15 @@ pipeline { stage('Build application') { steps { withCredentials([ - string(credentialsId: 'supabase-public-url', variable: 'NEXT_PUBLIC_SUPABASE_URL'), + string(credentialsId: 'supabase-public-url', variable: 'SUPABASE_PUBLIC_URL'), string(credentialsId: 'supabase-public-anon-key', variable: 'NEXT_PUBLIC_SUPABASE_ANON_KEY') ]) { - sh 'npm run build' + sh ''' + NEXT_PUBLIC_SUPABASE_URL="$SUPABASE_PUBLIC_URL" \ + SUPABASE_URL="$SUPABASE_PUBLIC_URL" \ + NEXT_PUBLIC_APP_URL="$NEXT_PUBLIC_APP_URL" \ + npm run build + ''' } } } @@ -75,10 +81,10 @@ pipeline { stage('Build Docker image') { steps { withCredentials([ - string(credentialsId: 'supabase-public-url', variable: 'NEXT_PUBLIC_SUPABASE_URL'), + string(credentialsId: 'supabase-public-url', variable: 'SUPABASE_PUBLIC_URL'), string(credentialsId: 'supabase-public-anon-key', variable: 'NEXT_PUBLIC_SUPABASE_ANON_KEY') ]) { - sh 'docker build --build-arg NEXT_PUBLIC_SUPABASE_URL="$NEXT_PUBLIC_SUPABASE_URL" --build-arg NEXT_PUBLIC_SUPABASE_ANON_KEY="$NEXT_PUBLIC_SUPABASE_ANON_KEY" --build-arg BUILD_CACHE_BUSTER="${BUILD_NUMBER}" -t ${IMAGE_LATEST} -t ${IMAGE_BUILD} .' + sh 'docker build --build-arg NEXT_PUBLIC_SUPABASE_URL="$SUPABASE_PUBLIC_URL" --build-arg SUPABASE_URL="$SUPABASE_PUBLIC_URL" --build-arg NEXT_PUBLIC_APP_URL="$NEXT_PUBLIC_APP_URL" --build-arg NEXT_PUBLIC_SUPABASE_ANON_KEY="$NEXT_PUBLIC_SUPABASE_ANON_KEY" --build-arg BUILD_CACHE_BUSTER="${BUILD_NUMBER}" -t ${IMAGE_LATEST} -t ${IMAGE_BUILD} .' } } } diff --git a/docs/GUARDRAILS.md b/docs/GUARDRAILS.md index 519720d..cae8090 100644 --- a/docs/GUARDRAILS.md +++ b/docs/GUARDRAILS.md @@ -1,38 +1,245 @@ # GUARDRAILS -These systems are currently working and must not be broken by AI refactors. +These systems are **currently working** and must **not be broken by AI refactors**. -## CI/CD +AI tools must **prefer minimal changes** and avoid architecture changes unless explicitly instructed. -Jenkins pipeline builds Docker image and deploys it. +--- + +# Core Principle + +If a task can be solved with a **small change**, the AI must **not perform a large rewrite**. + +--- + +# Git Workflow Rules + +The AI must **NEVER commit directly to `master` or `main`.** + +All changes must be made via a branch. + +## Branch naming conventions + +Feature work: + +feature/ + +Bug fixes: + +fix/ + +Examples: + +feature/supabase-public-endpoint +fix/smoke-check-url +fix/magic-link-auth + +## Required workflow + +1. Create a branch from `master` +2. Make the required changes +3. Commit changes to that branch +4. Show the diff +5. Do **not merge automatically** +6. Raise a pull request +7. User performs merge after review + +--- + +# Infrastructure Protection + +The AI must **not modify infrastructure** unless explicitly instructed. + +This includes: + +- DNS records +- reverse proxy configuration +- SSL certificates +- server networking +- firewall rules +- Proxmox configuration +- VM/LXC creation +- Nginx Proxy Manager configuration +- Supabase server configuration + +These systems are **managed manually**. + +--- + +# CI/CD + +The Jenkins pipeline currently **builds and deploys the application**. Deployment process: docker save → scp → docker load -## Container +The AI must **not change the deployment architecture** without instruction. + +Allowed CI changes: + +- fixing pipeline bugs +- improving reliability +- adding environment variables +- improving logs + +Not allowed: + +- replacing Jenkins +- replacing Docker deployment +- changing deployment host +- introducing Kubernetes +- major CI architecture changes + +--- + +# Container + +Container name: -Name: plesk-agency-portal -Deploy path: +Deployment path: + /opt/plesk-agency-portal -## Reverse Proxy +The AI must **not rename containers or paths** without explicit approval. -Managed by Nginx Proxy Manager +--- -Public URL: +# Reverse Proxy + +Reverse proxy is managed by: + +Nginx Proxy Manager + +Public application URL: https://portal.rdbcloud.co.uk -## Auth +Supabase public endpoint: -Supabase Magic Link authentication +https://supabase.rdbcloud.co.uk -Environment variables: +The AI must **not change reverse proxy configuration**. + +--- + +# Authentication + +Authentication system: + +Supabase Magic Link + +Required environment variables: NEXT_PUBLIC_SUPABASE_URL SUPABASE_URL +NEXT_PUBLIC_SUPABASE_ANON_KEY -AI tools must avoid large rewrites or architectural changes without explicit instruction. \ No newline at end of file +The AI must **not replace the authentication system**. + +--- + +# Environment Variables + +Secrets must **never be committed to the repository**. + +Secrets must come from: + +- Jenkins credentials +- environment variables +- deployment configuration + +Never commit: + +API keys +private tokens +database passwords +service keys + +--- + +# Docker + +Docker is used for **build and deployment**. + +The AI may: + +- update Dockerfile +- fix build issues +- improve caching + +The AI must **not introduce complex container orchestration**. + +Not allowed: + +kubernetes +docker swarm +nomad +terraform + +Unless explicitly requested. + +--- + +# Database + +Database system: + +Supabase Postgres + +The AI must **not perform destructive database changes**. + +Not allowed automatically: + +DROP TABLE +DROP COLUMN +DELETE large datasets +schema rewrites + +Schema changes must be **reviewed first**. + +--- + +# Safe Refactoring Rules + +Allowed: + +- small code improvements +- bug fixes +- performance improvements +- logging improvements +- type fixes +- lint fixes + +Avoid: + +- large rewrites +- framework changes +- directory restructuring +- renaming large parts of the codebase + +Unless specifically requested. + +--- + +# When AI Is Unsure + +If the AI is unsure: + +1. Explain the risk +2. Ask for clarification +3. Do **not proceed with risky changes** + +--- + +# Priority Order + +When making decisions, the AI must prioritise: + +1. **Do not break production** +2. **Respect guardrails** +3. **Make minimal safe changes** +4. **Preserve deployment pipeline** +5. **Follow branch workflow** diff --git a/lib/env.ts b/lib/env.ts index 1fb90ef..ae42496 100644 --- a/lib/env.ts +++ b/lib/env.ts @@ -35,7 +35,8 @@ export const env = { stripeSecretKey: process.env.STRIPE_SECRET_KEY ?? "", stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET ?? "", stripePriceId: process.env.STRIPE_PRICE_ID ?? "", - supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL ?? "", + supabaseUrl: + process.env.SUPABASE_URL ?? process.env.NEXT_PUBLIC_SUPABASE_URL ?? "", supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ?? "", supabaseServiceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY ?? "", };