master
md 650 lines 33 KB
Rendered Raw
1 # Spec - Topology Function Schema
2
3 ## Status
4
5 Active for new topology Function work. Existing deployed topology producers are
6 to be migrated to this contract.
7
8 ## Contract
9
10 Topology Functions return normal Function envelopes with `type: "topology"` and
11 `data.schema_version: "netdata.topology.v1"`.
12
13 The production schema is defined by:
14
15 - `src/plugins.d/FUNCTION_TOPOLOGY_SCHEMA.json`
16 - `src/plugins.d/FUNCTION_TOPOLOGY_DEVELOPER_GUIDE.md`
17
18 The schema is generic across topology domains. It applies to network
19 connections, streaming, SNMP/L2, vSphere, and future topology producers.
20
21 ## Planes
22
23 Topology payloads separate these planes:
24
25 - actors: observed entities such as nodes, processes, containers, ports,
26 devices, streaming agents, or virtualization objects;
27 - graph links: renderable relationship groups between actors;
28 - evidence: canonical relationship facts behind graph links;
29 - detail tables: actor-owned or relationship-owned drilldown data;
30 - actor labels: actor-owned key/value rows for modal labels and filters, not a
31 replacement for canonical identity or grouping columns;
32 - presentation: backend-selected UI-token composition for labels, colors,
33 icons, legends, highlighting, link styles, scale keys, and graph port
34 bullets;
35 - modal composition: actor/link modal recipes over existing actors, links,
36 evidence, labels, and detail tables;
37 - correlation: producer-visible rules, loose-side resolution, replacement,
38 enrichment, visible correlation points, and claims used by an aggregator to
39 correlate independently produced topology maps without exposing aggregator
40 internal states;
41 - overlay refs: compact references for refreshable metrics or Function-backed
42 snapshots.
43
44 Graph links are projections. Evidence rows are the facts used by Cloud
45 aggregation, matching, and detailed drilldowns.
46
47 ## Mode Requests
48
49 Mode requests use `__topology_mode` when a producer has a real detailed vs
50 aggregated output difference. Valid values are `detailed` and `aggregated`.
51 Mode-invariant topologies should not expose a selector only to return identical
52 payloads. Mode-capable producers declare `data.view.supported_modes`; absent
53 or single-value `supported_modes` means the topology is mode-invariant for UI
54 control purposes. The Cloud topology aggregator consumes detailed payloads for
55 mode-capable producers before returning an aggregated view, so producers must
56 preserve correlation-grade evidence in detailed mode.
57
58 ## Compact Tables
59
60 Large sections use compact columnar tables with:
61
62 - `rows`
63 - `columns`
64 - `values`
65
66 Supported column codecs are:
67
68 - `const`
69 - `values`
70 - `dict`
71
72 Every decoded column must produce exactly `rows` values. Producers should use
73 shared helpers for table building, dictionary encoding, validation, and
74 deterministic sorting rather than hand-rolling encoders in each plugin.
75
76 Column type `json` is allowed only for actor-owned or custom detail cells that
77 must preserve nested producer-owned values. It is not the default for
78 relationship evidence, because high-cardinality evidence needs typed scalar,
79 reference, array, or dictionary-backed columns for compactness and aggregation
80 semantics.
81
82 ## Identity And Aggregation
83
84 Actor types declare:
85
86 - source-local `identity`;
87 - cross-payload `merge_identity`;
88 - optional `parent_identity`;
89 - supported `aggregation_scopes`.
90 - optional `search` policy over actor table columns and actor label keys.
91 - optional `presentation` with UI-owned tokens, safe label policy, size policy,
92 actor repulsion policy, and graph port-bullet policy.
93
94 Link types declare:
95
96 - `orientation`: `directed`, `undirected`, `hierarchical`, or
97 `observed_bidirectional`;
98 - `direction_role`: `none`, `flow`, `dependency`, `ownership`, or
99 `observation`;
100 - optional `semantic_role`: `normal`, `discovery`, `ownership`, `traffic`,
101 `correlation`, or `control`;
102 - aggregation policy for direction, evidence, metrics, tables, and overlays.
103 - optional `presentation` with UI-owned color, line style, width, curve, arrow,
104 tokenized layout strength/distance, and one variable visual channel.
105
106 Port types are optional and declare graph port-bullet presentation only.
107 Actor/link modal composition is declared separately under actor/link type
108 presentation and table type presentation. Modal recipes are selectors and
109 projections over existing facts; they are not duplicate row stores.
110
111 Cloud aggregation may only canonicalize endpoint order when link type policy
112 explicitly allows unordered aggregation. Direction-significant links must
113 preserve direction.
114
115 ## Evidence And Tables
116
117 Relationship evidence is not actor custom data.
118
119 Evidence tables carry matchable relationship facts such as socket tuples,
120 streaming hops, LLDP/CDP observations, or vSphere inventory edges. Actor-detail
121 tables carry actor-owned data such as streaming path inventory or local status
122 tables. Table metadata must state role and aggregation policy.
123
124 Production payloads must not duplicate the same evidence under every actor only
125 to populate drilldown modals. The UI and aggregator derive drilldown views from
126 shared evidence and typed table references.
127
128 Actor labels use a compact actor-owned table, normally
129 `tables.actor.actor_labels`, with rows shaped as:
130
131 ```text
132 actor, key, value, source?, kind?, value_index?
133 ```
134
135 `key`, `value`, `source`, and `kind` are logical strings and may be encoded as
136 `string` or `string_ref`. Producers should prefer `string_ref` when they already
137 maintain a local dictionary; aggregators and UI adapters must normalize both
138 encodings as equivalent label strings.
139
140 Host/node actors should expose the complete host label set when available.
141 Non-node actors should expose useful producer-known labels and metadata, such
142 as process command line, user, group, namespace, interface role, or
143 virtualization object properties. Repeated values are repeated rows ordered by
144 `value_index`, not JSON arrays. Facts needed for identity, correlation,
145 grouping, sorting, filtering, or aggregation must remain typed canonical
146 columns too.
147
148 `actor_labels` inherits the topology Function sensitive-data classification.
149 Consumers must preserve the same access-control assumptions as the source
150 Function because labels may include command lines, users, host labels, system
151 contact/location fields, or other operator-controlled metadata.
152
153 Actor modal identification is producer-selected through
154 `presentation.modal.labels.identification.fields[]`. Each field references an
155 existing `actor_labels.key`, provides the label to render near the actor title,
156 and may limit the number of displayed values with `max_values`. The full Labels
157 tab remains complete; identification is a curated header projection, not a
158 second table.
159
160 ## Presentation
161
162 Presentation belongs in the production `netdata.topology.v1` payload, not in
163 Function `info`, except for old-schema compatibility during rollout.
164
165 Function `info` responses are metadata responses. They may omit `data` and
166 advertise only parameters, help text, and timing. The topology JSON schema
167 applies to full topology responses, not metadata-only `info` responses.
168
169 Type definitions carry type-local presentation:
170
171 - `types.actor_types.<id>.presentation`
172 - `types.link_types.<id>.presentation`
173 - `types.port_types.<id>.presentation`
174
175 Graph-level `data.presentation` carries legend order, actor-click highlight
176 behavior, port tooltip field labels, and scale-key definitions.
177
178 Actor and link type presentation may also carry modal composition:
179
180 - `presentation.modal.labels` describes the actor label table, usually
181 `actor_labels`;
182 - `presentation.modal.mini_topology` describes a depth-1 modal graph preview
183 built from incident links and opposite actors;
184 - `presentation.modal.sections[]` describes table sections over existing
185 actors, links, evidence, actor detail tables, or relationship tables.
186
187 Table types may carry `presentation` defaults for table label, order, default
188 visibility, and column display metadata. Table type presentation does not
189 replace actor/link modal sections; it gives reusable defaults for existing
190 table rows.
191
192 Modal sections require non-empty `id`, non-empty `label`, a source, and at
193 least one column. `empty_label` is section-only empty-state text. Modal columns
194 require non-empty `id`, non-empty `label`, and a projection. `badge_map`,
195 `align`, and `sortable` are presentation hints over projected values and must
196 not introduce new facts.
197
198 `label_lookup` uses `label_key` and optionally an `actor_column`; omitted
199 `actor_column` means the selected modal actor. `json_path` always requires both
200 the JSON `column` and the scalar `path` to extract.
201
202 Presentation uses closed UI-owned tokens. Producers must not emit raw SVG, raw
203 CSS, coordinates, component names, raw force-layout physics, or viewport state.
204
205 Closed token values are part of the schema contract:
206
207 - color slots: `primary`, `secondary`, `accent`, `self`, `neutral`, `muted`,
208 `dim`, `derived`, `info`, `structural`, `warning`, `success`, `danger`,
209 `blue`, `green`, `orange`, `purple`, `cyan`, `yellow`, `teal`, `gray`;
210 - opacity tokens: `normal`, `muted`, `faded`;
211 - width tokens: `thin`, `normal`, `thick`, `emphasis`;
212 - link layout strength tokens: `weakest`, `weaker`, `normal`, `stronger`,
213 `strongest`;
214 - link layout distance tokens: `closest`, `closer`, `normal`, `farther`,
215 `farthest`;
216 - actor layout repulsion tokens: `weakest`, `weaker`, `normal`, `stronger`,
217 `strongest`;
218 - actor size scale tokens: `compact`, `normal`, `emphasized`;
219 - link semantic roles: `normal`, `discovery`, `ownership`, `traffic`,
220 `correlation`, `control`;
221 - icons: `router`, `switch`, `firewall`, `access_point`, `server`, `storage`,
222 `load_balancer`, `printer`, `phone`, `ups`, `camera`, `process`, `agent`,
223 `netdata-agent`, `parent`, `remote-endpoint`, `local-endpoint`, `segment`,
224 `self`, `ip`, `cloud`, `container`, `vm`, `database`, `service`,
225 `datacenter`, `cluster`, `host`, `network`, `datastore`,
226 `datastore_cluster`, `resource_pool`, `device`, `endpoint`, `correlation`,
227 `interface`, `group`, `unknown`.
228
229 The UI owns token rendering and must treat producer labels as plain text. If a
230 new producer emits a schema-valid token that an older UI does not know, the UI
231 must use a safe fallback and record diagnostics.
232
233 Actor `label_policy` is the only approved way to choose display labels from
234 actor rows. Canonical identity is not display text. The UI must reject array
235 values by default so aggregated identities do not become long actor names.
236 Label-policy columns must be safe scalar actor-table columns. Producers must
237 not reference secrets, tokens, customer-identifying fields, or unbounded arrays
238 from `label_policy.columns`.
239
240 Actor `search` is the only approved way to choose graph search content for v1.
241 `search.columns[]` references scalar actor-table columns. `search.label_keys[]`
242 references values in the actor label table, normally `actor_labels.key`. Set
243 `search.enabled: false` for helper actors that should not be searchable. The UI
244 must not traverse producer-specific `details`, `match`, `attributes`, or label
245 paths when rendering v1.
246
247 Link types may define one variable visual channel using `variable.channel`,
248 `variable.scale_key`, and `variable.value_column`. Producers emit raw domain
249 values, such as socket counts or traffic bytes. Cloud or the UI scales values
250 per `scale_key` across the visible graph. `variable.min` and `variable.max`
251 are visual tokens for the chosen channel: width variables use width tokens,
252 opacity variables use opacity tokens.
253
254 Link types may also define tokenized force-layout hints using
255 `presentation.layout.strength` and `presentation.layout.distance`. These are
256 relative UI-owned tokens, not numeric physics. Current producer tuning keeps
257 `strength` at `normal` and varies only `distance` where the topology needs
258 semantic separation. Do not reintroduce non-normal `strength` tokens for graph
259 polish unless a later product decision explicitly re-enables force-strength
260 tuning.
261
262 Actor types may define tokenized force-layout hints using
263 `presentation.layout.repulsion`. Repulsion is separate from link strength:
264 repulsion pushes actors apart, while link strength pulls endpoints together.
265 Producers must not emit raw charge values. Actor size may define a type-level
266 `size.scale` token for deliberate fixed emphasis, such as current/self actors;
267 the UI must not infer this from actor type names or labels.
268
269 `link_types.<id>.semantic_role` is behavior metadata, not visual styling. It
270 drives UI behavior such as discovery-link filtering, ownership/coherence
271 treatment, traffic emphasis, and correlation treatment without hardcoded
272 protocol or type-name checks. Link appearance still comes from
273 `presentation`.
274
275 When link `presentation.arrow` is `auto` or omitted, the UI derives arrows from
276 `orientation` and `direction_role`:
277
278 - `undirected` -> no arrow;
279 - `observed_bidirectional` -> no arrow;
280 - `direction_role: none` -> no arrow;
281 - `direction_role: observation` -> no arrow;
282 - `directed` with `flow` or `dependency` -> forward from `src_actor` to
283 `dst_actor`;
284 - `hierarchical` with `ownership` -> forward from `src_actor` to `dst_actor`;
285 - all other combinations -> no arrow and a diagnostic if the combination is
286 schema-valid but semantically unusual.
287
288 `observed_bidirectional` means observation completeness, not "draw both
289 arrows". Producers that need reverse or both arrows must set
290 `presentation.arrow` explicitly.
291
292 `direction_role` is required by the v1 schema. Missing `direction_role` is
293 schema-invalid and must not produce an inferred arrow from `orientation` alone.
294 The UI should render `auto` as no arrow and emit the normal missing-field
295 diagnostic for that invalid input.
296
297 For schema-valid values, the `auto` semantic diagnostic boundary is:
298
299 - no diagnostic for `directed+flow`, `directed+dependency`,
300 `hierarchical+ownership`, `undirected+none`, `undirected+observation`,
301 `observed_bidirectional+none`, or `observed_bidirectional+observation`;
302 - diagnostic for `directed+none`, `directed+observation`,
303 `directed+ownership`, `hierarchical+none`, `hierarchical+flow`,
304 `hierarchical+dependency`, `hierarchical+observation`, `undirected+flow`,
305 `undirected+dependency`, `undirected+ownership`,
306 `observed_bidirectional+flow`, `observed_bidirectional+dependency`, or
307 `observed_bidirectional+ownership`.
308
309 Initial UI-owned mappings are:
310
311 - `size.scale`: `compact=0.85`, `normal=1.0`, `emphasized=1.18`;
312 - `layout.repulsion`: `weakest=-200`, `weaker=-300`, `normal=-450`,
313 `stronger=-700`, `strongest=-1000`.
314
315 These numeric values are not schema and may be tuned after visual QA.
316 `size.scale` composes with `size.mode`; it does not override data-driven
317 sizing. Missing optional fields use neutral defaults (`scale: normal`,
318 `repulsion: normal`) and must not trigger v1 UI fallback heuristics.
319
320 Actor port bullets require explicit `ports.sources[]` when
321 `show_bullets: true`. The source may be `links`, `evidence`, or an
322 `actor_table`. Source column names are table-local and must remain unchanged
323 during Cloud aggregation. Type ids inside row values and `default_type` values
324 are rewritten only when they refer to type registries. `ports.sources[].evidence`
325 is an evidence type id. `name_column` must reference a scalar display column,
326 not a raw actor/link/evidence reference, array, or JSON cell.
327 `ports.sources[].value_column` is optional and must reference a numeric source
328 column. When present, the UI sums values for matching bullet keys and uses the
329 sum for bullet multiplicity, overflow, and sizing. Aggregated producers should
330 use this instead of sending repeated rows only to drive presentation.
331
332 Modal/table composition uses closed source, projection, cell, and visibility
333 tokens. Supported source kinds are `actors`, `links`, `evidence`,
334 `actor_table`, and `relationship_table`. Supported projections include direct
335 column values, actor-ref labels, opposite actor labels, formatted endpoints,
336 selected-side endpoints, label-table lookups, coalesced columns, constants,
337 and explicitly declared scalar JSON paths. Supported cell types include text,
338 number, badge, actor link, timestamp, duration, endpoint, array count, and
339 debug JSON. Raw JSON belongs behind `debug` visibility or an explicit scalar
340 projection; it must not be the default polished actor modal rendering.
341 Selected-side endpoint projections must be self-contained: the projection
342 names source and destination actor-ref columns, plus at least one source-side
343 endpoint column and one destination-side endpoint column.
344
345 `selection.actor_click.mode: highlight_path` requires `path_table`,
346 `path_actor_column`, and `path_order_column`. `path_actor_column` identifies
347 path members. When one table contains different paths for different clicked
348 actors, `path_owner_column` identifies the actor that owns each path row.
349 `highlight_connections` requires no path table.
350
351 Presentation conflict policy:
352
353 - producer-local type ids, port ids, scale keys, evidence ids, table type ids,
354 and overlay template ids are namespaced before aggregation;
355 - identical definitions are deduplicated after canonicalization;
356 - conflicting local definitions are preserved as distinct canonical ids rather
357 than hard-failing aggregation;
358 - `label_policy` belongs to the actor type presentation and follows the same
359 namespace/deduplicate rule;
360 - `profile_version` is diagnostic. It may help choose a preferred display
361 profile later, but it is not a comparable semantic-version contract and must
362 not be used to drop facts or rows.
363
364 ## Correlation Contract
365
366 Correlation is producer-visible graph semantics, not aggregator state.
367 Producers must not encode correlation as hidden flags on real actors, and must
368 not expose aggregator internal states such as absorbed, candidate, equivalence
369 class, or rewrite plan. The final aggregated output is always a normal topology
370 payload.
371
372 Correlation can resolve several shapes:
373
374 - loose relationship sides, where one side of a detailed row has endpoint facts
375 but no known actor;
376 - visible correlation actors, where the input graph intentionally materializes
377 unresolved peers;
378 - weaker placeholder actors that should be replaced by stronger managed actors;
379 - equivalent actors that should be merged and enriched with facts from multiple
380 payloads.
381
382 `data.correlation.rules` defines how independent payloads of the same topology
383 kind can be correlated. Each rule defines:
384
385 - optional `class`: `resolve_loose_side`, `replace_actor`, or
386 `merge_enrich_actor`;
387 - `action`: `absorb` for exact matches that remove visible correlation actors
388 or consume loose-side placeholders and rewrite incident correlation
389 relationships, or `link` for partial/broader matches that keep the visible
390 correlation/materialized actor and add a weak correlation link;
391 - `priority`: lower numbers run first;
392 - `key_space`: namespace for exact string-key matching;
393 - `key`: a declarative template built from point/claim table columns and
394 literals;
395 - `point_actor_types`: actor types that are visible correlation points when the
396 input graph materializes points;
397 - optional `claim_actor_types`: actor types that may satisfy the point;
398 - optional `correlation_link_types`: link types that connect real actors to
399 correlation actors and may be consumed/replaced by the rule;
400 - `output_link_type`: link type emitted for rewritten absorb links or visible
401 partial correlation links.
402
403 `data.correlation.points` is a compact table of visible correlation actors and keys.
404 `data.correlation.claims` is a compact table of real actors and keys they can
405 satisfy. Both tables require `actor`, `rule`, and the key columns referenced by
406 their rules.
407
408 The aggregator is intentionally agnostic. It builds normalized keys from
409 declared columns and literals, applies rule priority, and handles ambiguity
410 conservatively. It must not need new code to understand every future IP, port,
411 MAC, chassis id, object id, label, or topology-domain key.
412
413 No match keeps the visible correlation actor or loose-side materialization
414 visible. Ambiguous matches remain unresolved and produce diagnostics. NAT or
415 other alias evidence can be modeled by adding extra point/claim rows for the
416 same actor and rule; aliases add facts without mutating the original
417 observation.
418
419 Correlation links must be semantic link types even for single-node payloads.
420 The legend must include visible correlation actors and links when they are
421 visible, so users can distinguish unresolved, partial, inferred, and resolved
422 graph relationships.
423
424 ## Telemetry Overlays
425
426 Refreshable traffic, state, error, packet, or utilization data is represented by
427 overlay templates and per-actor/per-link refs.
428
429 Templates define the query mechanism once. Refs provide only template ids, one
430 owner reference, and selector parameters. The refs table uses schema ids for
431 column names, so template ids, selector params, and refs column ids must match
432 the topology `$defs/id` contract: start with a letter and then use only letters,
433 digits, `_`, `.`, `:`, or `-`.
434
435 The refs-table convention is:
436
437 - `template`: string or string_ref template name resolving to
438 `data.types.overlay_templates`;
439 - exactly one convention owner column: `actor` with type `actor_ref` or `link`
440 with type `link_ref`; every row must have a non-null owner value;
441 - one column for each selector param required by the referenced template.
442
443 Selector params must not use reserved refs-table convention column names:
444 `template`, `actor`, or `link`.
445
446 No other `actor_ref` or `link_ref` columns are valid in overlay refs. Consumers
447 can identify ownership from the fixed `actor` / `link` column ids instead of
448 scanning all columns by type.
449
450 The `template` column and all selector-param columns required by a row's
451 resolved template must be `string` or `string_ref`. Required selector-param row
452 values must resolve to non-empty strings. Selector-param columns used by other
453 templates may be nullable and null on rows whose template does not require them.
454 Future selectors that need `ip_ref`, `mac_ref`, or empty-string matching must
455 relax this contract explicitly.
456
457 For `provider: "netdata.metrics"`, selector params are interpreted as:
458
459 - `node_id`: node-scope selector, not a chart label;
460 - `collect_job`: chart label `_collect_job`;
461 - other params: same-named chart labels.
462
463 Aggregated actors or links merge overlay refs according to the template merge
464 policy. `merge.refs` controls ref-list handling, currently `append` or `set`.
465 `merge.values` controls how multiple matching metric values collapse, currently
466 `sum`, `min`, `max`, `avg`, `last`, or `none`.
467
468 ## Compatibility
469
470 Production payloads carry canonical topology facts, not compatibility
471 reconstruction instructions. Projection code for parity with deployed
472 compatibility consumers is test or rollout code only.
473
474 Agent/backend contracts and docs should point new work to
475 `netdata.topology.v1`. Temporary compatibility handling belongs in isolated
476 Cloud frontend adapters during rollout.
477
478 ## Validation
479
480 Topology producer changes must include:
481
482 - JSON Schema validation against `FUNCTION_TOPOLOGY_SCHEMA.json`;
483 - semantic validation for table column lengths and reference bounds;
484 - fixture or corpus tests for payload size and evidence preservation;
485 - tests proving direction and aggregation policy are honored;
486 - checks that evidence is not silently truncated.
487
488 Cloud topology aggregation service readiness also requires service-level
489 fixtures for every topology kind covered by this contract. `network-connections`
490 is the high-cardinality benchmark, but the service is not considered ready if
491 the UI can use it for only some topology kinds while bypassing it for others.
492
493 ## Migration Notes
494
495 `topology:network-connections` now emits `netdata.topology.v1` directly from
496 the C network-viewer Function. Aggregated mode is the default and emits compact
497 actor, graph-link, and actor-owned `socket_ports` tables. Detailed mode adds a
498 shared socket relationship-evidence table for exact tuple matching and
499 drilldowns. Process actor size uses the actor row `socket_count` metric, while
500 process port bullets read the `socket_ports.socket_count` value column so an
501 aggregated port row can represent several sockets. The producer no longer emits
502 the superseded old-schema presentation object or duplicated actor-nested socket
503 modal tables. It now emits compact graph presentation metadata in type
504 definitions plus `data.presentation`, and repeated string columns use
505 dictionary encoding when it reduces raw payload size.
506
507 Network-connections distinguishes unresolved endpoint links from aggregator
508 correlation output. `endpoint_socket` connects a process to a visible unresolved
509 endpoint actor and must not use the farthest layout distance because that makes
510 single-node maps zoom out unnecessarily. `correlated_socket` is the output link
511 type after exact endpoint absorption by an aggregator and may use farthest
512 distance to keep independent topology clusters from blending.
513
514 Network-connections modal composition is producer-declared. Self/node actors use
515 a `Processes` section over `ownership` graph links filtered by link type.
516 Network-connections socket link types use `direction_role: "dependency"` and
517 are client-to-server: `src_actor` is the client/dependant and `dst_actor` is the
518 server/dependency target. Non-node actors therefore use two primary sections in
519 both aggregated and detailed mode:
520 `Dependencies`, filtered to rows where the selected actor is `src_actor`, and
521 `Dependants`, filtered to rows where the selected actor is `dst_actor`.
522 Aggregated mode reads these sections from `tables.relationship.connections`;
523 detailed mode reads them from `evidence.socket`. `socket_ports` is an actor
524 inventory for process port bullets only; it is not a standalone modal tab for
525 network-connections.
526
527 `topology:snmp` now emits `netdata.topology.v1` from the Function handler
528 through an adapter over the existing SNMP topology engine output. The adapter
529 preserves actors, links, L2 observation evidence, actor metadata, and actor
530 custom detail tables. Remaining SNMP refinement is to promote interface metric
531 lookup fragments into first-class overlay templates/refs.
532
533 SNMP modal composition must be port-centric for managed device actors. A managed
534 device modal uses actor-label identification for important device facts, a
535 primary `Ports` section over `actor_ports`, and a `Port Neighbors` section over
536 `actor_port_links`. Generic graph-link `Links` sections are reserved for
537 endpoint, segment, or custom actors that do not own port inventory.
538
539 SNMP `actor_ports` exposes real port identity and status as typed columns:
540 SNMP `if_index` as the visible numeric port ID when known, source `port_id`,
541 display `name`, `if_name`, `if_descr`, `if_alias`, MAC, speed, status, mode,
542 role, VLAN, FDB, link, and neighbor counts. It must never fabricate numeric
543 port IDs; row order and generated sequences must not be used. `if_index` must
544 come from the device/SNMP facts and must align with `actor_port_links.if_index`.
545
546 SNMP `actor_ports` may also carry compact expanded-row neighbor columns such as
547 nullable `neighbor_actor` and `neighbor_port_name`, derived from graph-link
548 endpoint facts. These columns make the port row clickable without duplicating
549 raw LLDP/CDP/FDB/ARP/STP evidence.
550
551 SNMP `actor_port_links` is a compact actor-owned modal index over existing graph
552 links and evidence. It has one row per incident actor side and carries the local
553 `if_index`/port name, remote actor, remote port facts, protocol, link type,
554 state, evidence count, confidence, inference, attachment mode, and timestamps.
555 It exists so device modals can align neighbor rows with the same port identity
556 shown in `actor_ports`; it is not a second copy of raw evidence.
557
558 SNMP polished UI must not depend on raw `actor_metadata` and endpoint JSON.
559 Important scalar/count summary values live in typed actor or actor-detail
560 columns and are also available through `actor_labels`. Nested neighbors, VLANs,
561 unknown custom port attributes, and endpoint objects stay in expanded or debug
562 sections unless a structured child table is defined. Link endpoint port labels
563 must come only from real port fields such as `port_name`, `if_name`,
564 `if_descr`, or source `port_id`; actor labels such as `display_name` or
565 `sys_name` must not be used as port-name fallbacks.
566
567 `topology:streaming` now emits `netdata.topology.v1` directly from the C
568 Function. It models streaming agents as compact actor rows, streaming/virtual/
569 stale relationships as directed graph links with matching evidence types, and
570 keeps `stream_path`, retention, inbound, and outbound modal data as typed
571 actor-detail or relationship-summary tables. Streaming also emits graph
572 presentation metadata for highlight-path behavior, legend, link styles, and
573 port bullets. Streaming hops remain signed so stale path values are not
574 corrupted.
575
576 Streaming parent actor size is data-driven by the actor row
577 `retained_node_count` metric, not by graph degree or direct child count. This
578 count represents nodes for which the parent has retained DB data, including
579 self, virtual nodes, stale nodes, and transit descendants when they have
580 retention state. The parent actor type must declare `presentation.size:
581 {"mode":"metric","metric_column":"retained_node_count"}`. Parent port bullets
582 represent child or vnode streams attached to the parent side of streaming graph
583 links, so the parent `ports.sources[]` entry over `links` must use
584 `actor_column: "dst_actor"` with a scalar child/node display column such as
585 `port_name`.
586
587 Streaming modal composition emits `actor_labels`, complete host labels where
588 available, host/system metadata labels needed by old summaries, and typed
589 OS/architecture/CPU columns. The actor modal header must select important
590 identity/status labels from `actor_labels`, including hostname, node type,
591 stream status, ingest status, health status, retained-node count where
592 applicable, direct-child count where applicable, OS/platform labels, and Agent
593 version. Existing `stream_path`, `retention`, and `inbound` tables have the
594 right actor-ref shape for recipe-based table rendering. The `outbound` table
595 must use the parent-owned shape described below; a table that only records the
596 selected actor's own upstream destination is insufficient for parent operator
597 workflows.
598
599 Streaming actor modal identification is role-specific. Host-like actors
600 (`parent`, `child`, and `stale`) should expose operational status plus
601 OS/hardware/platform labels such as OS, OS version, kernel, architecture, CPU
602 model, cores, RAM, virtualization, container, cloud provider/type/region, and
603 Agent version. Parents additionally expose `retained_node_count` and
604 `child_count` so the visual size and direct attachments are both explainable.
605 Vnode actors should expose inventory/device labels such as vnode type, vendor,
606 model, address, location, sys object id, LLDP system name, and status. Long
607 stable identifiers such as `machine_guid` and `node_id` remain in the full
608 Labels tab by default unless a future product decision explicitly promotes them.
609
610 Streaming actor modals must keep those tables as the single source of truth and
611 must not duplicate rows only for modal display. The default visible sections are:
612
613 - `Stream path`: rows from `stream_path` filtered by `actor`, ordered by
614 `path_index`. The table shows the selected actor's own path only; virtual
615 nodes and children have their own actors and therefore their own path rows.
616 `since` and `first_time` must be populated from the best canonical source
617 available for every path row. Synthetic path rows added only for rendering or
618 highlighting must still carry timestamps when the producer can derive them
619 from the adjacent path edge, the selected actor's ingest status, or database
620 first-time status. They may be null only when the Agent genuinely does not
621 know the value.
622 - `Retained nodes`: rows from the same `retention` table filtered by
623 `observer_actor`; this view answers which nodes' data the selected actor
624 maintains. The table must include self, virtual nodes, direct children,
625 transit descendants, and stale/archived hosts when those hosts are present in
626 the Agent root index and have retention state. It must show retained node,
627 node type, retention status, from/to timestamps, duration, metrics, instances,
628 and contexts. `db_from` and `db_to` may be null only when the database status
629 genuinely has no time range.
630 - `Received nodes`: rows from `inbound` filtered by `parent_actor`; this view
631 represents children, virtual nodes, stale nodes, and descendants received or
632 transiting through the selected parent. `source_actor` is the immediate actor
633 from which the selected parent receives the row. For direct local receipt,
634 `source_actor` should be the child/vnode actor itself; it should be null only
635 when the immediate source is genuinely unknown.
636 - `Outbound streams`: rows from `outbound` filtered by the sending parent
637 actor, not by the streamed node actor. This view answers which node payloads
638 the selected parent currently streams, and where it streams each one. Each row
639 must include the streamed node actor, destination actor when known, status,
640 age, hops, TLS, compression, and useful stream/replication/count metrics when
641 available. In clustered-parent setups, the selected parent must list self,
642 virtual nodes, direct children, and transit descendants that are sent to each
643 upstream destination.
644
645 The old `Retention for node` default section is not part of the current
646 streaming modal contract. The canonical `retention` table still keeps both
647 `actor` and `observer_actor` so Cloud aggregation can preserve multiple
648 retaining parents for the same node. If a future modal needs a selected-node
649 "who retains me" view, it must be explicitly named `Retained by` and must not
650 replace the parent-owned `Retained nodes` view.