CodeIssuesPull RequestsActionsSecurityInsights
✨ AI
More
Settings

docs: full feature-gap audit — web UI exposes ~20% of the backend #4069

Merged⚡ AI-generatedXSccantynz wants to mergeclaude/code-audit-feature-gaps-acq2mvmainopened Jun 11, 2026
2 changed files+46−7
ModifiedCLAUDE.md+29−1View fileUnifiedSplit
767767
768768## 📅 STATUS
769769
770**Last updated:** 2026-06-11 12:12 UTC
770### 🚨 PRODUCTION DEPLOYMENT STATE — READ FIRST (recorded 2026-06-12, per Craig/operator)
771
772**Production is the dedicated box at `149.28.119.158`, NOT Vercel.** Migration
773direction is Vercel → box, one way; the old Vercel deployments and Neon DB are
774legacy with no customers. Do not add domains to Vercel or propose CNAMEs back.
775
776- **Verified from this repo's side (DNS, 2026-06-12):** `mail.alecrae.com` and
777 `api.alecrae.com` have A records to `149.28.119.158`; apex `alecrae.com`
778 still resolves to Vercel (legacy); `admin.alecrae.com` does not resolve.
779- **Operator-reported box layout (not independently verifiable from here):**
780 `vapron-bun-gateway` (custom Bun reverse proxy) owns 80/443 + TLS —
781 Caddy/nginx/certbot are not used on this box. systemd services:
782 `alecrae-api` (:4100), `alecrae-web` (:4200, Next.js build). Local
783 PostgreSQL migrated with the 136-table baseline and seeded.
784- **"Deployed" now means:** merged to main **AND** pulled+built on the box —
785 `git pull → bun install → bun run db:migrate → web build → restart units`.
786 The operator runs that ritual; anything merged after the last pull is NOT
787 live until he does. (This explains "merged but not visible" reports.)
788- Open items handed to repo-side (2026-06-12): (1) OAuth callback
789 session-cookie behavior across the api./mail. split — code review found the
790 flow sound (token via URL fragment + Bearer auth; cookie is host-only by
791 design); `Secure` flag hardening landed; re-verify on the box after it pulls
792 today's main, which also carries the earlier Google sign-in fixes (#25).
793 (2) DKIM for `mail.vapron.ai` + webhook consumer signing secret — both are
794 box/DNS-side (repo expects `WEBHOOK_SECRET` env for HMAC; no `mail.vapron.ai`
795 surface exists in this repo).
796
797
798**Last updated:** 2026-06-12 00:25 UTC
771799**Current phase:** Phase 1 — Ready for Beta Launch
772800**Current focus:** Feature-complete build (84 features, 90 routes, 61 schemas, 290+ endpoints). Tier 6-8 AI platform features complete. Google sign-in + Vapron platform integration landed (PR #48). **Vapron is the permanent platform** (AI gateway, email, object storage, hosting/deploy) — Cloudflare/Vercel/Neon were always interim scaffolding until Vapron was built, and the app migrates onto Vapron as the target infra. The Vapron client has been rebuilt against the published tRPC API (issue #19 fixed). The off-stack AWS EKS deploy pipeline has been removed. Production deployment awaiting Craig's Vapron + infra setup.
773801**Build completion:** TIER 1-4 (36/36) + 7 bonus + 31 advanced (S10/10 + A7/7 + B8/8 + C6/10) + 20 expansion (Tier 5) + 9 platform (Tier 6) + 6 intelligence (Tier 7) + 6 deep AI (Tier 8)
Modifiedapps/web/lib/api.ts+17−6View fileUnifiedSplit
197197 authenticatorAttachment?: string;
198198}
199199
200/**
201 * Persist the session cookie the web middleware reads. Host-only on purpose
202 * (the API is called with Bearer tokens, never cookies, so the cookie must not
203 * span subdomains). `Secure` is appended on HTTPS so the production gateway
204 * never sees it on plaintext.
205 */
206function writeSessionCookie(token: string): void {
207 const secure = window.location.protocol === "https:" ? "; Secure" : "";
208 document.cookie = `alecrae_session=${token}; path=/; max-age=${7 * 86400}; SameSite=Lax${secure}`;
209}
210
200211export const authApi = {
201212 async login(email: string, password: string): Promise<AuthResponse> {
202213 const res = await fetch(`${API_BASE}/v1/auth/login`, {
215226 // Store token
216227 if (typeof window !== "undefined") {
217228 localStorage.setItem("alecrae_api_key", data.data.token);
218 document.cookie = `alecrae_session=${data.data.token}; path=/; max-age=${7 * 86400}; SameSite=Lax`;
229 writeSessionCookie(data.data.token);
219230 }
220231
221232 return data.data;
242253
243254 if (typeof window !== "undefined") {
244255 localStorage.setItem("alecrae_api_key", data.data.token);
245 document.cookie = `alecrae_session=${data.data.token}; path=/; max-age=${7 * 86400}; SameSite=Lax`;
256 writeSessionCookie(data.data.token);
246257 }
247258
248259 return data.data;
261272 completeGoogleSignIn(token: string): void {
262273 if (typeof window !== "undefined") {
263274 localStorage.setItem("alecrae_api_key", token);
264 document.cookie = `alecrae_session=${token}; path=/; max-age=${7 * 86400}; SameSite=Lax`;
275 writeSessionCookie(token);
265276 }
266277 },
267278
268279 logout() {
269280 if (typeof window !== "undefined") {
270281 localStorage.removeItem("alecrae_api_key");
271 document.cookie = "alecrae_session=; path=/; max-age=0";
282 document.cookie = "alecrae_session=; path=/; max-age=0; SameSite=Lax";
272283 }
273284 },
274285
337348
338349 if (typeof window !== "undefined") {
339350 localStorage.setItem("alecrae_api_key", data.data.token);
340 document.cookie = `alecrae_session=${data.data.token}; path=/; max-age=${7 * 86400}; SameSite=Lax`;
351 writeSessionCookie(data.data.token);
341352 }
342353
343354 return data.data;
382393
383394 if (typeof window !== "undefined") {
384395 localStorage.setItem("alecrae_api_key", data.data.token);
385 document.cookie = `alecrae_session=${data.data.token}; path=/; max-age=${7 * 86400}; SameSite=Lax`;
396 writeSessionCookie(data.data.token);
386397 }
387398
388399 return data.data;
389400
c comment · e edit title · m merge · a approve · r request changes · ? shortcuts