Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
280 lines
16 KiB
Markdown
280 lines
16 KiB
Markdown
# PRD — AlgaDesk Product Seam Remediation
|
|
|
|
- Slug: `2026-05-06-algadesk-remediation-product-seam`
|
|
- Date: `2026-05-06`
|
|
- Status: Draft
|
|
- Parent plan: `ee/docs/plans/2026-05-05-algadesk-lightweight-helpdesk-product-seam/`
|
|
- Source design: `docs/plans/2026-05-05-algadesk-lightweight-helpdesk-product-seam-design.md`
|
|
- Reviewed implementation range: `422df13c8..09f09a919` on `feature/algadesk-lightweight-ticketing`
|
|
|
|
## Summary
|
|
|
|
Remediate the current AlgaDesk product seam implementation so it satisfies the original product intent: AlgaDesk must be a coherent help-desk wedge product inside the existing Alga PSA app, with a real product entitlement boundary, a purpose-built AlgaDesk shell, server-side route/API enforcement, accurate metadata filtering, and confidence-building tests that compile and run.
|
|
|
|
The remediation job is not a second attempt to expand scope. It is a stabilization and correctness pass over work already implemented in the parent plan. The top priority is to fix blockers identified in review: typecheck failures, missing session product propagation, client-side-only route boundaries, API bypasses in overridden controllers, incomplete registry coverage, metadata leakage, overclaimed checklist status, and non-runnable or low-confidence tests.
|
|
|
|
## Original Product Intent to Preserve
|
|
|
|
AlgaDesk is an orthogonal product entitlement, not a new `solo | pro | premium` tier. It runs from the same codebase, Next.js app, database schema, and background-worker model as Alga PSA. The seam is product/licensing and composition, not a separate physical process.
|
|
|
|
AlgaDesk includes:
|
|
|
|
1. MSP dashboard focused on ticket and email health.
|
|
2. Ticket list/detail, comments, assignment, boards, statuses, priorities, categories, tags, response state, attachments, and email conversation context.
|
|
3. Clients, contacts, and locations needed for support.
|
|
4. Client portal dashboard, free-form tickets, ticket detail/replies, knowledge base, profile, and client settings.
|
|
5. Ticket attachments and knowledge base, but not full document management.
|
|
6. Email-to-ticket and ticket reply/update by email.
|
|
7. Users, teams, ticketing, email channel, client portal, and KB settings required for help desk operations.
|
|
|
|
AlgaDesk excludes in v1:
|
|
|
|
- Billing, invoices, quotes, contracts, contract lines, service catalog, tax/accounting exports.
|
|
- Projects and project tasks.
|
|
- Time entry, approvals, scheduling, dispatch, calendars.
|
|
- Assets/RMM/devices.
|
|
- Workflows/automation and service request forms.
|
|
- Surveys.
|
|
- Extensions framework and extension pages.
|
|
- AI/chat.
|
|
- Full integrations outside required email-channel paths.
|
|
- Full document management, folders, broad sharing, and project/client document surfaces.
|
|
- Broad reporting/platform/admin surfaces not required by help desk.
|
|
|
|
## Current Implementation State and Findings
|
|
|
|
The current branch contains substantial work: `product_code`, product constants, a registry, an AlgaDesk composition scaffold, dashboard/settings/ticket/client/portal/email/API boundary work, and many tests. However, review found it is not merge-ready.
|
|
|
|
### Confirmed blockers
|
|
|
|
1. **Typecheck fails.**
|
|
- Command: `cd server && npm run typecheck -- --pretty false`
|
|
- Failing files include:
|
|
- `server/src/components/layout/SidebarWithFeatureFlags.tsx`
|
|
- `server/src/types/next-auth.ts`
|
|
- Root issue: product-specific NextAuth augmentation conflicts with `packages/auth/src/types/next-auth.ts`, and registry menu helper generics do not type cleanly with `NavigationSection`.
|
|
|
|
2. **Client product context defaults AlgaDesk users to PSA.**
|
|
- `server/src/context/ProductContext.tsx` reads `session.user.product_code`.
|
|
- `packages/auth/src/lib/nextAuthOptions.ts` fetches/maps `plan`, but not `product_code`.
|
|
- Client components using `useProduct()` can expose PSA surfaces for AlgaDesk tenants.
|
|
|
|
3. **AlgaDesk MSP shell bypasses sidebar/header.**
|
|
- `server/src/app/msp/MspLayoutClient.tsx` renders raw children inside `<div data-product-shell="algadesk">` for AlgaDesk.
|
|
- This does not mount a real AlgaDesk sidebar/header/layout.
|
|
|
|
4. **Browser route boundary is client-side only.**
|
|
- MSP and portal layout clients use `usePathname()` and render `ProductRouteBoundary` client-side.
|
|
- Excluded server pages may still execute data fetching before the boundary UI appears.
|
|
- Product boundaries must prevent excluded page execution server-side.
|
|
|
|
5. **API product enforcement is bypassed by overridden controllers.**
|
|
- `ApiBaseController` checks product access in base CRUD methods.
|
|
- Controllers with overridden methods, e.g. `ApiProjectController.list()`, authenticate and run without calling the product gate.
|
|
- Product API enforcement must be unavoidable for controller-backed routes.
|
|
|
|
6. **Product registry is incomplete/inconsistent.**
|
|
- Portal sidebar can show `/client-portal/client-settings`, but registry does not allow it.
|
|
- `/msp/settings/*` handling is too broad; direct routes like notifications/extensions/integrations can leak.
|
|
- API routes use mismatched paths, e.g. KB route is `/api/v1/kb-articles`, not `/api/v1/knowledge-base`.
|
|
- Denylist misses multiple PSA route families.
|
|
|
|
7. **Metadata/OpenAPI filtering is partial.**
|
|
- Endpoint paths are filtered in some places.
|
|
- Schemas, permissions, stats, and other discovery data can still reveal PSA-only surfaces.
|
|
|
|
8. **Product-denied errors are not consistently mapped to 403.**
|
|
- `ProductAccessError` uses `status = 403`.
|
|
- Some API error handlers honor `statusCode`, so product denial can become 500.
|
|
- Some route handlers catch product denial as generic errors.
|
|
|
|
9. **Test/checklist status is overclaimed.**
|
|
- Parent `features.json` marks 356/356 implemented.
|
|
- Parent `tests.json` marks 27/27 implemented.
|
|
- This does not reflect current blockers.
|
|
- Many tests are source-string contracts rather than behavior/integration tests matching their descriptions.
|
|
|
|
10. **There are unsafe/unrelated uncommitted changes.**
|
|
- `.env.localtest` contains plaintext DB credentials and must not be committed.
|
|
- `package-lock.json` has package version regressions and should be reviewed/reverted unless intentional.
|
|
- Uncommitted contact-detail changes appear relevant, but must be isolated from unrelated local changes.
|
|
|
|
## Goals
|
|
|
|
1. Make the branch compile.
|
|
2. Make product entitlement available consistently on server and client session contexts.
|
|
3. Render a real AlgaDesk MSP shell with sidebar/header while avoiding full PSA cross-feature providers.
|
|
4. Enforce product route boundaries server-side before excluded page data fetching.
|
|
5. Make API product gates unavoidable for controller-backed and standalone API routes.
|
|
6. Complete and correct the product surface registry for browser, portal, API, settings, and metadata use cases.
|
|
7. Ensure ProductAccessError maps to structured 403 responses everywhere product guards are used.
|
|
8. Replace misleading or non-runnable tests with a small set of real confidence-building tests.
|
|
9. Correct the parent checklist status or explicitly annotate it as superseded by this remediation plan.
|
|
10. Preserve existing PSA behavior.
|
|
|
|
## Non-goals
|
|
|
|
1. Do not add new AlgaDesk product scope beyond the parent PRD.
|
|
2. Do not create a separate app, database, process, or repository.
|
|
3. Do not redesign ticketing, client portal, email, or API frameworks beyond what is needed for enforcement.
|
|
4. Do not strive for comprehensive test coverage.
|
|
5. Do not commit local secrets or incidental lockfile noise.
|
|
6. Do not mark remediation features/tests implemented until verified by compiling/running relevant checks.
|
|
|
|
## Target Users and Flows
|
|
|
|
### Remediation engineer
|
|
|
|
1. Starts from the current feature branch.
|
|
2. Cleans local/uncommitted noise.
|
|
3. Fixes compile/session/registry/enforcement blockers.
|
|
4. Runs targeted confidence-building tests.
|
|
5. Updates plan status honestly.
|
|
6. Hands off a branch that can be reviewed without hidden PSA leaks.
|
|
|
|
### AlgaDesk MSP user after remediation
|
|
|
|
1. Logs into an AlgaDesk tenant.
|
|
2. Sees an AlgaDesk-branded shell with help-desk navigation, not raw page content.
|
|
3. Can access dashboard, tickets, clients, contacts, KB, and allowed settings.
|
|
4. Direct hits to excluded PSA pages are blocked server-side before data fetching.
|
|
|
|
### AlgaDesk API consumer after remediation
|
|
|
|
1. Uses an API key for an AlgaDesk tenant.
|
|
2. Allowed APIs work.
|
|
3. PSA-only APIs fail with structured 403 product-denied responses even when a controller overrides base CRUD methods.
|
|
4. Metadata/OpenAPI/docs do not expose denied PSA paths, schemas, permissions, or misleading stats.
|
|
|
|
## Functional Requirements
|
|
|
|
### Hygiene and baseline
|
|
|
|
1. Keep remediation work isolated from local env and lockfile noise.
|
|
2. Do not commit `.env.localtest` credential changes.
|
|
3. Revert or justify `package-lock.json` version changes before merge.
|
|
4. Record current known blockers and commands in the remediation scratchpad.
|
|
|
|
### Type/session remediation
|
|
|
|
1. Define `product_code` in the shared NextAuth type augmentation used by both package and server consumers.
|
|
2. Remove conflicting duplicate declarations.
|
|
3. Fetch `product_code` with tenant subscription/product info.
|
|
4. Persist `product_code` onto JWT token on initial sign-in and refresh paths.
|
|
5. Copy `product_code` from JWT token into `session.user`.
|
|
6. Keep `plan`, addons, and trial fields unchanged.
|
|
7. Make `ProductProvider` resolve AlgaDesk correctly from session.
|
|
8. Add tests proving AlgaDesk sessions do not default to PSA.
|
|
|
|
### AlgaDesk shell remediation
|
|
|
|
1. Replace raw AlgaDesk children rendering with a real AlgaDesk shell.
|
|
2. Shell must include sidebar, header/app chrome, main content area, and product branding.
|
|
3. Shell must avoid full PSA providers for workflows, scheduling, projects, assets, SLA, surveys, extensions, and AI chat.
|
|
4. Sidebar filtering must typecheck and preserve PSA behavior.
|
|
5. Settings navigation must align with route registry and allowed tabs.
|
|
|
|
### Server route boundary remediation
|
|
|
|
1. Add server-side product route guard helpers.
|
|
2. Apply guards before excluded server page data fetching.
|
|
3. Ensure major excluded MSP routes render upgrade boundary or not-found according to registry.
|
|
4. Ensure major excluded portal routes render upgrade boundary or not-found according to registry.
|
|
5. Keep client-side boundary only as a secondary safety net, not primary enforcement.
|
|
6. Ensure allowed AlgaDesk pages still render their AlgaDesk compositions.
|
|
|
|
### Registry remediation
|
|
|
|
1. Correct MSP settings route and tab behavior.
|
|
2. Allow `/client-portal/client-settings` for AlgaDesk.
|
|
3. Deny excluded portal surfaces consistently.
|
|
4. Correct API allowed route names, especially `/api/v1/kb-articles`.
|
|
5. Add missing API deny groups for financial, quotes, contracts, contract-line variants, services/products, accounting exports, platform/admin, tenant management, feature flags, full documents, automation/workflows, AI/chat, assets/RMM, scheduling/time, projects, surveys, extensions, and broad integrations.
|
|
6. Add representative tests for exact paths and unknown path fail-closed behavior.
|
|
|
|
### API remediation
|
|
|
|
1. Move product API enforcement to a place every authenticated API controller path must pass, such as authentication/context creation or a required wrapper.
|
|
2. Audit overridden controllers and custom route handlers.
|
|
3. Add product guards to standalone API route handlers outside `ApiBaseController`.
|
|
4. Ensure denied AlgaDesk API requests return structured 403 responses.
|
|
5. Ensure allowed AlgaDesk APIs continue to work.
|
|
6. Ensure PSA APIs remain unchanged.
|
|
|
|
### Metadata/OpenAPI remediation
|
|
|
|
1. Filter endpoint path lists by product.
|
|
2. Filter OpenAPI paths by product.
|
|
3. Filter schemas/models where they only support denied endpoints.
|
|
4. Filter generated permission metadata by product.
|
|
5. Filter stats/counts so AlgaDesk metadata is not misleading.
|
|
6. Preserve full PSA metadata for PSA tenants.
|
|
|
|
### Product error remediation
|
|
|
|
1. Standardize product-denied errors on `statusCode = 403` and `code = PRODUCT_ACCESS_DENIED`.
|
|
2. Update `handleApiError` or error classes so both `status` and `statusCode` product errors map to 403.
|
|
3. Ensure standalone route handlers return 403 for product denial rather than 500.
|
|
4. Add tests around representative API and route handlers.
|
|
|
|
### Contact/detail and document leak remediation
|
|
|
|
1. Fold in the relevant uncommitted contact document hiding changes.
|
|
2. Ensure AlgaDesk contact detail does not fetch contact documents for `tab=documents`.
|
|
3. Ensure AlgaDesk contact detail does not render the Documents tab.
|
|
4. Preserve PSA contact document behavior.
|
|
5. Add behavior/component tests for both AlgaDesk and PSA contact detail.
|
|
|
|
### Test remediation
|
|
|
|
1. Fix existing runnable tests that fail before executing.
|
|
2. Fix Playwright T015 helper signatures and route assumptions.
|
|
3. Ensure DB-backed tests use real database behavior and clean up tenant data.
|
|
4. Downgrade or rewrite source-string contract tests whose names claim integration behavior.
|
|
5. Add a small number of high-confidence tests for compile/session/shell/route/API/metadata/portal/email behavior.
|
|
6. Do not mark remediation tests implemented until they are runnable or explicitly documented as requiring external DB/browser prerequisites.
|
|
|
|
### Plan/checklist remediation
|
|
|
|
1. Create this remediation plan as the source of truth for fixing the current branch.
|
|
2. Update the parent plan scratchpad to reference this remediation plan if desired.
|
|
3. Revisit parent `features.json` and `tests.json` implementation status after remediation, or explicitly mark the parent plan superseded for implementation tracking.
|
|
4. Keep remediation `features.json` and `tests.json` honest.
|
|
|
|
## Security / Permissions
|
|
|
|
1. Product access is a security boundary in addition to UI composition.
|
|
2. AlgaDesk must fail closed on unknown product, unknown route group, or unknown API group.
|
|
3. AlgaDesk API keys must not access denied PSA endpoints even with broad RBAC permissions.
|
|
4. Product-denied errors should not expose sensitive implementation details.
|
|
5. Route guards must prevent excluded page data fetching, not merely hide rendered output.
|
|
|
|
## Rollout / Migration Notes
|
|
|
|
1. Remediation should preserve the existing `product_code` migration if it is correct.
|
|
2. Existing tenants should remain PSA by default.
|
|
3. Ensure auth/session changes are backward-compatible for sessions without `product_code` during rollout.
|
|
4. If token/session refresh behavior means old sessions lack `product_code`, define fallback behavior and force refresh strategy.
|
|
5. Keep the final branch reviewable: one or more commits focused on remediation categories, not mixed with env/lockfile noise.
|
|
|
|
## Open Questions
|
|
|
|
1. Should route guarding be implemented through middleware using session token product_code, page-level server helpers, or both?
|
|
2. Should AlgaDesk shell reuse the existing Sidebar component with a minimal provider stack, or introduce a dedicated AlgaDesk shell component?
|
|
3. How aggressively should metadata schema filtering remove PSA models that are shared by allowed and denied routes?
|
|
4. Which existing source-contract tests should be retained as lightweight guardrails after behavior tests are added?
|
|
5. Should the parent plan's 356 implemented feature flags be reset, partially corrected, or left with a superseded note?
|
|
|
|
## Acceptance Criteria
|
|
|
|
1. `cd server && npm run typecheck -- --pretty false` passes.
|
|
2. AlgaDesk `product_code` is present in JWT/session and `useProduct()` resolves AlgaDesk correctly.
|
|
3. AlgaDesk MSP tenants see a real shell/sidebar/header with only allowed navigation.
|
|
4. Direct server-side access to representative excluded MSP and portal routes does not execute excluded page data fetching.
|
|
5. Representative overridden API controllers deny AlgaDesk access before returning PSA data.
|
|
6. Standalone denied API routes return structured 403 product-denied responses.
|
|
7. Metadata/OpenAPI/docs no longer expose denied AlgaDesk API paths and do not leak obvious PSA-only permissions/stats.
|
|
8. Contact documents are hidden and not fetched for AlgaDesk, while PSA behavior remains unchanged.
|
|
9. The highest-risk tests run or have clearly documented external prerequisites.
|
|
10. Parent plan status is reconciled or explicitly superseded by this remediation plan.
|