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

20 KiB
Raw Permalink Blame History

Scratchpad — Tanium RMM Integration Plan

  • Plan slug: tanium-rmm-integration-plan
  • Created: 2026-04-06

What This Is

Working notes for the Tanium RMM planning effort. This is intentionally biased toward repo seams, official Tanium guidance, and concrete implementation consequences.

Decisions

  • (2026-04-06) Tanium should not be implemented by copying NinjaOne or Tactical RMM. The missing seam is a shared provider registry plus shared normalized ingestion pipeline.
  • (2026-04-06) tenant_external_entity_mappings is the main simplification-cascade seam. Treat external RMM providers as identity sources that feed one shared asset correlation/upsert path.
  • (2026-04-06) Tanium v1 is pull-oriented and Gateway-first.
  • (2026-04-06) Tanium Connect is a later optional capability for outbound/event-triggered delivery, not a prerequisite for inventory sync.
  • (2026-04-06) Tanium Asset API is a fallback for aged-out endpoint coverage, not the primary default integration surface.
  • (2026-04-06) Tanium Direct Connect / Threat Response should be capability-flagged later work, not v1 scope.
  • (2026-04-06) Feature F001 is complete: plan artifacts now capture exact documented Gateway query/object/mutation families for inventory, scope discovery, actions, Connect, and Direct Connect, plus Asset API fallback posture and assetUpsertEndpoints usage constraints.

Discoveries / Constraints

  • (2026-04-06) Current RMM UI is hard-coded in packages/integrations/src/components/settings/integrations/RmmIntegrationsSetup.tsx.
  • (2026-04-06) Current public ingress handling is hard-coded in server/src/middleware.ts for /api/integrations/ninjaone/callback, /api/webhooks/ninjaone, and /api/webhooks/tacticalrmm.
  • (2026-04-06) Shared RMM types already leak provider specifics, for example ninja_instance_region inside ee/server/src/interfaces/rmm.interfaces.ts.
  • (2026-04-06) NinjaOne sync logic is split across provider-specific strategy/orchestration and duplicated persistence logic in Temporal activities.
  • (2026-04-06) Tactical RMM keeps orchestration and persistence mostly inside one large action file, which reinforces the need for a shared ingestion seam before adding Tanium.
  • (2026-04-06) Official Tanium docs say Gateway is preferred for querying online and offline systems, managing groups, deploying actions, establishing direct endpoint connections, and inserting/updating Asset records.
  • (2026-04-06) Official Tanium docs say Connect is best for scheduled or event-triggered outbound delivery, including webhook destinations and detected-event delivery.
  • (2026-04-06) Official Tanium docs say Asset API is useful for endpoints that have aged out of TDS.
  • (2026-04-06) Feature F002 implementation detail: provider unions are duplicated across packages/types, server, and ee/server; adding a provider requires touching all three type seams until a single source-of-truth type export is introduced.
  • (2026-04-06) Feature F003/F004 implementation detail: provider metadata and capability gating are now centralized in packages/integrations/src/lib/rmm/providerRegistry.ts, while provider settings components remain pluggable in UI composition code.
  • (2026-04-06) Feature F005F009 implementation detail: normalized RMM contracts and the shared ingestion engine now live in packages/integrations/src/lib/rmm/, allowing provider fetchers to hand off provider-neutral snapshots into a single create/update/delete pipeline.
  • (2026-04-06) Feature F010F018 implementation detail: Tanium v1 is implemented as pull-oriented server actions backed by a Gateway client plus shared ingestion, with no public webhook/callback route additions.

