From 301962aa82eeaa94181da755bc04684d0dfc13fb Mon Sep 17 00:00:00 2001 From: Jonathan <64296013+Joncallim@users.noreply.github.com> Date: Sat, 5 Sep 2026 11:46:38 +0800 Subject: [PATCH 1/7] docs: add Infrastructure Atlas architecture gate --- docs/architecture/INFRASTRUCTURE_ATLAS.md | 331 ++++++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100644 docs/architecture/INFRASTRUCTURE_ATLAS.md diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS.md b/docs/architecture/INFRASTRUCTURE_ATLAS.md new file mode 100644 index 00000000..238d5bf9 --- /dev/null +++ b/docs/architecture/INFRASTRUCTURE_ATLAS.md @@ -0,0 +1,331 @@ +# Infrastructure Atlas Architecture + +Status: prospective architecture for #250/#251. This document does **not** describe shipped behavior. The as-built design docs remain authoritative until #256/#265 cutover. + +## 1. Product objective + +The Infrastructure Atlas replaces the current service graph as DockerMap's flagship spatial product. Its job is to make observed infrastructure understandable without inventing architecture. + +The Atlas must be: + +- truthful: every subject, group, membership, attachment and directional relation has a deterministic source rule; +- deterministic: equivalent canonical evidence produces equivalent projection and logical layout; +- structurally stable: unrelated changes do not globally reshuffle the host; +- useful: a user can locate subjects, exposure, attachments, declared relationships, attention and uncertainty quickly; +- visually restrained: simple HTML/SVG/CSS, strong alignment/hierarchy, low simultaneous color, progressive disclosure; +- continuous: Home, Atlas, Networking, Runtime and detail surfaces reuse one topology identity/interaction language; +- read-only, collision-safe, redaction-safe and bounded. + +Runtime AI/LLM involvement is prohibited. AI may assist implementation and review only. + +## 2. Repo facts that constrain the design + +The current web runtime depends on React, React DOM and React Router; it has no dedicated graph/layout dependency. Zero new graphics dependency is therefore the baseline to beat. + +`ServiceMap.tsx` currently owns custom SVG pan/zoom/selection and uses `lib/layout.ts`, a seeded force simulation followed by global min/max normalization. The new Atlas must not inherit the global-normalization failure mode: adding one extreme subject must not move every existing subject. + +`Map.tsx` deliberately limits graph relationships to resolved Compose start-order declarations and explicitly states that shared networks/storage are context, not proof of communication or causality. This non-claim is mandatory. + +`SystemModel` contains useful collision-safe services, networks, volumes and runtime records, but `ServiceKind` is heuristic classification. It is never topology authority. + +The canonical `ContainerRecord` currently contains id/name/role/image/status/ports/networks/mounts/dependsOn but no Compose project identity. V1 therefore cannot assume project grouping. Project grouping is optional only if #259 identifies a trustworthy existing source; otherwise Docker subjects remain ungrouped or use a provider-neutral presentation taxonomy. + +Runtime contracts contain many distinct node/provider kinds. Atlas must not flatten them all into fake generic services. + +## 3. Source authority gate + +Before implementation, #259 must produce an authority matrix for `DockerSnapshot`, `SystemModel`, `RuntimeMap`, `/api/graph`, and relevant Compose surfaces. + +For every Atlas object class, record: + +1. authoritative source; +2. stable/collision-safe identity; +3. whether direction or causality is actually established; +4. source/evidence reference form; +5. freshness/availability semantics; +6. safe route/focus identity. + +Prefer a narrow frontend adapter over existing authorities. Do not expand backend contracts only to satisfy a preferred diagram. + +## 4. Presentation-domain model + +The exact TypeScript names may change only in the #251 architecture PR. The model must remain closed and serialisable. + +```ts +interface AtlasModel { + projectionVersion: number; + subjects: AtlasSubject[]; + groups: AtlasGroup[]; + relations: AtlasRelation[]; + memberships: AtlasMembership[]; + attachments: AtlasAttachment[]; + aggregates: AtlasAggregate[]; + diagnostics: AtlasDiagnostic[]; + stats: AtlasStats; +} +``` + +### Subject +A routable or visible infrastructure identity. It carries provider/kind metadata plus **separate** operational state, freshness, attention and ambiguity fields. + +### Group +Exists only when a trustworthy source establishes grouping. No fuzzy grouping, image-name clustering or inferred architecture. + +### Relation +Directional only when the source establishes direction. Compose start-order and qualifying runtime evidence are examples; shared network/storage membership is not. + +### Membership / attachment +Non-causal context such as network membership or storage attachment. + +### Aggregate +A bounded deterministic presentation object for high-degree structures. Aggregation may reduce detail but must propagate material child attention/ambiguity/exposure counts. + +### Diagnostic +Represents unsupported, unresolved, collided or otherwise non-routable presentation evidence without selecting an arbitrary endpoint. + +Every projected object carries a named/versioned projection rule and bounded source reference. Renderer-specific geometry does not enter AtlasModel. + +## 5. Orthogonal state model + +Never collapse these concepts into one status color: + +- operational state/health; +- provider/evidence freshness; +- Findings/attention severity; +- identity ambiguity/collision. + +A healthy subject observed through stale evidence is not automatically unhealthy. A healthy subject with a Finding is not degraded. A collision is not a health failure. + +Compact aggregate summaries may define explicit precedence for markers/text, but the underlying fields remain separate and fixtures cover cross-products. + +## 6. Provider-neutral presentation taxonomy + +#262 must exhaustively classify supported runtime kinds into one of: + +- primary spatial subject; +- secondary/context subject; +- membership/attachment object; +- inspector-only evidence; +- unsupported/neutral fallback. + +The taxonomy preserves provider truth. `runtime.layer` and provider names may organise presentation but never become causal architecture by themselves. Unknown future kinds fail closed to neutral/unsupported presentation. + +## 7. Logical layout contract + +The layout consumes AtlasModel only. + +### Required invariants + +- logical coordinates are viewport/theme independent; +- group/lane ordering is canonical; +- local subject ordering is canonical; +- content uses fixed documented geometry classes; long text does not change global topology; +- no random, time, DOM measurement or AI input; +- no global min/max normalization; +- lens changes preserve canonical subject coordinates; +- focus expansion is local, deterministic and reversible. + +### Structural-stability classes + +1. state/freshness/finding-only mutation: zero subject displacement; +2. relation/attachment-only mutation: subject anchors unchanged; affected connector/aggregate region may change; +3. add/remove subject within a group: affected group may reflow; unrelated group anchors/order remain stable; +4. group/lane creation/removal: affected lane may reflow; unrelated lanes preserve order and bounded anchors; +5. viewport/theme/lens change: logical coordinates unchanged. + +#252 turns these into property tests and freezes a numeric displacement budget where exact zero is not appropriate. + +The preferred family of algorithms is deterministic lanes/regions/slots with local reflow. A third-party layout library is not architecture by default. + +## 8. One Atlas, multiple lenses + +Canonical logical placement is shared by: + +- Overview; +- Connectivity; +- Dependencies; +- Storage; +- Runtime; +- Attention. + +Lenses alter emphasis, secondary visibility and inspector content. They do not rebuild the host into unrelated maps. + +### Overview +Orientation-first, not edge-first. Prioritise host/group/subject placement, identity and material attention. Do not draw every relation. Secondary relationship detail appears in a lens or selected local context. + +### Connectivity +Shows bounded network membership, published host bindings and other explicitly evidenced connectivity context. Membership is not traffic. + +### Dependencies +Shows only genuinely directional evidence. Dense relation sets obey #268 congestion/aggregation rules. + +### Storage +Shows volumes/bind/storage attachment without implying data direction. + +### Runtime +Adds provider-neutral host/runtime context according to #262 rather than flattening unlike runtime objects into containers. + +### Attention +Overlays existing Findings/attention/freshness/ambiguity without creating new topology semantics. + +## 9. High-degree policy + +Networks, storage, ports, dependencies and large groups use deterministic aggregation classes. Thresholds are named/versioned constants established from #252/#253 fixtures. + +A threshold transition may reflow the affected structure only. It must not globally rearrange the host. Selected subjects/networks may expand local detail deterministically. + +No runtime aesthetic heuristic chooses between rail/card/aggregate forms. + +## 10. Visual grammar + +#257 owns exact geometry/tokens. Architecture requires: + +- neutral topology by default; +- identity/hierarchy dominates normal healthy views; +- healthy state is quiet rather than a field of green; +- attention becomes prominent when present; +- Hearth Azure for action/focus; +- AI Purple only for AI; +- non-color cues for every semantic distinction; +- technical mono only for technical values; +- compact fixed geometry classes; +- deterministic label wrap/truncate plus full-value access; +- no decorative gradients, glass, glow, particles, animated traffic or physics settling; +- no rainbow project/network palette. + +Relationship grammar: + +| Class | Direction | Default presentation | +| --- | --- | --- | +| evidenced dependency | as evidenced | restrained directed connector in dependency/focus context | +| network membership | none | membership/rail/aggregate | +| storage attachment | none | attachment/aggregate | +| published host port/socket | binding only | host-boundary marker | +| provider/runtime membership | none unless source says otherwise | context/grouping | +| unresolved/collided | none | visible non-routable uncertainty | +| heuristic kind | none | icon/search metadata only | + +#268 freezes edge-routing and congestion budgets. When the budget is exceeded, aggregate/focus; do not draw more lines. + +## 11. Cross-screen continuity + +Continuity is semantic and interaction-level, not merely matching colors. + +The same safe subject retains: + +- canonical display identity; +- provider/kind glyph family; +- state/freshness/attention/ambiguity semantics; +- selected/focused treatment; +- route/focus target where safe; +- evidence language. + +Home uses a crop/summary of the same Atlas model, not an independent mini-map algorithm. Networking/Runtime may remain list/table-heavy where clearer but reuse the same subject contract. Detail screens may show a compact subject header/local context rather than a separate graph. + +#261 freezes URL/lens/selection/expansion/focus state. Durable state stores semantic identities, never layout coordinates. + +## 12. Live refresh + +#269 freezes refresh behavior: + +- one coherent model revision projects/layouts atomically; +- no half-updated layout; +- state-only changes do not move subjects; +- safe surviving selection remains; +- removed/collided selection fails closed with deterministic focus recovery; +- no physics settling or decorative exit animation; +- pan/zoom is preserved/reset only by explicit context policy. + +## 13. Renderer decision + +#253 compares the same fixtures across native SVG/HTML and any justified third-party candidate. + +A dependency must materially beat the zero-dependency baseline on deterministic routing/stability, accessibility, maintainability and accepted visual quality while staying inside bundle/runtime/security budgets. Reject a library that mainly replaces simple pan/zoom/selection. + +Any selected dependency is pinned and cannot add runtime egress, telemetry, remote assets/fonts, unsafe HTML, WASM or workers without separate approval. + +## 14. Module ownership + +Target dependency direction: + +```text +screens + ↓ +atlas presentation + interaction + ↓ +renderer/lenses → deterministic layout + \ / + AtlasModel/projection + ↓ + existing model/contracts +``` + +Suggested implementation map: + +- `apps/web/src/lib/atlas/types.ts` +- `apps/web/src/lib/atlas/source.ts` +- `apps/web/src/lib/atlas/project.ts` +- `apps/web/src/lib/atlas/rules.ts` +- `apps/web/src/lib/atlas/layout.ts` +- `apps/web/src/lib/atlas/layoutPolicy.ts` +- `apps/web/src/lib/atlas/version.ts` +- `apps/web/src/components/atlas/*` +- `apps/web/src/components/atlas/lenses/*` +- `apps/web/src/hooks/useAtlasState.ts` +- `apps/web/src/lib/atlas/__fixtures__/*` + +Rules: pure projection/layout where possible; closed unions; exhaustive switches; stable keys; bounded work; no screen-local topology derivation; no renderer→raw API dependency. `ServiceMap.tsx` remains legacy until cutover. + +## 15. Test architecture + +#252 builds designed adversarial fixtures plus property generation across subject counts, grouping absence/presence, sparse/dense/cyclic declarations, high-degree/multi-membership networks, storage patterns, mixed providers, ports, collisions, long/Unicode labels, orthogonal states/freshness, and controlled mutations/permutations. + +Exact semantic/layout goldens are separate from browser geometry and screenshots (#270): + +1. exact AtlasModel/layout JSON; +2. numeric geometry assertions; +3. controlled screenshot matrix; +4. human approval for intentional visual redesign. + +Screenshot or AI visual review cannot authorize semantic change. + +## 16. Usefulness and visual-quality gates + +#260 freezes task-oriented acceptance: locate a subject, attention, host-published exposure, network/storage membership, a recorded dependency, ambiguity, and the boundary of unknown evidence without critical facts depending on hover. + +Visual rubric covers hierarchy, alignment, whitespace/rhythm, label legibility, connector congestion/crossings, simultaneous color count, group distinguishability, selected/focus clarity, attention salience and continuity with adjacent screens. + +## 17. Security and bounds + +#263 treats all observed labels/metadata as untrusted presentation input. No raw argv/env/secret promotion; no raw value→CSS class/style channel; bounded strings/object/edge/segment counts; safe text rendering; collision/redaction preserved; screenshot fixtures contain no live secrets. + +The 250-object fixture is a stress gate, not permission for unbounded O(n²) behavior. Expansion/routing work has explicit caps. + +## 18. Accessibility/responsive + +#35/#67 remain the floor. Required: keyboard operation, visible non-state focus, deterministic focus recovery, semantic text/table alternative, 200% zoom, reduced motion, touch targets, Axe/manual keyboard evidence. + +Narrow screens switch to directory + focused local topology + inspector rather than shrinking the desktop Atlas until unreadable. + +## 19. Version/change control + +#264 owns internal projection/layout policy versioning. Intentional rule changes update exact goldens with explicit review. Dependency upgrades cannot silently churn coordinates. Do not make internal layout version a public API promise unless separately justified. + +## 20. Implementation spine + +1. #259/#251/#262/#267/#266: authority + semantics + taxonomy + state + module freeze. +2. #252/#260/#270: fixtures, property/usefulness/golden harness. +3. #257/#268: visual grammar and congestion policy. +4. #253/#263/#264: renderer, security/dependency and version decision. +5. #254: projection/layout + Overview behind parallel route/feature gate. +6. #258: bounded high-degree connectivity/storage/port projection. +7. #261/#269/#255: route/revision continuity, lenses and cross-screen integration. +8. #256/#265: heterogeneous-host certification, cutover and as-built docs. + +Do not collapse this into one implementation PR. + +## 21. Review convergence + +Before #251 closure, hostile passes must cover truth/authority, determinism/stability, provider taxonomy, design language, information architecture, coding boundaries, dependency/performance, accessibility, security, cross-screen state, high-degree geometry, live refresh, test governance and documentation control. + +A pass is converged when it produces no new independent P1/P2 architecture requirement and every prior finding is represented here or in a child issue. From 5259a8a3177f2249fa2fb36f2a5ee501dc15258e Mon Sep 17 00:00:00 2001 From: Jonathan <64296013+Joncallim@users.noreply.github.com> Date: Sat, 5 Sep 2026 11:47:36 +0800 Subject: [PATCH 2/7] docs: record Atlas orthogonal architecture reviews --- .../INFRASTRUCTURE_ATLAS_REVIEW.md | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md new file mode 100644 index 00000000..f1e6b605 --- /dev/null +++ b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md @@ -0,0 +1,231 @@ +# Infrastructure Atlas — Orthogonal Review Ledger + +Companion to `INFRASTRUCTURE_ATLAS.md` for #250/#251. This records repo-grounded review findings so implementation agents do not need to reconstruct the reasoning. + +## Review method + +Each pass asks a different failure question. A finding is considered absorbed only when it appears in the architecture spec or a tracked #250 child issue. Review converges when another pass yields no new independent P1/P2 architecture class. + +## Pass 1 — truth and contract authority + +### Finding +The initial Atlas concept assumed evidence-backed application/project grouping. The live generated `ContainerRecord` contract has no Compose project identity. `SystemModel` also contains heuristic `ServiceKind` classification. + +### Refinement +- V1 may not assume project grouping. +- #259 must inventory the actual source authority and choose the narrowest truthful Atlas adapter. +- No name/image clustering or aesthetic backend contract expansion. +- If no trustworthy grouping source exists, render ungrouped/provider-standardised subjects. + +Status: absorbed by #250/#251/#259. + +## Pass 2 — identity and permutation safety + +### Finding +A layout can be permutation-invariant at the canonical-id level while still assigning arbitrary occurrence positions when post-redaction IDs collide. Array index is not a safe semantic identity. + +### Refinement +The projection architecture must distinguish: +- safe routable identity; +- visible non-routable occurrence identity; +- fully indistinguishable duplicate observations. + +For collided visible occurrences, derive presentation occurrence ordering from a canonical safe published tuple/fingerprint plus deterministic duplicate ordinal **after canonical sorting**. The occurrence key is presentation-only and must never become a route or imply underlying identity. If records are indistinguishable after publication, an ambiguity aggregate/count is preferable to inventing distinguishable identities. + +All Atlas arrays and map iteration feeding layout must be canonically sorted before projection/layout. Exact goldens assert this. + +Status: required addition to #251/#252 implementation. + +## Pass 3 — revision coherence vs semantic determinism + +### Finding +`DockerSnapshot.modelRevision` is an opaque publication revision and `lastUpdated` is temporal metadata. If either is embedded in the exact semantic `AtlasModel`, equivalent content across refreshes will fail byte-determinism despite identical topology. + +### Refinement +Separate the deterministic semantic payload from live revision metadata, e.g. conceptually: + +```ts +interface AtlasEnvelope { + sourceRevision: string | null; + projectedAtSourceRevision: string | null; + atlas: AtlasModel; // deterministic from semantic inputs only +} +``` + +Exact AtlasModel/layout goldens exclude wall-clock timestamps and opaque publication revisions. Revision metadata is used to apply coherent updates and reject stale async results, not to determine topology or coordinates. + +Status: required addition to #251/#269. + +## Pass 4 — design language and flagship visual quality + +### Finding +Current as-built design docs say state dominates and describe the old force/impact graph. Carrying that literally into Atlas would create a field of green and make healthy state visually louder than topology identity. + +### Refinement +Atlas-specific exception: normal healthy topology is identity/hierarchy first; health remains truthful but quiet. Attention escalates only when present. Health, freshness, Findings and ambiguity remain orthogonal. + +Overview is orientation-first, not edge-first. Secondary relations move to lenses/selected local context. Beauty comes from alignment, whitespace, regular geometry, limited simultaneous color and low connector congestion. + +Status: absorbed by #257/#260/#265/#267/#268. + +## Pass 5 — graphics/dependency weight + +### Finding +The current web package has no graph/layout runtime dependency. Adding React Flow/ELK simply for pan/zoom/layout could increase bundle/maintenance cost while making the product look like a generic editor. + +### Refinement +Zero graphics dependency is the baseline to beat. Native HTML/SVG/CSS is preferred if it passes fixtures. Any dependency must materially improve accepted deterministic routing/stability/accessibility and pass security/egress/bundle gates. + +Status: absorbed by #253/#263. + +## Pass 6 — structural stability + +### Finding +A blanket requirement that every unrelated mutation cause zero displacement is unrealistic, while simple seeded determinism is too weak. The existing global force normalization demonstrates why global coordinate churn is dangerous. + +### Refinement +Freeze mutation classes: +1. state/freshness/finding only → zero displacement; +2. relation/attachment only → subject anchors fixed; +3. add/remove subject → affected group may reflow only; +4. group/lane change → affected lane may reflow only; +5. lens/theme/viewport → logical coordinates unchanged. + +Do not use global min/max normalization. + +Status: absorbed by #251/#252. + +## Pass 7 — layout complexity and browser denial of service + +### Finding +The existing force layout is pairwise repulsion. A 250-object Atlas cannot simply replace one O(n²) global visual algorithm with another and call it bounded. + +### Refinement +Projection and base placement should target near-linear/log-linear behavior in subjects plus observed relations (conceptually O(n log n + e)) and use explicit caps for routing/expansion. Any super-linear operation must be bounded to a local affected region with a stress test. #253 freezes measured budgets rather than accepting theoretical claims alone. + +Status: absorbed by #253/#263; add explicit complexity assertion to implementation review. + +## Pass 8 — provider standardisation + +### Finding +Runtime contracts contain containers, systemd services, jobs, PM2 apps, tmux sessions, processes, listeners, package nodes, external APIs and other kinds. Flattening them into one `service` visual lies; giving every provider its own dialect destroys continuity. + +### Refinement +#262 defines a provider-neutral presentation taxonomy with primary/context/attachment/inspector-only roles and exhaustive unknown-kind fallback. Provider/layer may organise presentation but does not establish causal architecture. + +Status: absorbed by #262. + +## Pass 9 — cross-screen continuity + +### Finding +Home currently embeds a separate noninteractive ServiceMap while Runtime/Networking/details use different structures. Reusing colors alone will not create continuity. + +### Refinement +One topology-subject contract and one safe interaction state model. Home derives a crop/summary from the same Atlas model. Detail screens use the same subject header/local context. Networking/Runtime may remain table/list-heavy but share identity, state, focus, ambiguity and evidence grammar. Lens/subject state may deep-link; coordinates do not. + +Status: absorbed by #255/#261. + +## Pass 10 — live refresh + +### Finding +Even a deterministic snapshot can flicker or temporarily lie if projection/layout results from different model revisions are interleaved. + +### Refinement +Projection/layout applies atomically for one coherent source revision. Async work must be revision-gated. State-only updates do not move subjects. Safe selection survives; collision/disappearance fails closed. No physics settling. + +Status: absorbed by #269. + +## Pass 11 — high-degree topology and connector congestion + +### Finding +Network rails can become horizontal spaghetti; dependency lenses can become line carpets. Thin lines do not solve information overload. + +### Refinement +Use deterministic aggregation classes and explicit connector/crossing/segment budgets. Overview does not render all edges. Selected context gets priority. When a budget is exceeded, aggregate/focus rather than draw more. + +Status: absorbed by #258/#268. + +## Pass 12 — accessibility/responsive + +### Finding +A spatial flagship can accidentally become mouse/desktop-only even if the rest of DockerMap passes Axe. + +### Refinement +Maintain a semantic non-spatial equivalent, keyboard focus/selection/expansion, deterministic focus recovery, 200% zoom, reduced motion and touch. Narrow screens switch to directory + focused topology + inspector rather than shrinking desktop geometry. + +Status: absorbed by #250/#256. + +## Pass 13 — test governance + +### Finding +Pixel screenshots alone are too brittle and too weak: they can fail for antialiasing while missing semantic drift. + +### Refinement +Separate exact semantic/layout goldens, numeric geometry tests, controlled screenshot regression and human approval. AI screenshot critique is supplementary only. Intentional layout-version changes explicitly migrate exact goldens. + +Status: absorbed by #264/#270. + +## Pass 14 — documentation/change control + +### Finding +Updating current design docs before the feature ships would make them aspirational and break their stated as-built role. + +### Refinement +Keep this prospective architecture separate. #265 updates `DESIGN.md`, `DESIGN_LANGUAGE.md` and screenshots only at accepted cutover. + +Status: absorbed by #265. + +## Pass 15 — coding structure + +### Finding +`ServiceMap.tsx` and `Map.tsx` already combine substantial layout, selection, focus, filter and inspector behavior. Reusing them as the Atlas container would recreate a monolith. + +### Refinement +Freeze dependency direction and modules before implementation (#266). Screens do not derive topology. Renderer does not fetch raw APIs. Projection/layout are pure. Closed semantic unions use exhaustive handling. + +Status: absorbed by #251/#266. + +## Pass 16 — usefulness vs prettiness + +### Finding +A deterministic, unclipped, accessible Atlas can still be a poor flagship if users cannot answer basic topology questions quickly. + +### Refinement +#260 adds task-oriented usefulness and visual-quality rubrics. Critical facts cannot depend on hover. Measure hierarchy, label legibility, crossings/congestion, simultaneous color, focus/attention salience and continuity. Human approval remains required for the final certified screenshots. + +Status: absorbed by #260. + +## Pass 17 — final orthogonal sweep + +Re-ran the architecture against: + +- hosts with no Compose grouping; +- one giant network; +- many small networks; +- no dependency declarations; +- dense dependency declarations; +- Docker-only hosts; +- host-native-heavy mixed runtime; +- collision/redaction-heavy inputs; +- stale/unavailable provider evidence; +- long/Unicode identities; +- state-only rapid refreshes; +- single unrelated subject additions; +- narrow/touch/200% zoom; +- third-party renderer upgrades; +- screenshot/golden migrations. + +No new independent P1/P2 architecture class emerged. Remaining decisions are intentionally delegated to the frozen gates: source authority (#259), exact taxonomy (#262), fixture-derived thresholds/budgets (#252/#253/#257/#268), and implementation evidence. + +## Coding-agent handoff rule + +A coding orchestrator should not reason from this ledger ad hoc. It should execute the issue spine in #250 and treat the review-derived children as acceptance gates: + +1. close authority/semantics architecture; +2. build fixtures/properties/rubrics; +3. freeze visual grammar and renderer decision; +4. implement Overview behind parallel route; +5. implement bounded attachments/lenses/continuity; +6. certify heterogeneous hosts and cut over. + +If implementation requires inventing a new semantic rule not present in `INFRASTRUCTURE_ATLAS.md` or the child issues, stop and reopen architecture rather than improvising in code. From bde02d2d2ecacf78c92d3f6c5ac217c7a369dde4 Mon Sep 17 00:00:00 2001 From: Jonathan <64296013+Joncallim@users.noreply.github.com> Date: Sat, 5 Sep 2026 12:12:39 +0800 Subject: [PATCH 3/7] docs: harden Atlas architecture with second hostile sweep --- .../INFRASTRUCTURE_ATLAS_REVIEW.md | 135 +++++++++++++++++- 1 file changed, 128 insertions(+), 7 deletions(-) diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md index f1e6b605..4cc6f730 100644 --- a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md +++ b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md @@ -195,7 +195,7 @@ A deterministic, unclipped, accessible Atlas can still be a poor flagship if use Status: absorbed by #260. -## Pass 17 — final orthogonal sweep +## Pass 17 — first convergence sweep Re-ran the architecture against: @@ -215,17 +215,138 @@ Re-ran the architecture against: - third-party renderer upgrades; - screenshot/golden migrations. -No new independent P1/P2 architecture class emerged. Remaining decisions are intentionally delegated to the frozen gates: source authority (#259), exact taxonomy (#262), fixture-derived thresholds/budgets (#252/#253/#257/#268), and implementation evidence. +No new independent P1/P2 architecture class emerged at that stage. A subsequent deeper repo-grounded sweep deliberately reopened convergence rather than treating this result as permanent. + +## Pass 18 — exposure semantics are weaker than the mock-up assumed + +### Finding +The generated canonical `ContainerRecord` exposes `ports: string[]`, not a structured `hostIp/hostPort/containerPort/protocol/exposureScope` contract. A visually attractive host-boundary port marker could therefore upgrade opaque display text into a stronger claim such as “externally exposed”. + +### Refinement +#259 now requires an exposure authority audit. Atlas may render stronger host-published/bind-scope semantics only from a structured canonical source or a separately approved closed parser/adapter over an authoritative format. Otherwise ports remain observed text/context and the Atlas omits the stronger boundary claim. + +Status: absorbed by #259; acceptance fixtures must include opaque/ambiguous port strings. + +## Pass 19 — visual containment can fabricate ownership + +### Finding +The architecture distinguished evidence-backed groups from no grouping, but it still allowed “lanes/regions” without explicitly protecting against a renderer making those regions look like semantic containment. A box around nodes is itself a claim to most users. + +### Refinement +Create two distinct model/presentation concepts: +- semantic group/containment: evidence-backed and attributable; +- presentation lane/region: deterministic organisational scaffolding only. + +They require different types and visibly different grammar. Presentation lanes cannot acquire group labels/counts/ownership language that imply membership. + +Status: absorbed into #259; #257 must encode the non-semantic lane treatment. + +## Pass 20 — inspection scope is not automatically host containment + +### Finding +`RuntimeMap` can contain external APIs, DNS/provider context, tailnet/network entities and other subjects that are discoverable while inspecting a host but are not necessarily located on that host. A giant “host” rectangle around all runtime subjects would be false containment. + +### Refinement +Use an inspection-scope concept separately from host containment. Place a subject inside a host only when location/containment/runs-on evidence establishes it. Off-host/context/unresolved subjects remain outside or in an explicitly non-containment context region. Discovery source does not establish physical/logical location. + +Status: absorbed by #259/#262. + +## Pass 21 — duplicate truth across Docker and runtime surfaces + +### Finding +`SystemModel` contains both service/Docker records and a runtime model. Multiple surfaces/providers can describe the same underlying container/service/listener. Atlas could either double-render the same thing or incorrectly merge records by label similarity. + +### Refinement +#259 now requires a source-correlation matrix. Unification is allowed only through canonical collision-safe identity or explicit backend correlation that proves equivalence. Otherwise keep source-scoped subjects/context distinct. Relation/membership dedupe also requires proven semantic equivalence, not merely matching endpoints. Conflicting correlated facts use explicit source ownership/precedence or a diagnostic; no last-write-wins reconciliation. + +Status: absorbed by #259/#262/#252. + +## Pass 22 — split-revision fetching could be accidentally reintroduced + +### Finding +The current `useSystemModel` is already careful: snapshot and runtime responses publish together only when generation, provenance and non-empty `modelRevision` match. A new Atlas hook that independently fetches runtime/network/graph APIs would bypass that protection and visually combine different publications. + +### Refinement +Atlas consumes the coherent model/envelope path and does not independently fetch topology authorities from presentation code. If the authority audit requires data absent from that coherent path, architecture must extend the coherent publication/adaptation boundary first rather than fetch piecemeal in a screen. + +Status: absorbed by #259/#269/#266. + +## Pass 23 — camera stability is separate from coordinate stability + +### Finding +A layout can satisfy every logical-coordinate invariant and still appear to reshuffle if the renderer runs `fitToContent` on every refresh. One unrelated node changes content bounds, changing scale/translation for every visible subject. + +### Refinement +#269 now freezes camera state independently: +- deterministic fit only on initial entry or explicit reset; +- routine model revisions preserve camera exactly where context survives; +- focus uses bounded ensure-visible/local-centre behavior; +- lenses preserve camera where meaningful; +- resize may clamp but never mutate logical coordinates; +- Home preview framing is noninteractive and separate from durable Atlas camera. + +Tests assert both logical displacement and screen-space/camera displacement. + +Status: absorbed by #269/#252. + +## Pass 24 — global density settings can undermine spatial continuity + +### Finding +DockerMap has a global density setting. If Atlas node dimensions/order/layout are recomputed from compact/cozy CSS measurements, changing density can reshuffle topology even though the infrastructure did not change. + +### Refinement +Atlas uses fixed documented spatial geometry or otherwise preserves subject anchor centres/order across density changes. Theme and density never become semantic/layout inputs. Density may affect surrounding directories/inspectors and bounded internal text/padding, but must not cause whole-map re-layout. + +Status: absorbed by #269/#257. + +## Pass 25 — camera, focus and semantic alternative must share one selection authority + +### Finding +The spatial canvas, directory/text alternative and detail inspector could each maintain their own selected subject. This creates split-brain UI state, especially with keyboard navigation, browser back/forward and model revisions. + +### Refinement +`useAtlasState` (or equivalent) owns the single semantic selection/lens/expansion/focus target. Canvas, directory, text alternative and inspector are projections of that state. Visual hover may remain ephemeral and local, but selected identity cannot diverge between representations. Route state and model-revision reconciliation flow through the same authority. + +Status: add to #261/#266 implementation contract. + +## Pass 26 — hidden relations cannot silently disappear from aggregate claims + +### Finding +Overview intentionally suppresses most relations. Aggregate cards such as “3 dependencies” can become misleading if the count mixes resolved, unresolved, filtered, stale or unsupported evidence without exposing coverage. + +### Refinement +Every aggregate/count must define its population and evidence state. Prefer explicit labels such as `3 resolved declarations · 1 unresolved` over a generic `4 dependencies`. Filtering/lens suppression changes presentation, not the underlying count authority. Ambiguous/unresolved evidence remains separately countable and inspectable. + +Status: add to #251/#257/#260/#252. + +## Pass 27 — second convergence sweep + +Re-ran the hardened architecture against additional failure scenarios: + +- opaque port strings that look published but lack structured bind scope; +- the same container represented by Docker and runtime providers; +- two different subjects with identical human labels; +- provider disagreement over correlated subject metadata; +- external API/tailnet/DNS nodes discovered from a host; +- presentation lanes mistaken for evidence-backed groups; +- unchanged Atlas coordinates with auto-fit camera churn; +- density/theme changes during an active inspection; +- selected subject present in canvas but absent from current text filter; +- unresolved relation counts hidden by Overview suppression; +- rapid coherent revisions while selection and camera are active; +- narrow-screen switch between spatial and directory-first representation. + +No further independent P1/P2 architecture class emerged after Passes 18–26. Remaining open choices are now explicitly empirical or authority-driven rather than left to implementation taste: source/correlation authority (#259), provider taxonomy (#262), deterministic fixtures/budgets (#252/#253/#268), visual grammar (#257), interaction/camera policy (#261/#269), and acceptance rubric (#260). ## Coding-agent handoff rule A coding orchestrator should not reason from this ledger ad hoc. It should execute the issue spine in #250 and treat the review-derived children as acceptance gates: -1. close authority/semantics architecture; -2. build fixtures/properties/rubrics; -3. freeze visual grammar and renderer decision; -4. implement Overview behind parallel route; +1. close authority/correlation/semantics architecture; +2. build fixtures/properties/rubrics including second-sweep cases; +3. freeze visual grammar, camera behavior and renderer decision; +4. implement Overview behind parallel route using one selection authority; 5. implement bounded attachments/lenses/continuity; 6. certify heterogeneous hosts and cut over. -If implementation requires inventing a new semantic rule not present in `INFRASTRUCTURE_ATLAS.md` or the child issues, stop and reopen architecture rather than improvising in code. +If implementation requires inventing a new semantic rule not present in `INFRASTRUCTURE_ATLAS.md`, this ledger, or the child issues, stop and reopen architecture rather than improvising in code. From 3cffe2f938072578f7175d0fa63610f3dc21fd0c Mon Sep 17 00:00:00 2001 From: Jonathan <64296013+Joncallim@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:33:31 +0800 Subject: [PATCH 4/7] docs: freeze Atlas authority and correlation boundary --- docs/architecture/INFRASTRUCTURE_ATLAS.md | 70 +++++++++++++++---- .../INFRASTRUCTURE_ATLAS_REVIEW.md | 21 ++++++ 2 files changed, 77 insertions(+), 14 deletions(-) diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS.md b/docs/architecture/INFRASTRUCTURE_ATLAS.md index 238d5bf9..508800dd 100644 --- a/docs/architecture/INFRASTRUCTURE_ATLAS.md +++ b/docs/architecture/INFRASTRUCTURE_ATLAS.md @@ -32,20 +32,41 @@ The canonical `ContainerRecord` currently contains id/name/role/image/status/por Runtime contracts contain many distinct node/provider kinds. Atlas must not flatten them all into fake generic services. -## 3. Source authority gate - -Before implementation, #259 must produce an authority matrix for `DockerSnapshot`, `SystemModel`, `RuntimeMap`, `/api/graph`, and relevant Compose surfaces. - -For every Atlas object class, record: - -1. authoritative source; -2. stable/collision-safe identity; -3. whether direction or causality is actually established; -4. source/evidence reference form; -5. freshness/availability semantics; -6. safe route/focus identity. - -Prefer a narrow frontend adapter over existing authorities. Do not expand backend contracts only to satisfy a preferred diagram. +## 3. Frozen source authority and correlation boundary + +Atlas consumes exactly one coherent `useSystemModel` publication: a snapshot and +runtime map with the same request generation, source/provenance and non-empty +`modelRevision`. Screens, renderers and lenses must not independently fetch +`/api/graph`, Compose, network or runtime endpoints and join their responses. +`/api/graph` is excluded from semantic input because it collapses different +relationship classes into an unproven `connected_to` shape. + +The adapter starts with the coherent runtime map and carries its source revision +only in an outer live envelope. The deterministic `AtlasModel` excludes revision, +timestamps and wall-clock data. `SystemModel` supplies collision-aware lookup and +derived display state only; its `ServiceKind` and status parsing are presentation +metadata, never topology authority. + +| Atlas fact | Authority and safe identity | V1 outcome | +| --- | --- | --- | +| Docker/runtime subject | unique, non-empty published `RuntimeMapNode.id`, source-scoped by closed provider/kind | supported primary, context or inspector-only subject under the taxonomy | +| Docker network, volume or listener | closed fresh runtime evidence with collision-safe endpoints | supported non-causal attachment/context only | +| Compose dependency | closed `docker_compose_depends_on` evidence | supported directional *declaration*, never traffic, readiness, health or causality | +| Systemd dependency | closed V2 Systemd evidence | supported directional *declaration* with independent freshness | +| Provider freshness | matching `providerStates` and evidence freshness | independent marker, never health or membership | +| Finding attention | only a response with the exact coherent model revision and a proven subject identity | independent overlay; unresolved identity remains a diagnostic | +| Compose project/group | no published project identity | unsupported; no name/image/role inference | +| Port/bind/external scope | opaque `ContainerRecord.ports` display strings | context-only observed text; no host-published, protocol, bind-address or reachability claim | +| `/api/graph` and Compose graph/scan | no coherent revisioned evidence/correlation shape | context/inspector-only; excluded from topology projection | +| Cross-source Docker/runtime equivalence | no browser-visible explicit correlation key | unsupported; retain source-scoped records, never fuzzy-merge | +| Host containment and off-host placement | no emitted location/containment fact | requires a future contract change; provider/layer is a presentation lane only | + +Every relation endpoint must have a unique safe key after publication redaction. +Empty or collided identities remain visible as bounded non-routable diagnostics; +array index, name, image, role and label similarity are never fallback identity. +When a future source disagrees with a proven correlation, Atlas preserves a +diagnostic or source-owned fields rather than selecting the most recent value. +Prefer this narrow adapter over backend changes made solely for aesthetics. ## 4. Presentation-domain model @@ -56,6 +77,7 @@ interface AtlasModel { projectionVersion: number; subjects: AtlasSubject[]; groups: AtlasGroup[]; + lanes: AtlasLane[]; relations: AtlasRelation[]; memberships: AtlasMembership[]; attachments: AtlasAttachment[]; @@ -65,12 +87,22 @@ interface AtlasModel { } ``` +`AtlasEnvelope` separately carries the coherent source revision/provenance used +to apply or reject a live result. It is not an input to semantic projection, +exact layout golden files or logical coordinates. + ### Subject A routable or visible infrastructure identity. It carries provider/kind metadata plus **separate** operational state, freshness, attention and ambiguity fields. ### Group Exists only when a trustworthy source establishes grouping. No fuzzy grouping, image-name clustering or inferred architecture. +### Lane +A deterministic presentation scaffold, explicitly distinct from containment. +It has no membership/ownership claim, cannot reuse group styling or labels, and +cannot be promoted to an `AtlasGroup` by a renderer. Provider/layer lanes may +organise safe subjects but do not establish host placement. + ### Relation Directional only when the source establishes direction. Compose start-order and qualifying runtime evidence are examples; shared network/storage membership is not. @@ -85,6 +117,16 @@ Represents unsupported, unresolved, collided or otherwise non-routable presentat Every projected object carries a named/versioned projection rule and bounded source reference. Renderer-specific geometry does not enter AtlasModel. +The closed serialisable union also includes safe routability, source kind/ref, +taxonomy role, operational state, evidence freshness, attention and ambiguity +on each subject; relation evidence refs and direction; aggregate population +coverage (resolved, unresolved and ambiguous); and diagnostics for unsupported +kinds, collisions, disagreement and omitted bounded input. Unknown future +provider/kind pairs must become neutral unsupported diagnostics, never guessed +services. Projection sorts all input and output by canonical safe keys before +layout and imposes named/versioned caps on subjects, relations, attachments per +subject, groups, metadata keys/value length and aggregate expansion. + ## 5. Orthogonal state model Never collapse these concepts into one status color: diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md index 4cc6f730..49e74461 100644 --- a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md +++ b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md @@ -350,3 +350,24 @@ A coding orchestrator should not reason from this ledger ad hoc. It should execu 6. certify heterogeneous hosts and cut over. If implementation requires inventing a new semantic rule not present in `INFRASTRUCTURE_ATLAS.md`, this ledger, or the child issues, stop and reopen architecture rather than improvising in code. + +## Pass 28 — authority and correlation closure sweep + +### Finding +The previous document deferred the authority matrix to #259. That left a coding +agent able to choose a convenient but weaker source, merge Docker and runtime +records by name, or turn a provider/layer lane into host containment. + +### Refinement +`INFRASTRUCTURE_ATLAS.md` now freezes the V1 authority matrix: one coherent +runtime-map-backed publication is the only topology input; `/api/graph` and +Compose surfaces are excluded from semantic projection; project identity, +cross-source correlation and host containment are unsupported without a future +contract. Valid closed runtime evidence distinguishes directional declarations +from non-causal network/storage/listener attachments. Opaque port strings remain +context text. Every supported endpoint requires a unique published identity; +collisions, disagreement and unsupported data become bounded non-routable +diagnostics. The model separately defines non-semantic lanes, source-revision +envelopes and named projection/bounds rules. + +Status: absorbed by #251/#259; no renderer or backend expansion is authorised. From 6b3c153222c50935bc3d8495363cf034648da22b Mon Sep 17 00:00:00 2001 From: Jonathan <64296013+Joncallim@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:35:58 +0800 Subject: [PATCH 5/7] docs: close Atlas semantic authority gaps --- docs/architecture/INFRASTRUCTURE_ATLAS.md | 71 +++++++++++++++---- .../INFRASTRUCTURE_ATLAS_REVIEW.md | 18 +++++ 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS.md b/docs/architecture/INFRASTRUCTURE_ATLAS.md index 508800dd..e2e06e97 100644 --- a/docs/architecture/INFRASTRUCTURE_ATLAS.md +++ b/docs/architecture/INFRASTRUCTURE_ATLAS.md @@ -11,7 +11,7 @@ The Atlas must be: - truthful: every subject, group, membership, attachment and directional relation has a deterministic source rule; - deterministic: equivalent canonical evidence produces equivalent projection and logical layout; - structurally stable: unrelated changes do not globally reshuffle the host; -- useful: a user can locate subjects, exposure, attachments, declared relationships, attention and uncertainty quickly; +- useful: a user can locate subjects, recorded port-publication context, attachments, declared relationships, attention and uncertainty quickly; - visually restrained: simple HTML/SVG/CSS, strong alignment/hierarchy, low simultaneous color, progressive disclosure; - continuous: Home, Atlas, Networking, Runtime and detail surfaces reuse one topology identity/interaction language; - read-only, collision-safe, redaction-safe and bounded. @@ -28,7 +28,7 @@ The current web runtime depends on React, React DOM and React Router; it has no `SystemModel` contains useful collision-safe services, networks, volumes and runtime records, but `ServiceKind` is heuristic classification. It is never topology authority. -The canonical `ContainerRecord` currently contains id/name/role/image/status/ports/networks/mounts/dependsOn but no Compose project identity. V1 therefore cannot assume project grouping. Project grouping is optional only if #259 identifies a trustworthy existing source; otherwise Docker subjects remain ungrouped or use a provider-neutral presentation taxonomy. +The canonical `ContainerRecord` currently contains id/name/role/image/status/ports/networks/mounts/dependsOn but no Compose project identity. V1 therefore has no project grouping. A future project group requires a separately approved, collision-safe contract; until then Docker subjects are ungrouped or use a provider-neutral presentation taxonomy. Runtime contracts contain many distinct node/provider kinds. Atlas must not flatten them all into fake generic services. @@ -91,6 +91,43 @@ interface AtlasModel { to apply or reject a live result. It is not an input to semantic projection, exact layout golden files or logical coordinates. +```ts +type AtlasKey = string; // opaque, non-empty, unique after publication +type AtlasRoutability = "routable" | "non_routable"; +type AtlasRole = "primary" | "context" | "attachment" | "inspector_only" | "unsupported"; +type AtlasSourceRef = + | { kind: "runtime_node"; provider: RuntimeProviderKind; nodeId: AtlasKey } + | { kind: "runtime_evidence"; evidenceId: string; subjectId: AtlasKey } + | { kind: "projection"; rule: ProjectionRuleId }; +type ProjectionRuleId = `atlas-v1/${string}`; + +interface AtlasSubject { + key: AtlasKey; + routability: AtlasRoutability; + role: AtlasRole; + source: AtlasSourceRef; + display: string; // bounded, redacted React text only; never a key + operationalState: "healthy" | "warning" | "degraded" | "offline" | "updating" | "unknown"; + freshness: "fresh" | "stale" | "timed_out" | "unavailable" | "disabled" | "unknown"; + attention: "none" | "advisory" | "warning"; + ambiguity: "none" | "collision" | "unresolved" | "unsupported"; + rule: ProjectionRuleId; +} +interface AtlasGroup { key: AtlasKey; memberKeys: AtlasKey[]; membershipEvidence: AtlasSourceRef[]; rule: ProjectionRuleId; } +interface AtlasLane { key: string; subjectKeys: AtlasKey[]; rule: ProjectionRuleId; } // presentation only, never containment +interface AtlasRelation { source: AtlasKey; target: AtlasKey; direction: "forward"; evidence: AtlasSourceRef[]; rule: ProjectionRuleId; } +interface AtlasMembership { subject: AtlasKey; context: AtlasKey; evidence: AtlasSourceRef[]; rule: ProjectionRuleId; } +interface AtlasAttachment { subject: AtlasKey; context: AtlasKey; evidence: AtlasSourceRef[]; rule: ProjectionRuleId; } +interface AtlasAggregate { key: string; population: { resolved: number; unresolved: number; ambiguous: number }; rule: ProjectionRuleId; } +interface AtlasDiagnostic { kind: "collision" | "unresolved" | "unsupported" | "disagreement" | "bounded_omission"; source: AtlasSourceRef; rule: ProjectionRuleId; } +interface AtlasStats { subjects: number; relations: number; attachments: number; unsupported: number; boundedOmissions: number; } +``` + +The actual implementation must use closed discriminated unions equivalent to +this contract (not free-form strings). `AtlasSourceRef` may contain only safe +published runtime node/evidence identifiers and named projection rules: never +raw metadata, path, label, port, Compose content or error text. + ### Subject A routable or visible infrastructure identity. It carries provider/kind metadata plus **separate** operational state, freshness, attention and ambiguity fields. @@ -110,7 +147,7 @@ Directional only when the source establishes direction. Compose start-order and Non-causal context such as network membership or storage attachment. ### Aggregate -A bounded deterministic presentation object for high-degree structures. Aggregation may reduce detail but must propagate material child attention/ambiguity/exposure counts. +A bounded deterministic presentation object for high-degree structures. Aggregation may reduce detail but must propagate material child attention, ambiguity and recorded-port context counts. ### Diagnostic Represents unsupported, unresolved, collided or otherwise non-routable presentation evidence without selecting an arbitrary endpoint. @@ -140,17 +177,23 @@ A healthy subject observed through stale evidence is not automatically unhealthy Compact aggregate summaries may define explicit precedence for markers/text, but the underlying fields remain separate and fixtures cover cross-products. -## 6. Provider-neutral presentation taxonomy +## 6. Frozen provider-neutral presentation taxonomy -#262 must exhaustively classify supported runtime kinds into one of: +The V1 adapter classifies every current `RuntimeNodeKind` as follows. This is +presentation vocabulary, not a claim of service ownership, containment or +causality; `provider` and `layer` may choose a non-semantic lane only. -- primary spatial subject; -- secondary/context subject; -- membership/attachment object; -- inspector-only evidence; -- unsupported/neutral fallback. +| Runtime kind | Atlas role | +| --- | --- | +| `container`, `systemd_service`, `pm2_app`, `node_application`, `python_application`, `database`, `worker` | primary subject | +| `host`, `tailnet_node`, `reverse_proxy`, `local_dns_resolver`, `dns_provider`, `external_api`, `orchestrator_workload` | context subject | +| `docker_network`, `docker_volume`, `storage`, `network_listener` | attachment/context; never causal containment | +| `scheduled_job`, `tmux_session`, `process`, `package`, `package_dependency`, `ai_agent`, `host_risk`, `service` | inspector-only unless a later closed rule promotes it | -The taxonomy preserves provider truth. `runtime.layer` and provider names may organise presentation but never become causal architecture by themselves. Unknown future kinds fail closed to neutral/unsupported presentation. +Unknown future kinds, unknown provider/kind pairs, and collision/unresolved +records become a visible neutral unsupported diagnostic. They never become a +guessed primary service. `runtime.layer` and provider names may organise +presentation but never become causal architecture by themselves. ## 7. Logical layout contract @@ -196,7 +239,7 @@ Lenses alter emphasis, secondary visibility and inspector content. They do not r Orientation-first, not edge-first. Prioritise host/group/subject placement, identity and material attention. Do not draw every relation. Secondary relationship detail appears in a lens or selected local context. ### Connectivity -Shows bounded network membership, published host bindings and other explicitly evidenced connectivity context. Membership is not traffic. +Shows bounded network membership, Docker-recorded port-publication context and other explicitly evidenced connectivity context. Membership is not traffic, and a port record is not a host-boundary, bind-scope, protocol or reachability claim. ### Dependencies Shows only genuinely directional evidence. Dense relation sets obey #268 congestion/aggregation rules. @@ -242,7 +285,7 @@ Relationship grammar: | evidenced dependency | as evidenced | restrained directed connector in dependency/focus context | | network membership | none | membership/rail/aggregate | | storage attachment | none | attachment/aggregate | -| published host port/socket | binding only | host-boundary marker | +| recorded port publication | no direction or reachability | bounded context/attachment | | provider/runtime membership | none unless source says otherwise | context/grouping | | unresolved/collided | none | visible non-routable uncertainty | | heuristic kind | none | icon/search metadata only | @@ -333,7 +376,7 @@ Screenshot or AI visual review cannot authorize semantic change. ## 16. Usefulness and visual-quality gates -#260 freezes task-oriented acceptance: locate a subject, attention, host-published exposure, network/storage membership, a recorded dependency, ambiguity, and the boundary of unknown evidence without critical facts depending on hover. +#260 freezes task-oriented acceptance: locate a subject, attention, recorded port-publication context, network/storage membership, a recorded dependency, ambiguity, and the boundary of unknown evidence without critical facts depending on hover. Visual rubric covers hierarchy, alignment, whitespace/rhythm, label legibility, connector congestion/crossings, simultaneous color count, group distinguishability, selected/focus clarity, attention salience and continuity with adjacent screens. diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md index 49e74461..fdbe1d29 100644 --- a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md +++ b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md @@ -371,3 +371,21 @@ diagnostics. The model separately defines non-semantic lanes, source-revision envelopes and named projection/bounds rules. Status: absorbed by #251/#259; no renderer or backend expansion is authorised. + +## Pass 29 — closure precision sweep + +### Finding +The first authority-matrix amendment still used host-boundary wording for opaque +port strings, described rather than defined the serialisable object contract, +and deferred the current runtime-kind taxonomy to a later issue. + +### Refinement +The architecture now calls opaque ports only Docker-recorded port-publication +context, with no host placement, bind scope, protocol or reachability meaning. +It includes a normative closed field contract for subjects, semantic groups, +presentation lanes, relations, memberships, attachments, aggregates, +diagnostics, statistics and safe source references. It also exhaustively maps +all current runtime node kinds to primary, context, attachment, inspector-only +or neutral unsupported roles. Unknown future kinds remain diagnostics. + +Status: absorbed by #251/#259/#262. No new production authority is authorised. From 07d1925f63a7aac56e12a5b3751fdbd53d31cb4b Mon Sep 17 00:00:00 2001 From: Jonathan <64296013+Joncallim@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:38:47 +0800 Subject: [PATCH 6/7] docs: bind Atlas semantics to structural evidence --- docs/architecture/INFRASTRUCTURE_ATLAS.md | 50 ++++++++++++------- .../INFRASTRUCTURE_ATLAS_REVIEW.md | 18 +++++++ 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS.md b/docs/architecture/INFRASTRUCTURE_ATLAS.md index e2e06e97..d4611d84 100644 --- a/docs/architecture/INFRASTRUCTURE_ATLAS.md +++ b/docs/architecture/INFRASTRUCTURE_ATLAS.md @@ -92,20 +92,28 @@ to apply or reject a live result. It is not an input to semantic projection, exact layout golden files or logical coordinates. ```ts -type AtlasKey = string; // opaque, non-empty, unique after publication +type AtlasKey = string; // opaque, bounded, non-empty, unique after publication +type AtlasDerivedKey = string; // named-rule-derived, bounded, never routable type AtlasRoutability = "routable" | "non_routable"; type AtlasRole = "primary" | "context" | "attachment" | "inspector_only" | "unsupported"; -type AtlasSourceRef = - | { kind: "runtime_node"; provider: RuntimeProviderKind; nodeId: AtlasKey } - | { kind: "runtime_evidence"; evidenceId: string; subjectId: AtlasKey } - | { kind: "projection"; rule: ProjectionRuleId }; type ProjectionRuleId = `atlas-v1/${string}`; +type AtlasNodeSourceRef = { kind: "runtime_node"; provider: RuntimeProviderKind; nodeId: AtlasKey; runtimeKind: RuntimeNodeKind }; +type AtlasEdgeEvidenceSourceRef = { + kind: "runtime_edge_evidence"; + source: AtlasKey; + target: AtlasKey; + relationship: RuntimeRelationshipKind; + evidence: RuntimeEvidenceRef; // exact existing closed, bounded published value +}; +type AtlasEvidenceSources = [AtlasEdgeEvidenceSourceRef, ...AtlasEdgeEvidenceSourceRef[]]; // capped at the RuntimeMap evidence limit +type AtlasProjectionRef = { kind: "projection"; rule: ProjectionRuleId }; interface AtlasSubject { key: AtlasKey; routability: AtlasRoutability; role: AtlasRole; - source: AtlasSourceRef; + source: AtlasNodeSourceRef; + runtimeKind: RuntimeNodeKind; display: string; // bounded, redacted React text only; never a key operationalState: "healthy" | "warning" | "degraded" | "offline" | "updating" | "unknown"; freshness: "fresh" | "stale" | "timed_out" | "unavailable" | "disabled" | "unknown"; @@ -113,20 +121,26 @@ interface AtlasSubject { ambiguity: "none" | "collision" | "unresolved" | "unsupported"; rule: ProjectionRuleId; } -interface AtlasGroup { key: AtlasKey; memberKeys: AtlasKey[]; membershipEvidence: AtlasSourceRef[]; rule: ProjectionRuleId; } -interface AtlasLane { key: string; subjectKeys: AtlasKey[]; rule: ProjectionRuleId; } // presentation only, never containment -interface AtlasRelation { source: AtlasKey; target: AtlasKey; direction: "forward"; evidence: AtlasSourceRef[]; rule: ProjectionRuleId; } -interface AtlasMembership { subject: AtlasKey; context: AtlasKey; evidence: AtlasSourceRef[]; rule: ProjectionRuleId; } -interface AtlasAttachment { subject: AtlasKey; context: AtlasKey; evidence: AtlasSourceRef[]; rule: ProjectionRuleId; } -interface AtlasAggregate { key: string; population: { resolved: number; unresolved: number; ambiguous: number }; rule: ProjectionRuleId; } -interface AtlasDiagnostic { kind: "collision" | "unresolved" | "unsupported" | "disagreement" | "bounded_omission"; source: AtlasSourceRef; rule: ProjectionRuleId; } +interface AtlasGroup { key: AtlasDerivedKey; memberKeys: AtlasKey[]; membershipEvidence: AtlasEvidenceSources; rule: ProjectionRuleId; } +interface AtlasLane { key: AtlasDerivedKey; subjectKeys: AtlasKey[]; rule: ProjectionRuleId; } // presentation only, never containment +interface AtlasRelation { source: AtlasKey; target: AtlasKey; direction: "forward"; evidence: AtlasEvidenceSources; rule: ProjectionRuleId; } +interface AtlasMembership { subject: AtlasKey; context: AtlasKey; evidence: AtlasEvidenceSources; rule: ProjectionRuleId; } +interface AtlasAttachment { subject: AtlasKey; context: AtlasKey; evidence: AtlasEvidenceSources; rule: ProjectionRuleId; } +interface AtlasAggregate { key: AtlasDerivedKey; population: { resolved: number; unresolved: number; ambiguous: number; omitted: number }; sourceCoverage: AtlasEvidenceSources; rule: ProjectionRuleId; } +interface AtlasDiagnostic { kind: "collision" | "unresolved" | "unsupported" | "disagreement" | "bounded_omission"; source: AtlasProjectionRef; rule: ProjectionRuleId; } interface AtlasStats { subjects: number; relations: number; attachments: number; unsupported: number; boundedOmissions: number; } ``` The actual implementation must use closed discriminated unions equivalent to -this contract (not free-form strings). `AtlasSourceRef` may contain only safe -published runtime node/evidence identifiers and named projection rules: never -raw metadata, path, label, port, Compose content or error text. +this contract (not free-form strings). A runtime evidence ref is structural and +edge-scoped: its source, target, relationship and full closed published evidence +record travel together. An evidence `id` is never a routing key. Relations, +memberships and attachments require one or more such evidence refs; projection +refs and bare node refs cannot manufacture a semantic link. Semantic groups +also require edge evidence and are `[]` in V1 because no supported grouping fact +exists. `AtlasProjectionRef` is only for adapter diagnostics/derived aggregates, +never a subject, relation or group fact. Raw metadata, path, label, port, +Compose content and error text are forbidden from every source ref. ### Subject A routable or visible infrastructure identity. It carries provider/kind metadata plus **separate** operational state, freshness, attention and ambiguity fields. @@ -152,12 +166,12 @@ A bounded deterministic presentation object for high-degree structures. Aggregat ### Diagnostic Represents unsupported, unresolved, collided or otherwise non-routable presentation evidence without selecting an arbitrary endpoint. -Every projected object carries a named/versioned projection rule and bounded source reference. Renderer-specific geometry does not enter AtlasModel. +Every projected object carries a named/versioned projection rule and bounded source reference. Non-routable diagnostics must not expose a collided node key as a focus or route target. Renderer-specific geometry does not enter AtlasModel. The closed serialisable union also includes safe routability, source kind/ref, taxonomy role, operational state, evidence freshness, attention and ambiguity on each subject; relation evidence refs and direction; aggregate population -coverage (resolved, unresolved and ambiguous); and diagnostics for unsupported +coverage (resolved, unresolved, ambiguous and omitted); and diagnostics for unsupported kinds, collisions, disagreement and omitted bounded input. Unknown future provider/kind pairs must become neutral unsupported diagnostics, never guessed services. Projection sorts all input and output by canonical safe keys before diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md index fdbe1d29..fa60ced6 100644 --- a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md +++ b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md @@ -389,3 +389,21 @@ all current runtime node kinds to primary, context, attachment, inspector-only or neutral unsupported roles. Unknown future kinds remain diagnostics. Status: absorbed by #251/#259/#262. No new production authority is authorised. + +## Pass 30 — structural provenance closure sweep + +### Finding +An evidence id is not a safe edge-routing key after publication redaction, and +a generic projection reference could accidentally manufacture a semantic link. + +### Refinement +The source-reference contract now separates runtime-node provenance, structural +runtime-edge evidence (source, target, relationship and the full closed +published evidence value) and projection-only references. Relations, +memberships, attachments and semantic groups require non-empty edge evidence; +V1 groups are explicitly empty until a grouping contract exists. Aggregates +carry bounded evidence coverage plus resolved/unresolved/ambiguous/omitted +counts. Subjects retain their closed runtime kind, derived keys are never +routable, and collision diagnostics cannot become focus targets. + +Status: absorbed by #251/#259. No renderer or backend change is authorised. From a5639858ae363b527c09b5f198d2f06a1e8713f5 Mon Sep 17 00:00:00 2001 From: Jonathan <64296013+Joncallim@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:40:07 +0800 Subject: [PATCH 7/7] docs: make Atlas collision identities non-routable --- docs/architecture/INFRASTRUCTURE_ATLAS.md | 10 ++++------ docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md | 7 +++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS.md b/docs/architecture/INFRASTRUCTURE_ATLAS.md index d4611d84..5fd74f03 100644 --- a/docs/architecture/INFRASTRUCTURE_ATLAS.md +++ b/docs/architecture/INFRASTRUCTURE_ATLAS.md @@ -94,7 +94,6 @@ exact layout golden files or logical coordinates. ```ts type AtlasKey = string; // opaque, bounded, non-empty, unique after publication type AtlasDerivedKey = string; // named-rule-derived, bounded, never routable -type AtlasRoutability = "routable" | "non_routable"; type AtlasRole = "primary" | "context" | "attachment" | "inspector_only" | "unsupported"; type ProjectionRuleId = `atlas-v1/${string}`; type AtlasNodeSourceRef = { kind: "runtime_node"; provider: RuntimeProviderKind; nodeId: AtlasKey; runtimeKind: RuntimeNodeKind }; @@ -108,12 +107,8 @@ type AtlasEdgeEvidenceSourceRef = { type AtlasEvidenceSources = [AtlasEdgeEvidenceSourceRef, ...AtlasEdgeEvidenceSourceRef[]]; // capped at the RuntimeMap evidence limit type AtlasProjectionRef = { kind: "projection"; rule: ProjectionRuleId }; -interface AtlasSubject { - key: AtlasKey; - routability: AtlasRoutability; +interface AtlasSubjectBase { role: AtlasRole; - source: AtlasNodeSourceRef; - runtimeKind: RuntimeNodeKind; display: string; // bounded, redacted React text only; never a key operationalState: "healthy" | "warning" | "degraded" | "offline" | "updating" | "unknown"; freshness: "fresh" | "stale" | "timed_out" | "unavailable" | "disabled" | "unknown"; @@ -121,6 +116,9 @@ interface AtlasSubject { ambiguity: "none" | "collision" | "unresolved" | "unsupported"; rule: ProjectionRuleId; } +type AtlasSubject = + | (AtlasSubjectBase & { key: AtlasKey; routability: "routable"; source: AtlasNodeSourceRef; runtimeKind: RuntimeNodeKind }) + | (AtlasSubjectBase & { key: AtlasDerivedKey; routability: "non_routable"; source: AtlasProjectionRef; runtimeKind: RuntimeNodeKind | null }); interface AtlasGroup { key: AtlasDerivedKey; memberKeys: AtlasKey[]; membershipEvidence: AtlasEvidenceSources; rule: ProjectionRuleId; } interface AtlasLane { key: AtlasDerivedKey; subjectKeys: AtlasKey[]; rule: ProjectionRuleId; } // presentation only, never containment interface AtlasRelation { source: AtlasKey; target: AtlasKey; direction: "forward"; evidence: AtlasEvidenceSources; rule: ProjectionRuleId; } diff --git a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md index fa60ced6..9f768bc6 100644 --- a/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md +++ b/docs/architecture/INFRASTRUCTURE_ATLAS_REVIEW.md @@ -407,3 +407,10 @@ counts. Subjects retain their closed runtime kind, derived keys are never routable, and collision diagnostics cannot become focus targets. Status: absorbed by #251/#259. No renderer or backend change is authorised. + +## Pass 31 — non-routable identity precision + +The illustrative subject type now separates routable subjects (unique published +runtime-node key) from visible non-routable occurrences (derived key plus +projection diagnostic). A collision occurrence therefore cannot accidentally +reuse a collided published node key as a route or focus identity.