Commit Graph

429 Commits

Author SHA1 Message Date
master
003b9269f1 Gate all sync triggers behind E2E_ACTIVE_SYNC to prevent transport cascade
Even a single sync trigger starts a background fetch job that degrades
the Valkey messaging transport for subsequent tests. Gate all sync
POST tests behind E2E_ACTIVE_SYNC=1 so the default suite only tests
read-only operations (catalog, status, enable/disable, UI).

Also fix tab switching test to navigate from registries tab (known state)
and verify URL instead of aria-selected attribute.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 15:14:03 +03:00
master
5fe42e171e Fix advisory-sync tests: add withRetry for 504 gateway timeouts
Root cause: The gateway's Valkey transport to Concelier has a ~30s
timeout. Under load, API calls to advisory-sources endpoints return
504 before the Concelier responds. This is not an auth issue — the
auth fixture works fine, but the API call itself gets a 504.

Fix: Add withRetry() helper that retries on 504 (up to 2 retries
with 3s delay). This handles transient gateway timeouts without
masking real errors. Also increased per-test timeout to 180s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:03:46 +03:00
master
79a214d259 feat(web): audit-log dashboard — quick links, simplified empty state, module label refresh
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 10:49:16 +03:00
master
14029c7e56 chore: archive completed FE and BE sprints
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 10:35:53 +03:00
master
9e75c49e59 feat(web): advisory-ai conversation resume, hotfix wizard SlicePipe, release-control tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 10:35:38 +03:00
master
5af14cf212 Add adaptive sync pipeline: freshness cache, backpressure, staged batching
Three-layer defense against Concelier overload during bulk advisory sync:

Layer 1 — Freshness query cache (30s TTL):
  GET /advisory-sources, /advisory-sources/summary, and
  /{id}/freshness now cache their results in IMemoryCache for 30s.
  Eliminates the expensive 4-table LEFT JOIN with computed freshness
  on every call during sync storms.

Layer 2 — Backpressure on sync endpoint (429 + Retry-After):
  POST /{sourceId}/sync checks active job count via GetActiveRunsAsync().
  When active runs >= MaxConcurrentJobs, returns 429 Too Many Requests
  with Retry-After: 30 header. Clients get a clear signal to back off.

Layer 3 — Staged sync-all with inter-batch delay:
  POST /sync now triggers sources in batches of MaxConcurrentJobs
  (default: 6) with SyncBatchDelaySeconds (default: 5s) between batches.
  21 sources → 4 batches over ~15s instead of 21 instant triggers.
  Each batch triggers in parallel (Task.WhenAll), then delays.

New config: JobScheduler:SyncBatchDelaySeconds (default: 5)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 09:02:07 +03:00
master
07f7cd91b0 feat(web): close sprint 006 onboarding ux 2026-04-01 03:59:48 +03:00
master
1d7c8fadbd Consolidate Operations UI, rename Policy Packs to Release Policies, add host infrastructure
Five sprints delivered in this change:

Sprint 001 - Ops UI Consolidation:
  Remove Operations Hub, Agents Fleet Dashboard, and Signals Runtime Dashboard
  (31 files deleted). Ops nav goes from 8 to 4 items. Redirects from old routes.

Sprint 002 - Host Infrastructure (Backend):
  Add SshHostConfig and WinRmHostConfig target connection types with validation.
  Implement AgentInventoryCollector (real IInventoryCollector that parses docker ps
  JSON via IRemoteCommandExecutor abstraction). Enrich TopologyHostProjection with
  ProbeStatus/ProbeType/ProbeLastHeartbeat fields.

Sprint 003 - Host UI + Environment Verification:
  Add runtime verification column to environment target list with Verified/Drift/
  Offline/Unmonitored badges. Add container-level verification detail to Deploy
  Status tab showing deployed vs running digests with drift highlighting.

Sprint 004 - Release Policies Rename:
  Move "Policy Packs" from Ops to Release Control as "Release Policies". Remove
  "Risk & Governance" from Security nav. Rename Pack Registry to Automation Catalog.
  Create gate-catalog.ts with 11 gate type display names and descriptions.

Sprint 005 - Policy Builder:
  Create visual policy builder (3-step: name, gates, review) with per-gate-type
  config forms (CVSS threshold slider, signature toggles, freshness days, etc).
  Simplify pack workspace tabs from 6 to 3 (Rules, Test, Activate). Add YAML
  toggle within Rules tab.

59/59 Playwright e2e tests pass across 4 test suites.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 00:31:38 +03:00
master
a4c4690fef Rewrite UI API clients from /api/v2/releases to /api/v1/release-orchestrator
Completes Sprint 323 TASK-001 using Option C (direct URL rewrite):
- release-management.client.ts: readBaseUrl and legacyBaseUrl now use
  /api/v1/release-orchestrator/releases, eliminating the v2 proxy dependency
- All 15+ component files updated: activity, approvals, runs, versions,
  bundle-organizer, sidebar queries, topology pages
- Spec files updated to match new URL patterns
- Added /releases/activity and /releases/versions backend route aliases
  in ReleaseEndpoints.cs with ListActivity and ListVersions handlers
- Fixed orphaned audit-log-dashboard.component import → audit-log-table
- Both Angular build and JobEngine build pass clean

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 00:16:32 +03:00
master
b6bf113b99 feat(web): harden split release promotion handoff
Signed-off-by: master <>
2026-03-31 23:52:32 +03:00
master
58f9d759f5 Add advisory source aggregation report to Advisory & VEX Sources tab
Enhances the Advisory & VEX Sources catalog page with per-source
advisory download counts, last sync timestamps, and freshness status.

Stats bar additions:
- Total advisory count across all sources
- "With Data" count (sources that have downloaded advisories)
- "Stale" count (sources past their freshness SLA)

Per-source row additions:
- Advisory count badge (e.g., "4,231 advisories")
- Freshness pill showing relative time since last sync ("2h ago", "3d ago")
- Color-coded freshness: green=healthy, yellow=warning, red=stale, gray=unavailable

Expanded detail section additions:
- "Sync & Advisory Data" section showing:
  - Total advisories, last successful sync, last attempt, sync runs, errors
  - Freshness status badge
  - Last error message (if any)

Data source: GET /api/v1/advisory-sources?includeDisabled=false
(already returns totalAdvisories, lastSuccessAt, syncCount, etc.)
Loaded non-blocking alongside existing catalog+status calls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 23:46:47 +03:00
master
0d858ba9d1 fix(platform): make topology probe fallback truthful
Signed-off-by: master <>
2026-03-31 23:44:40 +03:00
master
404d50bcb7 feat(web): complete topology host verification ui 2026-03-31 23:24:10 +03:00
master
5bb5596e2f Add advisory data aggregation e2e tests proving pipeline produces queryable data
New test file verifying the full fetch→parse→map advisory pipeline:

Tier 1 (smoke, always runs):
- Source metrics: totalAdvisories > 0, lastSuccessAt populated, summary health
- Per-source freshness: syncCount, advisory counts
- Canonical API: paginated query, by-ID with source edges, CVE search
- Score distribution: endpoint works, counts sum correctly
- Cross-source: multiple distinct sources have data, multi-edge advisories

Tier 2 (gated behind E2E_ACTIVE_SYNC=1):
- Triggers KEV source sync, polls freshness until syncCount advances
- Verifies advisory count doesn't decrease, timestamp is recent

Resilience: All advisory-sources endpoints use getWithRetry() helper
that retries on 504/503 (gateway timeout during cold start). Tests
skip gracefully rather than fail when services are warming up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 23:10:52 +03:00
master
513b0f7470 Fix flaky auth fixture and advisory-sync test timeouts
Root cause: after 20+ minutes of serial test execution, the OIDC login
flow becomes slower and the 30s token acquisition timeout in
live-auth.fixture.ts gets exceeded, causing cascading failures in the
last few test files.

Fixes:
- live-auth.fixture.ts: increase token waitForFunction timeout from 30s
  to 60s, add retry loop (2 attempts with backoff), increase initial
  navigation timeout to 45s, extract helper functions for clarity
- advisory-sync.e2e.spec.ts: increase page.goto timeout from 30s to 45s
  for UI tests, add explicit toBeVisible wait on tab before clicking,
  add explicit timeout on connectivity check API call

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 20:07:26 +03:00
master
3f6fb501dd Add GitLab, pagination, activity timeline, and error resilience e2e tests
Four new test suites expanding integration hub e2e coverage:

- gitlab-integration.e2e.spec.ts: Container health, direct probe, connector
  CRUD lifecycle (create/test/health/delete), SCM tab UI verification.
  Gracefully skips when GitLab container not running (heavy profile).

- pagination.e2e.spec.ts: API-level pagination (pageSize, page params,
  totalPages, sorting, last-page edge case, out-of-range page).
  UI pager rendering verification.

- activity-timeline.e2e.spec.ts: Page load, stats bar, activity items,
  event type filter dropdown, clear filters, back navigation.
  Tests against mock data rendered by the activity component.

- error-resilience.e2e.spec.ts: Unreachable endpoint returns failure/unhealthy,
  non-existent resource 404s, malformed input handling, duplicate name
  creation, UI empty tab rendering, deleted integration detail page.

Also adds GitLab config to shared helpers.ts INTEGRATION_CONFIGS.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 19:02:18 +03:00
master
2fef38b093 Add Vault, Consul, eBPF connector plugins and thorough integration e2e tests
Backend:
- Add SecretsManager=9 type, Vault=550 and Consul=551 providers to IntegrationEnums
- Create VaultConnectorPlugin (GET /v1/sys/health), ConsulConnectorPlugin
  (GET /v1/status/leader), EbpfAgentConnectorPlugin (GET /api/v1/health)
- Register all 3 plugins in Program.cs and WebService.csproj
- Extend Concelier JobRegistrationExtensions with 20 additional advisory
  source connectors (ghsa, kev, epss, debian, ubuntu, alpine, suse, etc.)
- Add connector project references to Concelier WebService.csproj so
  Type.GetType() can resolve job classes at runtime
- Fix job kind names to match SourceDefinitions IDs (jpcert not jvn,
  oracle not vndr-oracle, etc.)

Infrastructure:
- Add Consul service to docker-compose.integrations.yml (127.1.2.8:8500)
- Add runtime-host nginx fixture to docker-compose.integration-fixtures.yml
  (127.1.1.9:80)

Frontend:
- Mirror SecretsManager/Vault/Consul enum additions in integration.models.ts
- Fix Secrets tab route type from RepoSource to SecretsManager
- Add SecretsManager to parseType() and TYPE_DISPLAY_NAMES

E2E tests (117/117 passing):
- vault-consul-secrets.e2e.spec.ts: compose health, probes, CRUD, UI
- runtime-hosts.e2e.spec.ts: fixture probe, CRUD, hosts tab
- advisory-sync.e2e.spec.ts: 21 sources sync accepted, catalog, management
- ui-onboarding-wizard.e2e.spec.ts: wizard steps for registry/scm/ci
- ui-integration-detail.e2e.spec.ts: detail tabs, health data
- ui-crud-operations.e2e.spec.ts: search, sort, delete
- helpers.ts: shared configs, API helpers, screenshot util
- Updated playwright.integrations.config.ts with reporter and CI retries

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:39:08 +03:00
master
4a570b2842 Update integration service and search-assistant host component
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:26:14 +03:00
master
8536a6c707 Update compose config, policy simulation, and workflow replay
- devops/compose: README, docker-compose, hosts updates
- Policy simulation: pre-promotion and test-validate panels,
  routes, dashboard, and spec updates
- Workflow visualization: run-graph replay page template update
- Claude settings update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:26:02 +03:00
master
9c79b00598 Update navigation, layout, and feature pages for DevOps onboarding
Reorganize sidebar navigation, update topology/releases/platform
feature pages, and add environments command component. Improve
dashboard, security overview, and mission control pages.

- Navigation config: restructured groups and route mappings
- Sidebar: collapsible sections, preference persistence
- Topology: environments command component, detail page updates,
  remove readiness-dashboard (superseded)
- Releases: unified page, activity, and ops overview updates
- Platform ops/setup page improvements
- E2e specs for navigation, environments, and release workflows
- Nav model and route integrity test updates

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:25:19 +03:00
master
89a075ea21 Add integration connector plugins and compose fixtures
Scaffold connector plugins for DockerRegistry, GitLab, Gitea,
Jenkins, and Nexus. Wire plugin discovery in IntegrationService
and add compose fixtures for local integration testing.

- 5 new connector plugins under src/Integrations/__Plugins/
- docker-compose.integrations.yml for local fixture services
- Advisory source catalog and source management API updates
- Integration e2e test specs and Playwright config
- Integration hub docs under docs/integrations/

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:24:56 +03:00
master
8931fc7c0c Add unified Stella Assistant: mascot + search + AI chat as one
Merge three disconnected help surfaces (Stella mascot, Ctrl+K search,
Advisory AI chat) into one unified assistant. Mascot is the face,
search is its memory, AI chat is its voice.

