Boilerplate-Stack

Changelog

Follow the evolution of Boilerplate-Stack with all our updates, new features, and improvements.

v1.30Patch
May 29, 2026
Membership owner-mint INSERT guard, GDPR api-keys scoping, and resilient auth lookup
Closes an in-tenant privilege-escalation path on memberships (a non-owner admin could mint an owner via direct Data API insert), scopes the GDPR data export's api_keys section to owners/admins, and adds an edge-safe auth wrapper so missing or expired Supabase sessions are treated as anonymous instead of throwing. Plus an init-script fix so npm run init no longer drops the CDN config block.
  • Closed an in-tenant privilege-escalation path on memberships: the owner-mint guard (lock_membership_sensitive_columns) was bound BEFORE UPDATE only, while the 'Admins can insert memberships' RLS policy checks account-admin without constraining the inserted role — so a non-owner workspace admin could POST /rest/v1/memberships with role='owner' for a colluding user and escalate them to owner (billing + deletion powers). The trigger is now BEFORE INSERT OR UPDATE and rejects owner inserts/updates from Data API callers
  • Hotfixed the guard's role scope: the first cut used auth.role() is distinct from 'service_role', which caught the SECURITY DEFINER signup trigger handle_new_user_account() (it runs on the GoTrue auth-admin connection where auth.role() is NULL) and aborted signup with 'Database error saving new user'. Re-scoped to auth.role() in ('authenticated','anon') so the escalation is still blocked for direct PostgREST writes while internal triggers and service_role bootstrap are exempt
  • Scoped the GDPR data export's api_keys section to accounts where the requester is owner/admin (via getOrgManagerRoles() + hasRole()), matching the management-UI gate (requireApiKeyManager) so a plain member can no longer export key names/prefixes/scopes of keys they cannot otherwise see
  • Added lib/auth/safe-get-user.ts (safeGetUser) — an edge-safe wrapper that treats a missing/expired/invalid Supabase session as anonymous instead of letting @supabase/ssr throw AuthApiError: Invalid Refresh Token (which surfaced as an unhandled 500 / log noise). Wired into every server-side auth.getUser() site (get-user.ts, proxy.ts, api-security.ts, permissions/check.ts, verify-admin.ts, stripe/actions.ts, ai/stream). Fails closed — protected routes still redirect, authenticated routes still return 401
  • Fixed scripts/init-project.js regenerating config/app.ts without the cdn block and the isPublicCacheablePath() / PUBLIC_CACHEABLE_PATHS exports. The CDN feature (1.29) added these to the committed config, the wizard prompt, and .env.example, but the generateAppConfig() template was never updated — so running npm run init overwrote config/app.ts minus 57 lines, breaking proxy.ts
  • Mirrored the cdn block, PUBLIC_CACHEABLE_PATHS, and isPublicCacheablePath() into the generateAppConfig() template so future inits emit a complete config, and added anti-pattern A15: any field/helper added to a config file that init-project.js regenerates MUST be mirrored into the matching generate*() template in the same change — treated as one edit unit, like the migration↔schema.sql mirror (A1)
