The workflow service registers endpoints under /api/workflow/ (no v1 prefix),
but the gateway config only had /api/v1/workflows/* which routes to the
release-orchestrator. Added a dedicated route for the workflow engine.
Found during E2E testing — workflow definitions and instances were returning
404 through the gateway.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove jobengine and jobengine-worker containers from docker-compose
- Create release-orchestrator service (120 endpoints) with full auth, tenant, and infrastructure DI
- Wire workflow engine to PostgreSQL with definition store (wf_definitions table)
- Deploy 4 canonical workflow definitions on startup (release-promotion, scan-execution, advisory-refresh, compliance-sweep)
- Fix workflow definition JSON to match canonical contract schema (set-state, call-transport, decision)
- Add WorkflowClient to release-orchestrator for starting workflow instances on promotion
- Add WorkflowTriggerClient + endpoint to scheduler for triggering workflows from system schedules
- Update gateway routes from jobengine.stella-ops.local to release-orchestrator.stella-ops.local
- Remove Platform.Database dependency on JobEngine.Infrastructure
- Fix workflow csproj duplicate Content items (EmbeddedResource + SDK default)
- System-managed schedules with source column, SystemScheduleBootstrap, inline edit UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The sidebar component had its own hardcoded navSections array separate from
NAVIGATION_GROUPS config. Updated Security group from 5 items (Vulnerabilities,
Security Posture+4 children, Scan Image, VEX) to 4 flat items (Image Security,
Triage Queue, Risk Overview, Advisory Sources).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Security nav restructured from 8 items to 4: Image Security, Triage Queue,
Risk Overview, Advisory Sources. New Image Security page at /security/images
with scope selectors (repo/image/release/environment) and 6 tabs (Summary,
Findings, SBOM, Reachability, VEX, Evidence).
VEX Hub: removed dashboard tab, moved create to button, fixed filters to use
stella-filter-multi, fixed all navigation to absolute paths, fixed 72+ hardcoded
rgba colors, created proper page components for conflicts and create workflow.
Policy shell: added tabs for Packs, Governance, VEX & Exceptions, Simulation,
Audit — all sub-pages now accessible from the Release Policies page.
Integrations: moved symbol sources/marketplace and scanner config to
/setup/integrations.
Backend: mirror config changes now persist via IFeedMirrorConfigStore and
propagate to central Scheduler via SchedulerClient. MirrorExportScheduler
supports IMirrorSchedulerSignal for immediate wakeup on config change.
Mirror detail page: fixed all wrong CSS tokens (text colors used as
backgrounds, inverted borders) to canonical Stella Ops design system.
Exception dashboard: removed duplicate English/Bulgarian title headers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add AGENTS.md sections for the four late-stage post-processing steps
(SpreadOuterCorridors, CollapseOrthogonalBacktracks,
ExtendShortApproachSegments, ReduceLineNodeProximity) and the SVG
bridge gap detection corner radius rationale.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reduce the corner radius used in EnumerateEffectiveSegments for bridge
gap detection from 40px to 12px. The 40px pull-back eliminated segments
shorter than 80px from crossing detection, causing 3 of 4 crossings
with edge/22's vertical to show no visual "cut" effect. With 12px
pull-back, crossings on segments as short as 25px are now detected.
Bridge gap count: increased from ~4 to 11 in the document processing
render — all visible crossings now show the cut/bridge effect.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two fixes for the End approach area:
1. SpreadOuterCorridors now splits shared-Y lanes when edges have
overlapping X ranges (>40px overlap). edge/20 and edge/23 were both
at Y=-235 with 2257px of shared horizontal — now split to Y=-235
and Y=-267 (31.6px gap). Uses the entry's actual corridor Y for
shift point matching, not the lane's synthetic CurrentY.
2. Widen the lead-lane pre-terminal jog offset from minLineClearance*0.35
to minLineClearance*0.9. The jog now lands 15px above the End node
top instead of 6px above the neighboring edge's arrival slot.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Increase the preTerminalY offset in RewriteLeftFaceEndTopCorridorLeadLane
from minLineClearance*0.35 to minLineClearance*0.9. This pushes the
lead-lane jog above the End node boundary (Y=350 vs End top Y=365)
instead of between arrival slots (was Y=383, only 6px above the
neighboring edge/23 at Y=377). The jog is now 27px clear of the
nearest neighbor, eliminating the visual overlap the user reported.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add four late-stage post-processing steps that run after the iterative
optimizer to improve edge readability without affecting hard routing
correctness:
- SpreadOuterCorridors: enforce min 32px gap between adjacent above-graph
corridors and push End-bound corridors below all repeat-return corridors
into their own visual tier (Y=-235 vs Y=-203/-139/-36)
- CollapseOrthogonalBacktracks: detect and remove U-turn loops where edges
go right then backtrack left then right again (edge/17 fixed from
7-segment loop to clean 3-segment forward path)
- ExtendShortApproachSegments: extend short final approach segments to
half the average node width (~101px) so arrowheads have clear directional
runs into target nodes (11 edges improved, worst case 8px to 71px)
- ReduceLineNodeProximity: push edge segments away from non-terminal nodes
when within min-clearance (line-node proximity reduced to 2 violations)
Final metrics on document processing render:
- Edge crossings: 24 → 21 (-12.5%)
- Label proximity: 6 → 0 (eliminated)
- Line-node proximity: reduced to 2
- All 7 hard defect classes: zero (maintained)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce WorkflowCancelContracts, update IWorkflowRuntimeApi with cancel
support, and refine Postgres/Mongo projection store serialization.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add KnowledgeSearchDataSourceProvider for connection policy adoption,
update PostgresKnowledgeSearchStore and chat audit logger, refine
SearchAnalyticsService and SearchQualityMonitor queries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce SecurityVulnerabilityEndpoints, VulnerabilityDetailService,
and supporting contracts for the vulnerability detail page backend.
Includes integration tests for the new endpoints.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce PostgresDeploymentCompatibilityStore with migration 011, in-memory
fallback, deployment endpoints, and Postgres fixture for integration tests.
Update Scheduler repository with connection policy adoption.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce PostgresGraphSavedViewStore with SQL migration, in-memory fallback,
CompatibilityEndpoints for UI contract alignment, and integration tests
with a shared Postgres fixture.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce IntegrationDiscovery DTOs, GitLabCiConnectorPlugin,
GitLabContainerRegistryConnectorPlugin, CLI integrations command group,
and expand impact/service test coverage for all connector plugins.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major edge routing improvements including corridor spacing, crossing reduction,
focused gateway boundary repairs, setter families, and advanced restabilization.
Adds workflow renderer tests for document-processing and artifact inspection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce GatewayRegistrationResyncService to recover stale registrations,
extract IGatewayTransportClient interface, add EndpointsUpdate and
RegistrationResyncRequest frame types, and expand transport test coverage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set ClientName on every Redis/Valkey connection across Scanner, Signals,
Concelier, Notify, Scheduler, Timeline, and Router for easier connection
attribution in monitoring.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract connection string building into PostgresConnectionStringPolicy so all
services use consistent pooling, application_name, and timeout settings.
Adopt the new policy in 20+ module DataSource/ServiceCollectionExtensions classes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the corridor reroute pushes a horizontal segment away from a
blocking node, preserve the first point (source connection) and
insert a vertical step to reconnect the last point (target connection)
at the original Y. Previously, pushing all points uniformly would
disconnect the edge from its target node when the push Y exceeded
the target node's boundary.
Fixes edge/9 (Retry Decision → Set batchGenerateFailed) which was
pushed to Y=653 but the target node bottom is at Y=614 — the endpoint
now steps back up to Y=592 to reconnect.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix for the 2 remaining OIDC redirect failures: after login, the
page lands on Dashboard. When a test calls page.goto('/setup/...'),
Angular sometimes redirects back to Dashboard because the auth guard
hasn't settled.
Fix: After loginAndGetToken, navigate to /setup/integrations and
wait for [role="tab"] to render. This:
1. Settles the OIDC auth guard (validates token, caches auth state)
2. Lazy-loads the integration module chunk
3. Primes Angular's router with the /setup/ route tree
Subsequent page.goto() calls from tests will work reliably because
Angular already has auth state and the lazy chunk is cached.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three-layer edge-node clearance improvement:
1. A* proximity cost with correct coordinates: pass original (uninflated)
node bounds to ComputeNodeProximityCost so the pathfinder penalizes
edges near real node boundaries, not the inflated obstacle margin.
Weight=800, clearance=40px. Grid lines added at clearance distance
from real nodes.
2. Default LayerSpacing increased from 60 to 80, adaptive multiplier
floor raised from 0.92 to 1.0, giving wider routing corridors
between node rows.
3. Post-pipeline EnforceMinimumNodeClearance: final unconditional pass
pushes horizontal segments within 8px of node tops (12px push) or
within minClearance of node bottoms (full clearance push).
Also: bridge gap detection now uses curve-aware effective segments
(same preprocessing + corner pull-back as BuildRoundedEdgePath) so
gaps only appear at genuine visual crossings. Collector trunks and
same-group edges excluded from gap detection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Landing page: check for tabs/heading instead of waiting for redirect
(redirect needs loadCounts XHR which is slow from browser)
- Pagination: merged into one test, pager check is conditional on data
loading (pager only renders when table has rows)
- Wizard step 2: increased timeouts for Harbor selection
Also: Angular rebuild was required (stale 2-day-old build was the
hidden blocker for 15 UI tests).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause found via screenshot: page.goto with domcontentloaded
returned before Angular even bootstrapped — the page still showed
Dashboard while the test checked for integration content.
Fix: Change waitUntil from domcontentloaded to load across all 37
goto calls. 'load' waits for initial JS/CSS to load, meaning Angular
has bootstrapped and the SPA router has processed the route.
Simplified waitForAngular to wait for route-level content selectors
without the URL check (the load event handles that now).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Problem: After waitForAngular, content assertions ran before Angular's
XHR data loaded. Tests checked textContent('body') at a point when
the table/heading hadn't rendered yet.
Fix: Replace point-in-time checks with Playwright auto-retry assertions:
- expect(locator).toBeVisible({ timeout: 15_000 }) — retries until visible
- expect(locator).toContainText('X', { timeout: 15_000 }) — retries until text appears
- expect(rows.first()).toBeVisible() — retries until table has data
Also: landing page test now uses waitForFunction to detect Angular redirect.
10 files changed, net -45 lines (simpler, more robust assertions).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The generic waitForAngular matched the sidebar nav immediately but
route content (tables, tabs, forms) hadn't rendered yet.
Updated waitForAngular selector to wait for route-level elements:
stella-page-tabs, .integration-list, .source-catalog, table tbody tr,
h1, [role=tablist], .detail-grid, .wizard-step, form.
Also fixed activity-timeline and pagination tests (still had
waitForTimeout(2_000) instead of waitForAngular).
Increased fallback timeout from 5s to 8s for slow-loading pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The 3s waitForTimeout after page.goto wasn't enough for Angular to
bootstrap and render content. Replace with waitForAngular() helper
that waits for actual DOM elements (nav, headings) up to 15s, with
5s fallback.
32 calls updated across 10 test files.
Also adds waitForAngular to helpers.ts export.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause found via diagnostics: the handler call at 16:27:19 never
returned. Guard: processing message X logged, but Guard: processed
never appeared. The 55s CancellationToken fired but the handler
ignored it (blocked on a non-cancelable StackExchange.Redis operation
or DB query that uses its own timeout).
Fix: Replace await handler(token) with handler(token).WaitAsync(token).
WaitAsync returns when EITHER the handler completes OR the token fires,
regardless of whether the handler cooperatively checks the token.
The abandoned handler continues in background but the consumer loop
resumes immediately.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The advisory source API tests go through the Valkey transport with
withRetry (3 attempts). With the 55s transport timeout, worst case
is 3 × 55s = 165s, exceeding the default 120s test timeout.
Set advisory lifecycle describe block to 300s via beforeEach to
give enough headroom for all retry attempts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The white "cut" marks at edge crossings are distracting at small
rendering scales and make edges look broken/disconnected. Simple
overlapping crossings are cleaner and more readable.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a backtrack's return point is the endpoint (last point), remove
BOTH the overshoot and return — the pre-overshoot point becomes the
new endpoint. This prevents the rendered path from bending inside the
target node after backtrack removal.
edge/4 now ends cleanly at the Join's left face instead of bending
UP inside the node.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>