Hermes 284313f908
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
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

6.9 KiB

Scratchpad — Client Portal Board Visibility Model Correction

  • Plan slug: client-portal-board-visibility-model-correction
  • Created: 2026-04-15

What This Is

Keep a lightweight, continuously-updated log of discoveries and decisions made while implementing this plan.

Decisions

  • (2026-04-15) Treat this work as an implementation correction, not a new feature or schema expansion.
  • (2026-04-15) Boards are tenant-scoped for this feature; visibility groups are client-scoped.
  • (2026-04-15) Board pickers should show all active tenant boards.
  • (2026-04-15) Inactive boards stay in stored group membership but should be excluded from board pickers and new ticket creation choices.
  • (2026-04-15) Keep visibility resolver board membership tenant-scoped without forcing active-only filtering so historical group membership data remains intact; enforce active-only for pickers and ticket creation paths.

Discoveries / Constraints

  • (2026-04-15) The original migration created client_portal_visibility_groups(tenant, group_id, client_id, ...) and client_portal_visibility_group_boards(tenant, group_id, board_id) but did not add boards.client_id.
  • (2026-04-15) The live schema confirms boards has no client_id column.
  • (2026-04-15) Current MSP and client-portal visibility-group actions query boards.client_id, causing intermittent 500s and false empty board states.
  • (2026-04-15) The shared resolver in packages/tickets/src/lib/clientPortalVisibility.ts also filters on b.client_id, so the mismatch affects enforcement, not just UI loading.
  • (2026-04-15) Candidate smoke client: Emerald City (ea00c9e1-a294-40f8-84e7-f3e9bb9dd41c) with active boards including General Support and Projects.
  • (2026-04-15) packages/clients visibility-group tests currently pull a transitive dependency path that fails in this workspace (@alga-psa/event-schemas export resolution via packages/workflow-streams), so package-local execution for those tests remains environment-blocked.

Commands / Runbooks

  • (2026-04-15) Verify migration/schema:
    • PGPASSWORD=postpass123 psql -h localhost -p 57433 -U postgres -d server -c "select to_regclass('public.client_portal_visibility_groups'), to_regclass('public.client_portal_visibility_group_boards');"
  • (2026-04-15) Inspect board schema:
    • PGPASSWORD=postpass123 psql -h localhost -p 57433 -U postgres -d server -Atc "select column_name from information_schema.columns where table_schema='public' and table_name='boards';"
  • (2026-04-15) Verify candidate smoke client boards/tickets:
    • PGPASSWORD=postpass123 psql -h localhost -p 57433 -U postgres -d server -F $'\t' -Atc "select b.board_id, b.board_name, count(*) from tickets t join boards b on b.board_id = t.board_id and b.tenant = t.tenant where t.client_id = 'ea00c9e1-a294-40f8-84e7-f3e9bb9dd41c' and t.is_closed = false group by b.board_id, b.board_name order by count(*) desc;"
  • (2026-04-15) Current live app / smoke context:
    • server URL http://localhost:3784
    • log pane 2c6e6434-e6bd-4f16-a306-4ddf10c5f3d5
  • (2026-04-15) Executed test commands:
    • cd packages/client-portal && npx vitest run src/actions/client-portal-actions/visibilityGroupActions.test.ts
    • cd packages/tickets && npx vitest run src/lib/clientPortalVisibility.test.ts src/lib/clientPortalVisibility.userModelLifecycle.test.ts src/actions/ticketFormActions.clientPortalVisibility.test.ts
    • cd packages/client-portal && npx vitest run src/actions/client-portal-actions/client-tickets.visibility.test.ts -t "rejects inactive boards"
    • cd packages/clients && npx vitest run src/actions/contact-actions/visibilityGroupActions.integration.test.ts src/actions/contact-actions/visibilityGroupActions.permission.test.ts (blocked by package export resolution issue described above)
  • Original feature PRD: ee/docs/plans/2026-03-15-client-portal-board-visibility-groups/PRD.md
  • Model-correction design: docs/plans/2026-04-15-client-portal-board-visibility-model-correction-design.md
  • Migration: server/migrations/20260315110000_create_client_portal_visibility_groups.cjs
  • MSP contact actions: packages/clients/src/actions/contact-actions/contactActions.tsx
  • Client portal group actions: packages/client-portal/src/actions/client-portal-actions/visibilityGroupActions.ts
  • Shared resolver: packages/tickets/src/lib/clientPortalVisibility.ts

Open Questions

  • Whether inactive boards should remain effective for historical ticket-detail visibility or be fully excluded from resolved board IDs as well as pickers/creation. Current default is to preserve historical membership and only exclude from pickers and creation choices.

Implementation Log

  • (2026-04-15) F001, F013: Updated MSP board picker action (getClientPortalVisibilityBoardsByClient) to load active boards by tenant only (tenant + is_inactive=false) without boards.client_id.
  • (2026-04-15) F003, F004: Updated MSP create/update group validation to accept only board IDs that exist in-tenant and are active (is_inactive=false), rejecting missing/cross-tenant/inactive IDs with existing validation error.
  • (2026-04-15) F002, F013: Updated client-portal admin board picker action (getClientPortalVisibilityGroupBoards) to load active tenant boards without boards.client_id.
  • (2026-04-15) F003, F004: Replaced ensureBoardsBelongToClient with ensureBoardsAreActiveInTenant for client-portal admin create/update flows.
  • (2026-04-15) F007, F008: Updated shared resolver (getClientContactVisibilityContext) to remove b.client_id filtering while preserving strict group.client_id === contact.client_id mismatch guard.
  • (2026-04-15) F011, F014: Updated ticket creation board option loading (getClientTicketFormData) to exclude inactive boards for both unrestricted and restricted contacts.
  • (2026-04-15) F011, F014: Updated client portal ticket submit flow (createClientTicket) to resolve boards only from active records (is_inactive=false) and fail closed when requested board is inactive/disallowed.
  • (2026-04-15) F016: Updated model-facing docs (context.md) and added smoke runbook artifact (SMOKE.md) clarifying tenant-scoped boards vs client-scoped groups.
  • (2026-04-15) T001: Added MSP board-loading integration test to assert tenant-only active-board query path (no client_id filter requirement).
  • (2026-04-15) T002: Added client-portal admin board-loading test to assert active tenant board loading path.
  • (2026-04-15) T003: Added explicit inactive-board rejection test for visibility-group creation.
  • (2026-04-15) T005, T011: Updated resolver lifecycle/unit tests to remove b.client_id assumptions and added explicit empty-group behavior coverage.
  • (2026-04-15) T008: Added ticket form and ticket creation tests to verify inactive boards are excluded/rejected under restricted visibility.
  • (2026-04-15) T012: Added SMOKE.md runbook for Emerald City seeded-scenario validation across restricted/full/pre-invite flows.