Backend:
- DB schema (060/061): tips, greetings, glossary, tours, user_state
  tables with 189 tips + 101 greetings seed data
- REST API: GET tips/glossary/tours, GET/PUT user-state with
  longest-prefix route matching and locale fallback
- Admin endpoints: CRUD for tips, glossary, tours (SetupAdmin policy)

Frontend:
- StellaAssistantService: unified mode management (tips/search/chat),
  API-backed tips with static fallback, i18n integration
- Three-mode mascot component: tips, inline search, embedded chat
- StellaGlossaryDirective: DB-backed tooltip annotations for domain terms
- Admin tip editor: CRUD for tips/glossary/tours in Console Admin
- Tour player: step-through guided tours with element highlighting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:24:39 +03:00
master
ae5059aa1c Add hub-and-spoke audit tabs across 9 feature modules
Consolidate module-specific audit views from the unified audit
dashboard into contextual tabs on parent feature pages. Creates
reusable AuditModuleEventsComponent for embedding audit tables.

- Trust Admin: 4th tab with Trust Events / Air-Gap / Incidents sub-views
- Policy Governance: embedded audit child route with Governance Changes /
  Promotions & Approvals sub-toggle
- Console Admin: Management / Token Lifecycle & Security sub-tabs
- Integration Hub: Config Audit tab on per-integration detail page
- Slim unified audit dashboard to 4 tabs (Overview, All Events, Timeline,
  Correlations)
- Platform Jobs, Scanner Ops, SBOM Sources: audit tabs/sections added
- VEX Hub: Audit Trail tab
- Backward-compatible redirects for old audit URLs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:24:15 +03:00
master
7d6bc2b0ab Show pack display name instead of raw ID in title
The pack-shell title showed the raw packId like 'Pack pack-291b12b...'
which is unreadable. Now looks up the display name from the pack store
cache. Falls back to a truncated ID (first 12 chars) when no name is
available. Added PolicyPackStore.currentPacks() synchronous accessor
for the computed signal lookup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 16:09:25 +03:00
master
a8ad459506 Remove redundant headers from pack detail tabs, fix button theming
All 7 pack detail components (dashboard, editor, rule-builder, yaml,
simulation, approvals, explain) had their own eyebrow + h1 + lede
headers that duplicated the parent pack-shell's dynamic title+subtitle.

Changes per component:
- Dashboard: removed header, added empty state with guidance, themed btns
- Editor: removed header, kept metadata as right-aligned flex, themed btns
- YAML: removed header, fixed label colors and button theming
- Rule builder: removed header, fixed label colors
- Simulation: removed header, kept status pill, themed btns from gradient
  to btn-primary-bg, fixed hardcoded rgba colors
- Approvals: removed header, kept workflow status badges, themed btns
- Explain: removed header, kept action links, added btn/btn--secondary CSS

Button theming: replaced var(--color-status-info-text) backgrounds
and hardcoded rgba() with var(--color-btn-primary-bg/border/text)
and var(--color-btn-secondary-bg/border/text) across all components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 16:03:44 +03:00
master
01cc3f044f Fix pack detail dark backgrounds: surface-inverse → surface-primary
All 6 pack detail components (dashboard, editor, rule-builder, yaml,
simulation, approvals) had :host background set to surface-inverse
(dark/black) or gradient variations of it. Fixed to surface-primary
(warm cream) to match the rest of the app. Also removed excessive
min-height: 100vh from all components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 15:50:52 +03:00
master
d7efb2a6a4 Fix pack detail tab edge-case colors: surface-primary as text, inverse bg
Editor: color surface-primary (cream text on buttons) → text-inverse
Simulation: color surface-inverse (dark text) → text-inverse
Approvals: hardcoded rgba ghost button text → text-secondary
YAML: status-info-text button bg → btn-primary-bg
Explain: surface-inverse button bg → surface-elevated

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 15:44:06 +03:00
master
5dfd14bd55 Redesign pack cards to match Stella Ops Material, add delete action
Pack cards completely restyled following the releases page pattern:
- Status badge (Active/Draft/Archived) with semantic colors
- Pack name with text-overflow ellipsis and title tooltip
- Version badge in mono font with subtle background
- Description and creation date in proper typography scale
- Decision capsules for actions (Edit, Simulate, Approvals, Delete)
  matching the releases page capsule pattern with SVG icons