Gateway Schema Findings

  • (2026-04-06) Logged-in Gateway docs expose stable route families under https://developer.tanium.com/apis/tanium_gateway_schema/{queries|mutations|objects}/....
  • (2026-04-06) For Tanium inventory, the primary query surface is confirmed in the schema:
    • endpoints(...args)
    • endpointCounts(input)
    • endpointIdChanges(...args)
    • endpointLastSeen(eids)
  • (2026-04-06) The endpoint object family is concrete and broad enough for normalized inventory snapshots:
    • Endpoint
    • EndpointConnection
    • EndpointEdge
    • EndpointOS
    • EndpointUser
    • EndpointInstalledApplication
    • EndpointMetric
    • EndpointCompliance
  • (2026-04-06) The schema exposes a natural scope/group surface for client mapping:
    • queries: computerGroup(ref), computerGroups(...args)
    • objects: ComputerGroup, ComputerGroupConnection, ComputerGroupEdge
    • mutations also exist for later admin workflows: computerGroupCreate(input), computerGroupDelete(ref)
  • (2026-04-06) The schema exposes Connect as a first-class later event/export surface:
    • queries: connectConnection(ref), connectConnections(...args), connectRun(ref), connectRuns(...args)
    • objects: ConnectConnection, ConnectGraphConnection, ConnectRun, ConnectRunConnection
    • mutations: connectConnectionStart(input), connectConnectionStop(input)
  • (2026-04-06) The schema exposes Direct Connect as a first-class later remote-action surface:
    • queries: directConnectConnectionStatus(input), directConnectEndpoint(input), directConnection(connectionID), directEndpoint(input)
    • mutations: directConnectOpen(input), directConnectClose(input), directConnectPing(input), directConnectProcessTerminate(input)
    • objects: DirectConnect, DirectConnectOpenPayload, DirectConnectClosePayload, DirectConnectConnectionStatusPayload, DirectConnectPingPayload
  • (2026-04-06) Legacy direct-connect mutations still exist, but the docs explicitly mark them as not preferred:
    • closeDirectConnection(input) is documented as legacy and says to use directConnectClose because the directConnect* APIs better support tracking slow-to-establish connections.
    • openDirectConnection(input) and pingDirectConnection(input) still appear alongside the newer directConnect* family.
  • (2026-04-06) Action and scheduled-action surfaces are confirmed in Gateway and should remain capability-gated later work:
    • queries: action(ref), actions(...args), actionGroup(ref), actionGroups(...args), scheduledAction(ref), scheduledActions(...args)
    • mutations: actionCreate(input), actionPerform(input), actionGroupCreate(input), actionGroupDelete(ref), scheduledActionApprove(ref), scheduledActionCreate(input), scheduledActionDelete(ref)
    • objects: Action, ActionConnection, ActionGroup, ActionGroupConnection, ActionInfo, ScheduledAction
  • (2026-04-06) The logged-in object docs and screenshot evidence show ScheduledAction is a real first-class object with approval and scheduling metadata such as approved, approver, comment, creator, distributeSeconds, and endTime.
  • (2026-04-06) assetUpsertEndpoints(input) is the key Tanium Gateway write surface around Asset-managed endpoint records:
    • return type: AssetsUpsertPayload!
    • argument type: AssetUpsertEndpointsInput!
    • docs say it upserts endpoint records in the given Asset Import API source using the Asset entity/attribute model
    • docs say source keys must be present as entity values; matching keys update an existing endpoint, otherwise a new endpoint is created
    • docs say TTL is updated for both Asset and TDS
    • docs require the Asset solution and Asset Api User Write
  • (2026-04-06) assetsImport(input) is explicitly deprecated in favor of assetUpsertEndpoints(input) because assetUpsertEndpoints supports multi-row/reference entities.
  • (2026-04-06) Working decision from the schema:
    • v1 scope discovery should target computerGroups
    • v1 inventory sync should target endpoints and normalize from the Endpoint* object family
    • endpointIdChanges / endpointLastSeen are candidates for incremental sync later, not prerequisites for v1
    • Direct Connect, action execution, scheduled actions, and Connect export jobs are later capability flags, not part of the base Tanium inventory adapter
  • (2026-04-06) Docs-site gotcha: navigating directly to deep links or clicking raw anchors can bounce the browser into Redocly login. Expanding schema sections and changing routes inside the existing authenticated page was reliable; use that workflow if more schema mining is needed.

Commands / Runbooks

  • (2026-04-06) Find the live Tanium docs browser pane:
    • alga-dev list-browsers --allTabs --pretty
  • (2026-04-06) Pull Tanium doc text from the live pane:
    • alga-dev browser-eval --paneId=<pane> --script='(() => (document.body.innerText || \"\").slice(0, 10000))()'
  • (2026-04-06) Fetch official markdown docs directly:
    • python3 - <<'PY'
    • import requests
    • print(requests.get('https://developer.tanium.com/guides/core-platform/integration_methods.md').text)
    • PY
  • (2026-04-06) Scaffold this plan:
    • python3 /Users/roberisaacs/.codex/skills/alga-plan/scripts/scaffold_plan.py --slug tanium-rmm-integration-plan "Tanium RMM Integration Plan"
  • (2026-04-06) Validate F002 targeted changes:
    • npx nx test @alga-psa/assets --testFile=packages/assets/src/lib/rmmProviderDisplay.test.ts
    • npx nx test @alga-psa/types
  • (2026-04-06) Validate F003/F004 targeted changes:
    • npx nx typecheck @alga-psa/integrations
  • (2026-04-06) Validate F005-F009 targeted changes:
    • npx nx typecheck @alga-psa/integrations
  • (2026-04-06) Validate F010-F018/F020 targeted changes:
    • npx nx typecheck @alga-psa/integrations
    • npx nx typecheck sebastian-ee
  • (2026-04-06) Validate Tanium + shared RMM tests:
    • npx nx test sebastian-ee -- --run src/__tests__/unit/integrations/taniumActions.test.ts src/__tests__/unit/integrations/TaniumIntegrationSettings.ui.test.tsx src/__tests__/unit/integrations/rmm/syncOrchestration.test.ts
    • cd server && npx vitest run ../packages/integrations/src/lib/rmm/providerRegistry.test.ts ../packages/integrations/src/components/settings/integrations/RmmIntegrationsSetup.registry.test.tsx ../packages/integrations/src/lib/rmm/sharedAssetIngestionService.test.ts
    • Note: @alga-psa/integrations Nx test target currently points to deprecated @nx/vite:test without a config file; targeted package tests were executed via server Vitest harness instead.

