12 KiB
Zone Entity Visualization
Intent
The graph explorer currently treats zones as visual overlays derived from node metadata. That is useful for first orientation, but it keeps zones as a decoration around an already-laid-out graph. The next step is to make a zone a first-class visualization entity beside nodes and edges.
A zone is a bounded drawing surface for a subgraph. It is similar to a sheet of paper or a layer in a graphics application: it decides which graph elements are drawn inside it, how those elements are laid out, how it stacks with other zones, and whether it can be collapsed into a representative node.
Zones are view entities. They help the operator inspect the fabric without changing the underlying fabric graph. A zone can be based on deployment environment, ownership, tenant boundaries, cost center, access zone, or any other declared view rule, but those concepts remain distinct from the zone mechanism itself.
Core Model
A graph view contains three visible entity classes:
- nodes: fabric entities such as services, hosts, repos, scenarios, or owners
- edges: fabric relationships such as deployment, routing, ownership, policy, dependency, or evidence links
- zones: visual drawing surfaces that contain a selected subgraph
A zone definition describes how to derive and render one zone. A zone instance is the result of applying a definition to the current graph, filter state, and view profile.
Zone definitions should be serializable so they can later live in saved graph profiles, operator presets, or a dedicated view registry.
Zone Definition
A zone definition should contain at least these fields:
id: prod
label: Production
enabled: true
membership:
mode: include
rules:
- field: deploymentEnvironment
op: equals
value: prod
attraction:
rules:
- edge_type: fabric:serves
direction: both
depth: 1
node_filter:
field: kind
op: in
value: [service, endpoint]
layout:
algorithm: cose
options: {}
presentation:
height: 30
color: "#0f766e"
opacity: 0.16
blur_below: true
collapse:
enabled: true
label: Production Zone
The exact schema can evolve, but the responsibilities should stay separate:
- membership chooses seed nodes
- attraction optionally expands the zone from those seeds through selected edge types and depths
- layout chooses how the zone subgraph is arranged
- presentation chooses how the zone itself is drawn and stacked
- collapse chooses how the zone can become a representative node
Membership Rules
Membership rules decide which nodes initially belong to a zone. They should be declarative and inspect node data rather than hard-code UI concepts.
Useful operators:
equalsnot_equalsinnot_inexistsmissingmatches
Useful rule composition:
all: every nested rule must matchany: at least one nested rule must matchnone: no nested rule may match
The first implementation can support a small subset such as equals, in,
exists, all, and any, then widen the rule language once saved zone
profiles need it.
Attraction Rules
Attraction rules allow a zone to pull in additional nodes connected to the seed set. This is useful when the operator wants a zone to include the services, routes, machines, or contracts that make the zone understandable, even when those nodes do not carry the seed attribute themselves.
An attraction rule should define:
- edge type or edge-type pattern
- direction:
out,in, orboth - maximum depth
- optional node filter
- optional edge filter
Attraction must be deterministic. Given the same graph and zone definitions, the same node should land in the same zone every time.
Attraction also needs a conflict policy because a node must not belong to more than one zone. The recommended first policy is priority by zone height and then definition order:
- Seed membership wins over attracted membership.
- If two zones seed the same node, the conflict is reported and the node is assigned to the higher zone.
- If two zones attract the same node, the node is assigned to the higher zone.
- If height ties, the earlier definition wins.
- Every conflict is recorded as a view diagnostic.
This keeps the single-zone invariant while making ambiguous rules visible.
Single-Zone Invariant
A visible node must be assigned to zero or one zone in a given graph view. A node that belongs to no zone remains on the base canvas.
The invariant is important because zones are meant to behave like drawing surfaces, not like arbitrary tags. Allowing the same node to appear in multiple zones would make edge routing, selection, collapse behavior, and interaction state ambiguous.
The model can still support analytical overlap by reporting diagnostics and by offering alternative view presets. It should not solve overlap by duplicating nodes in the same rendered view.
Zone Layout
Each zone may choose its own layout algorithm for its subgraph. For example:
- deployment zones may use force-directed layout
- ownership zones may use concentric layout
- stage zones may use grid layout
- collapsed or nearly empty zones may use compact deterministic placement
The outer graph layout and the zone subgraph layouts are separate concerns. A first implementation can keep the current Cytoscape layout for all nodes and only render zone surfaces around assigned nodes. A later implementation should introduce a two-phase layout:
- Place zones and unzoned nodes on the main canvas.
- Place each zone's assigned subgraph inside that zone using the zone's layout.
This will likely require an internal view model that separates fabric graph data from rendered graph coordinates.
Per-Zone Layout Preparation
The current graph explorer should not immediately run independent Cytoscape layouts inside each zone rectangle. Cytoscape layouts operate on collections in one coordinate space, while the current zone overlay is a view layer drawn over the already-laid-out graph. Running nested layouts directly against visible nodes would make pan/zoom, filters, collapse state, and edge routing fragile.
The safer path is a two-phase view layout:
- Resolve zones from the current graph and view filters.
- Place zone containers and unzoned nodes in the global canvas.
- For each zone, compute local coordinates for its assigned nodes using the zone's configured layout algorithm.
- Project local zone coordinates into global graph coordinates.
- Route internal edges inside the zone and boundary edges through the zone perimeter or collapsed zone node.
The implementation needs these pieces before per-zone layouts become safe:
- a resolved zone view model that survives filtering and saved profiles;
- a stable assignment invariant so a visible node belongs to no more than one zone;
- a zone container model with size, position, padding, and height;
- a local coordinate projection layer from zone space to Cytoscape space;
- explicit boundary-edge routing rules;
- collapse state that can replace a zone subgraph with a representative node;
- diagnostics when a configured zone layout cannot be applied.
The present implementation already establishes the first, second, and sixth pieces. A follow-up should introduce a zone container placement phase before attempting per-zone node layout. That follow-up can keep Cytoscape as the final renderer while moving layout decisions into a Fabric-owned view model.
Stable Zone Containers
The first container implementation keeps zone surfaces as view state keyed by stable zone id. When a zone first appears, the global graph layout supplies its initial center. Once created, the container owns the zone surface position while the global layout continues to arrange the base canvas and unzoned nodes.
Dragging a zone moves the container and its currently assigned visible member nodes together. Rerunning layout or switching the layout algorithm should keep the container in its stored graph coordinates and then project the zone's visible subgraph back into that container.
Container state belongs in saved or copied graph view state, not in the Fabric payload. It is an operator workspace preference, similar to manual visibility overrides.
Zone-local layout is also view state. The first selectable algorithms are a compact grid and a circle layout. Switching between them should rearrange the assigned nodes inside each stable container without moving the container itself or changing the underlying Fabric relationships.
Context Edges
Display-only context edges are not zone connectivity. Repository declares
edges, for example, show which repository declared a node, but they should not
create boundary diagnostics, attraction paths, or collapsed-zone boundary
edges. A host can still show them as explanatory evidence in details, but a
zone boundary should only react to canonical or host-promoted graph
relationships.
Layer Height And Overlap
Zone presentation includes a height. Height is a visual stacking concept, not a security or ownership concept.
When zones overlap:
- higher zones should draw above lower zones
- lower zones may be desaturated when covered
- lower zones may be blurred or dimmed when covered
- labels should remain readable where practical
- pointer interaction should prefer the highest visible zone
The implementation should avoid implying that a higher zone is more important. Height is about rendering order and view ergonomics only.
Collapse To Zone Node
A zone can optionally collapse into a representative node. Collapsing is a view operation that preserves graph connectivity:
- nodes inside the zone become hidden from the current view
- the zone node represents the collapsed zone
- edges between inside and outside nodes are reconnected to the zone node
- edges fully inside the zone are hidden or summarized
- expanding restores the original nodes and edges
The collapsed zone node should expose useful summary data:
- contained node count
- contained edge count
- dominant node kinds
- inbound and outbound boundary edge counts
- diagnostics such as membership conflicts
This enables drill-down exploration without destroying the operator's context.
Hierarchical Zones
The collapse model naturally leads to hierarchical zones. A tenant subfabric may sit inside a landlord fabric, an access zone may sit inside a deployment environment, and a cost-center view may cut across both as an alternate profile.
Hierarchy should be introduced carefully:
- parent-child containment must be explicit in the zone definition or derived from a deterministic rule
- a node still belongs to exactly one visible leaf zone
- collapsing a parent collapses all visible descendants
- cross-boundary edges must remain visible at the collapsed boundary
The first implementation should support flat zones. The data model should avoid choices that would make hierarchy impossible later.
Diagnostics
Zones should produce diagnostics because rule-based view construction can hide important ambiguity.
Useful diagnostics:
- node matched by more than one membership rule
- node attracted by more than one zone
- edge crosses zone boundaries
- zone has no seed nodes
- attraction depth reached limit
- collapsed zone has hidden internal boundary evidence
Diagnostics belong to the visualization layer. They should not mutate the fabric graph.
Relationship To Fabric Concepts
Zones are not fabrics, subfabrics, realms, domains, environments, cost centers, or tenants. A zone is a view mechanism that can visualize those concepts.
Examples:
- a deployment-environment zone groups nodes by
dev-tegwick,test, orprod - a financial fabric zone groups nodes by lord or tenant responsibility
- a cost-center zone groups nodes for accounting analysis
- an access-zone view groups nodes by operational access policy once that metadata exists
This keeps the graph explorer flexible while preserving the stricter meaning of fabric boundaries: who pays for, owns, and is responsible for infrastructure.
Implementation Direction
The recommended path is incremental:
- Introduce a pure zone resolver that converts graph data and zone definitions into zone instances, node assignments, edge summaries, and diagnostics.
- Replace the current hard-coded environment/access overlay derivation with resolver-backed default zone definitions.
- Add zone-aware rendering state to the graph explorer UI.
- Add saved zone profiles once the model is stable.
- Add collapse-to-zone-node behavior.
- Add per-zone layout only after the resolver and rendering model are stable.
This order keeps the current useful overlay behavior while moving the engine toward zones as first-class view entities.