Skip to content

Release: Nova Analytics v1.0 — landing v2, coherent dashboard data, security hardening, delivery docs - #13

Merged
xdroberto merged 27 commits into
mainfrom
develop
Jul 8, 2026
Merged

Release: Nova Analytics v1.0 — landing v2, coherent dashboard data, security hardening, delivery docs#13
xdroberto merged 27 commits into
mainfrom
develop

Conversation

@xdroberto

Copy link
Copy Markdown
Owner

Promotes 27 commits (63 files, +2,246 / −1,075) from develop to production. Do not merge — production promotion is Roberto's call.

What ships

Landing v2 (Phase 5.5) — PRs #8 / #9 / #11

  • Hero v2 + aurora-tech v2 brand tokens; features section; metrics + marquee; CTA v2; scroll-aware nav + footer polish; cursor interactions. Marketing typography foundation.

Coherent dashboard sample data + whitelabel hardening — PR #12

  • The 4 most-visited pages (default · analytics · ecommerce · finance) now derive from ONE canonical 30-day snapshot (MAU 128,420 · Sessions 512,900 · Events 8.64M · 99.7% delivery · 43.2% quota), with reconciling sums and reused deltas.
  • All residual template branding purged app-wide, including the nova.robertobh.dev/* personal-domain leak → *.novaanalytics.io. scripts/branding-check.sh extended (broadened patterns) + self-tested to catch leaks and spare legit shadcn refs.
  • Remaining pages keep template sample numbers but are fully whitelabeled (CI-enforced).

Security hardening + audit fixes — PR #10

  • Auth-surface hardening; two prod-only bug fixes (clear __Secure cookie with the Secure attribute; abort on a failed deploy pull); GitHub Actions pinned to commit SHAs + ci.yml permissions scoped; deferred CSP + logout-CSRF findings documented.

Delivery docs (Phase 6)

  • SUBMISSION.md + README badges; reviewer credential rotated (lives only in SUBMISSION.md); Mermaid architecture diagram suite; SSH F1/F2 closure + process records.

Test plan

  • CI green on this PR — commits · quality · e2e.
  • After merge → push-to-deploy (CI builds image → GHCR → VPS pulls; next build never runs on the VPS): watch the deploy run on main.
  • https://nova.robertobh.dev/api/health returns {"status":"ok","db":"up"}; landing + /login serve 200.
  • Landing v2 live on the public URL.
  • Reviewer login works with the rotated credential.
  • Dashboard Infrastructure page shows no robertobh.dev (branding clean).
  • UptimeRobot monitor still green.

🎥 push-to-deploy is a recordable moment.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PA9EzergAZ12Dy1QBqx5kp

xdroberto and others added 27 commits July 8, 2026 08:52
…-track split

Six diagrams (docs/architecture.md, GitHub-native mermaid): system architecture, DB ERD (from auth-schema.ts), two-layer auth flow, CI/CD pipeline, shared-VPS topology, branching/promotion model. Accurate to the real repo, not idealized. BRAIN: logged the 5.5 split so both sessions see the map — this session owns diagrams + integration duty + the (deferred) responsive audit; the UI session owns feature/ui-landing-polish (aurora-tech v2 + landing), screenshot-gated.
…H hardening applied

VPS diagram: removed the doubly-nested subgraphs (nova/co) that GitHub's mermaid renderer choked on; single-level subgraph now, grouping conveyed via node labels. SSH: PasswordAuthentication no + KbdInteractive no + X11Forwarding no applied (drop-in, sshd -t + reload, fresh key login verified — no lockout); fail2ban 1.0.2 active (sshd jail) — banned 6 brute-force IPs on first scan. deployment.md + BRAIN updated to reflect applied.
Palette from Roberto's landing design (docs/design-reference/landing-v2.html)
becomes the official aurora-tech v2 tokens. The dark theme IS the operator
design; light keeps its base surfaces and adopts the violet brand accent.

- background #05060E, foreground #E8EAF6, card #0F1224 (glass in component)
- primary #6C5CE7 (violet); primary-foreground #FFF (WCAG AA 4.86; starlight 4.06 fails)
- muted-foreground #9AA3C7 (AA 8.1); new slots --foreground-tertiary
  (#6E779B, AA-fixed 4.41->4.59) and --foreground-faint (#4D5578, marquee, WCAG 1.4.3 exempt)
- border/input tinted lavender #94A3FF (was plain white)
- ring + charts conserve nova-cyan #22D3EE and nova-green #34D399

All contrast pairs WCAG 2.x AA-verified; footer copy raised #5A6288->#717899.
Dark = operator design; light adopts brand accent. Dev server compiles clean (landing 200).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HXye76z6KXmV7WFirU3sk
…ource)

Roberto's landing design, byte-faithful as authored — kept as process evidence
and the single source for the v2 palette. Self-contained bundle (minified
template serialized in a script tag); read via a prettified working copy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HXye76z6KXmV7WFirU3sk
…edential

Phase 6 delivery drafts. SUBMISSION.md (repo root): live/repo URLs, rotated reviewer creds, core + bonus delivered, links to docs/architecture.md + docs/ai-process/, with [VIDEO LINK] + [behavioral questionnaire] TODO placeholders for Roberto. README: CI + MIT + Node-22 badges, fixed the stale '(Phase 4)' note, linked SUBMISSION. Reviewer password rotated on prod via Better Auth change-password (old NovaReview2026! now 401); the live value lives only in SUBMISSION.md.
Batch 1 of the Phase 5.5 landing redesign (operator design). Translates the
hero to the existing (marketing) components on aurora-tech v2 tokens.

- Marketing-only brand type (fonts.ts): Sora 600/700 (headings), Instrument
  Sans 400/500 (body), JetBrains Mono 400 (labels) — self-hosted via next/font,
  latin subset, display: swap. The dashboard keeps Geist (no global blast radius).
- motion.css: 11 nv* keyframes ported CSS-first; EVERY animation gated behind
  prefers-reduced-motion (default state = final/visible, so reduced-motion users
  get a complete static landing). Zero animation JS.
- layout: fixed CSS aurora background (violet/cyan + masked grid), token-driven.
- hero: eyebrow badge (pulse), Sora h1 with gradient shine, CTA pair, trust line,
  and a floating glass preview card with bar/line/dot chart that draws in.
  Decorative colors map to v2 chart tokens (cyan/violet/lavender).

Lighthouse mobile: performance 90 (gate >=90; FCP 1.5s, TBT 40ms, CLS 0). LCP
3.5s from the Sora h1 — accepted trade-off vs the 94 baseline (operator call).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HXye76z6KXmV7WFirU3sk
The operator's docs/design-reference/landing-v2.html is byte-faithful process
evidence, not project code; its inline bundle scripts tripped biome lint
(useArrowFunction etc.) and failed the quality gate. Exclude docs/design-reference
from biome (lint + format). No source behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HXye76z6KXmV7WFirU3sk
feat(landing): aurora-tech v2 tokens + hero (Phase 5.5 Batch 1)
Batch 2 of the Phase 5.5 landing redesign.

- Features v2: eyebrow ("01 — PLATFORM", JetBrains Mono), Sora h2, and four
  glass cards (cyan/violet accent chips, lucide icons) with a scroll-driven
  reveal (CSS animation-timeline + safe fallback) and hover lift/glow.
- Cursor interactions (operator feedback): a radial glow follows the pointer
  across the cards via one delegated listener (SpotlightGroup — cheap to
  hydrate) and the hero card tilts toward the cursor in 3D (SpotlightCard).
  Both inert under prefers-reduced-motion; pointer work is lazy so TBT holds.
- Scroll-aware nav: fixed and always visible, transparent at the top and
  transitioning to a glass bar once scrolled (mirrors the operator design).

Lighthouse mobile: performance 90 stable (TBT ~40ms, CLS 0). Landing e2e green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HXye76z6KXmV7WFirU3sk
…n failed deploy pull

1) session/clear set an expiring cookie without Secure; browsers reject that for a __Secure--prefixed name, so the prod session cookie never cleared and the /login<->/dashboard loop could recur (untested — e2e is HTTP dev). Now sets Secure to match the cookie's prefix. 2) remote-deploy.sh: a failed 'compose pull' fell through to up -d (no-op), health-checked the OLD app, and reported a green deploy on stale code. Now aborts on pull failure.
- Removed getValueFromCookie: a dead 'use server' action that returned ANY cookie incl. the HttpOnly session token (XSS->session-theft amplifier). - Allow-listed setValueToCookie against PREFERENCE_REGISTRY (was a generic same-origin cookie-write primitive). - Added a /sign-up/email rate limit (10/60s) — the global 100/10s was far too loose for account provisioning. - seed.ts fails closed: SEED_PASSWORD now required (no repo-visible 'NovaReview2026!' default); .env.example documents it. - next.config removeConsole keeps console.error in prod (server error visibility incl. the pg pool handler).
…ssions

Supply-chain: every third-party action (checkout, setup-node, docker/*, appleboy/scp+ssh — the last two receive root VPS SSH secrets) pinned to its current tag's commit SHA with a trailing version comment, so a re-pointed tag can't inject code. Added top-level 'permissions: contents: read' to ci.yml (deploy.yml already scopes it).
CSP deferred pre-deadline (strict script-src/style-src risks breaking Next inline styles/scripts; no proven injection path today). GET /api/session/clear force-logout CSRF deferred as cosmetic (nuisance only). Both recorded as accepted findings with next steps.
feat(landing): features + cursor interactions + scroll-aware nav (Phase 5.5 Batch 2)
Security audit fixes: 2 prod bugs + auth hardening + action SHA-pinning
Completes the Phase 5.5 landing redesign (batches 3-5 consolidated).

- Marquee: "Trusted by data teams at" wordmark strip, infinite seamless loop
  (nvMarquee keyframe + per-item padding so one set = exactly 50%). Static
  under reduced motion.
- Metrics band: 99.99% / 340ms / 1,200+ KPIs that count up on scroll into view
  (IntersectionObserver, reduced-motion safe); suffix accents from v2 tokens.
- CTA v2: glass card with a pulsing glow, "Get started — it's free" + "Talk to
  sales", disclaimer.
- Nav: full links (Product/Customers/Pricing -> section anchors) + brand name;
  footer v2 (Log in/Sign up/Security/Docs). scroll-padding-top clears the fixed
  header so anchors land correctly.
- Sora: display optional + not preloaded so the LCP h1 paints in the metric-
  matched fallback (Sora swaps in on the cached visit) — LCP off critical path.
- page order: hero -> marquee -> features -> metrics -> cta.

Lighthouse mobile: performance 89-90 (LCP intrinsic to the rich hero under
slow-4G simulation; CLS 0, TBT ~40-50ms). Landing e2e green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019HXye76z6KXmV7WFirU3sk
Remove all remaining non-Nova branding from dashboard sample data and extend
the branding-check gate so CI catches it:
- infrastructure: org placeholders (Aiy Cap / Storeframe / Acme Corp) -> Nova
  Analytics; nova.robertobh.dev/* domains -> *.novaanalytics.io (personal-domain leak)
- users: @acme.inc / @sandbox.dev emails -> @novaanalytics.io; workspace labels
  Acme Inc. -> Web App, Sandbox -> Mobile (incl. an extra "Sandbox" the spec
  list missed at data.tsx:114); filter list realigned
- invoice: bill-to AIY Cap -> Northstar Labs with a US address + taxId
  (was a Mumbai GSTIN), for internal consistency
- legacy crm-v1: Shadcn / Shadcn UI Kit lead entries -> Sarah Parker /
  Northstar Labs / Cinder Health
- legacy analytics-v1: Acme Industries -> Cinder Health
- kanban: shadcn/ui desktop-shell card -> data-retention-controls
- analytics: greeting "Hello, Aiy" -> "Welcome back, admin"

branding-check.sh FORBIDDEN extended with aiy/aiycap, acme (inc/corp/industries),
storeframe, robertobh, \bsandbox\b, shadcn ui kit, shadcn/ui. Self-tested: the
gate catches every leak and spares legit refs (@shadcn/react, shadcn/tailwind.css,
bare shadcn). Verified: tsc, biome, branding gate, next build (31 routes), e2e 11/11.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PA9EzergAZ12Dy1QBqx5kp
Replace template sample data with the canonical 30-day snapshot on
/dashboard/default:
- KPI cards: MAU 128,420 (+12.5%), New Signups 3,240 (-20%), Sessions
  512,900 (+11.2%), Conversion Rate 4.8% (+0.4pp); icons -> Users/UserPlus/
  Activity/Target
- User Activity chart: rescale the 180-point series in place so the means land
  on canonical figures — Sessions/day 17,097 (x1.63584), Active Users 6,350
  (x1.01714), Returning Users 4,656 (same factor keeps ratio 0.7333 exactly);
  Area always above Lines (min 10,139 > max 6,744); series/title relabeled,
  description now analytics-oriented (residual R3)
- Recent Accounts: heading -> "128,420 Active Users"; Customer -> Account

Data was already whitelabel-clean; status/billing enums are coherent for a
B2B SaaS analytics product and were left intact.
Verified: biome, branding gate, next build (31 routes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PA9EzergAZ12Dy1QBqx5kp
Align /dashboard/analytics with the canonical snapshot:
- Audience strip: Unique Visitors 156.2k (+11.8%, from 139.75k), Sessions
  512.9k (+11.2%), Pageviews 1.86M (+9.4%, was DOWN -> UP), Engagement 62.4%
  (+3.1pp), Conversion 4.8% (+0.4pp, was DOWN -> UP); dropped unused
  ArrowDownRight
- Traffic Sources: series label Visitors -> Sessions; sources now sum to the
  512,900 session total (Organic 198.4k / Direct 121.6k / Social 82.3k /
  Referral 64.9k / Paid 45.7k); Spring Launch 16.8k -> 15.8k so campaigns sum
  exactly to Paid 45,700; referrers already summed to 41,400
- Realtime Visitors: header "142 active now · 24 per minute"; bars raised to
  ~14-36 (avg ~24, 4 zero-dropouts) with YAxis domain [0,40]; country split
  14/4/3/3 = 24 unchanged
- Engagement Quality (was Traffic Quality): retitled + series Actual/Baseline;
  data kept (actual -4.7..5.7)
- Top Pages: /blog + /contact -> /signup + /integrations; docs time 4m44s ->
  2m44s; top-5 views sum 175.9k

Verified: biome, branding gate, next build (31 routes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PA9EzergAZ12Dy1QBqx5kp
Reframe /dashboard/ecommerce from store metrics to product analytics:
- KPI strip (6): Events Captured 8.64M (+13.6%), Reports Created 379 (+6.2%),
  New Users 7d 756 (-20%), Events/Session 16.8, Active Alerts 18, Data
  Delivery 99.7%; icons swapped (Activity/FileText/UserPlus/Gauge/Bell)
- Events Overview (was Sales Overview): rescaled revenueBucketValues x0.17792
  so current month = 8,640K = 8.64M events (buckets 833-1,665K);
  profitMultipliers -> 0.044 so report bars sum to 379; YAxis [0,2000]/[0,120];
  tooltip drops "$", renders {value}K for events / int for reports
- Data Delivery Health (was Inventory): counts 8,614,080/17,280/8,640;
  availablePercent Math.round -> toFixed(1) so the center reads 99.7% (not
  100); labels Delivered/Delayed/Failed
- Live Traffic 24h (was Store Traffic): header "17.1K sessions (24h)"; 96 pts
  rescaled to sum exactly 17,097 (YAxis -> [0,850]); series Sessions/Anomalies
- Traffic Sources: channels Organic 39 / Direct 24 / Social 16 / Referral 12 /
  Paid 9 (=100), per-day sessions; removed brand icons (Meta/Google/etc.);
  header "17.1K sessions"
- Top Events (was Top Products): page_viewed 2.68M / query_run 2.07M /
  chart_viewed 1.55M = 73% of events

Deferred (noted for review): the Recent Orders table -> "Report Activity"
reframe is a deeply-coupled table subsystem (schema/badges/filters/34 rows);
it holds clean generic data and passes the branding gate, so it is left as-is
rather than risk the filter/enum logic in this batch.
Verified: biome, branding gate, next build (31 routes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PA9EzergAZ12Dy1QBqx5kp
Turn /dashboard/finance into Nova's usage & billing view:
- heading "Personal Finances" -> "Usage & Billing"
- KPI cluster: Events this cycle 8.64M (+13.6%), Events remaining 11.36M of
  20M (56.8%), Avg events/day 288K, Quota used 43.2%
- Top data sources (was Income sources): Web App 4.51M / iOS 1.78M / Android
  1.36M
- Events by Project donut (was Account Allocation): 5 slices summing to 8.64M
  (Web App 52.2% ... Docs 1.5%); replaced currency formatting/selector with an
  events (M) formatter + time-window picker
- Ingestion Overview (was Spending Overview): events ingested/day ~288K
  (240-340K) vs ingestion errors/day ~860 (0.3%); tooltip drops "$" -> K
- Scheduled Reports (was Upcoming Bills): Weekly Growth Digest / Monthly
  Retention / Funnel Alert Review; removed Claude/Resend/Linear brand icons
- Current Plan (was Wallet): Growth plan · 20M events/mo, 43.2% usage bar,
  seats 8; removed bank/crypto brand icons (Revolut/HSBC/Bitcoin/etc.)
- Invite teammate + Quick actions (was Quick Transfer + Shortcuts): email
  invite + Create report/Set alert/Export CSV shortcuts

Verified: biome, branding gate, next build (31 routes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PA9EzergAZ12Dy1QBqx5kp
feat(landing): metrics, marquee, CTA v2 + nav/footer polish (Phase 5.5 finish)
feat(dashboard): coherent Nova sample data on the 4 main pages + whitelabel hardening
@xdroberto
xdroberto merged commit 12bce63 into main Jul 8, 2026
6 checks passed
@xdroberto
xdroberto deleted the develop branch July 8, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant