Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
16 KiB
Scratchpad: Stale Code Quick Wins
Key Discoveries
Media package exists for a reason that no longer applies
The @alga-psa/media package was created to break the cycle documents -> users -> media -> documents. This cycle was resolved and removed from the known-cycles baseline. The media package's dynamic import workarounds (getStorageServiceAsync(), deleteDocumentAsync(), getDocumentTypeIdAsync()) are no longer needed -- the canonical documents/lib/entityImageService.ts uses direct imports to @alga-psa/storage/StorageService and internal documentActions.
Three copies of avatarUtils exist
@alga-psa/formatting/avatarUtils.ts(228 LOC) -- usesgetImageUrlInternalfrom./imageUrl.ts@alga-psa/user-composition/lib/avatarUtils.ts(~95 LOC) -- has its owngetImageUrlInternalLiteinline@alga-psa/media/lib/avatarUtils.ts(87 LOC) -- uses dynamic import from documents
This PR deletes #3. Consolidating #1 and #2 is a separate future task.
getTeamAvatarUrl only exists in media
The formatting package's EntityType already includes 'team', and getEntityImageUrl works for any entity type. But there's no getTeamAvatarUrl convenience function. Adding one is a trivial 4-line wrapper.
documents version of EntityImageService is the canonical one
The @alga-psa/documents version:
- Uses direct
StorageServiceimport (not dynamic) - Uses direct
deleteDocument/getDocumentTypeIdcalls - Has
isActionPermissionErrorhandling - Already used by 4 other packages (
clients,client-portal,tenancy, documents-internal)
The media version:
- Uses dynamic imports to break cycles (no longer needed)
- Less robust error handling (no permission error check)
- Only used by 3 callers (users x2, teams x1)
Cross-package violations trade-off
Adding users -> documents creates 2 new lint warnings. But:
- 4 other packages already do this exact import
- We delete an entire package (8 files) in exchange
teams -> documentscreates NO warning (teams not in VERTICAL_PACKAGES)
Test file reads source files via fs.readFileSync
server/src/test/teams-v2-improvements.test.ts does string-content assertions on source files:
const mediaAvatarUtils = read('packages/media/src/lib/avatarUtils.ts');
This must be updated to point at the formatting file, and assertions T085/T089 need adjustment.
Avatar Bug 1: Client portal user avatars on MSP user list
Root cause chain:
- Client portal user uploads avatar via
uploadContactAvatar(user.contact_id, formData)inclientUserActions.ts:289 - This stores
entity_type='contact',entity_id=contact_idindocument_associations - MSP UserList fetches via
getUserAvatarUrlAction(user.user_id)which queriesentity_type='user',entity_id=user_id - No match → null → no avatar displayed
Fix: Branch on user.user_type in UserList.tsx avatar fetch loop. Use getContactAvatarUrlAction(user.contact_id) for client users.
Avatar Bug 2: Contact avatar '?' fallback
Root cause chain:
ContactAvatarUpload.tsx:38passesentityName=""toEntityImageUploadEntityImageUploadrendersUserAvatarwithuserName=""ContactAvatar.getContactInitialsreturns'?'when!name(line 12 ofContactAvatar.tsx)
Fix: Add contactName: string prop to ContactAvatarUpload, pass it as entityName. Update 2 callers (ContactDetails.tsx, ContactDetailsEdit.tsx) to pass the contact's full_name.
Build Command
Use instead of npm run build:
NODE_OPTIONS=--max-old-space-size=32768 npx nx run-many -t build --maxParallel=4
File Inventory
Files to delete (10 total)
server/src/lib/posthog.ts(7 LOC)server/src/lib/actions/tenant-secret-actions.ts(222 LOC)packages/media/src/index.ts(3 LOC)packages/media/src/lib/avatarUtils.ts(87 LOC)packages/media/src/lib/documentsHelpers.ts(32 LOC)packages/media/src/services/EntityImageService.ts(296 LOC)packages/media/package.jsonpackages/media/project.jsonpackages/media/tsconfig.jsonpackages/media/tsup.config.ts
Files to edit (15 total)
server/src/components/settings/secrets/SecretsManagement.tsx(import path)server/src/components/settings/secrets/SecretDialog.tsx(import path)packages/formatting/src/avatarUtils.ts(add getTeamAvatarUrl)packages/users/src/services/UserService.ts(import paths)packages/users/src/actions/user-actions/userActions.ts(import path)packages/users/package.json(dependencies)packages/teams/src/actions/team-actions/avatarActions.ts(import paths)packages/teams/package.json(dependencies)server/next.config.mjs(remove media alias)server/tsconfig.json(remove media paths)ee/server/tsconfig.json(remove media paths)services/workflow-worker/Dockerfile(remove media workspace)server/src/test/teams-v2-improvements.test.ts(update file paths + assertions)server/src/components/settings/general/UserList.tsx(avatar fetch branch)packages/clients/src/components/contacts/ContactAvatarUpload.tsx(add contactName prop)packages/clients/src/components/contacts/ContactDetails.tsx(pass contactName)packages/clients/src/components/contacts/ContactDetailsEdit.tsx(pass contactName)
Execution Order
- Task 1: Delete posthog.ts (independent, no deps)
- Task 2: Redirect tenant-secret-actions callers, delete server copy (independent)
- Task 3: Media deletion (depends on nothing, but do in sub-steps):
a. Add
getTeamAvatarUrlto formatting b. Update 3 caller files (import paths) c. Update 2 package.json files (dependencies) d. Update test file e. Update config files (next.config, tsconfig x2, Dockerfile) f. Deletepackages/media/directory g.npm installto update lock file - Task 4: Fix UserList.tsx avatar fetch for client portal users
- Task 5: Fix ContactAvatarUpload.tsx and its 2 callers
- Build verification
Gotchas
- The
teams-v2-improvements.test.tstest does string matching on file content -- it will ENOENT if media files are deleted before the test path is updated. server/next.config.mjshas media referenced in 3 separate places (aliases object, transpilePackages array, resolve.alias). All 3 must be removed.package-lock.jsonwill have stale entries for@alga-psa/mediauntilnpm installis run.- The Dockerfile
--workspace=@alga-psa/medialine is in aCOPYinstruction context -- verify the line can be cleanly removed without breaking the multi-line command. - T102 in
teams-v2-improvements.test.tschecks that@alga-psa/mediais in teams package.json deps -- must update to check for@alga-psa/documentsand@alga-psa/formattinginstead.
Progress Log
- F001: Deleted
server/src/lib/posthog.tsafter validating the deprecated wrapper path had no remaining imports. - F002: Pointed
SecretsManagement.tsxat@alga-psa/tenancy/actionsso it uses the canonical tenant secret actions barrel. - F003: Updated
SecretDialog.tsxto import secret CRUD helpers from the canonical@alga-psa/tenancy/actionsbarrel. - F004: Deleted
server/src/lib/actions/tenant-secret-actions.tsonce both settings callers had been redirected to@alga-psa/tenancy/actions. - F005: Added
getTeamAvatarUrltopackages/formatting/src/avatarUtils.tsas the canonical wrapper overgetEntityImageUrl('team', ...). - F006: Repointed
packages/users/src/services/UserService.tsto import avatar URL lookup from formatting and image mutations from documents. - F007: Updated
packages/users/src/actions/user-actions/userActions.tsto consume entity image mutations from@alga-psa/documents. - F008: Split
packages/teams/src/actions/team-actions/avatarActions.tsimports across canonical documents and formatting packages. - F009: Replaced the stale
@alga-psa/mediadependency inpackages/users/package.jsonwith canonicaldocumentsandformattingpackage dependencies. - F010: Replaced the teams package dependency on
@alga-psa/mediawith the canonical documents and formatting packages. - F011: Removed all
@alga-psa/mediaalias and transpilation wiring fromserver/next.config.mjs. - F012: Removed the
@alga-psa/mediapath mappings fromserver/tsconfig.json. - F013: Removed the stale
@alga-psa/mediapath mappings fromee/server/tsconfig.json. - F014: Dropped the deleted
@alga-psa/mediaworkspace fromservices/workflow-worker/Dockerfile. - F015: Updated
server/src/test/teams-v2-improvements.test.tsto read formatting avatar utilities and assert the new canonical package dependencies. - F016: Deleted
packages/media/entirely after migrating its three callers, config references, and the source-reading regression test. - F017: Ran
npm installto refreshpackage-lock.jsonafter removing@alga-psa/mediaand adding canonical package dependencies. - F018: Imported
getContactAvatarUrlActionintoUserList.tsxto support client-user avatar lookup via contact records. - F019: Updated the
UserList.tsxavatar lookup loop to fetch contact avatars for client users, preserve user avatars for internal users, and fall back tonullwhen a client user lackscontact_id. - F020: Added a required
contactNameprop toContactAvatarUploadPropsand plumbed it into the component signature. - F021: Replaced the hardcoded empty
entityNameinContactAvatarUploadwith the newcontactNameprop so initials render correctly. - F022: Updated
ContactDetails.tsxto passeditedContact.full_nameintoContactAvatarUpload. - F023: Updated
ContactDetailsEdit.tsxto passcontact.full_nameintoContactAvatarUpload. - Discovery: the first full build after F023 failed because
server/src/app/api/secrets/route.tsandserver/src/app/api/secrets/[name]/route.tsstill imported the deleted server duplicate. Added follow-up itemsF023A/F023BandT041A/T041Bso the plan matches the real remaining work. - F023A: Repointed
server/src/app/api/secrets/route.tsto@alga-psa/tenancy/actionsto remove the hidden stale import found by the build. - F023B: Repointed
server/src/app/api/secrets/[name]/route.tsto@alga-psa/tenancy/actionsso the build no longer looks for the deleted server duplicate. - F024: Re-ran
NODE_OPTIONS=--max-old-space-size=32768 npx nx run-many -t build --maxParallel=4after fixing the hidden secrets API imports; the full build completed successfully. - Discovery: added
T042Abecause the PRD explicitly requiresserver/src/test/teams-v2-improvements.test.tsto pass after the media cleanup. - T001: Confirmed the deprecated
@/lib/posthogwrapper path has zero remaining imports anywhere outside docs and lockfiles. - T002: Verified
server/src/lib/posthog.tsis absent on disk after F001. - T003: Verified
SecretsManagement.tsximports tenant secret helpers from@alga-psa/tenancy/actions. - T004: Verified
SecretDialog.tsximports its secret helpers from@alga-psa/tenancy/actions. - T005: Verified the deleted server-side
tenant-secret-actions.tsduplicate is no longer present. - T006: Confirmed
server/src/no longer referencestenant-secret-actionsoutside excluded test/docs paths. - T007: Corrected the outdated checklist wording and verified the tenancy barrel re-exports the exact secret helpers now used by the settings UI and API routes.
- Discovery: added
T042Abecause the PRD explicitly requiresserver/src/test/teams-v2-improvements.test.tsto pass after the media cleanup. - T001: Confirmed the deprecated @/lib/posthog wrapper path has zero remaining imports anywhere outside docs and lockfiles.
- T002: Verified server/src/lib/posthog.ts is absent on disk after F001.
- T003: Verified SecretsManagement.tsx imports tenant secret helpers from @alga-psa/tenancy/actions.
- T004: Verified SecretDialog.tsx imports its secret helpers from @alga-psa/tenancy/actions.
- T005: Verified the deleted server-side tenant-secret-actions.ts duplicate is no longer present.
- T006: Confirmed server/src no longer references tenant-secret-actions outside excluded test/docs paths.
- T007: Corrected the outdated checklist wording and verified the tenancy barrel re-exports the exact secret helpers now used by the settings UI and API routes.
- T008: Verified getTeamAvatarUrl exists in formatting and delegates to getEntityImageUrl('team', teamId, tenant).
- T009: Confirmed getTeamAvatarUrl is exported directly from packages/formatting/src/avatarUtils.ts.
- T010: Verified UserService.ts imports getUserAvatarUrl from formatting instead of the deleted media package.
- T011: Verified UserService.ts imports uploadEntityImage and deleteEntityImage from @alga-psa/documents.
- T012: Verified userActions.ts imports uploadEntityImage and deleteEntityImage from @alga-psa/documents.
- T013: Verified teams avatarActions.ts imports uploadEntityImage and deleteEntityImage from @alga-psa/documents.
- T014: Verified teams avatarActions.ts imports getTeamAvatarUrl from formatting instead of media.
- T015: Verified packages/users/package.json no longer lists @alga-psa/media in dependencies.
- T016: Verified packages/users/package.json includes canonical documents and formatting dependencies.
- T017: Verified packages/teams/package.json no longer lists @alga-psa/media in dependencies.
- T018: Verified packages/teams/package.json includes canonical documents and formatting dependencies.
- T019: Confirmed server/next.config.mjs no longer contains any @alga-psa/media alias or transpile references.
- T020: Confirmed server/tsconfig.json no longer contains @alga-psa/media path mappings.
- T021: Confirmed ee/server/tsconfig.json no longer contains @alga-psa/media path mappings.
- T022: Confirmed the workflow-worker Dockerfile no longer references the deleted @alga-psa/media workspace.
- T023: Verified teams-v2-improvements.test.ts now reads packages/formatting/src/avatarUtils.ts instead of the deleted media file.
- T024: Verified the T085 assertion now checks formatting avatar utils for the team EntityType entry.
- T025: Verified the T089 assertion now checks formatting avatar utils for getTeamAvatarUrl.
- T026: Verified the entire packages/media directory has been removed from disk.
- T027: Confirmed there are no remaining @alga-psa/media references outside docs, plan artifacts, lockfiles, and AI metadata.
- T028: Re-ran npm install successfully after the dependency cleanup; see /tmp/t028-npm-install.log for the command output from this validation run.
- T029: Re-ran the full Nx build successfully; output captured in /tmp/t029-build.log.
- T030: Generated a fresh Nx graph and confirmed scripts/check-circular-deps.mjs reports no new cycles against .github/known-cycles.json.
- T031: Checked all modified source/config files and confirmed none are shim-only re-export files.
- T032: Verified packages/documents/src/lib/entityImageService.ts exports EntityType, uploadEntityImage, and deleteEntityImage for migrated callers.
- T033: Verified packages/formatting/src/avatarUtils.ts exports both getUserAvatarUrl and getTeamAvatarUrl.
- T034: Verified UserList.tsx imports getContactAvatarUrlAction alongside getUserAvatarUrlAction from @alga-psa/user-composition/actions.
- T035: Verified the avatar fetch loop branches on user.user_type === 'client' and uses getContactAvatarUrlAction(user.contact_id, user.tenant).
- T036: Verified the avatar fetch loop still uses getUserAvatarUrlAction(user.user_id, user.tenant) for non-client users.
- T037: Verified client users without contact_id fall back to a null avatar instead of querying the wrong entity type.
- T038: Verified ContactAvatarUploadProps includes a required contactName: string prop.
- T039: Verified ContactAvatarUpload passes contactName through as EntityImageUpload.entityName.
- T040: Verified ContactDetails.tsx passes editedContact.full_name to ContactAvatarUpload.
- T041: Verified ContactDetailsEdit.tsx passes contact.full_name to ContactAvatarUpload.
- T041A: Verified server/src/app/api/secrets/route.ts imports tenant secret actions from @alga-psa/tenancy/actions.
- T041B: Verified server/src/app/api/secrets/[name]/route.ts imports tenant secret actions from @alga-psa/tenancy/actions.
- T042A: Updated
server/src/test/teams-v2-improvements.test.tsto read the existingpackages/user-composition/src/lib/avatarUtils.tssource and to assert the current TeamDetails/UserManagement structure before rerunning the test successfully. - T042: Reused the successful full-build validation from T029, which ran after all planned feature work was complete.