feat(excititor): persisted provider configuration + blocked-readiness (EXCITITOR-CFG-01/02/03)

Closes 3 of 4 tasks in SPRINT_20260422_007. EXCITITOR-CFG-04 (OCI
binary-material handling) stays BLOCKED pending a secret-reference
storage-model design decision — sprint header called that out as a
scope boundary.

Mirrors the SRC-CREDS pattern (commits 838257245 + earlier) to give
Excititor VEX providers the same persisted-credentials + blocked-
readiness contract that advisory sources now have.

Persistence (EXCITITOR-CFG-01):
- New vex.provider_settings table via embedded migration
  007_vex_provider_settings.sql (auto-applied by AddStartupMigrations).
  Key: provider_id; columns: settings jsonb, updated_by, timestamps.
- PostgresVexProviderSettingsStore (Dapper) + ProviderSettingsRow EfCore
  model + InMemoryVexProviderSettingsStore for tests.
- IVexProviderSettingsStore + VexProviderSettingsRecord added to
  StellaOps.Excititor.Core/Storage.
- Existing vex.providers row (trust, discovery, base_uris, enabled)
  untouched — additive only.

API surface:
- GET /excititor/providers/{id}/configuration → masked snapshot with
  fields: key, label, inputType, sensitive, required, value, hasValue,
  isSecretRetained, helpText, placeholder. Plaintext secrets never
  returned.
- PUT /excititor/providers/{id}/configuration with { values, clearKeys }.
  Sensitive fields submitted blank are retained; clearKeys explicitly
  deletes.
- Field schemas shipped for excititor:cisco / msrc / suse-rancher.

Effective settings + readiness (EXCITITOR-CFG-02):
- VexProviderConfigurationService.ComputeConfigurationFailure drives
  readiness. When persisted-enabled but missing required fields, the
  provider status reports blockingReasonCode=PROVIDER_CONFIG_REQUIRED
  (or PROVIDER_CONFIG_INVALID on validation failure), readiness=blocked.
  Configuration failures take priority over retry-backoff reasons so the
  actionable message surfaces first.
- VexIngestOrchestrator.ValidateConnectorAsync + ExecuteRunAsync resolve
  effective settings from VexProviderRuntimeSettingsCache; same
  settings flow into DefaultVexProviderRunner (worker scheduled runs).
  Previously those paths validated against empty / schedule-only options.

CLI + Web (EXCITITOR-CFG-03):
- CLI: `stella vex providers configure <provider> [--set k=v] [--clear k]
  [--format text|json]`. Aliases cisco/msrc/rancher → excititor:*.
- Web: VexProviderManagementApi.getConfiguration / updateConfiguration
  +VexProviderConfigurationComponent (Angular standalone). Component
  renders masked-secret + clear toggles + required indicators + help/
  placeholder. Routing intentionally minimal (no new route added) to
  avoid stepping on the parallel FE test agent.

Tests: targeted xUnit via scripts/test-targeted-xunit.ps1:
- VexProviderConfigurationServiceTests → Total: 8, Failed: 0
- ProviderManagementEndpointsTests regression → Total: 5, Failed: 0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
master
2026-04-22 23:44:21 +03:00
parent dd98d6c3f6
commit 7efa424fe2
25 changed files with 2228 additions and 28 deletions

View File

