Repository navigation
Conversation
- Implemented user admin validation using zod schemas for listing, creating, updating, and deleting users. - Added privilege rules to enforce role-based access control for user management actions. chore: create foundation migration for user OTPs, password resets, audit logs, and impersonation sessions - Added columns to existing tables and created new tables for password resets, audit logs, and impersonation sessions. - Established necessary indexes and foreign key constraints. chore: create subjects command center migration for assessments, curriculum, and resources - Added tables for assessments, assessment targets, results, curriculum nodes, progress, class progress, resources, and visibility events. - Included indexes for optimized querying. feat: implement proxy for dashboard access control - Created a proxy to redirect unauthenticated requests to the login page for protected dashboard routes. feat: integrate Sentry for error and performance monitoring - Added Sentry configuration for client, edge, and server environments to capture errors and performance metrics.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unresolved authorization, logout, password-reset, enumeration, data-exposure, and production-route issues remain.
Review effort: Lite
Findings: 3
Open (6)
Enforce dashboard permission in the overview endpoint · New Revoke Better Auth sessions during logout · New Validate password UTF-8 byte length before bcrypt hashing · New Add IP-based rate limiting to password reset requests · New Prevent account enumeration through reset timing · New Remove or restrict the unconditional production error route · New
What changed in this PR
This PR adds a new authenticated dashboard platform with role-specific portals, Prisma-backed APIs, authentication flows, observability, and shared UI.
Changes:
- Adds student, teacher, parent, admin, and developer dashboards.
- Adds validation, repositories, services, caching, auditing, and impersonation.
- Adds Sentry/PostHog monitoring and password-reset/OTP flows.
| File | Change |
|---|---|
stackable-app/sentry.server.config.ts |
Server Sentry setup |
stackable-app/sentry.edge.config.ts |
Edge Sentry setup |
stackable-app/sentry.client.config.ts |
Client Sentry and replay setup |
stackable-app/proxy.ts |
Protected-route session gate |
stackable-app/package.json |
Monitoring and Prisma dependencies |
stackable-app/next.config.ts |
Sentry build integration |
stackable-app/lib/validation/students.ts |
Student validation |
stackable-app/lib/validation/shared.ts |
Portal role definitions |
stackable-app/lib/validation/auth.ts |
Password and reset validation |
stackable-app/lib/validation/admin-common.ts |
Admin validation helpers |
stackable-app/lib/supabase/supabase.ts |
Removed Supabase server client |
stackable-app/lib/supabase/supabase-admin.ts |
Removed admin client |
stackable-app/lib/supabase/client.ts |
Removed browser client |
stackable-app/lib/supabase/admin.ts |
Removed admin singleton |
stackable-app/lib/subjects.ts |
Subject upload constants |
stackable-app/lib/subjects-errors.ts |
Subject API errors |
stackable-app/lib/services/teacher-admin.api.ts |
Teacher service facade |
stackable-app/lib/services/student-admin.store.ts |
Student store contract |
stackable-app/lib/services/student-admin.api.ts |
Student service facade |
stackable-app/lib/repositories/me.repo.ts |
Current-user repository |
stackable-app/lib/repositories/auth.repo.check.ts |
Auth repository checks |
stackable-app/lib/repositories/audit-log.repo.ts |
Audit logging repository |
stackable-app/lib/query/keys.ts |
Query key registry |
stackable-app/lib/grade-points.ts |
Grade averaging |
stackable-app/lib/cn.ts |
Class-name helper |
stackable-app/lib/auth/otp.check.ts |
OTP checks |
stackable-app/lib/auth/auth.ts |
Better Auth configuration |
stackable-app/lib/auth-utils.ts |
IP and phone helpers |
stackable-app/lib/api/audit-context.ts |
Audit request context |
stackable-app/instrumentation.ts |
Server Sentry instrumentation |
stackable-app/instrumentation-client.ts |
Client instrumentation |
stackable-app/hooks/useStudentGrades.ts |
Student grades query |
stackable-app/hooks/useStudentDashboard.ts |
Student dashboard query |
stackable-app/hooks/useParentChildren.ts |
Parent children query |
stackable-app/hooks/useMe.ts |
Identity query |
stackable-app/hooks/useDevUsers.ts |
Developer users query |
stackable-app/hooks/useDevShared.ts |
Developer query helpers |
stackable-app/hooks/useDevSchools.ts |
Developer schools query |
stackable-app/hooks/useDevOverview.ts |
Developer overview query |
stackable-app/hooks/useDevImpersonate.ts |
Impersonation mutation |
stackable-app/hooks/useDevAudit.ts |
Developer audit query |
stackable-app/hooks/useChildOverview.ts |
Parent child query |
stackable-app/hooks/useAdminOverview.ts |
Admin overview query |
stackable-app/components/ui/Textarea.tsx |
Shared textarea |
stackable-app/components/ui/Skeleton.tsx |
Loading skeleton |
stackable-app/components/ui/Select.tsx |
Shared select |
stackable-app/components/ui/PageHeader.tsx |
Page header |
stackable-app/components/ui/Input.tsx |
Shared input |
stackable-app/components/ui/index.ts |
UI exports |
stackable-app/components/ui/Icon.tsx |
Icon wrapper |
stackable-app/components/ui/EmptyState.tsx |
Empty-state component |
stackable-app/components/ui/controlStyles.ts |
Control styles |
stackable-app/components/ui/ComingSoon.tsx |
Placeholder component |
stackable-app/components/subjects/SlideOver.tsx |
Drawer adapter |
stackable-app/components/providers/PostHogProvider.tsx |
PostHog provider |
stackable-app/components/portal/teacher/TeacherHomeSkeleton.tsx |
Teacher loading state |
stackable-app/components/portal/teacher/RecentGrading.tsx |
Recent grading panel |
stackable-app/components/portal/teacher/QuickActions.tsx |
Teacher quick actions |
stackable-app/components/portal/teacher/AttentionList.tsx |
Student attention list |
stackable-app/components/portal/student/TermMatrix.tsx |
Student term matrix |
stackable-app/components/portal/student/QuickLinks.tsx |
Student quick links |
stackable-app/components/portal/student/ProgressPanel.tsx |
Student progress panel |
stackable-app/components/portal/student/Panel.tsx |
Shared panel exports |
stackable-app/components/portal/student/LatestGrades.tsx |
Latest grades panel |
stackable-app/components/portal/student/GradesSkeleton.tsx |
Grades loading state |
stackable-app/components/portal/student/clock.ts |
Student clock helpers |
stackable-app/components/portal/parent/helpers.ts |
Parent calculations |
stackable-app/components/portal/parent/helpers.check.ts |
Parent helper checks |
stackable-app/components/portal/admin/AttendanceTrend.tsx |
Attendance chart |
stackable-app/components/portal/admin/AdminOverviewSkeleton.tsx |
Admin loading state |
stackable-app/components/portal/admin/AdminGreeting.tsx |
Admin greeting |
stackable-app/components/portal/admin/ActivityFeed.tsx |
Admin activity feed |
stackable-app/components/email/otp-email.tsx |
OTP email template |
stackable-app/components/dev/useUrlFilters.ts |
URL filter state |
stackable-app/components/dev/useNow.ts |
Shared time ticker |
stackable-app/components/dev/ServiceStatusBadge.tsx |
Service status badge |
stackable-app/components/dev/services.ts |
Service metadata |
stackable-app/components/dev/SearchInput.tsx |
Developer search input |
stackable-app/components/dev/RelativeTime.tsx |
Relative timestamps |
stackable-app/components/dev/motion.ts |
Animation helpers |
stackable-app/components/dev/InfoBlock.tsx |
Developer detail block |
stackable-app/components/dev/DevIntro.tsx |
Developer page intro |
stackable-app/components/dev/DevCard.tsx |
Developer card |
stackable-app/components/dev/CopyButton.tsx |
Clipboard button |
stackable-app/components/dashboard/useUnreadCount.ts |
Notification placeholder |
stackable-app/components/dashboard/useLogout.ts |
Logout flow |
stackable-app/components/dashboard/useIdentifyUser.ts |
PostHog identity |
stackable-app/components/dashboard/ThemeToggle.tsx |
Theme toggle |
stackable-app/components/dashboard/format.ts |
Dashboard formatting |
stackable-app/components/auth/PasswordStrength.tsx |
Password strength UI |
stackable-app/components/auth/Checkbox.tsx |
Auth checkbox |
stackable-app/components/auth/checkbox.module.css |
Checkbox styling |
stackable-app/components/auth/AuthShell.tsx |
Auth layout |
stackable-app/components/admin/users/Switch.tsx |
Permission switch |
stackable-app/components/admin/users/Section.tsx |
User drawer section |
stackable-app/components/admin/users/RowActions.tsx |
User row actions |
stackable-app/components/admin/users/ProfileTab.tsx |
User profile tab |
stackable-app/components/admin/users/Badges.tsx |
User badges |
stackable-app/components/admin/teachers/StatusBadge.tsx |
Teacher status badge |
stackable-app/components/admin/students/StatusBadge.tsx |
Student status badge |
stackable-app/components/admin/schools/useErrorToast.ts |
School error toast |
stackable-app/components/admin/schools/StatusBadge.tsx |
School status badges |
stackable-app/components/admin/schools/permissions.ts |
School permissions |
stackable-app/components/admin/schools/LogoUploader.tsx |
School logo uploader |
stackable-app/app/proxy.ts |
Proxy placeholder |
stackable-app/app/layout.tsx |
PostHog provider integration |
stackable-app/app/global-error.tsx |
Global error reporting |
stackable-app/app/dashboard/page.tsx |
Shared admin overview |
stackable-app/app/dashboard/layout.tsx |
Protected dashboard shell |
stackable-app/app/api/teachers/form-options/route.ts |
Teacher form options API |
stackable-app/app/api/teachers/[id]/timetable/route.ts |
Timetable API |
stackable-app/app/api/teachers/[id]/edit-data/route.ts |
Teacher edit API |
stackable-app/app/api/teachers/[id]/attendance/route.ts |
Teacher attendance API |
stackable-app/app/api/teach/students/route.ts |
Teacher student list API |
stackable-app/app/api/teach/students/[studentId]/route.ts |
Teacher student profile API |
stackable-app/app/api/subjects/[id]/route.ts |
Subject detail API |
stackable-app/app/api/students/route.ts |
Student list API |
stackable-app/app/api/students/form-options/route.ts |
Student form options API |
stackable-app/app/api/students/[id]/route.ts |
Student CRUD API |
stackable-app/app/api/student/grades/route.ts |
Student grades API |
stackable-app/app/api/student/dashboard/route.ts |
Student dashboard API |
stackable-app/app/api/sentry-example-api/route.ts |
Sentry test endpoint |
stackable-app/app/api/parent/children/route.ts |
Parent children API |
stackable-app/app/api/parent/children/[studentId]/route.ts |
Child overview API |
stackable-app/app/api/jobs/send-otp-email/route.ts |
Removed old email job |
stackable-app/app/api/jobs/[job]/route.ts |
Generic job endpoint |
stackable-app/app/api/dev/users/route.ts |
Developer users API |
stackable-app/app/api/dev/schools/route.ts |
Developer schools API |
stackable-app/app/api/dev/overview/route.ts |
Developer overview API |
stackable-app/app/api/dev/impersonate/stop/route.ts |
Stop impersonation API |
stackable-app/app/api/dev/impersonate/start/route.ts |
Start impersonation API |
stackable-app/app/api/dev/audit/route.ts |
Developer audit API |
stackable-app/app/api/auth/verify-reset-code/route.ts |
Reset-code verification |
stackable-app/app/api/auth/reset-password/route.ts |
Password reset |
stackable-app/app/api/auth/me/route.ts |
Current-user API |
stackable-app/app/api/auth/logout/route.ts |
Logout implementation |
stackable-app/app/api/auth/forgot-password/route.ts |
Forgot-password flow |
stackable-app/app/api/admin/schools/route.ts |
Admin schools API |
stackable-app/app/api/admin/overview/route.ts |
Admin overview API |
stackable-app/app/(teacher)/teach/timetable/page.tsx |
Teacher timetable placeholder |
stackable-app/app/(teacher)/teach/settings/page.tsx |
Teacher settings placeholder |
stackable-app/app/(teacher)/teach/inbox/page.tsx |
Teacher inbox placeholder |
stackable-app/app/(teacher)/teach/grading/page.tsx |
Teacher grading placeholder |
stackable-app/app/(teacher)/teach/attendance/page.tsx |
Teacher attendance placeholder |
stackable-app/app/(student)/learn/settings/page.tsx |
Student settings placeholder |
stackable-app/app/(student)/learn/library/page.tsx |
Student library placeholder |
stackable-app/app/(student)/learn/inbox/page.tsx |
Student inbox placeholder |
stackable-app/app/(parent)/family/settings/page.tsx |
Parent settings placeholder |
stackable-app/app/(developer)/dev/users/page.tsx |
Developer users page |
stackable-app/app/(developer)/dev/sitemap/page.tsx |
Developer sitemap page |
stackable-app/app/(developer)/dev/settings/page.tsx |
Developer settings page |
stackable-app/app/(developer)/dev/schools/page.tsx |
Developer schools page |
stackable-app/app/(developer)/dev/page.tsx |
Developer overview page |
stackable-app/app/(developer)/dev/integrations/page.tsx |
Integrations page |
stackable-app/app/(developer)/dev/audit/page.tsx |
Audit page |
stackable-app/.tmp-lane-a/inspect3.ts |
Temporary schema inspection |
stackable-app/.tmp-lane-a/inspect2.ts |
Temporary schema inspection |
stackable-app/.tmp-lane-a/inspect.ts |
Temporary schema inspection |
stackable-app/.gitignore |
Sentry build exclusion |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+20
to
+23
| const auth = await requireAuth(request, { | ||
| roles: ["admin", "manager", "super-admin"], | ||
| rateLimit: "read", | ||
| }); |
Comment on lines
+4
to
8
| import { revokeSessionByTokenHash } from '@/lib/repositories/auth.repo'; | ||
|
|
||
| export async function POST() { | ||
| const cookieStore = await cookies(); | ||
| const rawToken = cookieStore.get('stackable_session')?.value; |
Comment on lines
+31
to
+35
| // max(72): bcrypt only reads the first 72 bytes, so longer input adds nothing. | ||
| export const passwordSchema = z | ||
| .string() | ||
| .max(72, "Use 72 characters or fewer.") | ||
| .refine((p) => PASSWORD_RULES.every((r) => r.test(p)), "Your password doesn't meet all the requirements."); |
Comment on lines
+23
to
+27
| await authLimit(`forgot:${email}`); | ||
|
|
||
| // Only a single, active account gets a code (an email shared by two schools is ambiguous). | ||
| const users = await findActiveUsersByEmail(email); | ||
| const user = users.length === 1 && users[0].status === 'active' && users[0].email ? users[0] : null; |
Comment on lines
+25
to
+28
| // Only a single, active account gets a code (an email shared by two schools is ambiguous). | ||
| const users = await findActiveUsersByEmail(email); | ||
| const user = users.length === 1 && users[0].status === 'active' && users[0].email ? users[0] : null; | ||
| if (!user) return NextResponse.json(GENERIC); |
Comment on lines
+11
to
+15
| export async function GET() { | ||
| // Opt out of prerendering so the error is thrown at request time | ||
| await connection(); | ||
| Sentry.logger.info("Sentry example API called"); | ||
| throw new SentryExampleAPIError( |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


No description provided.