v1.29Minor
May 29, 2026
Security, jobs, and database performance hardening, dynamic-slug rendering, optional CDN caching, and SEO/localization
A broad hardening pass across security, background jobs and database performance: tighter membership and account-deletion policies, centralized webhook SSRF validation, service-role-only Stripe sync, aggregate RPCs for dashboard counters, and pinned SECURITY DEFINER search paths. Plus a production blog/CMS dynamic-slug rendering fix, an opt-in CDN edge-caching layer, and SEO/localization improvements (server-rendered html lang, normalized site URLs, better locale negotiation).
  • Hardened memberships updates with WITH CHECK plus a trigger that blocks non-service-role account/user reassignment and owner self-escalation through either role or role_slug
  • Refactored /api/admin/jobs/** into thin routes backed by core/jobs/*, centralized webhook SSRF validation in lib/security/ssrf.ts, and documented the shared create-time/runtime DNS checks
  • Reworked sync-stripe to batch existing subscription state updates through a service-role-only RPC, while keeping missing-row creation inside the billing domain flow
  • Added aggregate RPC usage for admin/org AI statistics and documented the no-raw-row-download pattern for dashboard counters
  • Memoized CMS unstable_cache() wrappers per canonical key and documented the pattern for future dynamic-key caches
  • Tightened GDPR export failures so internal section messages are logged server-side and the client receives a generic EXPORT_FAILED response
  • Closed an in-tenant privilege-escalation path on account_deletion_requests: the owner-cancel UPDATE policy now carries a WITH CHECK, and a BEFORE UPDATE column-lock trigger restricts non-service-role owners to a status → 'cancelled' transition so a member or owner can no longer flip cascade_members (or any other field) via the Data API to force member-account deletion
  • Pinned SET search_path = public on the SECURITY DEFINER membership helpers (user_belongs_to_account, user_is_account_admin, user_has_permission) and the lock_membership_sensitive_columns / lock_notification_columns triggers
  • Added a matching WITH CHECK to the storage.objects 'Admins can update media' policy so an admin cannot move a media object out of the media bucket
  • Narrowed the pending_emails.email_type CHECK to the worker-supported set (contact, newsletter, notification) so unsupported types fail loudly at insert instead of being silently permanent-failed
  • Consolidated the admin jobs-URL SSRF validation in core/admin/settings.ts onto the canonical validatePublicWebhookUrl resolver (removed a drifting regex/DNS copy)
  • Replaced the admin overview revenue JS-reduce with a get_admin_revenue_sum aggregate RPC and wrapped getPlatformStats in unstable_cache (60s, per-locale)
  • Dropped redundant single-column indexes covered by composites (credit_tx_account_idx, subscriptions_account_idx) and added composites for the revenue (payments(status, created_at desc)) and job-run history (job_runs(job_id, started_at desc)) hot paths
  • Moved the documents/[id] detail route to a thin dispatch over a new core/documents reader, memoized the per-post blog cache wrapper, dropped a redundant getUser() round-trip on onboarding (now via SecurityContext.user_metadata), parallelized the email-provider per-list loops, removed ~20 stale as any casts on now-typed tables, and gave in-app notification helpers a core/notifications/ home
  • Fixed a production DYNAMIC_SERVER_USAGE 500 on blog posts / CMS pages published after the last build: blog/[slug] and [slug] are now force-dynamic (data still cached via unstable_cache) so on-demand ISR no longer conflicts with the root layout's per-request CSP-nonce headers() read
  • Added an opt-in CDN edge-caching layer (CDN_PUBLIC_CACHE_ENABLED, CDN_PUBLIC_S_MAXAGE, CDN_PUBLIC_SWR): when enabled, the middleware advertises a cacheable Cache-Control on anonymous GET requests to public content pages only (no auth cookie, no Set-Cookie), keeping the strict per-request CSP nonce intact while authenticated/dashboard/API responses stay private, no-store. Off by default; documented in caching.md, .env.example, and the production caching docs
  • Server-rendered the actual route locale on <html lang> (fr-FR, fr-CH, en-US, en-CA) instead of patching a default language after hydration, improving crawler and accessibility-tool accuracy
  • Centralized site URL normalization for canonical URLs, hreflang alternates, OpenGraph/JSON-LD, sitemap, and robots metadata so trailing slashes in NEXT_PUBLIC_APP_URL no longer produce duplicate slashes
  • Improved locale negotiation for unprefixed requests so Accept-Language can redirect to exact configured regional locales such as en-CA
v1.28Patch
May 27, 2026
Private sidebar credits widget sync, explicit Supabase Data API grants, and refreshed Supabase agent skills
The private dashboard sidebar credits widget now stays in sync with server-authoritative props after server actions like End Trial; a new migration makes Supabase Data API grants explicit for fresh projects and database resets, with documentation refreshed; local Supabase agent skills and AI-tool entrypoints are updated to invoke both the product-wide Supabase skill and the Postgres best-practices skill.
  • Private dashboard sidebar credits widget now updates immediately after server-side credit changes (notably the End Trial confirmation) without requiring a full page reload
  • Root cause fix: useState(initialCreditsBalance)'s lazy initializer only ran on mount, so router.refresh() re-rendered the layout with a new server-authoritative prop while the sidebar kept stale local state — added a useEffect that re-syncs creditsBalance whenever the initialCreditsBalance prop changes, preserving the existing 'credits-updated' listener for optimistic chat decrements
  • Org sidebar already read workspace.creditsBalance directly from props, so no change was needed there
  • New migration 20260527225001_explicit_data_api_grants.sql makes Supabase Data API access explicit for fresh projects and database resets: default public-schema privileges are revoked and intended anon/authenticated/service_role table grants are re-applied, with the full-schema mirrors carrying the same grant surface
  • Documented the Data API grant model in the Supabase setup docs, onboarding guide, README deployment notes, and AI database rules so future public tables, views, sequences and RPCs ship with grants/revokes alongside RLS policies
  • Updated local Supabase agent skills from supabase/agent-skills at 4e69c80: added the general supabase skill and refreshed supabase-postgres-best-practices to the upstream 1.1.1 references/ layout
  • Updated AI-tool entrypoints and generated skill/rule mirrors so future Supabase work invokes both the product-wide Supabase skill and the Postgres best-practices skill where relevant
v1.27Minor
May 27, 2026
Dashboard loading states, protected-layout async reads, and hardened job handlers
Route-segment loading-state guidance for platform admin, organization admin and private dashboards keeps immediate skeleton/spinner feedback while Server Components resolve; the protected dashboard async pattern is documented; background job handlers are hardened with safer GDPR deletion ordering and Stripe subscription mirror recovery.
  • Added route-segment loading-state guidance for platform admin, organization admin and private dashboard pages so future dashboard work keeps immediate skeleton + spinner feedback while Server Component data resolves
  • Documented the protected dashboard async pattern: start dashboard-context and translation promises together, await context for redirects, then await translations for rendering without moving user/account data into unstable_cache()
  • Synced generated AI-rule mirrors for the new dashboard loading and async-read guidance
  • Hardened background job handlers: GDPR deletion now checks Supabase mutation errors, keeps retry identifiers until destructive work succeeds, and deletes account rows last; Stripe sync creates missing subscription mirrors when create webhooks were missed
v1.26Minor
May 27, 2026
Privacy rights, regional compliance surfaces, and documentation
New customer-facing /[locale]/privacy-choices page and a My Account privacy/data-rights section surface do-not-sell/share, targeted-advertising opt-out, GDPR, Swiss FADP, US state privacy, Canada PIPEDA and CASL rights; cookie consent now honors browser Global Privacy Control signals; canonical security rules, AI-rule mirrors and product docs refreshed.
  • New /[locale]/privacy-choices page and footer link surfacing do-not-sell/share, targeted-advertising opt-out, GDPR, Swiss FADP, US state privacy, Canada PIPEDA and CASL rights
  • New My Account privacy/data-rights section with data export entry point, cookie consent management, regional rights summary, privacy policy access, privacy contact and deletion context
  • Privacy Choices cross-linked from the existing Terms, Privacy Policy and Legal Notice pages so users can move between all legal/privacy surfaces
  • /privacy-choices added to the sitemap and reserved CMS slug list so the route is discoverable and cannot be shadowed by dynamic CMS pages
  • Localized legal/footer/cookie/account copy added across en-US, en-CA, fr-FR and fr-CH
  • Cookie consent now honors browser Global Privacy Control signals — marketing/sharing/targeted-ad consent stays disabled even when 'Accept all' is clicked
  • Cookie settings UI surfaces the active GPC state and disables marketing consent while that signal is present
  • Canonical security rules updated to preserve /privacy-choices and Global Privacy Control behavior in future changes
  • Generated AI-rule mirrors synced for Codex, Gemini and OpenCode
  • Product docs updated for GDPR/privacy, cookie consent, analytics, My Account, production onboarding, README and the changelog
v1.25Minor
May 25, 2026
Marketing auth hydration, dashboard request deduplication, and docs
Public marketing pages stay anonymous-first and cacheable while authenticated UI hydrates client-side via /api/auth/me; private and org dashboards now share a request-cached context with aggregate SQL RPCs and composite indexes; canonical caching/auth rules and product docs refreshed.
  • Public marketing layout (app/[locale]/(frontend)/layout.tsx) no longer reads getUser() / Supabase session data server-side for navbar personalization — stays anonymous-first and cacheable
  • New GET /api/auth/me endpoint for client-side marketing-shell auth hydration: apiSecurity.public({ rateLimit: 'relaxed' }), server-side getUser(), minimal sanitized auth/profile/workspace payloads, and Cache-Control: private, no-store
  • New MarketingAuthProvider and MarketingCommandPalette; TransparentNavbar and AccountDropdown now consume hydrated auth context client-side — connected users clicking the anonymous login link are still routed to their dashboard by the existing auth-route guard
  • New core/accounts/dashboard-context.ts with React.cache() request-level helpers: getPrivateDashboardContext() for /private-dashboard/* and getOrgDashboardContext() for /org-dashboard/*
  • Private dashboard layout/pages (private-dashboard, chat, documents, referrals, affiliates) and org dashboard layout/pages (overview/admin, analytics, billing, API keys, members, roles, member detail, settings) now reuse shared auth/account/workspace context instead of repeating getUser(), profile, membership, billing-access and subscription reads
  • Protected dashboards remain dynamic and request-scoped; no user-specific data was moved to unstable_cache()
  • New dashboard aggregate RPCs for private overview counts, org analytics and org member usage summaries, plus composite indexes for ai_requests, chat_sessions and user_access_logs dashboard hot paths — org analytics/member pages now aggregate in SQL instead of pulling raw usage rows into Server Components
  • Credit purchase and end-trial client components lazy-loaded in dashboard sidebars/actions so modal/payment UI code is no longer part of the initial dashboard client bundle
  • Canonical caching rules updated to document marketing auth hydration, /api/auth/me rate-limit / Cache-Control expectations, and dashboard context deduplication
  • Product docs under content/docs refreshed for caching/performance, authentication, API reference and admin dashboards
v1.24Minor
May 24, 2026
Route-thinning, CI + Guardrails, Post-1.23 Security & Docs v2
Follow-on to 1.23: API route-thinning pass moves multi-step logic into core/*, a new GitHub Actions CI workflow with guardrail scripts and zero-warning lint gate, TRUST_CLOUDFLARE_IP / recent-auth / RLS-attribution security hardening, the multi-page public/docs/v2/ documentation rebuild, and refreshed AI-tool rules and entrypoints.
  • New TRUST_CLOUDFLARE_IP env gate so rate limiting no longer trusts spoofable CF-Connecting-IP — the header is only honored when explicitly enabled
  • Stripe webhook raw-body reads now enforce size while streaming the body instead of buffering the full arrayBuffer() first
  • /api/jobs/run cleanly separates the bearer-token cron path from the admin-session path with equivalent rate-limit, CSRF and body-size controls
  • Newsletter unsubscribe now targets only the authenticated user by default — no more anonymous arbitrary-email unsubscribes
  • Recent-auth + immutable admin_logs extended to subscription cancellation/reactivation, log purges, user credit grants and organization mutations
  • Org settings, invitation revocation, onboarding profile writes and /my-account profile updates moved behind validated server/API boundaries; account-scoped chat/document RLS tightened to block forged user_id attribution
  • API route-thinning pass: GDPR export, AI stream orchestration, CMS pages/media/blocks, admin settings/users/organizations/subscriptions and account API keys now delegate multi-step logic to core/gdpr, core/ai, core/cms, core/admin, core/organizations, core/billing and core/accounts — no app/api/**/route.ts remains over 250 lines
  • High-risk route splits completed: Stripe webhook dispatch in core/billing/stripe-webhook.ts, checkout session creation in core/billing/checkout.ts, job-run auth/execution in core/jobs/run-request.ts and bounded body / security-response helpers in lib/http/request-body.ts — routes are HTTP/security glue only
  • New .github/workflows/ci.yml runs on pull requests and pushes to main: typecheck, lint:ci, lint:strict, project guardrails, API-pattern coverage, API route size, RLS schema/policy coverage, Supabase type coverage, unit tests, secret scan, production build, accessibility and responsive checks
  • New/expanded guardrail scripts: project anti-patterns, API security-wrapper coverage, API route size, RLS coverage across schema.sql + cms-schema.sql, Supabase schema/type coverage, staging readiness probe and critical API load smoke test
  • lint:strict is now a zero-warning CI gate; historical warning visibility lives in npm run lint:debt (4,787 warnings measured during this pass)
  • New static multi-page documentation under public/docs/v2/ with shared navigation, responsive styling, grouped icon sidebar, per-page subsection menus, reused public/docs/screens/ assets, richer visual callouts and a global search-index.json covering setup, configuration, architecture, Supabase, auth/B2B, Stripe pricing, AI/RAG, operations, content, frontend, security, deployment, API reference and AI-tooling
  • public/docs/index.html reworked for first-project onboarding: clearer quick-start path, new-project configuration checklist, scenario-based environment guidance, explicit config/pricing.ts / Stripe Price ID setup, B2B checkout-before-onboarding and workspace auto-bootstrap notes, updated AI Blueprint skill counts, and removed stale local asset references
  • Canonical AI rules and /docs now document the admin-dashboard / billing maintainability split (core/admin/*, focused core/billing/* modules, affiliate/referral reversal hooks in risk-events.ts), the TRUST_CLOUDFLARE_IP env contract (also added to init-generated .env.local), authenticated unsubscribe behavior, the hardened jobs API, recent-auth admin requirements, stricter RLS/profile-write boundaries, the GDPR/US/Canada/Switzerland privacy expansion (fr-CH locale, CHF pricing, Swiss legal copy, CMS legal seeds), and the zero-warning lint gate / lint:debt / RLS coverage / staging probe / load smoke env contracts — generated AI-rule mirrors refreshed via scripts/sync-ai-rules.sh
  • Added .impeccable.md as the project design-context handoff; new CI/guardrail scripts documented across AI-tool entrypoints, canonical rules, README.md and product testing docs
v1.23Minor
May 19, 2026
Consolidated Audit Remediation, Billing, Docs, Email & AI Skills
Full-codebase audit fixes (foundingCodex.md / planFix.md): privacy-by-default tracking, GDPR/LPD deletion proof, export completeness, billing/pricing fixes, legal env contract, AI-tool doc parity, transactional email redesign and /ui-ux-pro-max refresh to v2.5.0.
  • Operators: apply 4 new migrations to the live DB — planfix DB hardening, subscriptions index (outside-tx), deletion processor status, and CMS locale key normalization (fr/en → fr-FR/en-US); mirrored in supabase/schema.sql and supabase/cms-schema.sql
  • Analytics + live-chat are now privacy-by-default: GTM, gtag/Google Ads, Meta Pixel, X Pixel and Crisp only load/fire after the matching analytics/marketing consent; purchase/signup events guarded at the application layer
  • Logged-in cookie consent now goes through POST /api/user/consents with apiSecurity.authenticated() + CSRF + Zod + rate limiting; browser components no longer upsert user_consents directly
  • CMS WYSIWYG image uploads now send the double-submit CSRF token and use media-appropriate rate limits; RAG document uploads keep auth + CSRF + body-size enforcement on the interactive standard limit
  • planFix.md remediation: 63/64 findings fixed — fail-closed auth.role() guard on referral/affiliate SECURITY DEFINER RPCs, API-key hash reads revoked from anon/authenticated roles, app_settings UPDATE RLS gained matching WITH CHECK
  • Admin verification + escalation tightened: 60s recent-auth cookie, per-email OTP rate-limit bucket, is_disabled rejection in verify-OTP and magic-link callback, recent-auth gates for admin_email and toggle_admin, audit logs for destructive actions
  • GDPR data export expanded — profile, memberships, chat sessions/messages, AI requests, consents, payments, subscriptions, licenses, invitations, access logs, deletion requests, notification prefs, pending emails, document metadata and API-key metadata (no secrets or hashes)
  • process-account-deletions records processor status for Stripe, newsletter/email, Supabase Storage, DB cascade and Supabase Auth; failures redacted, increment retry_count, mark the request failed and block false completion; Storage document/avatar cleanup runs before row deletion
  • New legal env contract: LEGAL_COMPANY_NAME, LEGAL_ADDRESS, LEGAL_REGISTRATION_NUMBER — npm run init, .env.example, config/app.ts and /docs all wired up; example placeholders intentionally block public/indexable production builds
  • npm run init now ends with a Pricing & Stripe guide — config/pricing.ts as the source of truth, price-ID mapping, billing model selection, webhook setup and payment methods
  • Ending a Stripe trial early synchronizes the local subscription mirror before responding (org-dashboard removes trial banners immediately); trial conversion credits subtract the configured trial-period grant from the plan allotment instead of adding the full plan amount on top
  • License-expiration warning now uses the documented two-step owner lookup instead of the invalid profiles!owner_user_id embed — fixes the live zero-email regression
  • Contact/newsletter attack-pattern detection wired; unwired CSRF helper code removed; CSRF Origin/Referer checks use appConfig.url; HTML iframe allowlisting now happens inside DOMPurify
  • Pricing tables now render included credits, project limits and trial credits from config/pricing.ts / trial env values instead of duplicated static feature value translations
  • CMS/page/blog/changelog locale lookup falls back from configured locales to legacy language-only keys; admin writes normalize payloads back to BCP-47 keys; seeds, sitemap and npm run init now use configured locales instead of fr / en
  • AI-tool docs synced across .claude/.codex/.gemini/.opencode/.agents — 22 files per mirror; coding-agent entrypoints now include a task-routing matrix, reviewer/skill selection and change-type verification pointers; scripts/sync-ai-rules.sh regenerates .agents/skills/ from .claude/skills/
  • Thin-route + core/ extractions cover AI streaming/accounting, changelog, chat mutations, billing subscribe-free, admin orgs/users and CMS validation; dead core/usage/ and core/memberships/ removed
  • CURRENCY_CODES is now the canonical currency tuple (Currency and SUPPORTED_CURRENCIES derive from it); agent model ids, referral salt, workspace signup bonus, RAG threshold, low-credit alert, locale/currency fallbacks and org-manager roles now use config helpers
  • Transactional email builders share lib/email/layout.ts: monochrome shell, table-based layout, dark-mode CSS, bulletproof CTA fallback and escaped text helpers; per-template gradients removed; covered by __tests__/email/templates-render.test.ts
  • /api/ai/stream body-size enforcement reads the cloned body as a stream instead of buffering the full arrayBuffer() first
  • RAG processing, Stripe sync, GDPR deletion processors, export reads, role reorders, affiliate revalidation and log purges parallelized or batched; select('*') replaced by explicit projections across the flagged hot paths
  • Next.js upgraded to 16.2.6; npm run audit:bundle now runs next build --webpack because @next/bundle-analyzer does not emit reports under Turbopack (reports in .next/analyze/)
  • /ui-ux-pro-max refreshed to v2.5.0: new data files (app-interface.csv, google-fonts.csv, design.csv, draft.csv), rewritten SKILL.md, web-stack lookup consolidated via --domain ux / --domain style; --stack nextjs / vue / shadcn deprecated
v1.22Minor
May 17, 2026
IPv6 Rate-Limit Fix & X Pixel
IPv6 rate-limit keys collapsed to the /64 prefix (bypass closed), a consent-gated X (Twitter) Pixel, and a /docs correctness + responsiveness pass.
  • IPv6 rate-limit bypass closed — keys collapsed to the /64 network prefix (RFC 4291) at a single chokepoint in createRateLimiter(); IPv4 unaffected
  • normalizeRateLimitIdentifier() never throws and leaves IPv4-mapped forms intact; getClientIP() still returns the full /128 for contact and IP-hash paths
  • New unit test __tests__/security/rate-limit-ip.test.ts: ::-expansion, prefix-collapse, IPv4 pass-through and malformed input
  • X (Twitter) Pixel via components/analytics/x-pixel.tsx — rendered only when consent.marketing is granted, same gate as the Meta Pixel
  • xEvents.purchase / xEvents.signUp fire from the existing trackPurchase / trackSignUp paths; no-op when conversion-event env vars are unset
  • Three optional NEXT_PUBLIC_X_PIXEL_* env vars, Zod-validated; static.ads-twitter.com added to the CSP allowlist
  • Standalone /docs page: removed two stale version sections, added a Changelog link to the single source of truth
  • Docs mobile table clipping fixed (13 tables wrapped), anchor scroll-offset, image lazy-loading, de-inlined a repeated pre style
v1.21Patch
May 14, 2026
Stripe Checkout Payment Methods
PayPal explicitly enabled for one-time payments via a single config source; subscriptions stay card-only (Stripe geo-restriction).
  • PayPal now appears on Stripe Checkout for one-time payments — payment_method_types explicitly requested instead of relying on Stripe auto-selection
  • New pricingConfig.checkoutPaymentMethods in config/pricing.ts, keyed per Stripe mode (subscription: card, payment: card + paypal)
  • CheckoutPaymentMethod literal union in lib/pricing/types.ts — a typo fails npm run build before deploy
  • Subscriptions stay card-only by default: Stripe restricts PayPal subscriptions to EEA/UK/CH merchants
  • Card-based wallets (Apple Pay / Google Pay) unaffected — they ride on the card entry
  • npm run init reminds operators to activate the methods in Stripe Dashboard for both test and live
  • Docs updated: .claude/rules/billing.md and mirrors, domain-map config-source registry
v1.20Minor
May 11, 2026
Magic-Link UX Overhaul
6-digit code fallback, cross-tab auto-redirect, resend cooldown and copy refresh to cut magic-link drop-off.
  • 6-digit OTP code surfaced in the magic-link email alongside the link; length configurable via OTP_LENGTH env (default 6, clamped 6-10)
  • New endpoint POST /api/auth/verify-otp — Zod-validated, apiSecurity.public() + strict rate limit, generic error (no enumeration)
  • Success screen shows the destination email, numeric OTP input (autoComplete one-time-code) and a Wrong email? back button
  • Cross-tab auto-redirect: success screen polls getUser() every 4s (paused when tab hidden); clicking the link in another tab redirects the original
  • Resend cooldown (30s countdown) and spam-folder reminder
  • Copy refresh: Continue with email, subtitle mentions link + code, email subject Your sign-in code
  • 9 new auth.login.* and 3 email.magicLink.* keys in both locales (parity test green)
  • Init script prompts for OTP_LENGTH (validated); operator caveat: it must match the Supabase project Email OTP length setting
v1.19Minor
May 10, 2026
Prelaunch Sign-In Gate & Dynamic OAuth Catalog
Server-side admin allowlist gating sign-in during prelaunch, plus a configurable multi-provider OAuth button catalog.
  • Prelaunch sign-in now gated server-side by PRELAUNCH_ALLOWED_EMAILS (server-only, comma-separated, case-insensitive; empty = locked)
  • Three enforcement points: magic-link 403 before generateLink, callback sign-out, OAuth sign-out + admin.deleteUser cleanup
  • Generic restriction message — no email-enumeration vector
  • Dynamic OAuth catalog: NEXT_PUBLIC_OAUTH_PROVIDERS renders one branded button per id, validated against all 19 Supabase-supported providers
  • New lib/auth/oauth-providers.tsx (inlined brand SVGs, no new dependency) + components/auth/oauth-buttons.tsx
  • login-form.tsx: hardcoded Google button removed; divider only shows when at least one provider is configured
  • i18n: auth.login.continueWithProvider with {provider} placeholder + auth.login.prelaunchRestricted, both locales (parity green)
  • Init script hydrates both env vars on re-runs; public/docs/index.html OAuth + prelaunch sections rewritten
v1.18Minor
May 4, 2026
Affiliation Program & Provider-Agnostic Email
Account-centric partner program with cash commissions (Stripe Connect deferred) and a pluggable email abstraction supporting Brevo, Mailjet and noop.
  • Affiliation Program: application + admin approval, 3 tiers (starter/partner/influencer), recurring or one-time commissions
  • ?aff=CODE / /[locale]/a/[code] tracking with httpOnly bsk_aff cookie (independent from referrals)
  • 9 SECURITY DEFINER RPCs, self-attribution + same-owner + IP rate-limit guards, stripe_event_id UNIQUE for idempotency
  • Stripe webhook hooks record conversions on credit packs, licenses and invoices; auto-reverse on refund/dispute
  • Daily approve-mature-affiliate-conversions job honors per-affiliate hold-period overrides
  • AFFILIATES_ENABLED feature gate returns 404 everywhere when off — surface invisible until you flip it
  • Provider-agnostic email abstraction (EmailProvider interface + factory + adapters); Brevo, Mailjet and noop ship in the box
  • EMAIL_PROVIDER env var with auto-fallback to noop when credentials missing (dev/CI friendly)
  • Newsletter forms (waitlist, landing-newsletter, newsletter-form) now actually call /api/newsletter/subscribe with Turnstile token — pre-existing 400 bug fixed
v1.17Patch
April 29, 2026
pg_cron Headers Fix & Cron Admin Dashboard
Critical pg_net positional-args fix (secret leak + 401 storm) plus a new admin surface for monitoring and managing cron.job entries.
  • CRITICAL: pg_net positional-args fix — JOBS_SECRET_KEY was being sent as URL query string, leaking into access logs every cron tick. Rotate the secret after upgrading.
  • Cron jobs were silently 401'ing — net.http_post now called with named arguments, robust across pg_net versions
  • Cron Admin Dashboard at /admin-dashboard/jobs/cron — list, toggle, unschedule, purge-orphans
  • Bearer tokens in cron.job.command redacted at the SQL layer — never cross the API/UI boundary
  • Recent-auth gate on destructive cron actions (unschedule, purge-orphans); audit trail on every mutation
  • Init script: restored missing security + logs config blocks (fresh inits now compile)
  • Init script: orphan cron purge step before re-sync, with anchored filter (won't touch unrelated cron entries)
  • Shared require-recent-auth helper factored from the inline admin-promotion check
v1.15Minor
April 27, 2026
AI Credit Accounting Realignment
Credits now map 1:1 to actual LLM tokens consumed. Plans recalibrated to token-scale amounts.
  • 1 credit = 1 LLM token across chat and RAG (no more reserve-refund drift)
  • Compact credit formatting helper (1M, 2.5M, 500K) with locale-aware FR/EN
  • Plans recalibrated to token-scale: Free 50K, Pro 1M, Business 5M (Stripe prices unchanged)
  • Phone input upgraded to react-international-phone (~250 countries, search, flag emojis)
  • /my-account now resolves accountId server-side — no more silently broken Subscription / Referral cards
  • Referral card on /my-account with stat tiles and link to full dashboard
  • Crisp chat bubble now restricted to the landing page only (no more SPA-bleed onto private/admin)
  • Admin sidebar Referrals entry visibility fixed (server-side feature flag pass-down)
v1.14Minor
April 21, 2026
Referral System
End-to-end account-centric referral program with feature gate, IP rate limit, and chargeback reversal.
  • Referral codes per account — both sides earn credits when the configured trigger fires
  • Hard DB invariants: self-referral blocked, one referral per account lifetime, IP-rate-limited apply
  • User dashboard at /private-dashboard/referrals with cursor-paginated history
  • Admin console: overview KPIs, top-10 leaderboard, filterable list, detail timeline, codes management
  • Signup banner + onboarding auto-attribution from httpOnly ref cookie
  • Stripe webhook hooks: qualify on purchase, automatic reversal on refund / lost dispute
  • 404 everywhere when REFERRAL_ENABLED is off — surface invisible until you flip it
  • AI blueprint deep-review: 19 domain rules, 11 specialized agents, 6 hooks, anti-pattern catalog
v1.13Patch
April 21, 2026
Codebase Review Follow-up
Critical-to-low fixes from the parallel-agent review pass across 4 severity tiers.
  • Schema drift closed — January 2026 index + RLS migrations mirrored to schema.sql
  • Stripe webhook extracted from a 1,632-line route to ~160 lines + reusable apply* functions
  • CSRF Double-Submit + nonce-based CSP in production (no more unsafe-inline)
  • DNS-rebinding defense on job webhooks — IP resolution rejects private/loopback ranges
  • AI stream latency: ~60–100 ms saved per chat request (duplicate auth lookup eliminated)
  • Blog listing egress: up to ~1MB saved per cold load by dropping JSONB content/seo_*
  • MarkdownRenderer is now a Server Component — ~100KB removed from changelog/CMS client bundle
  • Anthropic prompt caching applied — long system prompts hit the 0.1× read discount
v1.12Patch
April 1, 2026
SEO & Sitemap Fixes
Sitemap completeness, structured data corrections, and metadata polish across all page types.
  • Sitemap draft-page leak fixed (added missing published filter after switching to service client)
  • /contact, /blog, /changelog and individual blog posts now appear in the sitemap
  • All 10 page types now emit x-default hreflang for unmatched languages
  • Removed broken SearchAction from WebSite schema (referenced a non-existent /search route)
  • CMS pages: OG type corrected to website, noindex/nofollow honored, canonical + og_image supported
  • Description fallback for empty SEO metadata (excerpt → first 160 chars of content)
  • Blog: filtered/paginated URLs (?page=, ?category=, ?tag=) emit noindex,follow
v1.11Minor
March 29, 2026
UI/UX Pro Max Design Skill
AI-assisted UI/UX decisions with curated design databases and reasoning rules.
  • 67 UI styles (Glassmorphism, Brutalism, Neumorphism, Bento Grid, …) with performance + a11y grades
  • 161 industry-specific color palettes with semantic tokens
  • 57 curated Google Fonts pairings + 25 chart-type recommendations
  • 99 UX guidelines (WCAG, touch targets, performance, animation, forms, navigation)
  • 161 reasoning rules — analyzes product type and emits a complete design system
  • BM25 search engine across all design databases with auto-domain detection
  • Pre-delivery checklist: no-emoji icons, cursor-pointer, hover transitions, contrast, focus, reduced-motion
v1.10Patch
March 29, 2026
Admin & Org Dashboard Fixes
Wrong client, invalid joins, raw locale, and hardcoded fallbacks corrected across admin and org dashboards.
  • Settings page now uses supabaseAdmin for platform totals (was RLS-filtered through user session)
  • Removed invalid joins to a non-existent plans table — plans resolved from pricingConfig instead
  • All admin & org pages now use getIntlLocale() for date and currency formatting
  • Pricing page: 9 missing translation keys added in FR/EN (no more English fallback strings)
  • API routes: 8 hardcoded 'fr-FR' fallbacks replaced with defaultLocale from config
  • CMS API: locale keys built dynamically from SUPPORTED_LOCALES (was hardcoded { 'fr-FR', 'en-US' })
  • Locale conditional in api-keys-manager replaced with getIntlLocale(locale)
v1.9Patch
March 29, 2026
Stripe Webhook Security Pass
37 findings across Stripe webhooks, email templates, billing endpoints, and access control.
  • Webhook idempotency overhaul: license payment row inserted first as idempotency gate; refund/dispute checks payment status before deducting
  • B2B org credits now flow through add_credits RPC — audit trail restored
  • HTML escaping in magic-link, invite-link, roleLabel and workspaceName email templates
  • 1MB body size cap before Stripe signature verification
  • Admin user DELETE now calls auth.admin.deleteUser() — auth.users row no longer left behind
  • Invitation acceptance caps role_slug at 'admin' (owner only via checkout)
  • SVG uploads: full-content scan + javascript: / data:text/html pattern blocking
  • GDPR chat export now filtered by user_id (was leaking session-mate messages)
v1.8Patch
March 29, 2026
Comprehensive Security Audit
62 findings fixed across auth, API, sanitization, billing, AI, RLS, jobs, GDPR and HTTP headers.
  • Admin dashboard pages now require is_admin check in middleware (was auth-only)
  • pg_cron SECURITY DEFINER functions revoked from authenticated/anon — service_role only
  • Webhook auth secrets masked in admin GET responses
  • CMS URL validator enforces http/https — blocks javascript: and data: URIs
  • Hardcoded telemetry API key moved to NOTIFY_API_KEY env var
  • AI stream context schema strict-typed (max 10 keys, validated field types)
  • RLS role_slug parity on api_keys and invitations (legacy + new field both checked)
  • Checkout, license-checkout, portal endpoints require owner/admin role
v1.7Minor
March 23, 2026
Knowledge Base RAG Agent
Dedicated AI agent that answers from uploaded documents using pgvector + HNSW search.
  • New Knowledge Base RAG agent with bilingual system prompts and rose/pink branding
  • Dedicated Knowledge Base page at /private-dashboard/documents
  • Sub-menu navigation in private sidebar — AI Agents → My Agents / Knowledge Base
  • Configurable embedding models (text-embedding-3-small/-large, ada-002)
  • Credits deducted atomically on document upload via decrement_credits RPC
  • PDF text extraction via unpdf (replaces broken raw-binary read)
  • Prompt injection protection — chunks wrapped in <document_chunk> with 'treat as DATA only' prefix
  • Magic-byte validation on uploads + server-generated UUID storage paths
v1.6Minor
March 21, 2026
Command Palette, Notifications, API Keys, Changelog & RAG
Five major features shipped together with WCAG 2.2 AA pass and CSRF on every state-changing call.
  • Command Palette (Cmd+K / Ctrl+K) with fuzzy search across navigation, actions and admin items
  • In-App Notification Center — bell icon + unread badge, 5 notification types, polling, mark-all-read
  • API Key Management — sk_-prefixed, SHA-256 hashed, scope allowlist, owner/admin only
  • Public Changelog page + admin CRUD with multi-locale JSONB and markdown sanitization
  • RAG Document Chat — TXT/MD/PDF upload, pgvector HNSW similarity search, status polling
  • WCAG 2.2 AA: language attribute, form labels, color contrast, star ratings, reduced-motion preferences
  • LCP fixes (no more invisible-until-hydration), priority avatars, image optimization
  • csrfFetch on all 5 new features; notification links restricted to relative paths
v1.5Minor
March 20, 2026
Multi-Platform AI Code Assistant Configuration
Claude Code + Cursor IDE + OpenAI Codex configurations sharing the same reference rules and skills.
  • Comprehensive .claude/ config: 13 domain rules, 9 specialized agents, 11 skills, 3 automation hooks
  • Cursor IDE: .cursorrules + 7 scoped .cursor/rules/*.mdc with glob-based targeting
  • OpenAI Codex: AGENTS.md root instructions + .codex/instructions.md compact reference
  • New skills: /create-job-handler, /create-ai-agent, /create-admin-page
  • New agents: ai-engineer, performance-reviewer, jobs-engineer, testing-engineer, accessibility-reviewer
  • New rules: ai, jobs, cms, licensing, notifications, caching, testing
v1.4Minor
March 16, 2026
Blog Categories, Tags & Pagination
Multi-locale taxonomy with composable URL filters and a paginated 3×3 grid.
  • Multi-locale blog categories (name, description, color, display order)
  • Multi-locale blog tags with many-to-many post linking
  • Blog pagination — 9 posts per page, 3×3 grid, ?page= URL parameter
  • Category filter pills + tag filtering via ?tag= with active-filter banner
  • Composable filters (?category=tech&page=2) preserved across navigation
  • Admin pages for category and tag management with searchable popovers in editor sidebar
  • JSON-LD upgraded from WebPage to BlogPosting with articleSection + keywords
v1.3Patch
March 16, 2026
Critical Security Fixes & New Self-Service Features
Privilege escalation, open redirect, XSS and timing attack patches plus session management, GDPR export and email retry queue.
  • Privilege escalation fix: is_admin removed from client-side onboarding upsert
  • Open redirect & URL injection defenses on auth callback and magic-link routes
  • XSS fix on CMS preview + shortcode renderer (DOMPurify wrapping)
  • timingSafeEqual replaces !== for job secret key comparison
  • Session Management — list recent logins, revoke all other sessions
  • Email retry queue with exponential backoff (1min, 5min, 15min cap)
  • GDPR data export (Article 20) — full CSV download of user data
  • Chat: cancel running AI requests, smart auto-scroll, accessibility improvements
v1.2Minor
March 9, 2026
Google Ads Conversion Tracking
gtag.js integration coexisting with GTM and Meta Pixel under unified consent-aware tracking.
  • Google Ads conversion tracking via gtag.js (coexists with GTM through dataLayer)
  • Unified trackConversion() — fires Google Ads + GTM + Meta Pixel purchase events in one call
  • Checkout success page fires conversion automatically with real Stripe session data
  • Server-side Stripe session retrieval for accurate transaction amount and currency
  • Deduplication via transaction_id (Google Ads) and useRef (React strict mode)
  • Consent-aware: marketing consent for Google Ads + Meta Pixel, analytics consent for GTM
v1.1Patch
January 26, 2026
Best Practices Audit
Production-ready pattern compliance pass across React, Next.js, Tailwind v4 and Supabase.
  • Best practices audit for React/Next.js, Tailwind CSS v4 and Supabase/PostgreSQL
  • Production-ready pattern compliance enforced across the codebase
v1.0Major
Initial Release
Initial Launch
First public release of Boilerplate-Stack with all core features.
  • Next.js 16 App Router, React 19 and TypeScript foundation
  • Supabase integration (PostgreSQL + Auth + Storage + RLS)
  • Multi-tenant architecture (B2C personal + B2B workspace accounts)
  • Stripe billing — subscriptions, credit packs and license one-time payments
  • Multi-LLM AI integration (OpenAI, Claude, Gemini) with LangChain/LangGraph
  • GTM and Meta Pixel with consent management
  • Multi-locale CMS with pages, blocks, media, blog and shortcodes
  • Admin dashboard with user, org, subscription, role, jobs and CMS management
  • OWASP security baseline: CSP, CSRF, rate limiting, input sanitization
  • Progressive Web App with offline support and push notifications
  • Docker / Coolify deployment configuration