- Remove local filter bar (Search/Type/Health) — use global header
context (Region/Env/Stage) as single source of filtering
- Pass global context selections to layout API — graph re-fetches and
ElkSharp re-lays out only the filtered environments
- Fix backend: skip promotion edges where source or target environment
is outside the filtered set (was causing 400 errors)
- Replace below-graph detail zone with 360px right side drawer that
doesn't scroll away from the graph
- Stats badges (regions/environments/paths) moved to overlay on graph
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Region container rects were blocking pointer events on edges behind
them. Set pointer-events: none on .region-rect so clicks pass through
to the edges layer beneath.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The environments page is now a single graph + detail zone:
- Removed all 10 tabs from topology shell (StellaPageTabsComponent gone)
- Detail zone appears below graph at full width when node/edge selected
- Shows environment summary chips, hosts/targets table, and action links
Relocated pages to their conceptual homes with backward-compat redirects:
- Agents, Runtime Drift, Pending Deletions → /ops/operations/
- Connectivity → /security/connectivity
- Gate Profiles → /ops/policy/gates/profiles
- Promotion Graph, Workflows, Readiness → /releases/
- Added Agent Fleet + Runtime Drift to Operations sidebar
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The ops parent route had breadcrumb: 'Operations' which prepended
'Operations >' to every child section (Policy, Integrations, Platform
Setup, Scanner Ops). But the sidebar treats these as independent
top-level sections, not children of Operations.
Fix: suppress the ops breadcrumb (set to '') and move 'Operations'
breadcrumb to the operations child route. Each section now shows
its own breadcrumb independently:
- /ops/policy/governance → Policy > Governance
- /ops/operations → Operations
- /ops/integrations → Integrations
- /ops/platform-setup → Platform Setup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The stella-page-tabs component with urlParam="tab" uses query params
for tab state, which conflicts with child route navigation. The shell
uses router.navigate() for child routes, so urlParam must not be set.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All policy child routes were missing data.breadcrumb, causing the
breadcrumb trail to show only "Policy" regardless of depth.
Added breadcrumbs to: Packs, Governance, Simulation, VEX & Exceptions,
Gate Catalog, Gate Simulation, Environment/Release/Approval Gates,
and Audit. Tab children intentionally omit breadcrumbs since the
tab label provides that context.
Breadcrumb trails now show e.g. "Policy > Governance" or
"Policy > Simulation" matching the sidebar navigation hierarchy.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Increase LayerSpacing from 60 to 120 and NodeSpacing from 40 to 60
for wider promotion arrows between environments
- Increase CompoundPadding from 30 to 40 for better region container
separation
- Replace inline edge labels with tooltip callout pattern: truncated
text in a background box with dashed leader line to the edge
- Edge labels capped at 30 chars with ellipsis
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The line numbers sidebar and snippets bar used --color-terminal-bg
(dark/black) which created jarring dark patches on the light page.
Replaced with --color-surface-secondary for a subtle warm tint that
blends with the editor area.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When no pack is selected, the tab bar showed only one "Workspace" tab
which is pointless. Now tabs are conditionally rendered only when a
pack is opened (6 tabs: Dashboard, Edit, Rules, YAML, Approvals,
Simulate). Also removed urlParam="tab" to prevent double-navigation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The PlatformContextStore pre-selects regions/environments which caused
the layout API to return 400. The topology page should show everything
on initial load - filtering is done client-side via the filter bar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 3 fragmented environment views (2 hardcoded stubs + tables component)
and D3.js force-directed map with a single unified topology page at
/environments/overview. The page renders an interactive SVG graph using
ElkSharp compound layout (regions as parent containers, environments as
child nodes, promotion paths as directed edges with gate labels).
Backend: new GET /api/v2/topology/layout endpoint that builds ElkGraph
from topology read model, runs ElkSharp compound layout, returns enriched
positioned nodes and routed edges.
Frontend: topology-graph.component.ts (SVG renderer with zoom/pan/select),
topology-graph-page.component.ts (filter bar + graph + detail side panel).
Deleted: environments-list-page, platform-setup-regions-environments-page,
topology-map-page, topology-regions-environments-page. Routes consolidated
from ~12 paths to 6 with backward-compat redirects.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Operations Hub:
- "Jump to" links now use layout="aside" with descriptions for each
sub-page (Data Integrity, Jobs, Health, Quotas, AOC, Packs)
Advisories & VEX:
- Quick links use layout="aside" with label "Configure"
- Descriptions: "Configure NVD, OSV, and GHSA advisory sources"
Topology Environment Detail:
- "Navigate" links use layout="aside" with descriptions
Offline Kit:
- Replaced raw quick-link-pill divs with stella-quick-links component
- Uses layout="aside" with 4 links + descriptions
3 more pages (VEX Hub, Platform Setup, Administration) still use raw
quick-link-pill pattern — to be converted in follow-up.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Component extension:
- Add 'description' field to StellaQuickLink interface
- Add 'layout' input: 'inline' (default, horizontal dots) or 'aside' (vertical
with descriptions, border-left accent on hover)
- Aside layout shows label + description per link in a vertical list
- Full CSS for aside variant: hover states, focus ring, icon transitions
Dashboard page:
- Quick Links moved to aside panel with elevated background and border
- All 6 links now have descriptions (e.g., "Deployment timeline and run history")
Evidence Overview page:
- "Shortcuts" and "Related Domains" sections use layout="aside"
- All 10 links now have descriptions
AGENTS.md:
- New "Quick Links Convention (MANDATORY)" rule: must use stella-quick-links
with layout="aside", descriptions, and right-aligned aside placement
Remaining pages (8+) to be updated in follow-up commit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace btn backgrounds from --color-status-info to --color-btn-primary-bg
across all governance and simulation components (30+ instances)
- Fix code block backgrounds to use --color-terminal-bg instead of
--color-surface-inverse for proper syntax display contrast
- Fix JSON code text from --color-text-muted to --color-terminal-text
for readable code on dark backgrounds
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The shell's context header (title, subtitle, Reset view link) duplicated
context already provided by the sidebar navigation and each child page's
own header. Simplified the shell to a pure router-outlet passthrough.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each governance sub-component had its own h2 title + subtitle that
duplicated the tab label and the parent "Policy Governance" context.
Removed the redundant headers from 13 tab components while preserving
action buttons (Configure Budget, Add Weight, New Profile, etc.) as
standalone right-aligned action bars.
Detail sub-routes (risk-profile-editor, conflict-resolution-wizard)
keep their titles since they are not tab panels.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New test suite: navigation-restructure.e2e.spec.ts (26 tests, 7 groups)
Group 1 - Sidebar structure (7 tests):
- Dashboard ungrouped and first
- Release Control has Deployments, Releases, Environments
- Policy group has 5 items (no Release Gates)
- Security group has no Reports
- Operations has no Policy or Trust Analytics
- Audit & Evidence has Trust (not Trust Audit)
Group 2 - Releases unified page (5 tests):
- Title is "Release Control"
- Has Releases + Versions tabs
- Default tab is Releases
- Versions tab changes button to New Version
- /releases/versions redirects to ?tab=versions
Group 3 - Deployments page (7 tests):
- Has Pipeline + Approvals tabs (no Table/Correlations)
- No redundant context chips
- Approvals tab has gate summary cards + Gate Type column + search
- No Angular errors
Group 4 - Route redirects (2 tests):
- /security/reports → /security
- /triage/audit-bundles → /evidence/bundles
Group 5 - Page content consistency (6 tests):
- Dashboard, Vulnerabilities, Scheduled Jobs, Notifications, Audit Log headings correct
- No NG02100 errors on Audit Log
Group 6 - Diagnostics (1 test):
- NOT RUN labels (not NOT RAN)
Group 7 - Breadcrumbs (2 tests):
- Operations breadcrumb not duplicated
- Says "Operations" not "Ops"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Product rationale: Users asking "why is my release blocked?" had to check
3 places (Policy > Release Gates, Deployments > Approvals, Release Detail > Gates).
Now the Deployments Approvals tab is the single surface for all blocking
information with action capability.
Approvals tab enriched:
- Summary cards: Pending Approvals, Gate Failures, Gates Passed counts
- Table columns: Release, Promotion, Gate Type, Status, Reason, Requested, Actions
- Gate Type column shows approval/policy/security/freeze/dependency
- Reason column explains blocking status
- Contextual action: "Policy" link to policy packs when gates are blocking
- Approve/Reject buttons for pending human approvals
Policy sidebar:
- Release Gates removed from Policy group (5 items → 4: Packs, Governance,
Simulation, VEX & Exceptions, Audit)
- /ops/policy/gates redirects to /releases/deployments?view=approvals
- Sub-routes (gates/catalog, gates/simulate, etc.) retained for deep links
- Policy shell subtitle updated to remove "release gates" mention
No functionality loss — policy authors use Simulation to test rules and
Audit to review change history. The gate evaluation impact on releases
is now visible in context where operators can act on it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Approvals tab:
- Default gate toggles all OFF (shows all approvals, not just "gated" type)
- Add search input field that filters by release name, version, environment,
requestedBy, and status
- Approve/Reject buttons now visible for all pending approvals (gate filter
was hiding them by defaulting to only "gated" type)
Versions tab:
- Hide the ReleaseListComponent's own header (title + page-action-outlet)
when embedded=true, eliminating the duplicate "New Version" button
- Parent Release Control page already provides the header and dynamic button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pending actions lane:
- Only visible on Pipeline tab (not Approvals), uses showPendingLane computed
- Exit animation now works: pendingLaneHidden signal delays @if removal until
the 250ms CSS collapse animation completes
- Re-shows when switching back to Pipeline tab
Approvals tab:
- Replaced horizontal card scroll with a proper sortable table
- Columns: Release, Promotion (source → target), Status, Urgency, Gates, Requested, Actions
- Shows requestedAt date + requestedBy in the Requested column
- Approve/Reject/View buttons inline in the Actions column
- Empty state message when no approvals match gate filters
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Title: "Release Control" (encompasses both tabs)
- Subtitle changes per tab:
- Releases tab: "Promotion pipeline with gate status, risk posture, and evidence for every release."
- Versions tab: "Sealed digest-first version catalog across standard and hotfix lanes."
- Create button changes per tab:
- Releases tab: "New Release" → /releases/new
- Versions tab: "New Version" → /releases/versions/new
- Uses Angular effect() to reactively update pageAction when activeTab changes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both pages used self-closing <stella-page-tabs ... /> with content rendered
as sibling elements OUTSIDE the component. This caused an empty tabpanel
with content floating below on the page background.
Fix: wrap tab-conditional content INSIDE <stella-page-tabs>...</stella-page-tabs>
so it projects into the tabpanel slot. Now the tab bar and its content share
the same visual container with the correct border and background.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The "Approve (1)" action on the Releases table was a link navigating to
/releases/approvals (a separate page). Users expected an inline confirmation
to approve the release directly.
Now shows an app-confirm-dialog with the release name, then calls the
approval decision API (POST /api/v1/approvals/{id}/decision) and refreshes
the release list on success.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Revert to /api/v1/approvals (not /api/v1/release-orchestrator/approvals).
The gateway routes /api/v1/approvals/* → JobEngine, which registers the
/decision endpoint via ReleaseControlV2Endpoints.PostApprovalDecision().
The /api/v1/release-orchestrator/approvals/{id}/approve endpoints are
the classic routes from ApprovalEndpoints.cs — both work but the v1
/decision endpoint is the canonical one that supports approve/reject/
defer/escalate actions via a single body parameter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Approval API fix:
- Frontend was calling /api/v1/approvals/{id}/decision (wrong URL)
- Backend registers at /api/v1/release-orchestrator/approvals/{id}/approve
- Updated queueBaseUrl and detailBaseUrl to match actual backend routes
- Changed approve/reject to POST /{id}/approve and /{id}/reject (not /decision)
Pending actions animation:
- Add CSS keyframe animations for pending-lane enter (fade-in) and exit (collapse)
- onTabChange('approvals') now triggers exit animation (250ms) before switching tab
- Pending lane smoothly collapses when user clicks "View all"
AGENTS.md — No Mockups Convention:
- All UI must connect to real backend endpoints
- Never create mock/stub implementations unless explicitly requested
- Error states must be surfaced to user, never silently swallowed
- If backend endpoint doesn't exist, mark task BLOCKED
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Releases page:
- Rename "Pipeline" tab → "Releases" (first tab should match page name)
- Default activeTab from 'pipeline' → 'releases'
- Fix embedded ReleaseListComponent also clearing parent's pageAction on destroy
Deployments page:
- Approve/reject now show error banner when API fails instead of silently swallowing
(the demo env returns 404 for approval endpoints, making buttons appear broken)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: stella-page-tabs used urlParam="tab" while the component also
read the "view" query param via a manual queryParamMap subscriber. When
stella-page-tabs wrote ?tab=X to the URL, the subscriber re-read the stale
?view= param and reset viewMode back, causing tabs to appear frozen and
approve/reject button clicks to be swallowed by the stale state.
Fix:
- Change stella-page-tabs urlParam from "tab" to "view" so both the
component and the tab widget use the same query parameter
- Guard the manual subscriber to only update viewMode if it actually
differs, preventing feedback loops
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BC1 — Fix "Operations > Operations > ..." duplicate breadcrumb:
- Set breadcrumb to empty string on /ops/operations parent route
and /ops/operations (overview) route, so only the top-level
"Operations" breadcrumb from /ops renders. Affects 7 pages:
Feeds, Signals, Jobs, Diagnostics, Notifications, Watchlist, overview.
EC1 — Export Center delete confirmation:
- Replace window.confirm() with app-confirm-dialog variant="danger"
- Names the export profile being deleted in confirmation message
- Follows the destructive action convention from AGENTS.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Unify the Releases page with Pipeline + Versions tabs:
- Add stella-page-tabs with Pipeline (default) and Versions tabs
- Pipeline tab shows the existing release pipeline table
- Versions tab renders the ReleaseListComponent (version catalog) inline
- /releases/versions redirects to /releases?tab=versions for bookmarks
- Updated subtitle to "Versions, deployments, approvals, and promotion pipeline."
The Versions sidebar item was already removed in Phase A. This completes
the unification — one place for all release-related views.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bundles route moved to /evidence/bundles:
- Add /evidence/bundles and /evidence/bundles/new routes loading existing
TriageAuditBundlesComponent and TriageAuditBundleNewComponent
- /triage/audit-bundles and /triage/audit-bundles/new redirect to new paths
Security Reports merged into Security Posture:
- /security/reports redirects to /security (Security Posture page)
- Add Print/PDF button directly on Security Posture page header
- Reports page component retained for backward compat but no longer in sidebar or routes
All old routes have redirects to prevent bookmark breakage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major IA restructure based on product-level analysis of Stella Ops core
workflows (release lifecycle, policy gates, evidence chain, security posture).
New 7-group structure (was 5):
- Dashboard: new ungrouped home link (no group header)
- Release Control: Deployments, Releases, Environments (moved from Ops)
- Security: Vulnerabilities, Security Posture (+children), Scan Image
(Reports removed — will merge into Posture in Phase B)
- Policy: NEW GROUP — Packs, Governance, Simulation, VEX & Exceptions,
Release Gates, Policy Audit (promoted from buried Operations item)
- Operations: slimmed from 11→8 items (Hub, Jobs, Scripts, Signals,
Diagnostics, Notifications, Feeds, Watchlist)
- Audit & Evidence: Overview, Capsules, Replay, Export, Audit Log,
Bundles (route fixed to /evidence/bundles), Trust (merged name)
- Settings: unchanged
Rationale:
- Policy is a release-blocking gate with 6 deep sub-workflows — not an ops utility
- Environments define the promotion graph — belongs in Release Control
- Trust Audit + Trust Analytics merged into single "Trust" item
- Reports removed (duplicated Security Posture content)
- Versions removed from sidebar (will merge into Releases as tab in Phase C)
- Dashboard link ensures users can always navigate home without logo click
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
U2 — Promote button three-state model:
- showPromote: visible only when a next promotion target exists
- canPromote: enabled only when deployed + no blocking gates
- promoteDisabledReason: tooltip explaining why promotion is disabled
- Added .rdp__btn--disabled style (opacity + pointer-events)
W1 — Script delete confirmation:
- Replace window.confirm() with app-confirm-dialog variant="danger"
- Names the script being deleted in the confirmation message
W2 — Script description tooltip:
- Add [title] binding to truncated description text in scripts table
V1 — Remove duplicate "Profile" h2 in User Preferences tab panel
X1 — Breadcrumb root "Ops" → "Operations" to match sidebar group label
AGENTS.md — Three new mandatory conventions:
- Destructive Action Convention: all deletes/revokes must use app-confirm-dialog
- Truncated Text Convention: all text-overflow:ellipsis elements must have [title]
- Promote Button Convention: three-state (hidden/disabled/enabled) model
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add CRUD endpoints for script variables with validation and diff-compatible
models (ScriptEndpoints, ScriptApiModels, IScriptService, InMemoryScriptService).
Update PlatformScopes and PlatformPolicies for script.read/write permissions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement remediation-aware health checks across all Doctor plugin modules
(Agent, Attestor, Auth, BinaryAnalysis, Compliance, Crypto, Environment,
EvidenceLocker, Notify, Observability, Operations, Policy, Postgres, Release,
Scanner, Storage, Vex) and their backing library counterparts (AI, Attestation,
Authority, Core, Cryptography, Database, Docker, Integration, Notify,
Observability, Security, ServiceGraph, Sources, Verification).
Each check now emits structured remediation metadata (severity, category,
runbook links, and fix suggestions) consumed by the Doctor dashboard
remediation panel.
Also adds:
- docs/doctor/articles/ knowledge base for check explanations
- Advisory AI search seed and allowlist updates for doctor content
- Sprint plan for doctor checks documentation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Empty states:
- Audit Log "Recent Events" table: show "No audit events recorded yet." when empty
- Audit Log "All Events" table: show "No events match the current filters." when empty
Descriptions:
- Jobs & Queues: trim verbose 4-line description to single line
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Naming consistency:
- Dashboard heading "Mission Board" → "Dashboard" to match breadcrumb/title
- Vulnerabilities page: "Artifact workspace" → "Vulnerabilities" (heading, breadcrumb, route title)
- Doctor checks: "NOT RAN" → "NOT RUN" (grammar fix)
- Doctor pack categories: add label overrides for "servicegraph" → "Service Graph" and "binaryanalysis" → "Binary Analysis"
- Release digest placeholder: "digest-unavailable" → "Pending digest"
Bug fixes:
- Register locale data for all 8 supported locales (bg-BG, de-DE, ru-RU, es-ES, fr-FR, uk-UA, zh-TW, zh-CN) to fix NG02100 InvalidPipeArgument errors on Audit Log and other pages using Angular built-in pipes
- Null-safe json/number pipes in audit-log components (audit-log-table, audit-event-detail, audit-integrations, audit-export)
- Approval version fallback: use empty string instead of releaseName to prevent duplicate text in approval cards
- Approval card template: hide version span when it matches the release name
Layout/UX:
- stella-page-tabs: enable horizontal scroll on desktop (was mobile-only), prevents tab wrapping on Diagnostics (11 tabs), Audit Log (9 tabs)
- Triage date formatting: use DateFormatService for locale-aware dates instead of bare toLocaleString()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>