- Hover: brand-primary border glow + subtle shadow lift
- Delete button with app-confirm-dialog (danger variant)

Layout changed from multi-column grid to single-column list for
better readability (each card is a full-width row).

Empty state follows the releases empty state pattern with centered
SVG icon, title, description, and inline create form.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 15:38:42 +03:00
master
12dc9285f6 Invalidate stale pack cache with old packId format
The cache contained API responses with packId (old format) but the
new mapper produces id. The store read these from cache, bypassing
the API, and sortPacks filtered them out (no id field) → empty page.

Fix: readCache() now detects stale entries (packId present, id missing)
and clears them, forcing a fresh API fetch through the mapper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:41:49 +03:00
master
380d73a535 Map policy API response fields to UI model (packId→id, displayName→name)
The backend returns PolicyPackSummaryDto with fields: packId,
displayName, createdAt, versions. The UI model expects: id, name,
description, version, status, etc.

Added mapPackSummary() to translate API fields to UI model fields.
The sortPacks filter was removing all packs because p.id was undefined
(the API field is packId, not id).

Also maps createPack response and sends displayName in the POST body
to match the backend's expected field name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:39:12 +03:00
master
5c1fc56b5c Fix remaining VEX and policy-gates theme: borders, button bg, rgba
VEX hub (13 files): fixed 2px/3px/4px border variants using text
color vars, border-color with text-secondary, background text-secondary.

Policy gates (6 files): fixed all swapped theme patterns including
backgrounds, text colors, borders, button backgrounds, and rgba colors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 12:32:04 +03:00
master
f4efa5195f Fix VEX hub theming: replace swapped CSS vars, rgba colors, button colors
All 13 VEX hub components had the same swapped theme pattern:
- text-heading used as backgrounds → surface-elevated
- surface-secondary used as text color → text-heading
- border-primary used as text color → text-primary
- text-primary used as backgrounds → surface-tertiary
- status-info used as button bg → btn-primary-bg
- Hardcoded rgba() colors → CSS variable references
- text/border color swaps in border declarations

168 occurrences fixed across: vex-hub-dashboard, vex-statement-search,
vex-statement-detail, vex-statement-detail-panel, vex-create-workflow,
vex-hub-stats, vex-consensus, vex-conflict-resolution, vex-hub,
ai-explain-panel, ai-justify-panel, ai-remediate-panel, ai-consent-gate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 12:18:50 +03:00
master
ba33790d36 Fix pack store: don't cache empty fallback results
Two bugs caused the empty packs page:

1. When the API failed, catchError returned [] and writeCache() stored
   it in sessionStorage. On next visit, readCache() returned [] (truthy),
   so the store never re-fetched from the API — stuck on empty forever.

2. Fix: only cache successful non-empty API responses. Treat empty
   cached arrays as cache misses so the store always re-fetches.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 01:03:43 +02:00
master
887d2cb0eb Fix pack detail themes and guard against undefined pack IDs
Theme fixes across 7 pack detail sub-components (dashboard, editor,
rule-builder, yaml, simulation, approvals, explain):
- Replace swapped CSS variables (text colors as backgrounds, etc.)
- Replace hardcoded rgba() colors with CSS variable references
- Replace btn backgrounds from status-info to btn-primary-bg

Pack ID guard:
- Filter out packs with missing/undefined IDs in sortPacks() to
  prevent navigation to /packs/undefined/dashboard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 00:57:25 +02:00
master
c7cd5234bc Document zero-restart UI dev workflow in AGENTS.md
Add "Local UI Development" section with instructions for using the
docker-compose.dev-ui.yml override. Agents working on UI changes
should use this to avoid the slow volume-copy + restart cycle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 00:55:17 +02:00
master
39e1bf0bd4 Fix Pack creation: correct API path, signal-based reactivity, null-safe sort
Three root causes for "create does nothing":

1. Wrong API base path: PolicyApiService used /api/policy (routed to
   platform service via /api/ catch-all) instead of /policy/api (routed
   to policy-gateway via nginx regex). Fixed API_BASE.

2. OnPush + plain fields: loading/packs/refreshing were plain booleans
   and arrays. OnPush change detection ignored their mutations. Converted
   all three to signals so template reactivity works automatically.