Implementation Log

  • (2026-04-06) F002 completed.

    • Added tanium to RmmProvider unions in:
      • packages/types/src/interfaces/asset.interfaces.ts
      • server/src/interfaces/asset.interfaces.tsx
      • ee/server/src/interfaces/rmm.interfaces.ts
    • Refactored EE RMM settings typing to separate common settings from provider-specific payloads:
      • introduced RmmCommonIntegrationSettings
      • introduced typed provider payloads (NinjaOneRmmProviderSettings, TacticalRmmProviderSettings, TaniumRmmProviderSettings)
      • introduced RmmProviderConfigurationPayload and provider_settings
      • retained ninja_instance_region as a compatibility bridge during migration
    • Updated provider display utilities/tests to include tanium:
      • packages/assets/src/lib/rmmProviderDisplay.ts
      • packages/assets/src/lib/rmmProviderDisplay.test.ts
    • Expanded type-level coverage:
      • packages/types/src/interfaces/rmmProvider.typecheck.test.ts
  • (2026-04-06) F003 completed.

    • Added shared provider registry with normalized provider metadata and capability flags:
      • packages/integrations/src/lib/rmm/providerRegistry.ts
    • Registry now captures connection/scope/device/events/remote-action capability state per provider and centralizes enterprise/feature-flag availability gates.
  • (2026-04-06) F004 completed.

    • Refactored settings selector UI to render provider cards from registry output instead of hard-coded provider branches:
      • packages/integrations/src/components/settings/integrations/RmmIntegrationsSetup.tsx
    • Added Tanium placeholder settings component wiring behind the tanium-rmm-integration feature flag so registry-driven rendering can include Tanium metadata without breaking current behavior.
  • (2026-04-06) F005 completed.

    • Added normalized provider contracts for scopes and device snapshots:
      • packages/integrations/src/lib/rmm/contracts.ts
  • (2026-04-06) F006 completed.

    • Added shared RMM asset correlation/upsert ingestion service centered on tenant_external_entity_mappings:
      • packages/integrations/src/lib/rmm/sharedAssetIngestionService.ts
  • (2026-04-06) F007 completed.

    • Shared ingestion create path now provisions:
      • base assets row
      • extension row (workstation_assets / server_assets when applicable)
      • tenant_external_entity_mappings link
    • Creation is driven from normalized snapshots and resolved client mapping.
  • (2026-04-06) F008 completed.

    • Shared ingestion update path now:
      • updates mapped assets
      • upserts extension fields
      • refreshes mapping metadata/sync timestamps
    • Includes fallback correlation to an existing asset by rmm_provider + rmm_device_id when an external mapping row is missing.
  • (2026-04-06) F009 completed.

    • Shared ingestion now handles lifecycle states deleted/tombstoned with a single path that marks asset inactive/offline and updates mapping status/metadata (deleted, deletedAt).
  • (2026-04-06) F010 completed.

    • Added transport-agnostic sync orchestration seam:
      • ee/server/src/lib/integrations/rmm/sync/syncOrchestration.ts
    • Tanium full sync now executes through this seam (runRmmSyncWithTransport) with direct transport active by default and temporal transport hook points available via env configuration.
  • (2026-04-06) F011 completed.

    • Added Tanium Gateway client/query runner:
      • ee/server/src/lib/integrations/tanium/taniumGatewayClient.ts
    • Includes authenticated GraphQL query runner, connection test, scope discovery (computerGroups), endpoint inventory (endpoints), and optional Asset API fallback fetcher.
  • (2026-04-06) F012 completed.

    • Added tenant-scoped Tanium connection lifecycle actions:
      • ee/server/src/lib/actions/integrations/taniumActions.ts
    • Implements settings retrieval, configuration save, connection test (state transition to active on success), and disconnect (secret cleanup + inactive row state).
  • (2026-04-06) F013 completed.

    • Added Tanium provider settings UI:
      • Enterprise implementation: ee/server/src/components/settings/integrations/TaniumIntegrationSettings.tsx
      • CE stub path for shared alias resolution: packages/ee/src/components/settings/integrations/TaniumIntegrationSettings.tsx
    • Selector wiring updated via shared provider registry rendering:
      • packages/integrations/src/components/settings/integrations/RmmIntegrationsSetup.tsx
  • (2026-04-06) F014 completed.

    • Implemented Tanium scope discovery action (syncTaniumScopes) with rmm_organization_mappings upsert/refresh behavior.
  • (2026-04-06) F015 completed.

    • Tanium settings now exposes mapping management using existing rmm_organization_mappings flow and client assignment updates (updateTaniumOrganizationMapping).
  • (2026-04-06) F016 completed.

    • Implemented Tanium full inventory sync action (triggerTaniumFullSync) that fetches endpoint inventory, normalizes snapshots, and calls shared ingestion (ingestNormalizedRmmDeviceSnapshot).
  • (2026-04-06) F017 completed.

    • Implemented constrained Asset API fallback path in full sync when a mapped scope has no Gateway endpoints and fallback is enabled.
  • (2026-04-06) F018 completed.

    • Tanium phase-1 implementation remains pull-only: no new /api/webhooks/* or callback ingress routes added.
  • (2026-04-06) F020 completed.

    • Tanium actions reuse existing rmm_integrations sync lifecycle fields (sync_status, sync_error, last_sync_at, last_full_sync_at) rather than introducing a separate status subsystem.
  • (2026-04-06) F019 completed.

    • Legacy NinjaOne and Tactical settings flows remain operable and are now selected via registry-driven adapter wiring in RmmIntegrationsSetup (providerSettingsComponents) instead of bespoke top-level branching, allowing transition without rewriting either provider stack.

Test Implementation Log

  • (2026-04-06) T001 completed.

    • Added provider registry capability test:
      • packages/integrations/src/lib/rmm/providerRegistry.test.ts
    • Added selector registry-rendering test:
      • packages/integrations/src/components/settings/integrations/RmmIntegrationsSetup.registry.test.tsx
  • (2026-04-06) T002 completed.

    • Added shared ingestion create-path test:
      • packages/integrations/src/lib/rmm/sharedAssetIngestionService.test.ts
  • (2026-04-06) T003 completed.

    • Added shared ingestion update/no-duplicate test:
      • packages/integrations/src/lib/rmm/sharedAssetIngestionService.test.ts
  • (2026-04-06) T004 completed.

    • Added scope-discovery mapping preservation test in Tanium actions suite:
      • ee/server/src/__tests__/unit/integrations/taniumActions.test.ts
  • (2026-04-06) T005 completed.

    • Added Tanium full-sync happy-path test asserting Gateway fetch + shared ingestion invocation + completed sync status:
      • ee/server/src/__tests__/unit/integrations/taniumActions.test.ts
  • (2026-04-06) T006 completed.

    • Added Tanium fallback test asserting Asset API path ingestion when Gateway scope returns zero endpoints:
      • ee/server/src/__tests__/unit/integrations/taniumActions.test.ts
  • (2026-04-06) T007 completed.

    • Added connection failure test asserting inactive integration and actionable auth error:
      • ee/server/src/__tests__/unit/integrations/taniumActions.test.ts
  • (2026-04-06) T008 completed.

    • Added UI integration-style test for Tanium settings configuration/test/scope-discovery flow:
      • ee/server/src/__tests__/unit/integrations/TaniumIntegrationSettings.ui.test.tsx
  • (2026-04-06) T009 completed.

    • Added shared sync orchestration seam tests:
      • ee/server/src/__tests__/unit/integrations/rmm/syncOrchestration.test.ts

Open Questions

  • What exact Tanium auth material should Alga store per tenant for Gateway access?
  • Do we need incremental sync in Tanium v1, or is full inventory sync enough until real-world volume proves otherwise?
  • Is there an officially documented programmatic management surface for Tanium Connect destinations/jobs, or would later Connect event delivery be console-configured?
  • Does ComputerGroup map cleanly enough to rmm_organization_mappings for real MSP tenant usage, or do we need a provider-specific scope-normalization rule on top of Tanium groups?
  • Which exact Endpoint fields and nested objects are sufficient for Algas normalized device snapshot without overspecifying the first adapter?