chore: archive completed FE and BE sprints
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
114
docs-archived/implplan/SPRINT_20260322_001_FE_wizard_split.md
Normal file
114
docs-archived/implplan/SPRINT_20260322_001_FE_wizard_split.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Sprint 20260322-001 - Split Create Wizard into Version / Hotfix / Release
|
||||
|
||||
## Topic & Scope
|
||||
- Split the monolithic "Create Release" wizard into distinct version, hotfix, and promotion handoff flows that match Stella's current product model.
|
||||
- Keep `Version` focused on artifact identity and components only; no deployment targeting.
|
||||
- Keep `Hotfix` focused on a single emergency package with a fast-track confirmation flow.
|
||||
- Replace the fake combined release/deployment wizard with a split handoff surface at `/releases/new`, and move target selection plus approvals onto the canonical promotions wizard.
|
||||
- Working directory: `src/Web/StellaOps.Web/`.
|
||||
- Expected evidence: focused Angular route and handoff tests, updated docs and sprint state, and removal of canonical FE entry points that depended on the retired all-in-one deployment wizard.
|
||||
|
||||
## Dependencies & Concurrency
|
||||
- Tasks were originally planned sequentially: version wizard, hotfix wizard, release wizard, then route and navigation cleanup.
|
||||
- Product direction was re-scoped on 2026-03-31 after verifying Stella docs and current API reality: promotions own targeting, gate preview, and approvals; `/releases/new` is therefore a split-flow handoff instead of a fake deployment-plan wizard.
|
||||
|
||||
## Documentation Prerequisites
|
||||
- `docs/README.md`
|
||||
- `docs/07_HIGH_LEVEL_ARCHITECTURE.md`
|
||||
- `docs/modules/platform/architecture-overview.md`
|
||||
- `docs/modules/release-orchestrator/architecture.md`
|
||||
- `docs/modules/ui/v2-rewire/S00_endpoint_contract_ledger_v1.md`
|
||||
- `src/Web/StellaOps.Web/AGENTS.md`
|
||||
|
||||
## Delivery Tracker
|
||||
|
||||
### TASK-001 - Create Version wizard
|
||||
Status: DONE
|
||||
Dependency: none
|
||||
Owners: FE
|
||||
Task description:
|
||||
- New component: `create-version.component.ts`
|
||||
- Steps: 1) Name + Version + Description 2) Components (images + scripts) with autocomplete 3) Review & Seal
|
||||
- Autocomplete: name defaults to last used or generic, version auto-increments
|
||||
- Component search uses existing registry API
|
||||
- No regions, no stages, no strategy, no deployment config
|
||||
- Route: `/releases/versions/new`
|
||||
|
||||
Completion criteria:
|
||||
- [x] `create-version.component.ts` exists under the sprint working directory and supports identity, components, and review/seal steps.
|
||||
- [x] The canonical route `/releases/versions/new` resolves to the dedicated version wizard.
|
||||
- [x] Focused version-wizard coverage exists in the supported `src/tests/release-control` lane.
|
||||
|
||||
### TASK-002 - Create Hotfix wizard
|
||||
Status: DONE
|
||||
Dependency: TASK-001
|
||||
Owners: FE
|
||||
Task description:
|
||||
- New component: `create-hotfix.component.ts`
|
||||
- Single step or 2 steps: 1) Pick one Docker image + tag 2) Confirm
|
||||
- No name (derives from image), no version (uses digest)
|
||||
- Minimal, fast-track flow
|
||||
- Route: `/releases/hotfixes/new`
|
||||
|
||||
Completion criteria:
|
||||
- [x] `create-hotfix.component.ts` exists under the sprint working directory and supports the dedicated hotfix create/confirm flow.
|
||||
- [x] The canonical route `/releases/hotfixes/new` resolves to the dedicated hotfix wizard.
|
||||
- [x] Focused hotfix-wizard coverage exists in the supported `src/tests/release-control` lane.
|
||||
|
||||
### TASK-003 - Replace fake release wizard with split-flow handoff
|
||||
Status: DONE
|
||||
Dependency: TASK-001, TASK-002
|
||||
Owners: FE
|
||||
Task description:
|
||||
- New component: `release-flow-launchpad.component.ts`
|
||||
- `/releases/new` becomes a chooser/handoff page for `Create Version`, `Create Hotfix`, and `Request Promotion`
|
||||
- The handoff preserves release/environment context into the canonical promotions wizard and retains bundle/version/hotfix context on the handoff surface without coercing it into `releaseId`
|
||||
- `CreatePromotionComponent` accepts environment-first entry without requiring the release id to be present on initial load
|
||||
- Route: `/releases/new`
|
||||
|
||||
Completion criteria:
|
||||
- [x] `/releases/new` is a split-flow handoff surface instead of the retired fake deployment planner.
|
||||
- [x] The handoff preserves release/environment context into `/releases/promotions/create` without aliasing bundle/version identities into `releaseId`.
|
||||
- [x] `CreatePromotionComponent` hydrates legacy environment context and auto-selects the target once a release identity is provided.
|
||||
|
||||
### TASK-004 - Update routes and navigation to promotions-first flow
|
||||
Status: DONE
|
||||
Dependency: TASK-001, TASK-002
|
||||
Owners: FE
|
||||
Task description:
|
||||
- `/releases/versions/new` -> CreateVersionComponent
|
||||
- `/releases/hotfixes/new` -> CreateHotfixComponent
|
||||
- `/releases/new` -> ReleaseFlowLaunchpadComponent
|
||||
- `/releases/deployments/new` -> compatibility redirect to `/releases/promotions/create`
|
||||
- Update sidebar "New Version" page action to point to `/releases/versions/new`
|
||||
- Update release, topology, and launch-point UI actions to use `/releases/promotions/create`
|
||||
- Remove the fake deployment wizard from canonical FE routing
|
||||
|
||||
Completion criteria:
|
||||
- [x] Top-level Releases routing exposes dedicated version, hotfix, and handoff entry surfaces while redirecting legacy deployment-create bookmarks into promotions.
|
||||
- [x] Canonical in-app launch points no longer navigate to the retired all-in-one deployment wizard.
|
||||
- [x] Route-surface and promotion-handoff tests cover the updated route ownership and context-preserving navigation.
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2026-03-22 | Sprint created. | Planning |
|
||||
| 2026-03-31 | Verified the FE working directory against current code. `create-version` and `create-hotfix` are implemented, dedicated routes are mounted, stale route tests were repaired, and focused wizard tests were added. Marked the split release-plan wizard BLOCKED because the current Platform release-control materialization contract cannot persist the multi-stage and strategy semantics promised by this sprint. | FE implementer |
|
||||
| 2026-03-31 | Ran targeted Vitest coverage for `route-surface-ownership`, `release-control-routes`, `hotfixes-queue`, `create-version`, and `create-hotfix`: 18 tests passed. Repository-wide `ng test --include ...` still compiles unrelated red specs outside this sprint, so targeted file execution is the reliable evidence for this working directory. | FE implementer |
|
||||
| 2026-03-31 | Re-scoped the obsolete combined `/releases/new` wizard after product review: shipped `release-flow-launchpad`, redirected `/releases/deployments/new` into promotions, rewired release/topology launch points to `/releases/promotions/create`, and updated helper guidance to match the split flow. | FE implementer |
|
||||
| 2026-03-31 | Ran targeted Vitest coverage for `route-surface-ownership`, `release-control-routes`, `release-promotions-cutover`, `release-flow-launchpad`, and `release-detail-page-promotion-handoff`: 23 tests passed. | FE implementer |
|
||||
| 2026-03-31 | Hardened the handoff contract after follow-up review: `/releases/new` no longer aliases `versionId`/`bundleId`/`hotfixId` into `releaseId`, bundle-version post-seal actions now route through the handoff page, and approval detail decisioning context uses routed `releaseId` values instead of bundle labels. | FE implementer |
|
||||
| 2026-03-31 | All 4 tasks completed by agents. Version, Hotfix, and Release Flow Launchpad components implemented with full route wiring and test coverage (23 tests pass). | Developer (FE) |
|
||||
| 2026-03-31 | Audit verified: all completion criteria met. Build passes. | PM (audit) |
|
||||
|
||||
## Decisions & Risks
|
||||
- Decision: keep dedicated `/releases/versions/new` and `/releases/hotfixes/new` surfaces as the current shipped creation entry points; stale redirect-only test assumptions were removed.
|
||||
- Decision: `/releases/new` is now a split-flow handoff, not a deployment-plan wizard, because Stella's current product and API model separate release definition from promotion. Updated doc: `docs/modules/ui/v2-rewire/S00_endpoint_contract_ledger_v1.md`.
|
||||
- Decision: the FE must not coerce `versionId`, `bundleId`, or `hotfixId` into the promotion API's `releaseId` parameter. Those identities are preserved only as handoff context until a real release id exists.
|
||||
- Decision: `/releases/deployments/new` is retained only as a compatibility redirect into `/releases/promotions/create`; canonical UI entry points now launch the promotions wizard directly.
|
||||
- Risk: `src/Platform/StellaOps.Platform.WebService/Endpoints/ReleaseControlEndpoints.cs` still exposes only bundle create, version publish, and version materialize with `targetEnvironment`, `reason`, and `idempotencyKey`. A richer release-definition create API would still require cross-module contract work if Stella later wants a first-class bundle-to-release bridge instead of the current handoff model.
|
||||
- Risk: the frontend unit-test baseline outside this sprint is currently broken, so `ng test --include ...` still fails during global spec compilation. The focused release-control evidence for this sprint comes from direct Vitest file execution instead.
|
||||
|
||||
## Next Checkpoints
|
||||
- Validate whether Platform and JobEngine should eventually expose a first-class bundle-version to release bridge so the promotions wizard can preload richer release metadata without compatibility identity mapping.
|
||||
- If that bridge lands, follow up with a separate sprint rather than restoring a fake combined deployment planner.
|
||||
@@ -0,0 +1,127 @@
|
||||
# Sprint 001 — Operations UI Consolidation: Remove 3 Pages, Simplify Navigation
|
||||
|
||||
## Topic & Scope
|
||||
|
||||
- Remove Operations Hub, Agents Fleet Dashboard, and Signals Runtime Dashboard — 3 pages that add complexity without proportional value for the target user (small-team DevOps/Security engineer)
|
||||
- Operations Hub is a dashboard-of-dashboards duplicating sidebar navigation
|
||||
- Agents Fleet Dashboard is enterprise fleet management for what is typically 2-5 agents (topology-agents-page already provides the right-sized view)
|
||||
- Signals Runtime Dashboard shows internal telemetry for the backend scoring engine — misleadingly named, no operator action surface
|
||||
- Redistribute useful information: Doctor notifications already handle health alerts, Doctor page handles diagnostics, sidebar handles navigation
|
||||
- Working directory: `src/Web/StellaOps.Web/src/app/`
|
||||
- Expected evidence: Clean Angular build, sidebar shows 5 Ops items, no 404s on old routes
|
||||
|
||||
## Dependencies & Concurrency
|
||||
|
||||
- No upstream sprint dependencies
|
||||
- This sprint is purely frontend — zero backend changes
|
||||
- Can be done in parallel with Sprint 002 (backend host infrastructure)
|
||||
- Topology pages (hosts, targets, agents) under `features/topology/` are kept — they are the correct operational views
|
||||
|
||||
## Documentation Prerequisites
|
||||
|
||||
- `docs/product/VISION.md` — confirms target user is small teams, not enterprise platform engineering
|
||||
- Plan file: `.claude/plans/buzzing-napping-ember.md` — full investigation and rationale
|
||||
|
||||
---
|
||||
|
||||
## Delivery Tracker
|
||||
|
||||
### TASK-001 - Remove Operations Hub page
|
||||
Status: DONE
|
||||
Dependency: none
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Delete the Operations Hub component files:
|
||||
- `features/platform/ops/platform-ops-overview-page.component.ts`
|
||||
- `features/platform/ops/platform-ops-overview-page.component.html`
|
||||
- `features/platform/ops/platform-ops-overview-page.component.scss`
|
||||
- Update `routes/operations.routes.ts`: change the default `''` path from loading `PlatformOpsOverviewPageComponent` to a redirect to `jobs-queues` (first meaningful sub-page)
|
||||
- Remove "Operations Hub" nav item (id: `operations-hub`) from `core/navigation/navigation.config.ts`
|
||||
- Clean up `operations-paths.ts` if the `overview` path is referenced elsewhere
|
||||
- Keep: `platform-jobs-queues-page`, `platform-feeds-airgap-page`, `event-stream-page`, `feeds-offline-shell`
|
||||
|
||||
Completion criteria:
|
||||
- [x] 3 files deleted (component, template, styles)
|
||||
- [x] `/ops/operations` redirects to `/ops/operations/jobs-queues` (not 404)
|
||||
- [x] No "Operations Hub" in sidebar navigation
|
||||
- [x] No compilation errors
|
||||
|
||||
### TASK-002 - Remove Agents Fleet Dashboard
|
||||
Status: DONE
|
||||
Dependency: none
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Delete the entire `features/agents/` directory (23 files):
|
||||
- Pages: `agent-fleet-dashboard`, `agent-detail-page`, `agent-onboard-wizard`
|
||||
- Services: `agent.store.ts`, `agent-realtime.service.ts`
|
||||
- Models: `agent.models.ts`
|
||||
- Sub-components: `agent-card`, `agent-health-tab`, `agent-tasks-tab`, `capacity-heatmap`, `fleet-comparison`, `agent-action-modal`
|
||||
- Remove "Agent Fleet" nav item (id: `agent-fleet`) from `navigation.config.ts`
|
||||
- Remove agents routes from `operations.routes.ts` (lines ~246-262)
|
||||
- Remove/update agents redirect routes from `ops.routes.ts`
|
||||
- Verify no other components import from `features/agents/`
|
||||
|
||||
Completion criteria:
|
||||
- [x] `features/agents/` directory deleted (23 files)
|
||||
- [x] No "Agent Fleet" in sidebar navigation
|
||||
- [x] `/ops/operations/agents` handled gracefully (redirect or removed)
|
||||
- [x] `topology-agents-page.component.ts` still works (kept as the simple agent view)
|
||||
- [x] No compilation errors
|
||||
|
||||
### TASK-003 - Remove Signals Runtime Dashboard
|
||||
Status: DONE
|
||||
Dependency: none
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Delete the entire `features/signals/` directory (4 files):
|
||||
- `signals-runtime-dashboard.component.ts`
|
||||
- `signals-runtime-dashboard.service.ts`
|
||||
- `signals-runtime-dashboard.models.ts`
|
||||
- `signals.routes.ts`
|
||||
- Remove "Signals" nav item (id: `signals`) from `navigation.config.ts`
|
||||
- Remove signals route from `operations.routes.ts` (lines ~163-168)
|
||||
- Remove/update signals redirect routes from `ops.routes.ts`
|
||||
- All Signals backend code (`src/Signals/`) is completely untouched — it is the evidence-weighted scoring engine
|
||||
|
||||
Completion criteria:
|
||||
- [x] `features/signals/` directory deleted (4 files)
|
||||
- [x] No "Signals" in sidebar navigation
|
||||
- [x] Signals backend service unaffected
|
||||
- [x] No compilation errors
|
||||
|
||||
### TASK-004 - Verify final navigation and build
|
||||
Status: DONE
|
||||
Dependency: TASK-001, TASK-002, TASK-003
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Run `npx ng build --configuration=development` — must produce zero errors
|
||||
- Verify sidebar Ops section shows exactly 5 items: Policy Packs, Scheduled Jobs, Feeds & AirGap, Scripts, Diagnostics
|
||||
- Verify all redirect routes work (no broken links from old paths)
|
||||
- Check that `topology/` pages (hosts, targets, agents) still load correctly
|
||||
- Check that Doctor notification service still functions (toast alerts)
|
||||
|
||||
Completion criteria:
|
||||
- [x] Angular build succeeds with zero errors
|
||||
- [x] Ops nav has exactly 5 items (Policy Packs, Scheduled Jobs, Feeds & AirGap, Scripts, Diagnostics)
|
||||
- [x] No broken routes or 404s (legacy paths redirect gracefully)
|
||||
- [x] Topology pages unaffected
|
||||
- [x] Doctor notifications unaffected
|
||||
|
||||
---
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2026-03-31 | Sprint created from UI consolidation plan | Planning |
|
||||
| 2026-03-31 | All 4 tasks completed. 3 pages removed (30 files), nav updated to 5 items, build passes. Also fixed legacy redirects in platform-ops.routes.ts and breadcrumb in event-stream-page.component.ts | Developer (FE) |
|
||||
| 2026-03-31 | Audit: verified all completion criteria. Build passes (`ng build --configuration=development` — 29.6s, warnings only). Nav confirmed 5 items. All legacy routes redirect gracefully. | PM (audit) |
|
||||
|
||||
## Decisions & Risks
|
||||
- **Decision**: Redirect `/ops/operations` to `jobs-queues` rather than `doctor` — Scheduled Jobs is the most commonly used ops sub-page
|
||||
- **Decision**: Keep `topology-agents-page` as the agent view — it already shows status, capabilities, heartbeats in a simple table without fleet management overhead
|
||||
- **Risk**: Other components may import from deleted directories — mitigated by build verification in TASK-004
|
||||
- **Risk**: Legacy bookmarks to `/ops/operations` landing page — mitigated by redirect
|
||||
|
||||
## Next Checkpoints
|
||||
- Build verification after all 3 deletions
|
||||
- Visual verification of sidebar navigation
|
||||
@@ -0,0 +1,130 @@
|
||||
# Sprint 002 — Host Infrastructure: SSH/WinRM Targets, Inventory Collection, Topology Enrichment
|
||||
|
||||
## Topic & Scope
|
||||
|
||||
- Add SSH and WinRM as first-class target connection types — the SSH/WinRM agent implementations already exist (`StellaOps.Agent.Ssh`, `StellaOps.Agent.WinRM`) but there are no matching `TargetConnectionConfig` types to configure them
|
||||
- Implement a real `IInventoryCollector` — currently only `StubInventoryCollector` exists, making the entire inventory and drift detection system inert
|
||||
- Enrich the topology read model with runtime probe status — `TopologyHostProjection` currently has no probe/eBPF fields, and `AgentId` is a synthetic string unlinked to real agents
|
||||
- Working directory: `src/ReleaseOrchestrator/`, `src/Platform/StellaOps.Platform.WebService/`
|
||||
- Expected evidence: dotnet build success, unit tests for new types, inventory collection from SSH host
|
||||
|
||||
## Dependencies & Concurrency
|
||||
|
||||
- No upstream sprint dependency — can run in parallel with Sprint 001 (FE cleanup)
|
||||
- Sprint 003 (Host UI + Environment Verification) depends on this sprint's APIs
|
||||
- Existing code to build on:
|
||||
- SSH agent: `src/ReleaseOrchestrator/__Agents/StellaOps.Agent.Ssh/`
|
||||
- WinRM agent: `src/ReleaseOrchestrator/__Agents/StellaOps.Agent.WinRM/`
|
||||
- AgentCapability enum: `Ssh = 2`, `WinRm = 3` (already defined)
|
||||
- IInventoryCollector interface: `src/ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Environment/Inventory/IInventoryCollector.cs`
|
||||
- DriftDetector: `src/ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Environment/Inventory/DriftDetector.cs`
|
||||
- InventorySnapshot model: `src/ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Environment/Inventory/InventorySnapshot.cs`
|
||||
- Signals runtime agent API: `POST /api/v1/agents/register`, `POST /api/v1/agents/{id}/heartbeat`
|
||||
- eBPF integration plugin: `src/Integrations/__Plugins/StellaOps.Integrations.Plugin.EbpfAgent/`
|
||||
|
||||
## Documentation Prerequisites
|
||||
|
||||
- Plan file: `.claude/plans/buzzing-napping-ember.md` — full investigation with backend gap analysis
|
||||
- `src/ReleaseOrchestrator/__Agents/StellaOps.Agent.Ssh/SshCapability.cs` — SSH task types
|
||||
- `src/ReleaseOrchestrator/__Agents/StellaOps.Agent.WinRM/WinRmCapability.cs` — WinRM task types
|
||||
- `src/Signals/StellaOps.Signals.RuntimeAgent/` — agent registration models
|
||||
|
||||
---
|
||||
|
||||
## Delivery Tracker
|
||||
|
||||
### TASK-001 - Add SSH/WinRM target connection configs
|
||||
Status: DONE
|
||||
Dependency: none
|
||||
Owners: Developer (BE)
|
||||
Task description:
|
||||
- Modify `src/ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Environment/Models/TargetConnectionConfig.cs`:
|
||||
- Add `SshHostConfig` record: Host (string), Port (int, default 22), Username (string), PrivateKeyReference (string — secret store ref, not plaintext), KnownHostsPolicy (enum: Accept/Strict/Prompt)
|
||||
- Add `WinRmHostConfig` record: Host (string), Port (int, default 5985), Transport (enum: Http/Https), Username (string), PasswordReference (string — secret store ref), Domain (string?)
|
||||
- Register JSON polymorphic types: `[JsonDerivedType(typeof(SshHostConfig), "ssh_host")]`, `[JsonDerivedType(typeof(WinRmHostConfig), "winrm_host")]`
|
||||
- Modify `src/ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Environment/Models/Target.cs`:
|
||||
- Add `SshHost = 4` and `WinRmHost = 5` to `TargetType` enum
|
||||
- Modify `src/ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Environment/Target/TargetRegistry.cs`:
|
||||
- Add validation: SshHost targets must have SshHostConfig, WinRmHost targets must have WinRmHostConfig
|
||||
- Wire agent capability matching: SshHost requires agent with `AgentCapability.Ssh`, WinRmHost requires `AgentCapability.WinRm`
|
||||
|
||||
Completion criteria:
|
||||
- [x] `SshHostConfig` and `WinRmHostConfig` defined with JSON polymorphism (`JsonDerivedType`)
|
||||
- [x] `TargetType` enum extended with `SshHost = 4`, `WinRmHost = 5`
|
||||
- [x] TargetRegistry validates config type matches target type (SSH: host, port 1-65535, username, key or password; WinRM: host, port, username, password)
|
||||
- [x] dotnet build succeeds
|
||||
- [x] Serialization roundtrip test exists
|
||||
|
||||
### TASK-002 - Implement real IInventoryCollector (AgentInventoryCollector)
|
||||
Status: DONE
|
||||
Dependency: TASK-001
|
||||
Owners: Developer (BE)
|
||||
Task description:
|
||||
- Create `AgentInventoryCollector.cs` in `src/ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Environment/Inventory/`
|
||||
- Implements `IInventoryCollector` interface
|
||||
- Collection strategy per target type:
|
||||
- **SshHost**: Dispatch `ssh.execute` task with command `docker ps --format '{{json .}}' --no-trunc` to the host's assigned agent, parse JSON lines into ContainerInfo[]
|
||||
- **WinRmHost**: Dispatch `winrm.powershell` task with command `docker ps --format '{{json .}}' --no-trunc`, parse similarly
|
||||
- **DockerHost/ComposeHost**: Dispatch via Docker API (existing Docker agent capability)
|
||||
- **EcsService/NomadJob**: Use respective cloud API calls (can be stub initially)
|
||||
- Parse `docker ps` JSON output into `InventorySnapshot`:
|
||||
- Map: ID → ContainerInfo.ContainerId, Image → ImageReference, Names → Name, Status → Status, Ports → PortMappings, Labels → Labels
|
||||
- For image digest: run `docker inspect --format '{{.Image}}' <id>` as follow-up command
|
||||
- Handle errors: agent offline, command timeout, parse failure → produce `InventorySnapshot` with `CollectionError`
|
||||
- Register in DI as the primary `IInventoryCollector` implementation (replacing StubInventoryCollector in non-test environments)
|
||||
|
||||
Completion criteria:
|
||||
- [x] `AgentInventoryCollector` implements `IInventoryCollector` (uses `IRemoteCommandExecutor` abstraction)
|
||||
- [x] SSH path: dispatches docker ps command, parses JSON
|
||||
- [x] WinRM path: dispatches command, parses docker ps JSON
|
||||
- [x] Error handling: agent offline and command failures produce error snapshots
|
||||
- [x] DI registration replaces stub
|
||||
- [x] Unit tests with sample docker ps JSON output (3 test cases)
|
||||
- [x] DriftDetector works with snapshots
|
||||
|
||||
### TASK-003 - Enrich topology read model with probe status
|
||||
Status: DONE
|
||||
Dependency: none (Signals agent API already exists)
|
||||
Owners: Developer (BE)
|
||||
Task description:
|
||||
- Modify `src/Platform/StellaOps.Platform.WebService/Contracts/TopologyReadModels.cs`:
|
||||
- Extend `TopologyHostProjection` with: `string? ProbeStatus`, `string? ProbeType`, `DateTimeOffset? ProbeLastHeartbeat`
|
||||
- ProbeStatus values: `"active"`, `"offline"`, `"not_installed"`
|
||||
- ProbeType values: `"ebpf"`, `"etw"`, `"dyld"`, `null`
|
||||
- Modify `src/Platform/StellaOps.Platform.WebService/Services/TopologyReadModelService.cs`:
|
||||
- In `BuildSnapshotAsync()`, after building host projections, join with runtime agent data
|
||||
- Data source option A: Call Signals API `GET /api/v1/agents` and match agents to hosts by hostname
|
||||
- Data source option B: Query shared Valkey cache for agent heartbeat data
|
||||
- Match logic: agent's `Hostname` field matches host's `HostName`, or agent is explicitly bound to host via configuration
|
||||
- If matched: set ProbeStatus from agent health (active if recent heartbeat, offline if stale), ProbeType from agent platform, ProbeLastHeartbeat from last heartbeat timestamp
|
||||
- If not matched: ProbeStatus = "not_installed", ProbeType = null
|
||||
|
||||
Completion criteria:
|
||||
- [x] `TopologyHostProjection` includes ProbeStatus, ProbeType, ProbeLastHeartbeat
|
||||
- [x] Topology API returns probe data
|
||||
- [x] Hosts with active probes show `"active"` (within 2-min heartbeat window)
|
||||
- [x] Hosts without agents show `"not_installed"`
|
||||
- [x] Stale agents show `"offline"`
|
||||
- [x] dotnet build succeeds
|
||||
|
||||
---
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2026-03-31 | Sprint created from host infrastructure plan | Planning |
|
||||
| 2026-03-31 | All 3 tasks completed. SshHostConfig + WinRmHostConfig added with JSON polymorphism, KnownHostsPolicy + WinRmTransport enums. TargetType extended (SshHost=4, WinRmHost=5). TargetRegistry validation added for SSH/WinRM. AgentInventoryCollector created with IRemoteCommandExecutor abstraction (avoids circular dependency), parses docker ps NDJSON. TopologyHostProjection enriched with ProbeStatus/ProbeType/ProbeLastHeartbeat. Both dotnet builds pass. | Developer (BE) |
|
||||
| 2026-03-31 | Audit verified: all 3 tasks complete. SSH/WinRM configs with JSON polymorphism, AgentInventoryCollector with IRemoteCommandExecutor abstraction, topology probe enrichment with 2-min heartbeat threshold. All builds pass. | PM (audit) |
|
||||
|
||||
## Decisions & Risks
|
||||
- **Decision**: SSH/WinRM are target connection types (not just agent capabilities) because the user configures deployment targets at the host level, and needs connection details stored per target
|
||||
- **Decision**: Container inventory via `docker ps` over SSH, not via eBPF — eBPF does method-level tracing (reachability evidence), not container enumeration. `docker ps` gives the full container inventory.
|
||||
- **Decision**: Topology enrichment via Signals API call, not direct DB query — maintains service boundary between Platform and Signals
|
||||
- **Risk**: Agent hostname matching may be unreliable — mitigate by adding explicit host-agent binding in target configuration
|
||||
- **Risk**: `docker ps` output format may vary across Docker versions — mitigate by using `--format '{{json .}}'` which is stable JSON
|
||||
- **Risk**: InventoryCollector dispatch depends on agent being online — error handling must produce useful error snapshots, not silent failures
|
||||
|
||||
## Next Checkpoints
|
||||
- TASK-001: Build verification after adding new types
|
||||
- TASK-002: Integration test with sample SSH agent output
|
||||
- TASK-003: API response verification with enriched topology data
|
||||
@@ -0,0 +1,247 @@
|
||||
# Sprint 004 — Release Policies: Rename, Move, and Consolidate Navigation
|
||||
|
||||
## Topic & Scope
|
||||
|
||||
- Rename "Policy Packs" → "Release Policies" across all UI surfaces
|
||||
- Move Release Policies from Ops section to Release Control section in nav
|
||||
- Remove "Risk & Governance" from Security nav — governance lives inside the Release Policies workspace
|
||||
- Rename "Pack Registry" → "Automation Catalog" in Ops nav
|
||||
- Add human-readable gate display names as a frontend constant mapping
|
||||
- Update all route paths with backward-compatible redirects
|
||||
- Update Stella helper tips and contextual help
|
||||
- Working directory: `src/Web/StellaOps.Web/src/app/`
|
||||
- Expected evidence: Angular build passes, e2e tests pass, nav reflects new structure
|
||||
|
||||
## Dependencies & Concurrency
|
||||
|
||||
- Depends on Sprint 001 (Ops UI Consolidation) being complete — it is
|
||||
- No backend changes required — all existing Policy Engine APIs remain untouched
|
||||
- Can be done independently of Sprint 002/003 (host infrastructure)
|
||||
- The policy-decisioning and policy-governance feature modules stay in place; only nav/routes/labels change
|
||||
|
||||
## Documentation Prerequisites
|
||||
|
||||
- Plan file: `.claude/plans/buzzing-napping-ember.md`
|
||||
- `src/Web/StellaOps.Web/src/app/features/policy-decisioning/policy-decisioning.routes.ts` — current route tree
|
||||
- `src/Web/StellaOps.Web/src/app/features/policy-governance/policy-governance.routes.ts` — governance routes
|
||||
- `src/Web/StellaOps.Web/src/app/features/pack-registry/pack-registry.routes.ts` — pack registry routes
|
||||
- `src/Web/StellaOps.Web/src/app/core/api/policy-interop.models.ts` — gate type constants
|
||||
|
||||
---
|
||||
|
||||
## Delivery Tracker
|
||||
|
||||
### TASK-001 - Create gate display name mapping
|
||||
Status: DONE
|
||||
Dependency: none
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Create `src/Web/StellaOps.Web/src/app/core/policy/gate-catalog.ts` containing a static mapping of gate types to human-readable display names and descriptions:
|
||||
```typescript
|
||||
export const GATE_CATALOG: Record<string, { displayName: string; description: string; icon: string }> = {
|
||||
CvssThresholdGate: {
|
||||
displayName: 'Vulnerability Severity',
|
||||
description: 'Block releases with CVEs above a severity threshold',
|
||||
icon: 'alert-triangle',
|
||||
},
|
||||
SignatureRequiredGate: {
|
||||
displayName: 'Image Signature',
|
||||
description: 'Require cryptographic signature on container images',
|
||||
icon: 'lock',
|
||||
},
|
||||
EvidenceFreshnessGate: {
|
||||
displayName: 'Scan Freshness',
|
||||
description: 'Require scan results newer than a configured threshold',
|
||||
icon: 'clock',
|
||||
},
|
||||
SbomPresenceGate: {
|
||||
displayName: 'SBOM Required',
|
||||
description: 'Require a Software Bill of Materials for every image',
|
||||
icon: 'file-text',
|
||||
},
|
||||
MinimumConfidenceGate: {
|
||||
displayName: 'Detection Confidence',
|
||||
description: 'Minimum confidence level for vulnerability detections',
|
||||
icon: 'target',
|
||||
},
|
||||
UnknownsBudgetGate: {
|
||||
displayName: 'Unknowns Limit',
|
||||
description: 'Maximum acceptable fraction of unresolved findings',
|
||||
icon: 'help-circle',
|
||||
},
|
||||
ReachabilityRequirementGate: {
|
||||
displayName: 'Reachability Analysis',
|
||||
description: 'Require proof of exploitability before blocking',
|
||||
icon: 'git-branch',
|
||||
},
|
||||
SourceQuotaGate: {
|
||||
displayName: 'Data Source Diversity',
|
||||
description: 'Minimum number of independent intelligence sources',
|
||||
icon: 'layers',
|
||||
},
|
||||
};
|
||||
```
|
||||
- Export a `getGateDisplayName(gateType: string): string` helper function
|
||||
- Export a `getGateDescription(gateType: string): string` helper function
|
||||
|
||||
Completion criteria:
|
||||
- [ ] Gate catalog file created with all 8 standard gate types
|
||||
- [ ] Helper functions exported and usable
|
||||
- [ ] No backend dependency — pure frontend constants
|
||||
|
||||
### TASK-002 - Rename nav items and restructure sidebar
|
||||
Status: DONE
|
||||
Dependency: none
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Modify `core/navigation/navigation.config.ts`:
|
||||
- Move "Policy Packs" from `ops` group to `release-control` group
|
||||
- Rename label: "Policy Packs" → "Release Policies"
|
||||
- Update route: `/ops/policy/packs` → keep same route initially (route migration in TASK-003)
|
||||
- Remove "Risk & Governance" from `security` group (and its children: Simulation, Policy Audit)
|
||||
- Rename "Pack Registry" item (if referenced in nav config) to "Automation Catalog"
|
||||
- Modify `layout/app-sidebar/app-sidebar.component.ts`:
|
||||
- Same changes in the sidebar's own nav definition
|
||||
- Move policy-related items from operations group to release-control group
|
||||
- Rename labels to match
|
||||
- Remove governance items from security group
|
||||
|
||||
After changes, nav should be:
|
||||
```
|
||||
Release Control
|
||||
├── Environments
|
||||
├── Deployments
|
||||
├── Releases
|
||||
└── Release Policies ← moved from Ops, renamed
|
||||
|
||||
Security
|
||||
├── Vulnerabilities
|
||||
├── Security Posture
|
||||
├── Scan Image
|
||||
└── VEX & Exceptions ← Risk & Governance removed
|
||||
|
||||
Ops
|
||||
├── Scheduled Jobs
|
||||
├── Feeds & Airgap
|
||||
├── Automation Catalog ← renamed from Pack Registry (if in nav)
|
||||
├── Scripts
|
||||
└── Diagnostics
|
||||
```
|
||||
|
||||
Completion criteria:
|
||||
- [ ] "Release Policies" appears in Release Control section
|
||||
- [ ] "Policy Packs" no longer appears in Ops section
|
||||
- [ ] "Risk & Governance" no longer appears in Security section
|
||||
- [ ] "Pack Registry" renamed to "Automation Catalog" (if in sidebar)
|
||||
- [ ] Angular build passes
|
||||
|
||||
### TASK-003 - Update routes with backward-compatible redirects
|
||||
Status: DONE
|
||||
Dependency: TASK-002
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Create new route entry for Release Policies under the releases route tree:
|
||||
- `/releases/policies` → loads PolicyDecisioningShellComponent (same component, new route)
|
||||
- `/releases/policies/packs` → same as current `/ops/policy/packs`
|
||||
- `/releases/policies/governance` → same as current `/ops/policy/governance`
|
||||
- `/releases/policies/simulation` → same as current `/ops/policy/simulation`
|
||||
- `/releases/policies/audit` → same as current `/ops/policy/audit`
|
||||
- Add redirects from old paths to new paths:
|
||||
- `/ops/policy` → `/releases/policies`
|
||||
- `/ops/policy/packs` → `/releases/policies`
|
||||
- `/ops/policy/governance` → `/releases/policies/governance`
|
||||
- `/ops/policy/simulation` → `/releases/policies/simulation`
|
||||
- `/ops/policy/audit` → `/releases/policies/audit`
|
||||
- `/ops/policy/vex` → keep in place (VEX is security-adjacent, can stay or move)
|
||||
- `/ops/policy/gates/*` → keep in place (gate views are context-dependent)
|
||||
- Update `operations-paths.ts` if any policy paths are defined there
|
||||
- Update any internal links in policy components that reference old paths
|
||||
|
||||
Completion criteria:
|
||||
- [ ] `/releases/policies` loads the policy workspace
|
||||
- [ ] `/ops/policy` redirects to `/releases/policies`
|
||||
- [ ] All sub-routes (governance, simulation, audit) accessible under new path
|
||||
- [ ] Old bookmarks/links still work via redirects
|
||||
- [ ] Angular build passes
|
||||
|
||||
### TASK-004 - Update labels and text across policy components
|
||||
Status: DONE
|
||||
Dependency: TASK-002
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Update page titles, headings, and breadcrumbs in policy components:
|
||||
- `policy-decisioning-overview-page.component.ts` — change "Packs Workspace" card to "Release Policies"
|
||||
- `policy-pack-shell.component.ts` — update title/breadcrumb from "Policy Packs" to "Release Policies"
|
||||
- `policy-decisioning-shell.component.ts` — update any shell-level titles
|
||||
- `policy-governance.component.ts` — update breadcrumb from "Governance" to "Release Policies > Governance"
|
||||
- Rename "Pack Registry" browser:
|
||||
- `pack-registry-browser.component.ts` — update title from "Pack Registry" to "Automation Catalog"
|
||||
- Update any references to "TaskRunner packs" in descriptions
|
||||
- Update gate display names in `gate-summary-panel.component.ts`:
|
||||
- Import and use `GATE_CATALOG` from TASK-001 to display human-readable gate names
|
||||
- Update `gate-explain-drawer.component.ts` similarly
|
||||
- Update `stella-helper-tips.config.ts`:
|
||||
- Rename any "Policy Packs" references to "Release Policies"
|
||||
- Update tip text to use "Release Policies" language
|
||||
- Add/update tips for the Release Policies workspace
|
||||
|
||||
Completion criteria:
|
||||
- [ ] No UI text says "Policy Packs" (replaced with "Release Policies")
|
||||
- [ ] Pack Registry browser says "Automation Catalog"
|
||||
- [ ] Gate summary panels use human-readable names from GATE_CATALOG
|
||||
- [ ] Gate explain drawer uses human-readable names
|
||||
- [ ] Stella helper tips updated
|
||||
- [ ] Angular build passes
|
||||
|
||||
### TASK-005 - Write e2e tests for policy nav restructure
|
||||
Status: DONE
|
||||
Dependency: TASK-002, TASK-003, TASK-004
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Create `tests/e2e/release-policies-nav.spec.ts` testing:
|
||||
- "Release Policies" appears in Release Control nav section
|
||||
- "Policy Packs" does NOT appear in Ops nav section
|
||||
- "Risk & Governance" does NOT appear in Security nav section
|
||||
- `/releases/policies` loads the policy workspace with content
|
||||
- `/ops/policy` redirects to `/releases/policies`
|
||||
- `/ops/policy/governance` redirects to `/releases/policies/governance`
|
||||
- `/releases/policies/governance` renders governance controls
|
||||
- Gate summary panels show human-readable names (if testable)
|
||||
- No Angular runtime errors across policy routes
|
||||
- Browser back/forward works across policy routes
|
||||
|
||||
Completion criteria:
|
||||
- [ ] All e2e tests pass
|
||||
- [ ] Coverage includes: nav presence/absence, redirects, page rendering, error-free navigation
|
||||
|
||||
### TASK-006 - Update Sprint 006 (Onboarding UX) references
|
||||
Status: DONE
|
||||
Dependency: TASK-004
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Check `docs/implplan/SPRINT_20260329_006_FE_devops_onboarding_ux.md` for any references to "Policy Packs", "Operations Hub", "Agent Fleet", "Signals" and update them
|
||||
- Update any other sprint files or docs that reference the old names
|
||||
|
||||
Completion criteria:
|
||||
- [ ] No stale references to removed/renamed pages in active sprint files
|
||||
|
||||
---
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2026-03-31 | Sprint created from policy UX improvement plan | Planning |
|
||||
| 2026-03-31 | All 6 tasks completed. Gate catalog created (11 gate types). Nav restructured: Release Policies moved to Release Control, Risk & Governance removed from Security, Policy Packs removed from Ops. All labels updated across 8 components. Pack Registry renamed to Automation Catalog. 51/51 e2e tests pass. | Developer (FE) |
|
||||
|
||||
## Decisions & Risks
|
||||
- **Decision**: Gate display names are frontend constants, not backend API — the 8 gate types are stable and well-known. A backend catalog endpoint becomes necessary only if gates become plugin-extensible.
|
||||
- **Decision**: VEX & Exceptions stays under Security (not moved with governance) — VEX is security-adjacent, about vulnerability assessment statements, not about release governance
|
||||
- **Decision**: Gate views (`/ops/policy/gates/*`) stay at current paths — they are context-dependent (release, approval, environment) and linked from release detail pages
|
||||
- **Decision**: Route migration uses redirects, not breaking changes — old bookmarks and deep links continue to work
|
||||
- **Risk**: Internal component links may reference old paths — mitigated by grep for `/ops/policy` in all components
|
||||
- **Risk**: Scope-based nav visibility depends on correct scope assignments — verify that Release Control group doesn't require additional scopes for Release Policies visibility
|
||||
|
||||
## Next Checkpoints
|
||||
- TASK-002: Visual verification of new nav structure
|
||||
- TASK-003: Route redirect verification
|
||||
- TASK-005: Full e2e test pass
|
||||
@@ -0,0 +1,166 @@
|
||||
# Sprint 005 — Release Policy Builder: Visual Gate Configuration Flow
|
||||
|
||||
## Topic & Scope
|
||||
|
||||
- Replace the 6-tab pack editor with a simplified 3-tab workspace: Rules, Test, Activate
|
||||
- Create a visual policy builder that lets users configure gates via forms instead of YAML
|
||||
- Add plain-language rule summaries showing what the policy does in human terms
|
||||
- YAML editing becomes a toggle (power-user mode), not a separate tab
|
||||
- Dashboard tab eliminated — the rules list IS the overview
|
||||
- Edit and Rules tabs merged into a single "Rules" view with inline editing
|
||||
- Working directory: `src/Web/StellaOps.Web/src/app/features/policy-decisioning/`
|
||||
- Expected evidence: Angular build passes, builder creates valid policy YAML, simulation works with builder-created policies
|
||||
|
||||
## Dependencies & Concurrency
|
||||
|
||||
- Depends on Sprint 004 (nav rename) being complete — uses the "Release Policies" naming
|
||||
- Depends on TASK-001 from Sprint 004 (gate catalog constants) for display names
|
||||
- No backend changes required — builder generates YAML that feeds existing Pack API
|
||||
- The existing 7 sub-views (dashboard, edit, rules, yaml, approvals, simulate, explain) are refactored, not deleted — the underlying components are recomposed
|
||||
|
||||
## Documentation Prerequisites
|
||||
|
||||
- Sprint 004 TASK-001: `core/policy/gate-catalog.ts` — gate display names and descriptions
|
||||
- `features/policy-decisioning/policy-pack-shell.component.ts` — current tab structure
|
||||
- `core/api/policy-interop.models.ts` — PolicyGateDefinition, PolicyPackDocument models
|
||||
- Existing pack editor components under policy-decisioning routes
|
||||
|
||||
---
|
||||
|
||||
## Delivery Tracker
|
||||
|
||||
### TASK-001 - Create gate configuration form components
|
||||
Status: DONE
|
||||
Dependency: Sprint 004 TASK-001 (gate catalog)
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Create per-gate-type configuration form components in `features/policy-decisioning/gate-forms/`:
|
||||
- `cvss-threshold-form.component.ts` — severity threshold slider (0-10), action selector (block/warn/allow)
|
||||
- `signature-required-form.component.ts` — toggle (require DSSE signature: yes/no), allowed signers list
|
||||
- `evidence-freshness-form.component.ts` — max age input (days), action selector
|
||||
- `sbom-presence-form.component.ts` — toggle (require SBOM: yes/no), allowed formats
|
||||
- `minimum-confidence-form.component.ts` — confidence threshold slider (0-100%), action selector
|
||||
- `unknowns-budget-form.component.ts` — fraction slider (0-1.0), action selector
|
||||
- `reachability-requirement-form.component.ts` — toggle (require reachability: yes/no), minimum confidence
|
||||
- `source-quota-form.component.ts` — minimum sources count input, action selector
|
||||
- Each form component:
|
||||
- Accepts current gate config as input
|
||||
- Emits config changes as output
|
||||
- Shows human-readable description from GATE_CATALOG
|
||||
- Validates input (min/max, required fields)
|
||||
- Generates the `config` dictionary matching `PolicyGateDefinition.Config` shape
|
||||
|
||||
Completion criteria:
|
||||
- [ ] 8 gate form components created
|
||||
- [ ] Each renders appropriate form controls for its gate type
|
||||
- [ ] Each emits valid config matching backend expectations
|
||||
- [ ] Each shows gate display name and description from GATE_CATALOG
|
||||
- [ ] Input validation works (thresholds in range, required fields)
|
||||
|
||||
### TASK-002 - Create policy builder component
|
||||
Status: DONE
|
||||
Dependency: TASK-001
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Create `features/policy-decisioning/policy-builder/policy-builder.component.ts`:
|
||||
- Step 1: **Name & describe** — policy name, description, target environments
|
||||
- Step 2: **Select gates** — checklist of available gates with toggle switches:
|
||||
```
|
||||
✓ Vulnerability Severity Block if CVSS ≥ [9.0]
|
||||
✓ Image Signature Require DSSE signature
|
||||
✓ SBOM Required Block if missing
|
||||
✓ Scan Freshness Warn if older than [7] days
|
||||
○ Reachability Analysis (disabled by default)
|
||||
○ Unknowns Limit (disabled by default)
|
||||
○ Detection Confidence (disabled by default)
|
||||
○ Data Source Diversity (disabled by default)
|
||||
```
|
||||
Each enabled gate expands to show its configuration form (from TASK-001)
|
||||
- Step 3: **Review** — plain-language summary:
|
||||
```
|
||||
This policy will:
|
||||
• Block releases with vulnerabilities scoring 9.0 or higher (CVSS)
|
||||
• Block releases without a cryptographic image signature
|
||||
• Block releases without an SBOM
|
||||
• Warn if scan results are older than 7 days
|
||||
```
|
||||
- "View YAML" toggle at any point to see/edit the raw policy DSL
|
||||
- Builder generates a valid `PolicyPackDocument` (apiVersion: policy.stellaops.io/v2)
|
||||
- Builder output feeds into existing Pack API (create revision with compiled YAML)
|
||||
|
||||
Completion criteria:
|
||||
- [ ] 3-step builder flow works end-to-end
|
||||
- [ ] Gate toggle enables/disables gates with inline config forms
|
||||
- [ ] Plain-language review accurately reflects configured gates
|
||||
- [ ] YAML toggle shows valid policy DSL
|
||||
- [ ] Generated YAML matches PolicyPackDocument v2 schema
|
||||
- [ ] Builder can be used for both new policies and editing existing ones
|
||||
|
||||
### TASK-003 - Simplify pack workspace tabs (6 → 3)
|
||||
Status: DONE
|
||||
Dependency: TASK-002
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Modify `policy-pack-shell.component.ts` tab structure:
|
||||
- **Rules tab** (default): Shows the policy builder (TASK-002) for visual editing, with YAML toggle for power users. Merges current Dashboard + Edit + Rules + YAML tabs.
|
||||
- **Test tab**: Loads existing PolicySimulationComponent. Renamed from "Simulate" — clearer language.
|
||||
- **Activate tab**: Loads existing PolicyApprovalsComponent. Renamed from "Approvals" — the action is "activate", not "manage approvals".
|
||||
- **Explain** view stays as a drilldown from simulation results (not a persistent tab)
|
||||
- Update route configuration for pack detail:
|
||||
- `/releases/policies/:packId` → default to `/releases/policies/:packId/rules`
|
||||
- `/releases/policies/:packId/rules` → PolicyBuilderComponent (new) wrapping builder + YAML toggle
|
||||
- `/releases/policies/:packId/test` → PolicySimulationComponent (existing, relabeled)
|
||||
- `/releases/policies/:packId/activate` → PolicyApprovalsComponent (existing, relabeled)
|
||||
- Redirect old tab paths: `dashboard` → `rules`, `edit` → `rules`, `yaml` → `rules?view=yaml`, `approvals` → `activate`, `simulate` → `test`
|
||||
|
||||
Completion criteria:
|
||||
- [ ] Pack detail shows 3 tabs: Rules, Test, Activate
|
||||
- [ ] Rules tab loads the policy builder by default
|
||||
- [ ] YAML toggle within Rules tab shows raw editor
|
||||
- [ ] Test tab loads simulation
|
||||
- [ ] Activate tab loads approval workflow
|
||||
- [ ] Old tab URLs redirect to new ones
|
||||
- [ ] No functionality lost — all existing capabilities accessible
|
||||
|
||||
### TASK-004 - Write e2e tests for policy builder
|
||||
Status: DONE
|
||||
Dependency: TASK-003
|
||||
Owners: Developer (FE)
|
||||
Task description:
|
||||
- Create `tests/e2e/release-policy-builder.spec.ts`:
|
||||
- Policy list page loads under `/releases/policies`
|
||||
- Pack detail page shows 3 tabs (Rules, Test, Activate)
|
||||
- Old tab URLs redirect (dashboard → rules, simulate → test, approvals → activate)
|
||||
- Gate catalog constants render human-readable names in the builder
|
||||
- Builder generates valid structure when gates are toggled
|
||||
- Plain-language summary updates when gates change
|
||||
- YAML toggle works within Rules tab
|
||||
- No Angular runtime errors across the builder flow
|
||||
- Simulation tab loads and renders
|
||||
|
||||
Completion criteria:
|
||||
- [ ] All e2e tests pass
|
||||
- [ ] Coverage includes tab navigation, builder interaction, YAML toggle
|
||||
|
||||
---
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2026-03-31 | Sprint created from policy builder UX plan | Planning |
|
||||
| 2026-03-31 | All 4 tasks completed. Gate config forms (7 typed + generic fallback) and 3-step builder created. Pack shell tabs simplified 6→3 (Rules/Test/Activate). Legacy tab URLs resolve to new tabs. 59/59 e2e tests pass across all suites. | Developer (FE) |
|
||||
|
||||
## Decisions & Risks
|
||||
- **Decision**: Builder generates PolicyPackDocument v2 YAML, not a custom format — uses existing compilation/signing API without backend changes
|
||||
- **Decision**: YAML mode is a toggle within Rules tab, not a separate tab — power users get access without it taking a tab slot from the default flow
|
||||
- **Decision**: Explain view is not a tab — it's a drilldown from simulation results (opened via gate click in Test tab)
|
||||
- **Decision**: Gate forms are hardcoded per gate type, not schema-driven — the 8 gate types are stable; dynamic form generation from a backend schema can be added later if gates become extensible
|
||||
- **Risk**: Generated YAML must match what the compilation endpoint expects — test with existing PolicyBundleRequest format
|
||||
- **Risk**: Existing pack data may not roundtrip cleanly through the builder (packs created via YAML may have configs the builder doesn't understand) — mitigate by falling back to YAML view for unrecognized gate configs
|
||||
- **Risk**: Tab rename may break deep links from other pages (release detail → pack simulate) — mitigate with redirects
|
||||
|
||||
## Next Checkpoints
|
||||
- TASK-001: Gate form components visual review
|
||||
- TASK-002: Builder flow walkthrough with a sample policy
|
||||
- TASK-003: Tab simplification — verify no lost functionality
|
||||
- TASK-004: Full e2e test pass
|
||||
Reference in New Issue
Block a user