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
7.2 KiB
7.2 KiB
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_typenever 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_mappingsunique 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 columntenant_idbut Phase 1's companyMapping.ts queriestenantand 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 enumasset_type: 'workstation'|'network_device'|'server'| 'mobile_device'|'printer'|'unknown'; requiredasset_tag,name,status,client_id; optionalserial_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.tsxtab iddocuments(~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.tsx→packages/documents/src/components/DocumentsPage.tsx. - Hudu API (plan dir
hudu-api-reference.md): assets by companyGET /api/v1/assets?company_id=&page=&archived=false; articlesGET /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, tenantc7c99e9f-19dd-46b0-80be-0a2a59f5ab7a(hasenterpriseadd-on row). Flags forced viaserver/.env.local(NEXT_PUBLIC_FORCE_FEATURE_FLAGSDISABLE_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_mappingis(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 carryexternal_realm_id = String(hudu company id)(client rows use null). T215 proves coexistence with identical external ids. getHuduAssetMappingsreuses the Phase 1getHuduCompanyAssetsaction 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.successnarrowing, 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). HuduAssetin contracts.ts lacksasset_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 = omitcompany_id; response carriescompany_idper article. - OQ2 RESOLVED:
assets.asset_tagis notNullable but has NO unique constraint (migration20241112031330_create_asset_management_tables.cjs).primary_serialas tag is safe;hudu-<id>fallback only for missing serials. NOTE: assets table column iscompany_id(legacy name for client) +type_iduuid — theasset_typeenum 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_taguniqueness semantics unverified (R2) — check before usingprimary_serialas tag; fallbackhudu-<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).