Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
16 KiB
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..09f09a919onfeature/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:
- MSP dashboard focused on ticket and email health.
- Ticket list/detail, comments, assignment, boards, statuses, priorities, categories, tags, response state, attachments, and email conversation context.
- Clients, contacts, and locations needed for support.
- Client portal dashboard, free-form tickets, ticket detail/replies, knowledge base, profile, and client settings.
- Ticket attachments and knowledge base, but not full document management.
- Email-to-ticket and ticket reply/update by email.
- 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
-
Typecheck fails.
- Command:
cd server && npm run typecheck -- --pretty false - Failing files include:
server/src/components/layout/SidebarWithFeatureFlags.tsxserver/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 withNavigationSection.
- Command:
-
Client product context defaults AlgaDesk users to PSA.
server/src/context/ProductContext.tsxreadssession.user.product_code.packages/auth/src/lib/nextAuthOptions.tsfetches/mapsplan, but notproduct_code.- Client components using
useProduct()can expose PSA surfaces for AlgaDesk tenants.
-
AlgaDesk MSP shell bypasses sidebar/header.
server/src/app/msp/MspLayoutClient.tsxrenders raw children inside<div data-product-shell="algadesk">for AlgaDesk.- This does not mount a real AlgaDesk sidebar/header/layout.
-
Browser route boundary is client-side only.
- MSP and portal layout clients use
usePathname()and renderProductRouteBoundaryclient-side. - Excluded server pages may still execute data fetching before the boundary UI appears.
- Product boundaries must prevent excluded page execution server-side.
- MSP and portal layout clients use
-
API product enforcement is bypassed by overridden controllers.
ApiBaseControllerchecks 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.
-
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.
- Portal sidebar can show
-
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.
-
Product-denied errors are not consistently mapped to 403.
ProductAccessErrorusesstatus = 403.- Some API error handlers honor
statusCode, so product denial can become 500. - Some route handlers catch product denial as generic errors.
-
Test/checklist status is overclaimed.
- Parent
features.jsonmarks 356/356 implemented. - Parent
tests.jsonmarks 27/27 implemented. - This does not reflect current blockers.
- Many tests are source-string contracts rather than behavior/integration tests matching their descriptions.
- Parent
-
There are unsafe/unrelated uncommitted changes.
.env.localtestcontains plaintext DB credentials and must not be committed.package-lock.jsonhas 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
- Make the branch compile.
- Make product entitlement available consistently on server and client session contexts.
- Render a real AlgaDesk MSP shell with sidebar/header while avoiding full PSA cross-feature providers.
- Enforce product route boundaries server-side before excluded page data fetching.
- Make API product gates unavoidable for controller-backed and standalone API routes.
- Complete and correct the product surface registry for browser, portal, API, settings, and metadata use cases.
- Ensure ProductAccessError maps to structured 403 responses everywhere product guards are used.
- Replace misleading or non-runnable tests with a small set of real confidence-building tests.
- Correct the parent checklist status or explicitly annotate it as superseded by this remediation plan.
- Preserve existing PSA behavior.
Non-goals
- Do not add new AlgaDesk product scope beyond the parent PRD.
- Do not create a separate app, database, process, or repository.
- Do not redesign ticketing, client portal, email, or API frameworks beyond what is needed for enforcement.
- Do not strive for comprehensive test coverage.
- Do not commit local secrets or incidental lockfile noise.
- Do not mark remediation features/tests implemented until verified by compiling/running relevant checks.
Target Users and Flows
Remediation engineer
- Starts from the current feature branch.
- Cleans local/uncommitted noise.
- Fixes compile/session/registry/enforcement blockers.
- Runs targeted confidence-building tests.
- Updates plan status honestly.
- Hands off a branch that can be reviewed without hidden PSA leaks.
AlgaDesk MSP user after remediation
- Logs into an AlgaDesk tenant.
- Sees an AlgaDesk-branded shell with help-desk navigation, not raw page content.
- Can access dashboard, tickets, clients, contacts, KB, and allowed settings.
- Direct hits to excluded PSA pages are blocked server-side before data fetching.
AlgaDesk API consumer after remediation
- Uses an API key for an AlgaDesk tenant.
- Allowed APIs work.
- PSA-only APIs fail with structured 403 product-denied responses even when a controller overrides base CRUD methods.
- Metadata/OpenAPI/docs do not expose denied PSA paths, schemas, permissions, or misleading stats.
Functional Requirements
Hygiene and baseline
- Keep remediation work isolated from local env and lockfile noise.
- Do not commit
.env.localtestcredential changes. - Revert or justify
package-lock.jsonversion changes before merge. - Record current known blockers and commands in the remediation scratchpad.
Type/session remediation
- Define
product_codein the shared NextAuth type augmentation used by both package and server consumers. - Remove conflicting duplicate declarations.
- Fetch
product_codewith tenant subscription/product info. - Persist
product_codeonto JWT token on initial sign-in and refresh paths. - Copy
product_codefrom JWT token intosession.user. - Keep
plan, addons, and trial fields unchanged. - Make
ProductProviderresolve AlgaDesk correctly from session. - Add tests proving AlgaDesk sessions do not default to PSA.
AlgaDesk shell remediation
- Replace raw AlgaDesk children rendering with a real AlgaDesk shell.
- Shell must include sidebar, header/app chrome, main content area, and product branding.
- Shell must avoid full PSA providers for workflows, scheduling, projects, assets, SLA, surveys, extensions, and AI chat.
- Sidebar filtering must typecheck and preserve PSA behavior.
- Settings navigation must align with route registry and allowed tabs.
Server route boundary remediation
- Add server-side product route guard helpers.
- Apply guards before excluded server page data fetching.
- Ensure major excluded MSP routes render upgrade boundary or not-found according to registry.
- Ensure major excluded portal routes render upgrade boundary or not-found according to registry.
- Keep client-side boundary only as a secondary safety net, not primary enforcement.
- Ensure allowed AlgaDesk pages still render their AlgaDesk compositions.
Registry remediation
- Correct MSP settings route and tab behavior.
- Allow
/client-portal/client-settingsfor AlgaDesk. - Deny excluded portal surfaces consistently.
- Correct API allowed route names, especially
/api/v1/kb-articles. - 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.
- Add representative tests for exact paths and unknown path fail-closed behavior.
API remediation
- Move product API enforcement to a place every authenticated API controller path must pass, such as authentication/context creation or a required wrapper.
- Audit overridden controllers and custom route handlers.
- Add product guards to standalone API route handlers outside
ApiBaseController. - Ensure denied AlgaDesk API requests return structured 403 responses.
- Ensure allowed AlgaDesk APIs continue to work.
- Ensure PSA APIs remain unchanged.
Metadata/OpenAPI remediation
- Filter endpoint path lists by product.
- Filter OpenAPI paths by product.
- Filter schemas/models where they only support denied endpoints.
- Filter generated permission metadata by product.
- Filter stats/counts so AlgaDesk metadata is not misleading.
- Preserve full PSA metadata for PSA tenants.
Product error remediation
- Standardize product-denied errors on
statusCode = 403andcode = PRODUCT_ACCESS_DENIED. - Update
handleApiErroror error classes so bothstatusandstatusCodeproduct errors map to 403. - Ensure standalone route handlers return 403 for product denial rather than 500.
- Add tests around representative API and route handlers.
Contact/detail and document leak remediation
- Fold in the relevant uncommitted contact document hiding changes.
- Ensure AlgaDesk contact detail does not fetch contact documents for
tab=documents. - Ensure AlgaDesk contact detail does not render the Documents tab.
- Preserve PSA contact document behavior.
- Add behavior/component tests for both AlgaDesk and PSA contact detail.
Test remediation
- Fix existing runnable tests that fail before executing.
- Fix Playwright T015 helper signatures and route assumptions.
- Ensure DB-backed tests use real database behavior and clean up tenant data.
- Downgrade or rewrite source-string contract tests whose names claim integration behavior.
- Add a small number of high-confidence tests for compile/session/shell/route/API/metadata/portal/email behavior.
- Do not mark remediation tests implemented until they are runnable or explicitly documented as requiring external DB/browser prerequisites.
Plan/checklist remediation
- Create this remediation plan as the source of truth for fixing the current branch.
- Update the parent plan scratchpad to reference this remediation plan if desired.
- Revisit parent
features.jsonandtests.jsonimplementation status after remediation, or explicitly mark the parent plan superseded for implementation tracking. - Keep remediation
features.jsonandtests.jsonhonest.
Security / Permissions
- Product access is a security boundary in addition to UI composition.
- AlgaDesk must fail closed on unknown product, unknown route group, or unknown API group.
- AlgaDesk API keys must not access denied PSA endpoints even with broad RBAC permissions.
- Product-denied errors should not expose sensitive implementation details.
- Route guards must prevent excluded page data fetching, not merely hide rendered output.
Rollout / Migration Notes
- Remediation should preserve the existing
product_codemigration if it is correct. - Existing tenants should remain PSA by default.
- Ensure auth/session changes are backward-compatible for sessions without
product_codeduring rollout. - If token/session refresh behavior means old sessions lack
product_code, define fallback behavior and force refresh strategy. - Keep the final branch reviewable: one or more commits focused on remediation categories, not mixed with env/lockfile noise.
Open Questions
- Should route guarding be implemented through middleware using session token product_code, page-level server helpers, or both?
- Should AlgaDesk shell reuse the existing Sidebar component with a minimal provider stack, or introduce a dedicated AlgaDesk shell component?
- How aggressively should metadata schema filtering remove PSA models that are shared by allowed and denied routes?
- Which existing source-contract tests should be retained as lightweight guardrails after behavior tests are added?
- Should the parent plan's 356 implemented feature flags be reset, partially corrected, or left with a superseded note?
Acceptance Criteria
cd server && npm run typecheck -- --pretty falsepasses.- AlgaDesk
product_codeis present in JWT/session anduseProduct()resolves AlgaDesk correctly. - AlgaDesk MSP tenants see a real shell/sidebar/header with only allowed navigation.
- Direct server-side access to representative excluded MSP and portal routes does not execute excluded page data fetching.
- Representative overridden API controllers deny AlgaDesk access before returning PSA data.
- Standalone denied API routes return structured 403 product-denied responses.
- Metadata/OpenAPI/docs no longer expose denied AlgaDesk API paths and do not leak obvious PSA-only permissions/stats.
- Contact documents are hidden and not fetched for AlgaDesk, while PSA behavior remains unchanged.
- The highest-risk tests run or have clearly documented external prerequisites.
- Parent plan status is reconciled or explicitly superseded by this remediation plan.