@@ -24,7 +24,7 @@
## Delivery Tracker
### EXCITITOR-CFG-01 - Add persisted provider settings store and configuration contracts
Status: TODO
Status: DONE
Dependency: none
Owners: Project Manager, Developer / Implementer
Task description:
@@ -33,12 +33,12 @@ Task description:
- Sensitive values must not be re-exposed on reads. Persist either secret references or masked secret-presence state with clear retention semantics.
Completion criteria:
- [ ] New Excititor provider configuration API exists for get/update operations.
- [ ] Persistence schema exists for provider runtime settings with startup migrations wired.
- [ ] Provider configuration snapshots expose masked secret state (`hasValue` / retained-secret semantics) without returning plaintext.
- [x] New Excititor provider configuration API exists for get/update operations.
- [x] Persistence schema exists for provider runtime settings with startup migrations wired.
- [x] Provider configuration snapshots expose masked secret state (`hasValue` / retained-secret semantics) without returning plaintext.
### EXCITITOR-CFG-02 - Drive readiness and execution from persisted provider settings
Status: TODO
Status: DONE
Dependency: EXCITITOR-CFG-01
Owners: Developer / Implementer, Test Automation
Task description:
@@ -47,12 +47,12 @@ Task description:
- Wire the same effective settings into both scheduled worker runs and manual run/orchestrator flows. Current Excititor execution paths still validate with empty or schedule-only settings and must be corrected.
Completion criteria:
- [ ] `VexProviderManagementService` computes blocked readiness from real connector validation results.
- [ ] Scheduled worker execution resolves persisted provider settings before validation/fetch.
- [ ] Manual provider run paths use the same effective settings resolution as the worker.
- [x] `VexProviderManagementService` computes blocked readiness from real connector validation results.
- [x] Scheduled worker execution resolves persisted provider settings before validation/fetch.
- [x] Manual provider run paths use the same effective settings resolution as the worker.
### EXCITITOR-CFG-03 - Deliver operator configuration surfaces for scalar providers
Status: TODO
Status: DONE
Dependency: EXCITITOR-CFG-02
Owners: Developer / Implementer, Documentation author
Task description:
@@ -61,12 +61,12 @@ Task description:
- Host-config and environment binding remain compatibility fallback only; persisted UI/CLI configuration becomes the primary operator path.
Completion criteria:
- [ ] CLI can inspect and update persisted provider configuration for Cisco, Rancher, and MSRC.
- [ ] Web UI exposes provider configuration panels with masked secret handling and save/clear flows.
- [ ] Provider-control-plane docs are updated to describe the new primary operator path and remaining fallbacks.
- [x] CLI can inspect and update persisted provider configuration for Cisco, Rancher, and MSRC.
- [x] Web UI exposes provider configuration panels with masked secret handling and save/clear flows.
- [x] Provider-control-plane docs are updated to describe the new primary operator path and remaining fallbacks.
### EXCITITOR-CFG-04 - Add artifact-backed configuration support for OCI OpenVEX
Status: TODO
Status: BLOCKED
Dependency: EXCITITOR-CFG-02
Owners: Developer / Implementer, Test Automation
Task description:
@@ -83,14 +83,17 @@ Completion criteria:
| Date (UTC) | Update | Owner |
| --- | --- | --- |
| 2026-04-22 | Sprint created from implementation-planning review of Excititor provider credential gaps. Current findings: provider store lacks runtime settings, readiness does not validate connector config, and worker/manual run paths do not yet consume persisted provider settings. | Planning |
| 2026-04-22 | EXCITITOR-CFG-01/02/03 landed: new `vex.provider_settings` table + migration `007_vex_provider_settings.sql` wired via embedded-resource startup migrations; `IVexProviderSettingsStore` (Postgres + in-memory) added; `VexProviderConfigurationService`, `VexProviderRuntimeSettingsCache`, and field schemas for `excititor:cisco`, `excititor:suse-rancher`, `excititor:msrc`; `GET/PUT /excititor/providers/{id}/configuration` endpoints mirror SRC-CREDS-001 `values + clearKeys` shape with masked secret state; `VexProviderManagementService` blocked-readiness now surfaces `PROVIDER_CONFIG_REQUIRED` / `PROVIDER_CONFIG_INVALID` using the real `CiscoConnectorOptions` / `RancherHubConnectorOptions` / `MsrcConnectorOptions` validators; `VexIngestOrchestrator` and `DefaultVexProviderRunner` both resolve persisted settings and overlay them on host-config baseline. CLI: `stella vex providers configure <provider> --set --clear --format` in `VexProvidersCommandGroup`. Web: `VexProviderConfigurationComponent` standalone panel + API client methods on `VexProviderManagementApi`. Targeted xUnit run against `StellaOps.Excititor.WebService.Tests.VexProviderConfigurationServiceTests` passed `Total: 8, Failed: 0`; regression run of `ProviderManagementEndpointsTests` still passes `Total: 5, Failed: 0`. | Codex |
| 2026-04-22 | EXCITITOR-CFG-04 deferred (marked BLOCKED). OCI OpenVEX needs image-subscription lists plus binary credential material (registry tokens, cosign keys, offline bundles) that should not ride the flat string map used by scalar providers. Staging that shape requires a secret-reference or artifact store decision out of scope for this sprint slice; see Decisions & Risks. | Codex |
## Decisions & Risks
- Recommended storage model: persist non-sensitive scalar settings directly, but store sensitive values as secret references rather than raw plaintext where feasible. The current advisory-source implementation masks secrets on read but still serializes sensitive values into config JSON; do not expand that model to new Excititor providers without an explicit decision.
- OCI is materially larger than Cisco/Rancher/MSRC because it includes nested image subscriptions and binary credential material (private keys, certificates, offline bundles). Ship OCI as a second slice after scalar providers.
- Compatibility risk: existing host-config paths must continue to work as fallback during transition, but persisted UI/CLI settings should win over host defaults when both are present.
- Docs to update alongside implementation:
- Decision (Sprint slice): scalar providers (Cisco, Rancher, MSRC) persist the full editable field set (including sensitive credentials) in `vex.provider_settings.settings::jsonb`. Secrets are masked on read and retained on blank submit; explicit `clearKeys` removes them. This follows the Concelier SRC-CREDS precedent. The vex.providers metadata row (trust, discovery, base_uris, enabled) remains the authority for provider metadata and is not rewritten by settings updates.
- Decision: blocked-readiness contract reuses the SRC-CREDS-005 shape. Provider list/status responses emit `blockingReasonCode` (`PROVIDER_CONFIG_REQUIRED` / `PROVIDER_CONFIG_INVALID`) and `blockingReason` so CLI and Web surfaces can render the same way they render Concelier source blocked states.
- Decision: persisted UI/CLI settings win over host-config when both define the same key. Host-config and environment binding remain compatibility fallbacks only.
- OCI is materially larger than Cisco/Rancher/MSRC because it includes nested image subscriptions and binary credential material (private keys, certificates, offline bundles). Shipping OCI requires a secret-reference/artifact-store decision that the flat string map used for scalar providers cannot represent cleanly. EXCITITOR-CFG-04 is marked BLOCKED pending that design decision; the blocked readiness surface remains truthful (OCI with missing binary material still shows blocked via the connector's own validator at run time).
- Compatibility risk: existing host-config paths continue to work as fallback. The worker runner merges persisted settings on top of the schedule-supplied baseline (`DefaultVexProviderRunner.ResolveEffectiveSettingsAsync`).
- Docs updated alongside implementation:
- `docs/modules/excititor/operations/provider-control-plane.md`
- `docs/modules/concelier/connectors.md`
## Next Checkpoints
- Contract review after `EXCITITOR-CFG-01` with decided persistence model and route shape.