generated from coulomb/repo-seed
333 lines
12 KiB
Markdown
333 lines
12 KiB
Markdown
# 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:
|
|
|
|
```yaml
|
|
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:
|
|
|
|
- `equals`
|
|
- `not_equals`
|
|
- `in`
|
|
- `not_in`
|
|
- `exists`
|
|
- `missing`
|
|
- `matches`
|
|
|
|
Useful rule composition:
|
|
|
|
- `all`: every nested rule must match
|
|
- `any`: at least one nested rule must match
|
|
- `none`: 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`, or `both`
|
|
- 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:
|
|
|
|
1. Seed membership wins over attracted membership.
|
|
2. If two zones seed the same node, the conflict is reported and the node is
|
|
assigned to the higher zone.
|
|
3. If two zones attract the same node, the node is assigned to the higher zone.
|
|
4. If height ties, the earlier definition wins.
|
|
5. 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:
|
|
|
|
1. Place zones and unzoned nodes on the main canvas.
|
|
2. 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:
|
|
|
|
1. Resolve zones from the current graph and view filters.
|
|
2. Place zone containers and unzoned nodes in the global canvas.
|
|
3. For each zone, compute local coordinates for its assigned nodes using the
|
|
zone's configured layout algorithm.
|
|
4. Project local zone coordinates into global graph coordinates.
|
|
5. 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.
|
|
|
|
### 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`, or `prod`
|
|
- 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:
|
|
|
|
1. Introduce a pure zone resolver that converts graph data and zone definitions
|
|
into zone instances, node assignments, edge summaries, and diagnostics.
|
|
2. Replace the current hard-coded environment/access overlay derivation with
|
|
resolver-backed default zone definitions.
|
|
3. Add zone-aware rendering state to the graph explorer UI.
|
|
4. Add saved zone profiles once the model is stable.
|
|
5. Add collapse-to-zone-node behavior.
|
|
6. 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.
|