Add date domain, validation, Supabase reconciliation, generation safety, and CI/E2E tests - #10
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1e31271653
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| export function getSafeRedirectPath(value: string | null, fallback = '/') { | ||
| return value?.startsWith('/') && !value.startsWith('//') ? value : fallback |
There was a problem hiding this comment.
Reject backslash-prefixed callback redirects
When a successful authentication callback supplies next=/%5Cattacker.example, URLSearchParams decodes it to /\attacker.example, which this check accepts. Next.js then emits that value as the redirect destination, and browsers normalize the backslash so the navigation goes to https://attacker.example/, leaving the authentication callback vulnerable to an open redirect. Validate the destination by resolving it against the configured site origin and requiring the resolved origin to match.
Useful? React with 👍 / 👎.
| where user_id is null or date is null or workout_type is null or duration_minutes is null | ||
| or duration_minutes <= 0 or difficulty is null or exercises is null | ||
| or jsonb_typeof(exercises) <> 'array'; |
There was a problem hiding this comment.
Check constrained workout values during preflight
When an existing workout plan has a non-null but unsupported workout_type or difficulty—possible because the previous generator persisted unvalidated model output—this documented preflight returns no row, but the reconciliation migration later adds enum-like check constraints and aborts. Include the allowed-value predicates here so a zero-row preflight actually guarantees that the migration can apply.
Useful? React with 👍 / 👎.
| return ( | ||
| <div className="max-w-xl mx-auto p-6 bg-red-50 dark:bg-red-900/20 rounded-lg"> | ||
| <p className="text-red-600 dark:text-red-400">The saved meal plan is invalid. Generate a new plan to continue.</p> | ||
| </div> |
There was a problem hiding this comment.
Keep regeneration available for invalid saved plans
When a legacy meal plan fails the newly strict parser, this early return removes the New Plan button rendered later on the page, even though the message instructs the user to generate one. Because getMeal continues returning the same existing row, affected users cannot recover through the UI without manually deleting data; provide a regeneration action in this error state.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| const profile = ProfileSchema.parse(profileData) | ||
| const prompt = `Create a personalized ${duration}-minute bodyweight workout plan for a user with goal ${profile.goal}, gender ${profile.gender}, age ${profile.age}, and activity level ${profile.activity_level}. Return a JSON object with workout_type, difficulty, and a non-empty exercises array. Each exercise must include name and instructions, and may include sets, reps, duration, and rest.` |
There was a problem hiding this comment.
Tell the model the required workout enum values
When the model returns natural values such as "bodyweight circuit" or "moderate", generation now fails because GeneratedWorkoutPlanSchema only accepts the configured workout-type and difficulty enums, but this replacement prompt no longer lists those allowed values as the previous prompt did. Since JSON mode only guarantees valid JSON, include the exact enum contract or use a structured schema response to avoid intermittent user-visible generation failures.
Useful? React with 👍 / 👎.
Motivation
Description
app/lib/date.ts,app/lib/profile.ts,app/lib/generated-plans.ts,app/lib/auth.ts,app/lib/profile-options.ts, and a generated-compatible DB contractapp/lib/database.types.tsand used them across code paths.YYYY-MM-DDdate key (getLocalDateKey/parseDateKey), updated UI and client APIs to pass validated date keys, and removed fragiletoISOString().split('T')[0]usage.openaiJSON response formats, parsing and validating with Zod, and persisting withupsert(non-destructive) inapp/lib/workout-generator.tsandapp/protected/profile/meal-plan/action.ts; added parsing helpers and stricter schemas for exercises and meals.utils/supabase/{client,server,middleware}.tsto useDatabase, improved cookie handling, and changed middleware to fail-closed for protected routes while keeping public routes available.supabase/migrations/20260611170000_reconcile_fitness_schema.sqlandsupabase/preflight/...to align the remote schema, createsave_profile_with_tdeRPC, apply RLS, and enforce uniqueness constraints.app/forgot-password,app/reset-password, andapp/auth/confirm/route.ts) with safe redirect handling viagetSafeRedirectPath.imgwithnext/imageinNavBar, removed Google font integration for a simpler CSS fallback, and improved profile, meal plan, and workout components to surface validation and errors.tests/*.test.ts, Playwright e2e spece2e/public-auth.spec.ts, Playwright configplaywright.config.ts, CI workflow.github/workflows/quality.yml, and updatedpackage.jsonscripts andtsconfig.test.jsonto run typechecked unit tests and E2E runs.README.md, added.env.example, updated.gitignore, addedsupabase/config.toml, and adjustedeslint.config.mjsto ignore generated artifacts.Testing
tests/*.test.ts) and a Playwright e2e spec for public auth journeys (e2e/public-auth.spec.ts).playwright.config.tsand CI workflowquality.ymlthat runsnpm run check,npm run build, andnpm run test:e2eand uploads failure artifacts on CI failure.Codex Task