# Subscription Page Redirect Fix Plan ## 1. Objective Restore reliable access to: ```text http://localhost:3000/dashboard/subscription ``` The subscription page must remain accessible to authorized account owners, including owners whose subscription is expired, unpaid, past due, canceled, or suspended. The fix must not weaken backend authorization or allow non-owner employees to manage billing. --- ## 2. Current Problem The subscription page exists, but authorized users are redirected to: ```text http://localhost:3000/dashboard ``` The likely causes are: 1. The dashboard route guard treats the generated sidebar menu as a route-authorization list. 2. `/subscription` may not be returned by `GET /auth/employee/menu`. 3. The subscription page trusts the cached `employee_profile` value in `localStorage`. 4. Subscription enforcement may return `402 Payment Required` before the owner can reach the billing recovery page. 5. Redirect targets use ambiguous paths such as `/`, which resolve to `/dashboard` because of the configured Next.js base path. --- ## 3. Required Access Policy The subscription page must be classified as an owner-only system route. | User state | Expected access | |---|---| | Authenticated owner with active subscription | Allowed | | Authenticated owner in trial | Allowed | | Authenticated owner with expired subscription | Allowed | | Authenticated owner with past-due subscription | Allowed | | Authenticated owner with unpaid subscription | Allowed | | Authenticated owner with canceled subscription | Allowed | | Authenticated owner with suspended account | Allowed for billing recovery | | Manager | Denied | | Agent or regular employee | Denied | | Unauthenticated user | Redirect to sign-in | The route must not depend on whether it appears in the configurable dashboard menu. --- ## 4. Separate Navigation From Authorization ### Problem The dashboard menu currently appears to serve two different purposes: - Controlling which sidebar links are displayed - Controlling which routes a user may access These responsibilities must be separated. ### Required change Use the menu response only for navigation visibility. Use a dedicated access policy for route authorization. The following route categories should be defined: - Public authentication routes - Core authenticated dashboard routes - Owner-only system routes - Subscription-dependent feature routes - Admin-configurable feature routes - Billing recovery routes Register `/subscription` as: ```ts { authenticationRequired: true, allowedRoles: ["OWNER"], subscriptionRequired: false, menuRegistrationRequired: false } ``` The exact implementation may differ, but there must be one authoritative route policy. --- ## 5. Create a Central Route Access Policy Add a shared route-policy configuration. Example: ```ts export const dashboardRoutePolicies = { "/subscription": { authenticationRequired: true, allowedRoles: ["OWNER"], subscriptionRequired: false, menuRegistrationRequired: false, }, }; ``` The policy should be used by: - `DashboardAccessGuard` - Dashboard layout - Subscription page - Sidebar rendering - Subscription-status middleware - Automated tests Do not duplicate owner checks and subscription checks across unrelated components. --- ## 6. Update `DashboardAccessGuard` ### Current behavior to remove The guard must not redirect a user merely because the current route is absent from `/auth/employee/menu`. ### Required behavior The guard should: 1. Resolve the current route policy. 2. Confirm authentication. 3. Confirm the authenticated role. 4. Apply subscription restrictions only when the route requires an active subscription. 5. Allow billing recovery routes regardless of subscription state. 6. Redirect only after all required state has finished loading. 7. Avoid redirecting to the current route. 8. Use a stable role-based fallback route. ### Expected error handling | Response | Required behavior | |---|---| | `401 Unauthorized` | Redirect to sign-in | | `403 Forbidden` | Show access denied or redirect to an allowed dashboard route | | `402 Payment Required` | Redirect owner to `/subscription`, unless already there | | Network failure | Show retryable error | | Server failure | Show error state without pretending it is an authorization failure | --- ## 7. Fix Owner Verification on the Subscription Page ### Current risk The page uses `employee_profile` from `localStorage` as an authorization source. Browser storage can be: - Missing - Stale - Malformed - Left from another session - Temporarily unavailable ### Required behavior 1. Treat local storage only as optional display cache. 2. Fetch the authenticated profile from: ```text GET /auth/employee/me ``` 3. Wait for the request to resolve before redirecting. 4. Allow access only when the API confirms the user is an owner. 5. Redirect confirmed non-owners to an allowed dashboard route. 6. Redirect unauthenticated users to sign-in. 7. Show a loading state during verification. 8. Show a retryable error for temporary API failures. The page must not redirect while authentication or role state is unresolved. --- ## 8. Add Billing Recovery Route Exceptions Subscription enforcement must never block the routes needed to repair a subscription. Minimum allowlist: ```text /dashboard/subscription /dashboard/subscription/success /dashboard/subscription/cancel ``` Depending on the product flow, also consider: ```text /dashboard/profile /dashboard/support /dashboard/logout ``` These exceptions must be implemented wherever subscription enforcement occurs: - Frontend route guards - API middleware - API interceptors - Account suspension guards - Subscription-status hooks --- ## 9. Review Backend Authorization Inspect these API areas: - `GET /auth/employee/menu` - `GET /auth/employee/me` - Authentication middleware - Subscription-status middleware - Account suspension middleware - Subscription controllers - Subscription services - Billing portal endpoint - Checkout endpoint - Subscription update endpoint - Menu configuration schema - Menu seed data ### Backend requirements - `/auth/employee/me` must remain available to authenticated owners during billing failure. - Subscription read and recovery endpoints must remain available during `PAST_DUE`, `UNPAID`, `EXPIRED`, `CANCELED`, or `SUSPENDED` states. - Owner authorization must be enforced server-side. - Managers and employees must remain unable to manage subscriptions. - Menu entries must not be treated as route permissions unless the API explicitly defines them as permissions. - `402` responses must include enough structured information for the frontend to route owners to billing recovery. --- ## 10. Correct Redirect Targets Audit redirects in: - `DashboardAccessGuard.tsx` - `subscription/page.tsx` - Dashboard layout - Authentication hooks - API client interceptors - Subscription hooks - Suspended-account handling Avoid ambiguous redirects such as: ```ts router.replace("/"); ``` Use explicit destinations based on the router and base-path convention. Examples: ```ts router.replace("/dashboard"); router.replace("/login"); router.replace("/dashboard/subscription"); ``` Confirm whether the project router expects paths with or without the configured `/dashboard` base path, then use one convention consistently. --- ## 11. Prevent Redirect Loops Protect against: ```text /subscription -> /dashboard -> /subscription /login -> /dashboard -> /login /subscription -> / -> /dashboard ``` The route guard must: - Compare the current path with the redirect destination. - Never redirect to the current path. - Avoid redirecting while authentication is loading. - Avoid redirecting while role verification is loading. - Avoid redirecting while route policy is loading. - Preserve intended destinations after login where appropriate. - Use a deterministic fallback route for each role. --- ## 12. Fix Sidebar Behavior The sidebar must remain a navigation tool, not an authorization engine. Required behavior: - Show `Subscription` only to owners. - Hide it from managers and regular employees. - Keep it outside admin-configurable feature menu items. - Do not allow subscription-plan configuration to disable it. - Do not require it to be returned by `/auth/employee/menu`. - Validate direct URL access through the central route policy. The administrator may configure optional feature menus, but must not be able to remove the account owner's billing recovery route. --- ## 13. Add Loading and Error States The subscription page should support these explicit states: 1. Verifying authentication 2. Verifying owner role 3. Loading subscription data 4. Subscription loaded 5. No subscription found 6. Payment required 7. Subscription expired 8. Subscription past due 9. Subscription canceled 10. Account suspended 11. Access denied 12. API unavailable Do not briefly render protected content before redirecting. Do not convert every API failure into a redirect. --- ## 14. Add Development Logging During implementation, log structured route decisions: ```ts { pathname, authenticated, role, subscriptionStatus, menuContainsRoute, routePolicy, accessDecision, redirectTarget } ``` Do not log: - Authentication tokens - Payment details - Full customer records - Personal information - Complete API response bodies Remove or disable verbose logs before production release. --- ## 15. Automated Test Plan ### 15.1 Route guard tests Test that: - An owner can access `/subscription` when it is absent from the menu response. - An owner with an active subscription can access the page. - An owner in trial can access the page. - An owner with an expired subscription can access the page. - An owner with a past-due subscription can access the page. - An owner with an unpaid subscription can access the page. - An owner with a canceled subscription can access the page. - An owner can access the page when another request returns `402`. - Stale local storage does not override the authenticated API profile. - A manager cannot access the page. - An agent cannot access the page. - An unauthenticated user is redirected to sign-in. - A temporary API failure shows an error instead of redirecting. - A redirect is not issued when the destination equals the current path. ### 15.2 Subscription page tests Test that: - No redirect occurs before `/auth/employee/me` resolves. - A confirmed owner sees subscription information. - A confirmed non-owner is denied. - `401` redirects to sign-in. - `403` shows access denied or redirects safely. - `402` displays billing recovery. - Network errors provide retry behavior. - Loading state prevents protected-content flicker. ### 15.3 Integration tests Test the complete flow: ```text Owner login -> open /dashboard/subscription directly -> load current subscription -> open checkout or billing portal -> return through success or cancel URL -> subscription page loads correctly ``` Test all supported statuses: ```text ACTIVE TRIALING PAST_DUE UNPAID EXPIRED CANCELED SUSPENDED ``` --- ## 16. Localization Validation Validate the complete flow in: - English - French - Arabic Required checks: - All labels are translated. - Error messages are translated. - Loading states are translated. - Billing recovery messages are translated. - Access-denied messages are translated. - Arabic renders in true RTL. - Buttons and status badges remain correctly aligned in RTL. - No hard-coded English strings remain in the subscription flow. --- ## 17. Implementation Order Execute the work in this order: 1. Define the route access policy. 2. Classify `/subscription` as an owner-only recovery route. 3. Update `DashboardAccessGuard`. 4. Remove menu-based authorization for system routes. 5. Replace local-storage-only role verification. 6. Verify the user through `/auth/employee/me`. 7. Add subscription recovery exceptions. 8. Review backend subscription enforcement. 9. Correct redirect targets and base-path handling. 10. Add redirect-loop protection. 11. Update sidebar visibility rules. 12. Add loading and error states. 13. Add unit tests. 14. Add integration tests. 15. Validate every subscription state. 16. Validate English, French, and Arabic. 17. Run type-check, lint, tests, and production build. 18. Remove development-only logging. --- ## 18. Required Code for Complete Implementation The dashboard package is sufficient for a temporary frontend patch. A complete fix requires these API parts: - `/auth/employee/menu` route, controller, and service - `/auth/employee/me` route, controller, and service - Authentication middleware - Role authorization middleware - Subscription enforcement middleware - Account suspension middleware - Subscription routes - Subscription controller - Subscription service - Billing portal integration - Checkout integration - API error interceptor or response-normalization logic - Menu configuration schema - Menu seed files --- ## 19. Acceptance Criteria The fix is complete only when: - `/dashboard/subscription` no longer redirects an authorized owner to `/dashboard`. - The route works when it is absent from the generated menu. - Owners with billing problems can access billing recovery. - Non-owners remain blocked. - Backend authorization remains enforced. - Authorization does not rely on local storage. - No redirect loop occurs. - Direct URL access and sidebar navigation behave consistently. - Base-path routing works correctly. - `401`, `402`, `403`, network errors, and server errors are handled distinctly. - English, French, and Arabic render correctly. - Type-check passes. - Lint passes. - Unit tests pass. - Integration tests pass. - Production build succeeds. --- ## 20. Out of Scope Do not include unrelated work in this repair: - Subscription pricing redesign - Billing provider migration - Dashboard visual redesign - New subscription tiers - General sidebar restructuring - Domain or publishing settings - Unrelated permission-system changes Any broader authorization redesign should be handled as a separate phase after the subscription route is stable.