feat(web): add privacy/terms/api-docs/app/login routes; noindex prototype - #204
Conversation
… /prototype Resolves 404s on /privacy, /terms, /api/docs, /app, /login and ensures /prototype carries a noindex robots tag. Scope is intentionally narrow and does not overlap PR #202 (assets, robots, sitemap, JSON-LD, a11y). - /privacy, /terms: server-rendered legal placeholder pages with proper metadata, canonical URLs, and footer links. Plain-language, startup- friendly; will be replaced before enterprise contracts. - /api/docs: human-readable reference matching the documentation pointer returned by /api JSON. Lists actual /api/* routes that exist in code. - /app, /login: server redirects to /dashboard, marked noindex. UVAI has no auth gate today, so this matches actual product behavior. - /prototype: adds a route layout with robots.index=false because the underlying page is an internal prototype spec, not a public surface. - LandingFooter: surfaces Privacy and Terms links now that the pages exist. Build: next build succeeds, 25 routes generated. Type-check and ESLint clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR adds essential public-facing pages to the web application: privacy and terms of service policies, an API documentation reference page, server-side redirects for app and login routes, footer navigation links, and a prototype section layout. ChangesPublic Pages and Navigation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces several static and legal pages to the web application, including the API Reference, Privacy Policy, and Terms of Service, along with redirect pages for /app and /login to the dashboard. The feedback suggests clarifying that the playground exercises backend API v1 endpoints rather than the frontend API endpoints, and adding explicit return null; statements after redirect() calls in the redirect components to prevent potential TypeScript compiler warnings.
| <p className="mt-2 text-ink/60"> | ||
| The{' '} | ||
| <Link href="/playground" className="text-teal-400 hover:underline"> | ||
| playground | ||
| </Link>{' '} | ||
| exercises these endpoints end-to-end against a real YouTube URL. | ||
| </p> |
There was a problem hiding this comment.
The playground page actually exercises the backend API v1 endpoints (e.g., /api/v1/transcript-action, /api/v1/chat) rather than the Next.js frontend /api/* endpoints documented on this page. Stating that the playground "exercises these endpoints" is inaccurate and could confuse developers. Please clarify the copy to specify that it exercises the backend API v1 endpoints.
| <p className="mt-2 text-ink/60"> | |
| The{' '} | |
| <Link href="/playground" className="text-teal-400 hover:underline"> | |
| playground | |
| </Link>{' '} | |
| exercises these endpoints end-to-end against a real YouTube URL. | |
| </p> | |
| <p className="mt-2 text-ink/60"> | |
| The{' '} | |
| <Link href="/playground" className="text-teal-400 hover:underline"> | |
| playground | |
| </Link>{' '} | |
| exercises the backend API v1 endpoints end-to-end against a real YouTube URL. | |
| </p> |
| export default function AppRedirect() { | ||
| redirect('/dashboard'); | ||
| } |
There was a problem hiding this comment.
In strict TypeScript environments, a React component is expected to return a valid React element, null, or undefined. Since redirect() throws an error to trigger the redirect and technically returns never, adding an explicit return null; prevents any potential TypeScript compiler or linter warnings about a component returning void or missing a return statement.
| export default function AppRedirect() { | |
| redirect('/dashboard'); | |
| } | |
| export default function AppRedirect() { | |
| redirect('/dashboard'); | |
| return null; | |
| } |
|
|
||
| export default function LoginRedirect() { | ||
| redirect('/dashboard'); |
There was a problem hiding this comment.
In strict TypeScript environments, a React component is expected to return a valid React element, null, or undefined. Since redirect() throws an error to trigger the redirect and technically returns never, adding an explicit return null; prevents any potential TypeScript compiler or linter warnings about a component returning void or missing a return statement.
| export default function LoginRedirect() { | |
| redirect('/dashboard'); | |
| export default function LoginRedirect() { | |
| redirect('/dashboard'); | |
| return null; | |
| } |
🔴 E2E Test Results: FAILURE DETECTED
Test Output |
There was a problem hiding this comment.
Pull request overview
This PR adds missing public web routes for legal, API documentation, and redirect surfaces while marking the prototype route as non-indexable.
Changes:
- Adds
/privacy,/terms, and/api/docspages with route metadata. - Adds
/appand/loginserver redirects to/dashboard. - Adds noindex metadata for
/prototypeand links legal pages from the landing footer.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
apps/web/src/app/privacy/page.tsx |
Adds Privacy Policy page and metadata. |
apps/web/src/app/terms/page.tsx |
Adds Terms of Service page and metadata. |
apps/web/src/app/api/docs/page.tsx |
Adds human-readable API reference page. |
apps/web/src/app/app/page.tsx |
Adds /app redirect to dashboard. |
apps/web/src/app/login/page.tsx |
Adds /login redirect to dashboard. |
apps/web/src/app/prototype/layout.tsx |
Adds noindex metadata for prototype route. |
apps/web/src/components/landing/LandingFooter.tsx |
Adds Privacy and Terms links to landing footer. |
| title: 'Privacy Policy', | ||
| description: | ||
| 'How UVAI (EventRelay) collects, processes, and protects data when you analyze YouTube videos and use our AI pipelines.', | ||
| alternates: { canonical: '/privacy' }, |
| title: 'Terms of Service', | ||
| description: | ||
| 'Terms governing use of the UVAI hosted product. EventRelay is MIT-licensed and may be self-hosted at any time.', | ||
| alternates: { canonical: '/terms' }, |
| title: 'API Reference', | ||
| description: | ||
| 'HTTP reference for the UVAI / EventRelay public API: transcription, event extraction, agent pipelines, and video metadata.', | ||
| alternates: { canonical: '/api/docs' }, |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/src/app/api/docs/page.tsx`:
- Around line 21-36: The ENDPOINTS array lacks request body examples for most
POST routes which reduces docs usefulness; update the ENDPOINTS constant to
include a concise "body" string for each POST entry (e.g., for
'/api/extract-events', '/api/pipeline', '/api/pipeline/stream', '/api/chat',
'/api/video', '/api/dashboard', '/api/training/trigger') that shows the expected
JSON shape (e.g., keys like url, transcript, pipelineOptions, chatMessage,
videoMetadata, action, jobParams as appropriate) so the docs render example
request payloads alongside existing summaries.
- Around line 21-36: The ENDPOINTS array documents 14 API paths but only 11
Next.js route handlers exist and most POST entries lack request body examples;
update the docs by reconciling ENDPOINTS with actual handlers and adding missing
POST body examples: inspect the ENDPOINTS constant in
apps/web/src/app/api/docs/page.tsx, remove or correct any entries that don't
have corresponding route.ts modules (or add the missing route modules if
intended), and add representative JSON "body" strings for /api/extract-events,
/api/pipeline, /api/pipeline/stream, /api/chat, /api/video, /api/dashboard, and
/api/training/trigger so each POST entry includes a sample payload similar to
the existing /api/transcribe example.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ea117163-fe66-4641-bc23-71ca37c8ab8c
📒 Files selected for processing (7)
apps/web/src/app/api/docs/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/login/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/terms/page.tsxapps/web/src/components/landing/LandingFooter.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: copilot-pull-request-reviewer
- GitHub Check: E2E Pipeline Tests
- GitHub Check: trivy
- GitHub Check: Analyze (javascript)
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{py,js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{py,js,jsx,ts,tsx}: Use Python 3.9+ and Node 18+ for development
Never hardcode API keys, database URLs, or secrets in code
Make minimal, surgical changes and avoid deleting working code unless fixing security issues
Files:
apps/web/src/components/landing/LandingFooter.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/login/page.tsxapps/web/src/app/terms/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/api/docs/page.tsx
**/*.{py,js,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Maintain >80% code coverage for new features
Files:
apps/web/src/components/landing/LandingFooter.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/login/page.tsxapps/web/src/app/terms/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/api/docs/page.tsx
**/*.{py,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{py,ts,tsx}: Keep frontend and backend data models synchronized using matching Pydantic (backend) and TypeScript (frontend) interfaces
Use type-safe interfaces for backend-frontend data exchange
Files:
apps/web/src/components/landing/LandingFooter.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/login/page.tsxapps/web/src/app/terms/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/api/docs/page.tsx
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use strict mode TypeScript with strict mode enabled in apps/web/tsconfig.json
Use Tailwind CSS for styling in the frontend
Never use dangerouslySetInnerHTML in React components
apps/web/**/*.{ts,tsx}: Use TypeScript strict mode in tsconfig.json for frontend code
Use ESLint with Next.js rules via shared config from packages/eslint-config/
Use path alias@/* to reference src/* directory in frontend code
Never use dangerouslySetInnerHTML in React/TypeScript code
Use NextAuth.js for authentication in the frontend
Files:
apps/web/src/components/landing/LandingFooter.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/login/page.tsxapps/web/src/app/terms/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/api/docs/page.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with Next.js rules from shared config in packages/eslint-config/
Files:
apps/web/src/components/landing/LandingFooter.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/login/page.tsxapps/web/src/app/terms/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/api/docs/page.tsx
apps/web/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use path alias
@/* mapping to src/* in TypeScript/JavaScript frontend code
Files:
apps/web/src/components/landing/LandingFooter.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/login/page.tsxapps/web/src/app/terms/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/api/docs/page.tsx
apps/web/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (GEMINI.md)
Use Tailwind CSS for styling in the frontend
Files:
apps/web/src/components/landing/LandingFooter.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/login/page.tsxapps/web/src/app/terms/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/api/docs/page.tsx
apps/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (GEMINI.md)
Use Turbo for building, developing, linting, and testing JavaScript workspaces (apps/, packages/, mcp-servers/*)
Files:
apps/web/src/components/landing/LandingFooter.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/login/page.tsxapps/web/src/app/terms/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/api/docs/page.tsx
**/*.tsx
⚙️ CodeRabbit configuration file
React components in Next.js 16. Check for proper use of 'use client' directives, hook dependency arrays, memory leaks in useEffect, and accessibility issues. Flag any TODO or placeholder UI components that are not production-ready.
Files:
apps/web/src/components/landing/LandingFooter.tsxapps/web/src/app/prototype/layout.tsxapps/web/src/app/login/page.tsxapps/web/src/app/terms/page.tsxapps/web/src/app/app/page.tsxapps/web/src/app/privacy/page.tsxapps/web/src/app/api/docs/page.tsx
apps/web/src/app/api/**
⚙️ CodeRabbit configuration file
Next.js API routes including SSE streaming endpoints. Critical path — check for stream lifecycle issues, controller.close() always being called, and fire-and-forget patterns for non-blocking post-processing. This was the source of a production 95% hang bug (issue
#139).
Files:
apps/web/src/app/api/docs/page.tsx
🧬 Code graph analysis (6)
apps/web/src/app/prototype/layout.tsx (5)
apps/web/src/app/api/docs/page.tsx (1)
metadata(6-12)apps/web/src/app/app/page.tsx (1)
metadata(4-9)apps/web/src/app/login/page.tsx (1)
metadata(4-10)apps/web/src/app/privacy/page.tsx (1)
metadata(7-13)apps/web/src/app/terms/page.tsx (1)
metadata(7-13)
apps/web/src/app/login/page.tsx (1)
apps/web/src/app/app/page.tsx (1)
metadata(4-9)
apps/web/src/app/terms/page.tsx (1)
apps/web/src/app/privacy/page.tsx (1)
metadata(7-13)
apps/web/src/app/app/page.tsx (1)
apps/web/src/app/login/page.tsx (1)
metadata(4-10)
apps/web/src/app/privacy/page.tsx (1)
apps/web/src/app/terms/page.tsx (1)
metadata(7-13)
apps/web/src/app/api/docs/page.tsx (5)
apps/web/src/app/app/page.tsx (1)
metadata(4-9)apps/web/src/app/login/page.tsx (1)
metadata(4-10)apps/web/src/app/privacy/page.tsx (1)
metadata(7-13)apps/web/src/app/prototype/layout.tsx (1)
metadata(3-8)apps/web/src/app/terms/page.tsx (1)
metadata(7-13)
🔇 Additional comments (10)
apps/web/src/app/privacy/page.tsx (1)
1-115: LGTM!apps/web/src/app/terms/page.tsx (1)
1-101: LGTM!apps/web/src/app/app/page.tsx (1)
1-13: LGTM!apps/web/src/app/login/page.tsx (1)
1-14: LGTM!apps/web/src/app/prototype/layout.tsx (1)
1-12: LGTM!apps/web/src/components/landing/LandingFooter.tsx (1)
55-60: LGTM!apps/web/src/app/api/docs/page.tsx (4)
1-4: LGTM!
6-12: LGTM!
14-19: LGTM!
38-114: LGTM!
| const ENDPOINTS: Endpoint[] = [ | ||
| { method: 'GET', path: '/api', summary: 'Service descriptor (name, version, status).' }, | ||
| { method: 'POST', path: '/api/transcribe', summary: 'Fetch a transcript for a YouTube URL.', body: '{ "url": "https://youtu.be/..." }' }, | ||
| { method: 'POST', path: '/api/extract-events', summary: 'Extract typed events from a transcript.' }, | ||
| { method: 'GET', path: '/api/pipeline', summary: 'Inspect available pipeline stages.' }, | ||
| { method: 'POST', path: '/api/pipeline', summary: 'Run the full intake → events → agents pipeline.' }, | ||
| { method: 'POST', path: '/api/pipeline/stream', summary: 'Streaming variant of /api/pipeline (SSE).' }, | ||
| { method: 'POST', path: '/api/chat', summary: 'Conversational query over an analyzed video.' }, | ||
| { method: 'GET', path: '/api/video', summary: 'List recently analyzed videos.' }, | ||
| { method: 'POST', path: '/api/video', summary: 'Register a new video for analysis.' }, | ||
| { method: 'GET', path: '/api/video/search', summary: 'Semantic search across stored videos.' }, | ||
| { method: 'GET', path: '/api/dashboard', summary: 'Dashboard aggregates and recent runs.' }, | ||
| { method: 'POST', path: '/api/dashboard', summary: 'Mutate dashboard state (pin, archive, etc.).' }, | ||
| { method: 'GET', path: '/api/training/status', summary: 'Current status of training/embedding jobs.' }, | ||
| { method: 'POST', path: '/api/training/trigger', summary: 'Trigger a training/embedding job.' }, | ||
| ]; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
Consider adding request body examples for POST endpoints.
Only /api/transcribe (line 23) shows a request body example. Adding examples for the other POST endpoints would improve documentation usability:
/api/extract-events(line 24)/api/pipeline(line 26)/api/pipeline/stream(line 27)/api/chat(line 28)/api/video(line 30)/api/dashboard(line 33)/api/training/trigger(line 35)
While the playground provides interactive testing, reference docs are more useful when they show expected request structures.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/app/api/docs/page.tsx` around lines 21 - 36, The ENDPOINTS array
lacks request body examples for most POST routes which reduces docs usefulness;
update the ENDPOINTS constant to include a concise "body" string for each POST
entry (e.g., for '/api/extract-events', '/api/pipeline', '/api/pipeline/stream',
'/api/chat', '/api/video', '/api/dashboard', '/api/training/trigger') that shows
the expected JSON shape (e.g., keys like url, transcript, pipelineOptions,
chatMessage, videoMetadata, action, jobParams as appropriate) so the docs render
example request payloads alongside existing summaries.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify that documented API endpoints have corresponding route handlers
echo "Searching for API route handlers..."
echo ""
# List of paths to verify (removing /api prefix and parameters)
routes=(
"route.ts" # /api → apps/web/src/app/api/route.ts
"transcribe/route.ts"
"extract-events/route.ts"
"pipeline/route.ts"
"pipeline/stream/route.ts"
"chat/route.ts"
"video/route.ts"
"video/search/route.ts"
"dashboard/route.ts"
"training/status/route.ts"
"training/trigger/route.ts"
)
cd apps/web/src/app/api 2>/dev/null || { echo "Error: apps/web/src/app/api directory not found"; exit 1; }
missing=0
for route in "${routes[@]}"; do
if [[ -f "$route" ]]; then
echo "✓ Found: api/$route"
else
echo "✗ Missing: api/$route"
((missing++))
fi
done
echo ""
echo "Summary: $missing route(s) missing out of ${`#routes`[@]} documented endpoints"
exit $missingRepository: groupthinking/EventRelay
Length of output: 525
API docs: documented /api routes have matching Next.js handlers
The 11 expected apps/web/src/app/api/**/route.ts files exist for the 14 documented endpoints, so the docs shouldn’t point to non-existent route modules.
Documentation gap: add body examples to these POST endpoints (only /api/transcribe currently has one in the snippet): /api/extract-events, /api/pipeline, /api/pipeline/stream, /api/chat, /api/video, /api/dashboard, /api/training/trigger.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/app/api/docs/page.tsx` around lines 21 - 36, The ENDPOINTS array
documents 14 API paths but only 11 Next.js route handlers exist and most POST
entries lack request body examples; update the docs by reconciling ENDPOINTS
with actual handlers and adding missing POST body examples: inspect the
ENDPOINTS constant in apps/web/src/app/api/docs/page.tsx, remove or correct any
entries that don't have corresponding route.ts modules (or add the missing route
modules if intended), and add representative JSON "body" strings for
/api/extract-events, /api/pipeline, /api/pipeline/stream, /api/chat, /api/video,
/api/dashboard, and /api/training/trigger so each POST entry includes a sample
payload similar to the existing /api/transcribe example.
* chore: trigger uvai.io production deploy * feat: UVAI UI/UX full refactor — features page, pricing, Nav, LandingNav (#205) Zero emoji, real product mockups per feature section, SVG icons everywhere, LandingNav with proper cross-page routing and active states. Co-authored-by: v0[bot] <v0[bot]@users.noreply.github.com> * test: improve test coverage, fix Vercel build, dashboard auto-select, E2E resilience (#206) - 155 new unit tests (middleware, API models, error handling) - Fix Vercel ERESOLVE build failure via .npmrc legacy-peer-deps - Fix dashboard ?video= URL param auto-select (issue #159) - Fix next.config.js duplicate redirects/headers - Fix CI test dependency installation for Python 3.12 - Make SSE stream always emit terminal pipeline_status event - Make E2E tests resilient to live server degraded mode - Replace banned dQw4w9WgXcQ video ID with auJzb1D-fag throughout * fix: remove hardcoded Grok API key (#194) 🎯 What: Removed the hardcoded fallback value for the GROK_API_KEY in TriModelConsensusTool.⚠️ Risk: Hardcoded API keys in source code can be exploited if the codebase is exposed or leaked, leading to unauthorized API access, quota exhaustion, and potential financial loss. 🛡️ Solution: Removed the hardcoded string so the tool relies strictly on the environment variable, aligning with secure configuration management practices. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> * feat(web): add privacy/terms/api-docs/app/login routes; noindex prototype pages (#204) Resolves 404s on /privacy, /terms, /api/docs, /app, /login and ensures /prototype carries a noindex robots tag. Scope is intentionally narrow and does not overlap PR #202 (assets, robots, sitemap, JSON-LD, a11y). - /privacy, /terms: server-rendered legal placeholder pages with proper metadata, canonical URLs, and footer links. Plain-language, startup- friendly; will be replaced before enterprise contracts. - /api/docs: human-readable reference matching the documentation pointer returned by /api JSON. Lists actual /api/* routes that exist in code. - /app, /login: server redirects to /dashboard, marked noindex. UVAI has no auth gate today, so this matches actual product behavior. - /prototype: adds a route layout with robots.index=false because the underlying page is an internal prototype spec, not a public surface. - LandingFooter: surfaces Privacy and Terms links now that the pages exist. Build: next build succeeds, 25 routes generated. Type-check and ESLint clean. Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * test: add unit tests for DatabaseOptimizer._calculate_performance_grade (#182) Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> * fix(security): SECRET_KEY, CORS wildcard, SQL injection, command injection (#207) Resolves conflicts manually — the conflicting hunks were all in tests/e2e/pipeline.test.ts and .github/workflows/e2e-tests.yml which were already fixed better in #206. The security-relevant changes are applied cleanly: - code_generator.py (#193): replace hardcoded SECRET_KEY with os.getenv/secrets.token_urlsafe - code_generator.py (#195): restrict CORS allow_origins from ["*"] to localhost origins - real_api_endpoints.py (#196): read ALLOWED_ORIGINS from env; default to localhost origins - database_cleanup_service.py (#197): validate table name with regex before SQL use; quote safe_table_name with double quotes for PRAGMA and DELETE statements - deployment_manager.py (#200): add path traversal guard (resolve + is_dir check); add --ignore-scripts to npm install; use resolved_path for all cwd args - tests/unit/test_database_cleanup_security.py: new unit tests for SQL injection prevention Closes #193 #195 #196 #197 #200 https://claude.ai/code/session_01AgA9F82EwazbdB5R2f9nsd Co-authored-by: Claude <noreply@anthropic.com> * chore: move legacy .agent content under .github (#162) * chore: move legacy agent files into .github Agent-Logs-Url: https://github.com/groupthinking/EventRelay/sessions/8e79c6e5-9755-40a2-b8b0-73b9ff75249e Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com> * docs: fix relocated agent references Agent-Logs-Url: https://github.com/groupthinking/EventRelay/sessions/8e79c6e5-9755-40a2-b8b0-73b9ff75249e Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com> * docs: remove vague agent rule reference Agent-Logs-Url: https://github.com/groupthinking/EventRelay/sessions/8e79c6e5-9755-40a2-b8b0-73b9ff75249e Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com> * chore(web): UVAI Phase 1 — SEO, a11y, missing static assets Live uvai.io referenced /favicon.ico, /icon.svg, /apple-touch-icon.png but apps/web/public/ did not exist in the repo, producing 404s. Layout metadata also pointed metadataBase and og.url at the legacy v0-uvai.vercel.app host rather than the canonical uvai.io domain. Changes: - Add apps/web/public with favicon.ico (multi-res), icon.svg, apple-touch-icon.png, og-image.png (1200x630), manifest.json, robots.txt. - Add apps/web/src/app/sitemap.ts (Next.js Metadata Route sitemap). - layout.tsx: metadataBase + og.url -> https://uvai.io, add alternates.canonical, inject Organization/WebSite/SoftwareApplication JSON-LD, add skip-to-main link. - page.tsx: <main id=\"main\"> as skip-link target. - LandingNav.tsx: aria-label=\"Primary\" on nav, aria-labels on brand + GitHub external link, visible focus rings on all interactive elements. - HeroSection.tsx: focus rings on CTAs, honor prefers-reduced-motion for marquee. - Add CHANGELOG.md with timestamped entry. Local verification: - npx eslint on touched files: clean - npm run build (apps/web): success, /sitemap.xml route generated, TypeScript clean No production / deploy / DNS / secret changes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(web): PR #202 review fixes — no dangerouslySetInnerHTML, MD022, skip-link in layout, central SITE_URL Addresses code review feedback on PR #202. 1. layout.tsx: replace dangerouslySetInnerHTML JSON-LD with React <script>{jsonLdString}</script> children. jsonLdString escapes `<` -> `<` to prevent any nested `</script>` breakout. Build verified: rendered HTML contains exactly one valid JSON-LD block. Complies with repo policy that forbids dangerouslySetInnerHTML. 2. CHANGELOG.md: markdownlint MD022 — blank lines after `#### Added`, `### Changed`, and `### Notes / known follow-ups (not in this change)`. 3. Skip-to-main-content target moved from `apps/web/src/app/page.tsx`'s <main> to the root layout's content wrapper. The link now works on every route (dashboard, pricing, features, playground, prototype, not-found), not just the homepage. Duplicate `id="main"` removed from page.tsx — rendered HTML on `/` now contains exactly one `id="main"`. 4. Add apps/web/src/lib/site.ts exporting SITE_URL = 'https://uvai.io'. layout.tsx (metadataBase, alternates.canonical, og.url, JSON-LD URLs) and sitemap.ts both consume it. Pricing/playground references kept as-is — those are mailto: addresses and api.uvai.io examples in code samples, not the same axis as the site origin. Failing CI check (E2E Pipeline Tests) is unrelated to this PR: - E2E runs vitest against BASE_URL=https://uvai.io (the live deployment) - Live root returns 200 but is stale (title still "UVAI — Video to Software") - This PR touches zero files under tests/e2e/, src/youtube_extension/, or apps/web/src/app/api/ - Resolution requires a redeploy of the current main, which is outside this PR's scope per the original instructions Local verification: - npx eslint on touched files: clean (exit 0) - npm run build (apps/web): ✓ Compiled, TypeScript clean, 21 pages - Rendered HTML inspection: JSON-LD block present and well-formed; id="main" present on /, /pricing, /features, /dashboard, /playground; exactly one id="main" on each prerendered page (no duplicates) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: v0[bot] <v0[bot]@users.noreply.github.com> Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: Claude Code <claude-code@anthropic.com>
Summary
Second, scoped, low-risk PR for the route-coverage gaps that PR #202 does not address. PR #202 covers assets, robots, sitemap, canonical, JSON-LD, and a11y; this PR closes the remaining 404s on the public surface.
Verified gaps on
uvai.io(live monitor):/privacy,/terms— 404/api/docs— 404 (and/apiJSON points to it)/app,/login— 404 (no auth gate exists today)/prototype— 200 but is an internal spec; should benoindexChanges
apps/web/src/app/privacy/page.tsxapps/web/src/app/terms/page.tsx/privacyapps/web/src/app/api/docs/page.tsx/api/*routes; resolves thedocumentationlink in the/apiJSON descriptorapps/web/src/app/app/page.tsx/dashboard,robots: noindexapps/web/src/app/login/page.tsx/dashboard,robots: noindex(no auth gate today)apps/web/src/app/prototype/layout.tsxrobots: { index: false, follow: false }to the existing client page without touching itapps/web/src/components/landing/LandingFooter.tsxArchitecture delta
main(not stacked on PR chore(web): UVAI Phase 1 SEO, a11y, and missing assets #202). The two PRs do not touch the same files; PR chore(web): UVAI Phase 1 SEO, a11y, and missing assets #202'ssitemap.tswill need a follow-up to include the new public routes (/privacy,/terms,/api/docs) — flagged here intentionally rather than duplicating PR chore(web): UVAI Phase 1 SEO, a11y, and missing assets #202's diff.CHANGELOG.mdentry: that file is introduced by PR chore(web): UVAI Phase 1 SEO, a11y, and missing assets #202 and does not yet exist onmain. Once PR chore(web): UVAI Phase 1 SEO, a11y, and missing assets #202 lands, this can be amended or noted in a follow-up.Scope discipline
Deliberately not in scope:
/apiruntime errors, etc.) — out of scope, separate effort.Testing
npx tsc --noEmit— cleannpx eslinton the changed files — cleannpx next build— succeeds; 25 routes registered including the 6 new ones (/privacy,/terms,/api/docs,/app,/login, plus/prototypenow noindexed)Risk
Low. New routes are additive; the only modification to existing code is two
<Link>entries inLandingFooter. Redirects use Next's serverredirect(), so they're 307s without client hydration cost.🤖 Generated with Claude Code