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

7.2 KiB
Raw Permalink Blame History

Scratchpad — Hudu Phase 2 (Assets & Documents)

Decisions

  • 2026-06-11 — Scope settled with Natallia via three options questions: assets = import + pull sync (not mapping-only, not one-time import); articles = link-only section in client Documents tab; global view = Documents page "Hudu" tab (not global-search-only).
  • Sync is manual-only this phase (button per client); scheduled refresh stays a future enhancement (was already a Phase 1 non-goal).
  • Sync conflict policy: Hudu wins on synced fields only (name, serial_number); everything else in Alga untouched; asset_type never retro-changed after import/mapping.
  • Hudu disappearance → mapping metadata stale: true + badge. Never delete.
  • Layout→type map lives in hudu_integrations.settings.asset_layout_type_map (no new table); UI block inside HuduIntegrationSettings.
  • Asset mapping UI reuses the staged Save/Discard confirmation pattern built for company mappings on 2026-06-11 (picker stages; Save commits; dismissible suggestions; row revert/unmap actions).

Discoveries (verified in code)

  • tenant_external_entity_mappings unique indexes (server/migrations/20250502173321_…) are scoped by (tenant…, integration_type, alga_entity_type, …) → asset mappings (alga_entity_type='asset') coexist with Phase 1 client mappings. The original migration named the column tenant_id but Phase 1's companyMapping.ts queries tenant and its real-DB tests pass — a later rename superseded it. Mirror companyMapping.ts, not the old migration.
  • CreateAssetRequest (packages/types/src/interfaces/asset.interfaces.ts:378): fixed enum asset_type: 'workstation'|'network_device'|'server'| 'mobile_device'|'printer'|'unknown'; required asset_tag, name, status, client_id; optional serial_number; per-type extension blobs.
  • createAsset = packages/assets/src/actions/assetActions.ts:755 (withAuth wrapper → asset RBAC).
  • Client Documents tab: packages/clients/src/components/clients/ ClientDetails.tsx tab id documents (~line 1715). Phase 1 EE-injection precedent: useHuduClientTab(client.client_id) at line 283 + spread tabs at ~1844.
  • Main documents page: server/src/app/msp/documents/page.tsxpackages/documents/src/components/DocumentsPage.tsx.
  • Hudu API (plan dir hudu-api-reference.md): assets by company GET /api/v1/assets?company_id=&page=&archived=false; articles GET /api/v1/articles?company_id=&page=; global articles = omit company_id. Asset layouts: GET /api/v1/asset_layouts (verify response shape on local instance). 25/page, 300 req/min.
  • Hudu asset payload carries primary_serial, asset_layout_id, fields[] (layout custom fields), archived.

Environment / testing

  • Local Hudu: http://hudu.localtest.me (stack in ~/hudu2), API key unscoped, password access on. Companies: ExampleCo (1), Emerald City Ltd (2). Alga dev: bigmac worktree, localhost:3001, tenant c7c99e9f-19dd-46b0-80be-0a2a59f5ab7a (has enterprise add-on row). Flags forced via server/.env.local (NEXT_PUBLIC_FORCE_FEATURE_FLAGS
    • DISABLE_FEATURE_FLAGS=true).
  • Unit tests: cd ee/server && npx vitest run src/__tests__/unit/hudu — 273 passing pre-Phase-2 (incl. staged-save mapping manager rewrite).

Implementation findings

  • FR1 correction: idx_unique_external_mapping is (tenant, integration_type, external_entity_id, COALESCE(external_realm_id,'')) — NOT scoped by alga_entity_type (only the alga-direction index is). Hudu company and asset ids overlap numerically → asset mapping rows carry external_realm_id = String(hudu company id) (client rows use null). T215 proves coexistence with identical external ids.
  • getHuduAssetMappings reuses the Phase 1 getHuduCompanyAssets action for fetch+cache → effectively requires system_settings read in addition to asset read (technicians already have it for the client tab). Acceptable.
  • regression-phase2 DONE (2026-06-11): huduPermissions.test.ts now enumerates all 8 action modules (Phase 1 three + layoutMap/assetMapping/assetImport/ assetSync/globalDocs) — 97 tests. Layout-map actions joined the system_settings manage/view lists; the Technician flows got a resource+permission matrix (asset read/update/create, client read) plus an unauthenticated sweep over every entry (withAuth mock now drops the session user). T093 exhaustiveness still fails on any future unlisted export. T250 = information_schema column-list check in hudu-regression.integration.test.ts (real-DB harness): exactly the 12 Phase 1 columns, no pull-only additions (NFR4). T110 expected-file list extended with the 5 new action modules.
  • Found while running tsc for regression-phase2: 6 hudu type errors from earlier groups, all fixed — HuduAssetMappingManager.tsx relied on !result.success narrowing, which the non-strict EE tsconfig doesn't do (added isImportFailure/isBulkImportFailure guards, the file's existing isMappingFailure idiom); two TS2347s (type args on untyped vi helpers) in huduSettingsPageCategory.test.tsx / huduDocumentsTabGate.test.tsx became post-call casts. Remaining tsc errors are the known pre-existing chat registry / mcp agent-tooling / msp-composition ones (14).
  • HuduAsset in contracts.ts lacks asset_layout_id (runtime has it); typed locally in actions as HuduAssetListItem — consider lifting to contracts in a later group.

OQ resolutions (2026-06-11, verified on local instance)

  • OQ1 RESOLVED: GET /api/v1/articles?search= does case-insensitive partial matching ("vpn" → "VPN Setup Guide"); ?name= is exact-only. Use ?search=. Global list = omit company_id; response carries company_id per article.
  • OQ2 RESOLVED: assets.asset_tag is notNullable but has NO unique constraint (migration 20241112031330_create_asset_management_tables.cjs). primary_serial as tag is safe; hudu-<id> fallback only for missing serials. NOTE: assets table column is company_id (legacy name for client) + type_id uuid — the asset_type enum in CreateAssetRequest is the action-level API; verify createAsset's mapping when implementing.
  • Hudu asset payload verified: {id, name, company_id, asset_layout_id, primary_serial, archived, fields[]}. Default layouts on fresh instance incl. "Computer Assets" (7), "Databases" (9), "Applications" (3).
  • Seeded local data: articles (2× ExampleCo + 3 pre-existing, 1× Emerald), assets EC-WS-001 (SN-EC-1001), EC-SRV-01 (SN-EC-2001) in Computer Assets.
  • Git: commits require Natallia's explicit request (auto-mode enforces) — implement all groups, flip flags, let her commit per group at the end.

Gotchas

  • asset_tag uniqueness semantics unverified (R2) — check before using primary_serial as tag; fallback hudu-<id>.
  • Hudu article search param name unverified (OQ1): try ?search=, fall back to ?name=.
  • i18n: every new string needs en + de/es/fr/it/nl/pl/pt keys, and the Phase 1 static i18n test (huduI18n.test.ts) must be extended to scan the new components (it whitelists scanned sources explicitly).
  • DocumentsPage is a CE package — EE tab must inject via gate hook, never a hard import of EE components (R4).