Files
dashboardAPI/CONTRACT.md
znetsixe 2874608375 P6: convert dashboardAPI to platform infrastructure
Refactor of dashboardAPI to use BaseNodeAdapter + commandRegistry + statusBadge.
dashboardAPI follows the platform refactor plan in .claude/refactor/MODULE_SPLIT.md.
Tests stay green; CONTRACT.md generated; legacy aliases preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:23:45 +02:00

3.7 KiB

dashboardAPI — Contract

dashboardAPI is an EVOLV utility node that listens for child-registration events from other EVOLV nodes and emits Grafana dashboard upsert HTTP requests on Port 0. It has no domain measurements, no tick loop, and no parent of its own — it is a one-shot HTTP emitter. Per OPEN_QUESTIONS.md (2026-05-10) it does NOT extend BaseNodeAdapter / BaseDomain; it uses the shared command registry only.

Inputs (msg.topic on Port 0)

Canonical Aliases (deprecated) Payload Effect
child.register registerChild string (child node id) or { source: {...} } or { config: {...} } (optionally msg.includeChildren: boolean, default true) Resolves the child source (RED.nodes.getNodenode._flow.getNode → inline payload), calls source.generateDashboardsForGraph(child, { includeChildren }), then emits one topic: 'create' HTTP-upsert message on Port 0 per generated dashboard.

Aliases log a one-time deprecation warning the first time they fire.

Outputs (msg.topic on Port 0/1/2)

  • Port 0 (process): one message per generated dashboard, shaped for a downstream http request node:
    {
      topic: 'create',
      url: <grafanaUpsertUrl>,           // e.g. http://grafana:3000/api/dashboards/db
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        Authorization: 'Bearer …'        // only when bearerToken is set
      },
      payload: { dashboard: {}, folderId: 0, overwrite: true },
      meta: { nodeId, softwareType, uid, title }
    }
    
    Re-emits the inbound msg fields by spread ({...msg, ...}) so any caller-supplied correlation/trace fields propagate.
  • Port 1 (InfluxDB telemetry): not used. dashboardAPI has no measurements; nothing is emitted on Port 1.
  • Port 2 (registration / control plumbing): not used. dashboardAPI is a sink for child.register, not a source — it does not register itself with any parent.

Events emitted by source.emitter

None. The specificClass (DashboardApi) exposes no EventEmitter — it is a passive service that responds to method calls and returns built dashboard payloads.

Children accepted

Any EVOLV node whose nodeSource.config includes functionality.softwareType. The graph walk reads children via nodeSource.childRegistrationUtils.registeredChildren.values(). A dashboard template is loaded from config/<softwareType>.json (with case-insensitive fallback and a machineGroupControl → machineGroup.json alias); a missing template is logged at warn and the dashboard is skipped.

The dashboard's templating variables measurement and bucket are filled from the child's id and positionVsParent (or config.defaultBucket / config.bucketMap[position] overrides). The root dashboard is augmented with links[] entries pointing at each direct child dashboard.

Why no BaseNodeAdapter / BaseDomain

  • No generalFunctions/src/configs/dashboardapi.jsonBaseDomain's constructor unconditionally calls configManager.getConfig(ctor.name) and would throw. The local dependencies/dashboardapi/dashboardapiConfig.json is for the editor menu endpoint, not the runtime config pipeline.
  • No periodic output — BaseNodeAdapter's _emitOutputs() / outputUtils.formatMsg pipeline assumes a delta-compressed Port 0/1 stream; dashboardAPI emits HTTP-shaped messages instead.
  • No registration to a parent — BaseNodeAdapter._scheduleRegistration would emit a spurious child.register of its own.
  • No status badge / tick / measurements / children of its own.

dashboardAPI uses the shared commandRegistry (canonical topic naming + alias-with-deprecation) and stops there.