3. sortPacks crash: API returns packs with undefined modifiedAt/id
   fields. localeCompare on undefined threw TypeError, preventing the
   empty state from rendering. Added nullish coalescing fallbacks.

Also removed hardcoded fallback "Core Policy Pack" from the store —
it masked API failures and prevented the create form from appearing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 00:42:53 +02:00
master
d8e6a2a53d Add deployment status badges to environment nodes in topology graph
Each environment node now shows pill badges at the bottom:
- Deploying (blue, pulsing) — count of active deployments
- Pending (amber, pulsing) — count awaiting approval
- Failed (red) — count of failed deployments
- Total (muted) — historical deployment count
- Agent warning (!) — when no agent is assigned

Badges pulse with CSS animation (respects prefers-reduced-motion).
Native SVG <title> elements provide hover tooltips.
Backend enriches TopologyPositionedNode with deployment counts
from promotion path statuses and agent assignment data.
Also fixes duplicate environment IDs causing layout API 400 errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 00:23:19 +02:00
master
4e6c14037c Fix Pack creation: clear cache on refresh, trigger CD, navigate on success
PolicyPackStore.refresh() now clears the sessionStorage cache before
fetching, so API responses aren't hidden behind stale cached data.

PolicyWorkspaceComponent fixes:
- Add ChangeDetectorRef.markForCheck() after every async state mutation
  (OnPush was preventing UI updates from plain field assignments)
- Navigate to the new pack on successful creation
- Show clearer error when policy gateway is unreachable (status 0)
- Clear pack cache before navigation so the new pack appears

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 00:04:23 +02:00
master
55e6ea0672 Use standard Stella Ops patterns for deployments table in side drawer
- Rename Releases to Deployments
- Replace custom toggle with standard segmented control (ctx__seg-btn
  pattern from context-chips)
- Use stella-table with striped/hoverable classes
- Add sortable columns (Release, Status, Date) with sort arrows
- Add relative date formatting (2h ago, 3d ago, etc.)
- Add pagination via app-pagination component (5 per page)
- Add Event column showing eventType

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:57:27 +02:00
master
20feb042b1 Remove redundant header from Policy Workspace, move Refresh to top-right
The workspace component had its own header (eyebrow 'Policy Studio ·
Workspace', h1 'Policy packs', lede) that duplicated the parent
pack-shell's 'Policy Pack Workspace' title. Removed it.

Moved the Refresh button from bottom-left footer to top-right actions
bar using secondary button styling. Removed min-height: 100vh.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:48:44 +02:00
master
3692317663 Add releases table with pending/done toggle to environment side drawer
When an environment is selected, the side drawer now shows a Releases
section with a Pending/Done toggle. Fetches from /api/v2/releases/activity
filtered by environment. Release name and version are clickable links to
the release detail and version pages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:47:23 +02:00
master
2a77a27560 Fix stage filter showing empty graph when env filter is active
When stage filter is set, skip passing environment IDs to the layout
API. This fetches all environments for the selected regions, then the
client-side stage filter shows only matching types. Previously, the
env filter would narrow results before the stage filter could act,
causing an empty graph.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:27:10 +02:00
master
ddd4ee1fce Add stage filter support to topology graph
The global Stage dropdown (production/staging/development) now filters
the topology graph client-side by environmentType, hiding environments
that don't match the selected stage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:21:47 +02:00
master
4733285f03 Fix topology filtering: use global context, right side drawer, edge filter
- 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>
2026-03-28 22:49:24 +02:00
master
24964c8e53 Fix region rect intercepting edge clicks in SVG topology
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>
2026-03-28 22:31:47 +02:00
master
bf07f95ead Remove topology tabs, add detail zone below graph, relocate pages
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>
2026-03-28 22:24:35 +02:00
master
302de9bf46 Fix breadcrumb hierarchy: suppress ops parent, let sections self-identify
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>
2026-03-28 20:55:27 +02:00
master
3da2861f9e Fix tab navigation by removing urlParam from topology shell
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>
2026-03-28 20:55:09 +02:00
master
ba900dae12 Add breadcrumbs to all policy section routes
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>
2026-03-28 20:49:39 +02:00
master
f57b5efb31 Improve topology layout spacing and edge label readability
- 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>
2026-03-28 20:44:20 +02:00