Rename Feedser to Concelier
This commit is contained in:
10
AGENTS.md
10
AGENTS.md
@@ -10,7 +10,7 @@ Licence audit identifies potential conflicts, especially copyleft obligations.
|
|||||||
Misconfiguration checks detect unsafe Dockerfile patterns (root user, latest tags, permissive modes).
|
Misconfiguration checks detect unsafe Dockerfile patterns (root user, latest tags, permissive modes).
|
||||||
Provenance features include in-toto/SLSA attestations signed with cosign for supply-chain trust.
|
Provenance features include in-toto/SLSA attestations signed with cosign for supply-chain trust.
|
||||||
|
|
||||||
| Guiding principle | What it means for Feedser |
|
| Guiding principle | What it means for Concelier |
|
||||||
|-------------------|---------------------------|
|
|-------------------|---------------------------|
|
||||||
| **SBOM-first ingest** | Prefer signed SBOMs or reproducible layer diffs before falling back to raw scraping; connectors treat source docs as provenance, never as mutable truth. |
|
| **SBOM-first ingest** | Prefer signed SBOMs or reproducible layer diffs before falling back to raw scraping; connectors treat source docs as provenance, never as mutable truth. |
|
||||||
| **Deterministic outputs** | Same inputs yield identical canonical advisories and exported JSON/Trivy DB artefacts; merge hashes and export manifests are reproducible across machines. |
|
| **Deterministic outputs** | Same inputs yield identical canonical advisories and exported JSON/Trivy DB artefacts; merge hashes and export manifests are reproducible across machines. |
|
||||||
@@ -41,14 +41,14 @@ All modules are contained by one or more projects. Each project goes in its dedi
|
|||||||
|
|
||||||
# 4) Modules
|
# 4) Modules
|
||||||
StellaOps is contained by different modules installable via docker containers
|
StellaOps is contained by different modules installable via docker containers
|
||||||
- Feedser. Responsible for aggregation and delivery of vulnerability database
|
- Concelier. Responsible for aggregation and delivery of vulnerability database
|
||||||
- Cli. Command line tool to unlock full potential - request database operations, install scanner, request scan, configure backend
|
- Cli. Command line tool to unlock full potential - request database operations, install scanner, request scan, configure backend
|
||||||
- Backend. Configures and Manages scans
|
- Backend. Configures and Manages scans
|
||||||
- UI. UI to access the backend (and scanners)
|
- UI. UI to access the backend (and scanners)
|
||||||
- Agent. Installable daemon that does the scanning
|
- Agent. Installable daemon that does the scanning
|
||||||
- Zastava. Realtime monitor for allowed (verified) installations.
|
- Zastava. Realtime monitor for allowed (verified) installations.
|
||||||
|
|
||||||
## 4.1) Feedser
|
## 4.1) Concelier
|
||||||
It is webservice based module that is responsible for aggregating vulnerabilities information from various sources, parsing and normalizing them into a canonical shape, merging and deduplicating the results in one place, with export capabilities to Json and TrivyDb. It supports init and resume for all of the sources, parse/normalize and merge/deduplication operations, plus export. Export supports delta exports—similarly to full and incremential database backups.
|
It is webservice based module that is responsible for aggregating vulnerabilities information from various sources, parsing and normalizing them into a canonical shape, merging and deduplicating the results in one place, with export capabilities to Json and TrivyDb. It supports init and resume for all of the sources, parse/normalize and merge/deduplication operations, plus export. Export supports delta exports—similarly to full and incremential database backups.
|
||||||
|
|
||||||
### 4.1.1) Usage
|
### 4.1.1) Usage
|
||||||
@@ -65,7 +65,7 @@ api available on https://db.stella-ops.org
|
|||||||
4. **Export**: JSON tree and/or Trivy DB; package and (optionally) push; write export state.
|
4. **Export**: JSON tree and/or Trivy DB; package and (optionally) push; write export state.
|
||||||
|
|
||||||
### 4.1.3) Architecture
|
### 4.1.3) Architecture
|
||||||
For more information of the architecture see `./docs/ARCHITECTURE_FEEDSER.md`.
|
For more information of the architecture see `./docs/ARCHITECTURE_CONCELIER.md`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ You main characteristics:
|
|||||||
- **Coordination**: In case task is discovered as blocked on other team or task, according TASKS.md files that dependency is on needs to be changed by adding new tasks describing the requirement. the current task must be updated as completed. In case task changes, scope or requirements or rules - other documentations needs be updated accordingly.
|
- **Coordination**: In case task is discovered as blocked on other team or task, according TASKS.md files that dependency is on needs to be changed by adding new tasks describing the requirement. the current task must be updated as completed. In case task changes, scope or requirements or rules - other documentations needs be updated accordingly.
|
||||||
- **Sprint synchronization**: When given task seek for relevant directory to work on from SPRINTS.md. Confirm its state on both SPRINTS.md and the relevant TODOS.md file. Always check the AGENTS.md in the relevant TODOS.md directory.
|
- **Sprint synchronization**: When given task seek for relevant directory to work on from SPRINTS.md. Confirm its state on both SPRINTS.md and the relevant TODOS.md file. Always check the AGENTS.md in the relevant TODOS.md directory.
|
||||||
- **Tests**: Add/extend fixtures and unit tests per change; never regress determinism or precedence.
|
- **Tests**: Add/extend fixtures and unit tests per change; never regress determinism or precedence.
|
||||||
- **Test layout**: Use module-specific projects in `StellaOps.Feedser.<Component>.Tests`; shared fixtures/harnesses live in `StellaOps.Feedser.Testing`.
|
- **Test layout**: Use module-specific projects in `StellaOps.Concelier.<Component>.Tests`; shared fixtures/harnesses live in `StellaOps.Concelier.Testing`.
|
||||||
- **Execution autonomous**: In case you need to continue with more than one options just continue sequentially, unless the continue requires design decision.
|
- **Execution autonomous**: In case you need to continue with more than one options just continue sequentially, unless the continue requires design decision.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -1,27 +1,27 @@
|
|||||||
# StellaOps Feedser & CLI
|
# StellaOps Concelier & CLI
|
||||||
|
|
||||||
This repository hosts the StellaOps Feedser service, its plug-in ecosystem, and the
|
This repository hosts the StellaOps Concelier service, its plug-in ecosystem, and the
|
||||||
first-party CLI (`stellaops-cli`). Feedser ingests vulnerability advisories from
|
first-party CLI (`stellaops-cli`). Concelier ingests vulnerability advisories from
|
||||||
authoritative sources, stores them in MongoDB, and exports deterministic JSON and
|
authoritative sources, stores them in MongoDB, and exports deterministic JSON and
|
||||||
Trivy DB artefacts. The CLI drives scanner distribution, scan execution, and job
|
Trivy DB artefacts. The CLI drives scanner distribution, scan execution, and job
|
||||||
control against the Feedser API.
|
control against the Concelier API.
|
||||||
|
|
||||||
## Quickstart
|
## Quickstart
|
||||||
|
|
||||||
1. Prepare a MongoDB instance and (optionally) install `trivy-db`/`oras`.
|
1. Prepare a MongoDB instance and (optionally) install `trivy-db`/`oras`.
|
||||||
2. Copy `etc/feedser.yaml.sample` to `etc/feedser.yaml` and update the storage + telemetry
|
2. Copy `etc/concelier.yaml.sample` to `etc/concelier.yaml` and update the storage + telemetry
|
||||||
settings.
|
settings.
|
||||||
3. Copy `etc/authority.yaml.sample` to `etc/authority.yaml`, review the issuer, token
|
3. Copy `etc/authority.yaml.sample` to `etc/authority.yaml`, review the issuer, token
|
||||||
lifetimes, and plug-in descriptors, then edit the companion manifests under
|
lifetimes, and plug-in descriptors, then edit the companion manifests under
|
||||||
`etc/authority.plugins/*.yaml` to match your deployment.
|
`etc/authority.plugins/*.yaml` to match your deployment.
|
||||||
4. Start the web service with `dotnet run --project src/StellaOps.Feedser.WebService`.
|
4. Start the web service with `dotnet run --project src/StellaOps.Concelier.WebService`.
|
||||||
5. Configure the CLI via environment variables (e.g. `STELLAOPS_BACKEND_URL`) and trigger
|
5. Configure the CLI via environment variables (e.g. `STELLAOPS_BACKEND_URL`) and trigger
|
||||||
jobs with `dotnet run --project src/StellaOps.Cli -- db merge`.
|
jobs with `dotnet run --project src/StellaOps.Cli -- db merge`.
|
||||||
|
|
||||||
Detailed operator guidance is available in `docs/10_FEEDSER_CLI_QUICKSTART.md`. API and
|
Detailed operator guidance is available in `docs/10_CONCELIER_CLI_QUICKSTART.md`. API and
|
||||||
command reference material lives in `docs/09_API_CLI_REFERENCE.md`.
|
command reference material lives in `docs/09_API_CLI_REFERENCE.md`.
|
||||||
|
|
||||||
Pipeline note: deployment workflows should template `etc/feedser.yaml` during CI/CD,
|
Pipeline note: deployment workflows should template `etc/concelier.yaml` during CI/CD,
|
||||||
injecting environment-specific Mongo credentials and telemetry endpoints. Upcoming
|
injecting environment-specific Mongo credentials and telemetry endpoints. Upcoming
|
||||||
releases will add Microsoft OAuth (Entra ID) authentication support—track the quickstart
|
releases will add Microsoft OAuth (Entra ID) authentication support—track the quickstart
|
||||||
for integration steps once available.
|
for integration steps once available.
|
||||||
@@ -29,6 +29,6 @@ for integration steps once available.
|
|||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- `docs/README.md` now consolidates the platform index and points to the updated high-level architecture.
|
- `docs/README.md` now consolidates the platform index and points to the updated high-level architecture.
|
||||||
- Module architecture dossiers live under `docs/ARCHITECTURE_*.md`; the most relevant here are `docs/ARCHITECTURE_FEEDSER.md` (service layout, merge engine, exports) and `docs/ARCHITECTURE_CLI.md` (command surface, AOT packaging, auth flows). Related services such as the Signer, Attestor, Authority, Scanner, UI, Excititor, Zastava, and DevOps pipeline each have their own dossier.
|
- Module architecture dossiers live under `docs/ARCHITECTURE_*.md`; the most relevant here are `docs/ARCHITECTURE_CONCELIER.md` (service layout, merge engine, exports) and `docs/ARCHITECTURE_CLI.md` (command surface, AOT packaging, auth flows). Related services such as the Signer, Attestor, Authority, Scanner, UI, Excititor, Zastava, and DevOps pipeline each have their own dossier.
|
||||||
- Offline operation guidance moved to `docs/24_OFFLINE_KIT.md`, which details bundle composition, verification, and delta workflows. Feedser-specific connector operations stay in `docs/ops/feedser-certbund-operations.md` and companion runbooks under `docs/ops/`.
|
- Offline operation guidance moved to `docs/24_OFFLINE_KIT.md`, which details bundle composition, verification, and delta workflows. Concelier-specific connector operations stay in `docs/ops/concelier-certbund-operations.md` and companion runbooks under `docs/ops/`.
|
||||||
|
|
||||||
|
|||||||
198
SPRINTS.md
198
SPRINTS.md
@@ -1,52 +1,52 @@
|
|||||||
| Sprint | Theme | Tasks File Path | Status | Type of Specialist | Task ID | Task Description |
|
| Sprint | Theme | Tasks File Path | Status | Type of Specialist | Task ID | Task Description |
|
||||||
| --- | --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- | --- |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Models/TASKS.md | DONE (2025-10-12) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-01-001 | SemVer primitive range-style metadata<br>Instructions to work:<br>DONE Read ./AGENTS.md and src/StellaOps.Feedser.Models/AGENTS.md. This task lays the groundwork—complete the SemVer helper updates before teammates pick up FEEDMODELS-SCHEMA-01-002/003 and FEEDMODELS-SCHEMA-02-900. Use ./src/FASTER_MODELING_AND_NORMALIZATION.md for the target rule structure. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Models/TASKS.md | DONE (2025-10-12) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-01-001 | SemVer primitive range-style metadata<br>Instructions to work:<br>DONE Read ./AGENTS.md and src/StellaOps.Concelier.Models/AGENTS.md. This task lays the groundwork—complete the SemVer helper updates before teammates pick up FEEDMODELS-SCHEMA-01-002/003 and FEEDMODELS-SCHEMA-02-900. Use ./src/FASTER_MODELING_AND_NORMALIZATION.md for the target rule structure. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Models/TASKS.md | DONE (2025-10-11) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-01-002 | Provenance decision rationale field<br>Instructions to work:<br>AdvisoryProvenance now carries `decisionReason` and docs/tests were updated. Connectors and merge tasks should populate the field when applying precedence/freshness/tie-breaker logic; see src/StellaOps.Feedser.Models/PROVENANCE_GUIDELINES.md for usage guidance. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Models/TASKS.md | DONE (2025-10-11) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-01-002 | Provenance decision rationale field<br>Instructions to work:<br>AdvisoryProvenance now carries `decisionReason` and docs/tests were updated. Connectors and merge tasks should populate the field when applying precedence/freshness/tie-breaker logic; see src/StellaOps.Concelier.Models/PROVENANCE_GUIDELINES.md for usage guidance. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Models/TASKS.md | DONE (2025-10-11) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-01-003 | Normalized version rules collection<br>Instructions to work:<br>`AffectedPackage.NormalizedVersions` and supporting comparer/docs/tests shipped. Connector owners must emit rule arrays per ./src/FASTER_MODELING_AND_NORMALIZATION.md and report progress via FEEDMERGE-COORD-02-900 so merge/storage backfills can proceed. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Models/TASKS.md | DONE (2025-10-11) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-01-003 | Normalized version rules collection<br>Instructions to work:<br>`AffectedPackage.NormalizedVersions` and supporting comparer/docs/tests shipped. Connector owners must emit rule arrays per ./src/FASTER_MODELING_AND_NORMALIZATION.md and report progress via FEEDMERGE-COORD-02-900 so merge/storage backfills can proceed. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Models/TASKS.md | DONE (2025-10-12) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-02-900 | Range primitives for SemVer/EVR/NEVRA metadata<br>Instructions to work:<br>DONE Read ./AGENTS.md and src/StellaOps.Feedser.Models/AGENTS.md before resuming this stalled effort. Confirm helpers align with the new `NormalizedVersions` representation so connectors finishing in Sprint 2 can emit consistent metadata. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Models/TASKS.md | DONE (2025-10-12) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-02-900 | Range primitives for SemVer/EVR/NEVRA metadata<br>Instructions to work:<br>DONE Read ./AGENTS.md and src/StellaOps.Concelier.Models/AGENTS.md before resuming this stalled effort. Confirm helpers align with the new `NormalizedVersions` representation so connectors finishing in Sprint 2 can emit consistent metadata. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Normalization/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDNORM-NORM-02-001 | SemVer normalized rule emitter<br>Shared `SemVerRangeRuleBuilder` now outputs primitives + normalized rules per `FASTER_MODELING_AND_NORMALIZATION.md`; CVE/GHSA connectors consuming the API have verified fixtures. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Normalization/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDNORM-NORM-02-001 | SemVer normalized rule emitter<br>Shared `SemVerRangeRuleBuilder` now outputs primitives + normalized rules per `FASTER_MODELING_AND_NORMALIZATION.md`; CVE/GHSA connectors consuming the API have verified fixtures. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-001 | Normalized range dual-write + backfill<br>AdvisoryStore dual-writes flattened `normalizedVersions` when `feedser.storage.enableSemVerStyle` is set; migration `20251011-semver-style-backfill` updates historical records and docs outline the rollout. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-001 | Normalized range dual-write + backfill<br>AdvisoryStore dual-writes flattened `normalizedVersions` when `concelier.storage.enableSemVerStyle` is set; migration `20251011-semver-style-backfill` updates historical records and docs outline the rollout. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-002 | Provenance decision reason persistence<br>Storage now persists `provenance.decisionReason` for advisories and merge events; tests cover round-trips. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-002 | Provenance decision reason persistence<br>Storage now persists `provenance.decisionReason` for advisories and merge events; tests cover round-trips. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-003 | Normalized versions indexing<br>Bootstrapper seeds compound/sparse indexes for flattened normalized rules and `docs/dev/mongo_indices.md` documents query guidance. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-003 | Normalized versions indexing<br>Bootstrapper seeds compound/sparse indexes for flattened normalized rules and `docs/dev/mongo_indices.md` documents query guidance. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-TESTS-02-004 | Restore AdvisoryStore build after normalized versions refactor<br>Updated constructors/tests keep storage suites passing with the new feature flag defaults. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-TESTS-02-004 | Restore AdvisoryStore build after normalized versions refactor<br>Updated constructors/tests keep storage suites passing with the new feature flag defaults. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-ENGINE-01-002 | Plumb Authority client resilience options<br>WebService wires `authority.resilience.*` into `AddStellaOpsAuthClient` and adds binding coverage via `AuthorityClientResilienceOptionsAreBound`. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-ENGINE-01-002 | Plumb Authority client resilience options<br>WebService wires `authority.resilience.*` into `AddStellaOpsAuthClient` and adds binding coverage via `AuthorityClientResilienceOptionsAreBound`. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-003 | Author ops guidance for resilience tuning<br>Install/runbooks document connected vs air-gapped resilience profiles and monitoring hooks. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-003 | Author ops guidance for resilience tuning<br>Install/runbooks document connected vs air-gapped resilience profiles and monitoring hooks. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-004 | Document authority bypass logging patterns<br>Operator guides now call out `route/status/subject/clientId/scopes/bypass/remote` audit fields and SIEM triggers. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-004 | Document authority bypass logging patterns<br>Operator guides now call out `route/status/subject/clientId/scopes/bypass/remote` audit fields and SIEM triggers. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-005 | Update Feedser operator guide for enforcement cutoff<br>Install guide reiterates the 2025-12-31 cutoff and links audit signals to the rollout checklist. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-005 | Update Concelier operator guide for enforcement cutoff<br>Install guide reiterates the 2025-12-31 cutoff and links audit signals to the rollout checklist. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | SEC3.HOST | Rate limiter policy binding<br>Authority host now applies configuration-driven fixed windows to `/token`, `/authorize`, and `/internal/*`; integration tests assert 429 + `Retry-After` headers; docs/config samples refreshed for Docs guild diagrams. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | SEC3.HOST | Rate limiter policy binding<br>Authority host now applies configuration-driven fixed windows to `/token`, `/authorize`, and `/internal/*`; integration tests assert 429 + `Retry-After` headers; docs/config samples refreshed for Docs guild diagrams. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | SEC3.BUILD | Authority rate-limiter follow-through<br>`Security.RateLimiting` now fronts token/authorize/internal limiters; Authority + Configuration matrices (`dotnet test src/StellaOps.Authority/StellaOps.Authority.sln`, `dotnet test src/StellaOps.Configuration.Tests/StellaOps.Configuration.Tests.csproj`) passed on 2025-10-11; awaiting #authority-core broadcast. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | SEC3.BUILD | Authority rate-limiter follow-through<br>`Security.RateLimiting` now fronts token/authorize/internal limiters; Authority + Configuration matrices (`dotnet test src/StellaOps.Authority/StellaOps.Authority.sln`, `dotnet test src/StellaOps.Configuration.Tests/StellaOps.Configuration.Tests.csproj`) passed on 2025-10-11; awaiting #authority-core broadcast. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/TASKS.md | DONE (2025-10-14) | Team Authority Platform & Security Guild | AUTHCORE-BUILD-OPENIDDICT / AUTHCORE-STORAGE-DEVICE-TOKENS / AUTHCORE-BOOTSTRAP-INVITES | Address remaining Authority compile blockers (OpenIddict transaction shim, token device document, bootstrap invite cleanup) so `dotnet build src/StellaOps.Authority.sln` returns success. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/TASKS.md | DONE (2025-10-14) | Team Authority Platform & Security Guild | AUTHCORE-BUILD-OPENIDDICT / AUTHCORE-STORAGE-DEVICE-TOKENS / AUTHCORE-BOOTSTRAP-INVITES | Address remaining Authority compile blockers (OpenIddict transaction shim, token device document, bootstrap invite cleanup) so `dotnet build src/StellaOps.Authority.sln` returns success. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | PLG6.DOC | Plugin developer guide polish<br>Section 9 now documents rate limiter metadata, config keys, and lockout interplay; YAML samples updated alongside Authority config templates. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | PLG6.DOC | Plugin developer guide polish<br>Section 9 now documents rate limiter metadata, config keys, and lockout interplay; YAML samples updated alongside Authority config templates. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-001 | Fetch pipeline & state tracking<br>Summary planner now drives monthly/yearly VINCE fetches, persists pending summaries/notes, and hydrates VINCE detail queue with telemetry.<br>Team instructions: Read ./AGENTS.md and src/StellaOps.Feedser.Source.CertCc/AGENTS.md. Coordinate daily with Models/Merge leads so new normalizedVersions output and provenance tags stay aligned with ./src/FASTER_MODELING_AND_NORMALIZATION.md. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-001 | Fetch pipeline & state tracking<br>Summary planner now drives monthly/yearly VINCE fetches, persists pending summaries/notes, and hydrates VINCE detail queue with telemetry.<br>Team instructions: Read ./AGENTS.md and src/StellaOps.Concelier.Source.CertCc/AGENTS.md. Coordinate daily with Models/Merge leads so new normalizedVersions output and provenance tags stay aligned with ./src/FASTER_MODELING_AND_NORMALIZATION.md. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-002 | VINCE note detail fetcher<br>Summary planner queues VINCE note detail endpoints, persists raw JSON with SHA/ETag metadata, and records retry/backoff metrics. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-002 | VINCE note detail fetcher<br>Summary planner queues VINCE note detail endpoints, persists raw JSON with SHA/ETag metadata, and records retry/backoff metrics. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-003 | DTO & parser implementation<br>Added VINCE DTO aggregate, Markdown→text sanitizer, vendor/status/vulnerability parsers, and parser regression fixture. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-003 | DTO & parser implementation<br>Added VINCE DTO aggregate, Markdown→text sanitizer, vendor/status/vulnerability parsers, and parser regression fixture. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-004 | Canonical mapping & range primitives<br>VINCE DTO aggregate flows through `CertCcMapper`, emitting vendor range primitives + normalized version rules that persist via `_advisoryStore`. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-004 | Canonical mapping & range primitives<br>VINCE DTO aggregate flows through `CertCcMapper`, emitting vendor range primitives + normalized version rules that persist via `_advisoryStore`. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-005 | Deterministic fixtures/tests<br>Snapshot harness refreshed 2025-10-12; `certcc-*.snapshot.json` regenerated and regression suite green without UPDATE flag drift. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-005 | Deterministic fixtures/tests<br>Snapshot harness refreshed 2025-10-12; `certcc-*.snapshot.json` regenerated and regression suite green without UPDATE flag drift. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-006 | Telemetry & documentation<br>`CertCcDiagnostics` publishes summary/detail/parse/map metrics (meter `StellaOps.Feedser.Source.CertCc`), README documents instruments, and log guidance captured for Ops on 2025-10-12. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-006 | Telemetry & documentation<br>`CertCcDiagnostics` publishes summary/detail/parse/map metrics (meter `StellaOps.Concelier.Source.CertCc`), README documents instruments, and log guidance captured for Ops on 2025-10-12. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-007 | Connector test harness remediation<br>Harness now wires `AddSourceCommon`, resets `FakeTimeProvider`, and passes canned-response regression run dated 2025-10-12. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-007 | Connector test harness remediation<br>Harness now wires `AddSourceCommon`, resets `FakeTimeProvider`, and passes canned-response regression run dated 2025-10-12. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-008 | Snapshot coverage handoff<br>Fixtures regenerated with normalized ranges + provenance fields on 2025-10-11; QA handoff notes published and merge backfill unblocked. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-008 | Snapshot coverage handoff<br>Fixtures regenerated with normalized ranges + provenance fields on 2025-10-11; QA handoff notes published and merge backfill unblocked. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-012 | Schema sync & snapshot regen follow-up<br>Fixtures regenerated with normalizedVersions + provenance decision reasons; handoff notes updated for Merge backfill 2025-10-12. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-012 | Schema sync & snapshot regen follow-up<br>Fixtures regenerated with normalizedVersions + provenance decision reasons; handoff notes updated for Merge backfill 2025-10-12. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-009 | Detail/map reintegration plan<br>Staged reintegration plan published in `src/StellaOps.Feedser.Source.CertCc/FEEDCONN-CERTCC-02-009_PLAN.md`; coordinates enablement with FEEDCONN-CERTCC-02-004. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-009 | Detail/map reintegration plan<br>Staged reintegration plan published in `src/StellaOps.Concelier.Source.CertCc/FEEDCONN-CERTCC-02-009_PLAN.md`; coordinates enablement with FEEDCONN-CERTCC-02-004. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-010 | Partial-detail graceful degradation<br>Detail fetch now tolerates 404/403/410 responses and regression tests cover mixed endpoint availability. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.CertCc/TASKS.md | DONE (2025-10-12) | Team Connector Resumption – CERT/RedHat | FEEDCONN-CERTCC-02-010 | Partial-detail graceful degradation<br>Detail fetch now tolerates 404/403/410 responses and regression tests cover mixed endpoint availability. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Distro.RedHat/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-REDHAT-02-001 | Fixture validation sweep<br>Instructions to work:<br>Fixtures regenerated post-model-helper rollout; provenance ordering and normalizedVersions scaffolding verified via tests. Conflict resolver deltas logged in src/StellaOps.Feedser.Source.Distro.RedHat/CONFLICT_RESOLVER_NOTES.md for Sprint 3 consumers. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Distro.RedHat/TASKS.md | DONE (2025-10-11) | Team Connector Resumption – CERT/RedHat | FEEDCONN-REDHAT-02-001 | Fixture validation sweep<br>Instructions to work:<br>Fixtures regenerated post-model-helper rollout; provenance ordering and normalizedVersions scaffolding verified via tests. Conflict resolver deltas logged in src/StellaOps.Concelier.Source.Distro.RedHat/CONFLICT_RESOLVER_NOTES.md for Sprint 3 consumers. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Vndr.Apple/TASKS.md | DONE (2025-10-12) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-001 | Canonical mapping & range primitives<br>Mapper emits SemVer rules (`scheme=apple:*`); fixtures regenerated with trimmed references + new RSR coverage, update tooling finalized. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Vndr.Apple/TASKS.md | DONE (2025-10-12) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-001 | Canonical mapping & range primitives<br>Mapper emits SemVer rules (`scheme=apple:*`); fixtures regenerated with trimmed references + new RSR coverage, update tooling finalized. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Vndr.Apple/TASKS.md | DONE (2025-10-11) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-002 | Deterministic fixtures/tests<br>Sanitized live fixtures + regression snapshots wired into tests; normalized rule coverage asserted. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Vndr.Apple/TASKS.md | DONE (2025-10-11) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-002 | Deterministic fixtures/tests<br>Sanitized live fixtures + regression snapshots wired into tests; normalized rule coverage asserted. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Vndr.Apple/TASKS.md | DONE (2025-10-11) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-003 | Telemetry & documentation<br>Apple meter metrics wired into Feedser WebService OpenTelemetry configuration; README and fixtures document normalizedVersions coverage. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Vndr.Apple/TASKS.md | DONE (2025-10-11) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-003 | Telemetry & documentation<br>Apple meter metrics wired into Concelier WebService OpenTelemetry configuration; README and fixtures document normalizedVersions coverage. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Vndr.Apple/TASKS.md | DONE (2025-10-12) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-004 | Live HTML regression sweep<br>Sanitised HT125326/HT125328/HT106355/HT214108/HT215500 fixtures recorded and regression tests green on 2025-10-12. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Vndr.Apple/TASKS.md | DONE (2025-10-12) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-004 | Live HTML regression sweep<br>Sanitised HT125326/HT125328/HT106355/HT214108/HT215500 fixtures recorded and regression tests green on 2025-10-12. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Vndr.Apple/TASKS.md | DONE (2025-10-11) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-005 | Fixture regeneration tooling<br>`UPDATE_APPLE_FIXTURES=1` flow fetches & rewrites fixtures; README documents usage.<br>Instructions to work:<br>DONE Read ./AGENTS.md and src/StellaOps.Feedser.Source.Vndr.Apple/AGENTS.md. Resume stalled tasks, ensuring normalizedVersions output and fixtures align with ./src/FASTER_MODELING_AND_NORMALIZATION.md before handing data to the conflict sprint. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Vndr.Apple/TASKS.md | DONE (2025-10-11) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-005 | Fixture regeneration tooling<br>`UPDATE_APPLE_FIXTURES=1` flow fetches & rewrites fixtures; README documents usage.<br>Instructions to work:<br>DONE Read ./AGENTS.md and src/StellaOps.Concelier.Source.Vndr.Apple/AGENTS.md. Resume stalled tasks, ensuring normalizedVersions output and fixtures align with ./src/FASTER_MODELING_AND_NORMALIZATION.md before handing data to the conflict sprint. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-GHSA-02-001 | GHSA normalized versions & provenance<br>Team instructions: Read ./AGENTS.md and each module's AGENTS file. Adopt the `NormalizedVersions` array emitted by the models sprint, wiring provenance `decisionReason` where merge overrides occur. Follow ./src/FASTER_MODELING_AND_NORMALIZATION.md; report via src/StellaOps.Feedser.Merge/TASKS.md (FEEDMERGE-COORD-02-900). Progress 2025-10-11: GHSA/OSV emit normalized arrays with refreshed fixtures; CVE mapper now surfaces SemVer normalized ranges; NVD/KEV adoption pending; outstanding follow-ups include FEEDSTORAGE-DATA-02-001, FEEDMERGE-ENGINE-02-002, and rolling `tools/FixtureUpdater` updates across connectors. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-GHSA-02-001 | GHSA normalized versions & provenance<br>Team instructions: Read ./AGENTS.md and each module's AGENTS file. Adopt the `NormalizedVersions` array emitted by the models sprint, wiring provenance `decisionReason` where merge overrides occur. Follow ./src/FASTER_MODELING_AND_NORMALIZATION.md; report via src/StellaOps.Concelier.Merge/TASKS.md (FEEDMERGE-COORD-02-900). Progress 2025-10-11: GHSA/OSV emit normalized arrays with refreshed fixtures; CVE mapper now surfaces SemVer normalized ranges; NVD/KEV adoption pending; outstanding follow-ups include FEEDSTORAGE-DATA-02-001, FEEDMERGE-ENGINE-02-002, and rolling `tools/FixtureUpdater` updates across connectors. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-OSV-02-003 | OSV normalized versions & freshness |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-OSV-02-003 | OSV normalized versions & freshness |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Nvd/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-NVD-02-002 | NVD normalized versions & timestamps |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Nvd/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-NVD-02-002 | NVD normalized versions & timestamps |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Cve/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-CVE-02-003 | CVE normalized versions uplift |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Cve/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-CVE-02-003 | CVE normalized versions uplift |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Kev/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-KEV-02-003 | KEV normalized versions propagation |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Kev/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-KEV-02-003 | KEV normalized versions propagation |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-OSV-04-003 | OSV parity fixture refresh |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.Source.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-OSV-04-003 | OSV parity fixture refresh |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-10) | Team WebService & Authority | FEEDWEB-DOCS-01-001 | Document authority toggle & scope requirements<br>Quickstart carries toggle/scope guidance pending docs guild review (no change this sprint). |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-10) | Team WebService & Authority | FEEDWEB-DOCS-01-001 | Document authority toggle & scope requirements<br>Quickstart carries toggle/scope guidance pending docs guild review (no change this sprint). |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-ENGINE-01-002 | Plumb Authority client resilience options<br>WebService wires `authority.resilience.*` into `AddStellaOpsAuthClient` and adds binding coverage via `AuthorityClientResilienceOptionsAreBound`. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-ENGINE-01-002 | Plumb Authority client resilience options<br>WebService wires `authority.resilience.*` into `AddStellaOpsAuthClient` and adds binding coverage via `AuthorityClientResilienceOptionsAreBound`. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-003 | Author ops guidance for resilience tuning<br>Operator docs now outline connected vs air-gapped resilience profiles and monitoring cues. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-003 | Author ops guidance for resilience tuning<br>Operator docs now outline connected vs air-gapped resilience profiles and monitoring cues. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-004 | Document authority bypass logging patterns<br>Audit logging guidance highlights `route/status/subject/clientId/scopes/bypass/remote` fields and SIEM alerts. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-004 | Document authority bypass logging patterns<br>Audit logging guidance highlights `route/status/subject/clientId/scopes/bypass/remote` fields and SIEM alerts. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-005 | Update Feedser operator guide for enforcement cutoff<br>Install guide reiterates the 2025-12-31 cutoff and ties audit signals to rollout checks. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-12) | Team WebService & Authority | FEEDWEB-DOCS-01-005 | Update Concelier operator guide for enforcement cutoff<br>Install guide reiterates the 2025-12-31 cutoff and ties audit signals to rollout checks. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | FEEDWEB-OPS-01-006 | Rename plugin drop directory to namespaced path<br>Build outputs, tests, and docs now target `StellaOps.Feedser.PluginBinaries`/`StellaOps.Authority.PluginBinaries`. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | FEEDWEB-OPS-01-006 | Rename plugin drop directory to namespaced path<br>Build outputs, tests, and docs now target `StellaOps.Concelier.PluginBinaries`/`StellaOps.Authority.PluginBinaries`. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Feedser.WebService/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | FEEDWEB-OPS-01-007 | Authority resilience adoption<br>Deployment docs and CLI notes explain the LIB5 resilience knobs for rollout.<br>Instructions to work:<br>DONE Read ./AGENTS.md and src/StellaOps.Feedser.WebService/AGENTS.md. These items were mid-flight; resume implementation ensuring docs/operators receive timely updates. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-11) | Team WebService & Authority | FEEDWEB-OPS-01-007 | Authority resilience adoption<br>Deployment docs and CLI notes explain the LIB5 resilience knobs for rollout.<br>Instructions to work:<br>DONE Read ./AGENTS.md and src/StellaOps.Concelier.WebService/AGENTS.md. These items were mid-flight; resume implementation ensuring docs/operators receive timely updates. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/TASKS.md | DONE (2025-10-11) | Team Authority Platform & Security Guild | AUTHCORE-ENGINE-01-001 | CORE8.RL — Rate limiter plumbing validated; integration tests green and docs handoff recorded for middleware ordering + Retry-After headers (see `docs/dev/authority-rate-limit-tuning-outline.md` for continuing guidance). |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/TASKS.md | DONE (2025-10-11) | Team Authority Platform & Security Guild | AUTHCORE-ENGINE-01-001 | CORE8.RL — Rate limiter plumbing validated; integration tests green and docs handoff recorded for middleware ordering + Retry-After headers (see `docs/dev/authority-rate-limit-tuning-outline.md` for continuing guidance). |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Cryptography/TASKS.md | DONE (2025-10-11) | Team Authority Platform & Security Guild | AUTHCRYPTO-ENGINE-01-001 | SEC3.A — Shared metadata resolver confirmed via host test run; SEC3.B now unblocked for tuning guidance (outline captured in `docs/dev/authority-rate-limit-tuning-outline.md`). |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Cryptography/TASKS.md | DONE (2025-10-11) | Team Authority Platform & Security Guild | AUTHCRYPTO-ENGINE-01-001 | SEC3.A — Shared metadata resolver confirmed via host test run; SEC3.B now unblocked for tuning guidance (outline captured in `docs/dev/authority-rate-limit-tuning-outline.md`). |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Cryptography/TASKS.md | DONE (2025-10-13) | Team Authority Platform & Security Guild | AUTHSEC-DOCS-01-002 | SEC3.B — Published `docs/security/rate-limits.md` with tuning matrix, alert thresholds, and lockout interplay guidance; Docs guild can lift copy into plugin guide. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Cryptography/TASKS.md | DONE (2025-10-13) | Team Authority Platform & Security Guild | AUTHSEC-DOCS-01-002 | SEC3.B — Published `docs/security/rate-limits.md` with tuning matrix, alert thresholds, and lockout interplay guidance; Docs guild can lift copy into plugin guide. |
|
||||||
@@ -54,59 +54,59 @@
|
|||||||
| Sprint 1 | Bootstrap & Replay Hardening | src/StellaOps.Cryptography/TASKS.md | DONE (2025-10-14) | Security Guild | AUTHSEC-CRYPTO-02-004 | SEC5.D/E — Finish bootstrap invite lifecycle (API/store/cleanup) and token device heuristics; build currently red due to pending handler integration. |
|
| Sprint 1 | Bootstrap & Replay Hardening | src/StellaOps.Cryptography/TASKS.md | DONE (2025-10-14) | Security Guild | AUTHSEC-CRYPTO-02-004 | SEC5.D/E — Finish bootstrap invite lifecycle (API/store/cleanup) and token device heuristics; build currently red due to pending handler integration. |
|
||||||
| Sprint 1 | Developer Tooling | src/StellaOps.Cli/TASKS.md | DONE (2025-10-15) | DevEx/CLI | AUTHCLI-DIAG-01-001 | Surface password policy diagnostics in CLI startup/output so operators see weakened overrides immediately.<br>CLI now loads Authority plug-ins at startup, logs weakened password policies (length/complexity), and regression coverage lives in `StellaOps.Cli.Tests/Services/AuthorityDiagnosticsReporterTests`. |
|
| Sprint 1 | Developer Tooling | src/StellaOps.Cli/TASKS.md | DONE (2025-10-15) | DevEx/CLI | AUTHCLI-DIAG-01-001 | Surface password policy diagnostics in CLI startup/output so operators see weakened overrides immediately.<br>CLI now loads Authority plug-ins at startup, logs weakened password policies (length/complexity), and regression coverage lives in `StellaOps.Cli.Tests/Services/AuthorityDiagnosticsReporterTests`. |
|
||||||
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md | DONE (2025-10-11) | Team Authority Platform & Security Guild | AUTHPLUG-DOCS-01-001 | PLG6.DOC — Developer guide copy + diagrams merged 2025-10-11; limiter guidance incorporated and handed to Docs guild for asset export. |
|
| Sprint 1 | Stabilize In-Progress Foundations | src/StellaOps.Authority/StellaOps.Authority.Plugin.Standard/TASKS.md | DONE (2025-10-11) | Team Authority Platform & Security Guild | AUTHPLUG-DOCS-01-001 | PLG6.DOC — Developer guide copy + diagrams merged 2025-10-11; limiter guidance incorporated and handed to Docs guild for asset export. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Normalization/TASKS.md | DONE (2025-10-12) | Team Normalization & Storage Backbone | FEEDNORM-NORM-02-001 | SemVer normalized rule emitter<br>`SemVerRangeRuleBuilder` shipped 2025-10-12 with comparator/`||` support and fixtures aligning to `FASTER_MODELING_AND_NORMALIZATION.md`. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Normalization/TASKS.md | DONE (2025-10-12) | Team Normalization & Storage Backbone | FEEDNORM-NORM-02-001 | SemVer normalized rule emitter<br>`SemVerRangeRuleBuilder` shipped 2025-10-12 with comparator/`||` support and fixtures aligning to `FASTER_MODELING_AND_NORMALIZATION.md`. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-001 | Normalized range dual-write + backfill |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-001 | Normalized range dual-write + backfill |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-002 | Provenance decision reason persistence |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-002 | Provenance decision reason persistence |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-003 | Normalized versions indexing<br>Indexes seeded + docs updated 2025-10-11 to cover flattened normalized rules for connector adoption. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-02-003 | Normalized versions indexing<br>Indexes seeded + docs updated 2025-10-11 to cover flattened normalized rules for connector adoption. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Merge/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDMERGE-ENGINE-02-002 | Normalized versions union & dedupe<br>Affected package resolver unions/dedupes normalized rules, stamps merge provenance with `decisionReason`, and tests cover the rollout. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Merge/TASKS.md | DONE (2025-10-11) | Team Normalization & Storage Backbone | FEEDMERGE-ENGINE-02-002 | Normalized versions union & dedupe<br>Affected package resolver unions/dedupes normalized rules, stamps merge provenance with `decisionReason`, and tests cover the rollout. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Ghsa/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-001 | GHSA normalized versions & provenance |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Ghsa/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-001 | GHSA normalized versions & provenance |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Ghsa/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-004 | GHSA credits & ecosystem severity mapping |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Ghsa/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-004 | GHSA credits & ecosystem severity mapping |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-005 | GitHub quota monitoring & retries |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-005 | GitHub quota monitoring & retries |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-006 | Production credential & scheduler rollout |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-006 | Production credential & scheduler rollout |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-007 | Credit parity regression fixtures |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-GHSA-02-007 | Credit parity regression fixtures |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Nvd/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-NVD-02-002 | NVD normalized versions & timestamps |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Nvd/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-NVD-02-002 | NVD normalized versions & timestamps |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Nvd/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-NVD-02-004 | NVD CVSS & CWE precedence payloads |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Nvd/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-NVD-02-004 | NVD CVSS & CWE precedence payloads |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Nvd/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-NVD-02-005 | NVD merge/export parity regression |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Nvd/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-NVD-02-005 | NVD merge/export parity regression |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-003 | OSV normalized versions & freshness |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Osv/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-003 | OSV normalized versions & freshness |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-004 | OSV references & credits alignment |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Osv/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-004 | OSV references & credits alignment |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-005 | Fixture updater workflow<br>Resolved 2025-10-12: OSV mapper now derives canonical PURLs for Go + scoped npm packages when raw payloads omit `purl`; conflict fixtures unchanged for invalid npm names. Verified via `dotnet test src/StellaOps.Feedser.Source.Osv.Tests`, `src/StellaOps.Feedser.Source.Ghsa.Tests`, `src/StellaOps.Feedser.Source.Nvd.Tests`, and backbone normalization/storage suites. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-005 | Fixture updater workflow<br>Resolved 2025-10-12: OSV mapper now derives canonical PURLs for Go + scoped npm packages when raw payloads omit `purl`; conflict fixtures unchanged for invalid npm names. Verified via `dotnet test src/StellaOps.Concelier.Source.Osv.Tests`, `src/StellaOps.Concelier.Source.Ghsa.Tests`, `src/StellaOps.Concelier.Source.Nvd.Tests`, and backbone normalization/storage suites. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Acsc/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-ACSC-02-001 … 02-008 | Fetch→parse→map pipeline, fixtures, diagnostics, and README finished 2025-10-12; downstream export parity captured via FEEDEXPORT-JSON-04-001 / FEEDEXPORT-TRIVY-04-001 (completed). |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Acsc/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-ACSC-02-001 … 02-008 | Fetch→parse→map pipeline, fixtures, diagnostics, and README finished 2025-10-12; downstream export parity captured via FEEDEXPORT-JSON-04-001 / FEEDEXPORT-TRIVY-04-001 (completed). |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Cccs/TASKS.md | DONE (2025-10-16) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CCCS-02-001 … 02-008 | Observability meter, historical harvest plan, and DOM sanitizer refinements wrapped; ops notes live under `docs/ops/feedser-cccs-operations.md` with fixtures validating EN/FR list handling. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Cccs/TASKS.md | DONE (2025-10-16) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CCCS-02-001 … 02-008 | Observability meter, historical harvest plan, and DOM sanitizer refinements wrapped; ops notes live under `docs/ops/concelier-cccs-operations.md` with fixtures validating EN/FR list handling. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.CertBund/TASKS.md | DONE (2025-10-15) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CERTBUND-02-001 … 02-008 | Telemetry/docs (02-006) and history/locale sweep (02-007) completed alongside pipeline; runbook `docs/ops/feedser-certbund-operations.md` captures locale guidance and offline packaging. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.CertBund/TASKS.md | DONE (2025-10-15) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CERTBUND-02-001 … 02-008 | Telemetry/docs (02-006) and history/locale sweep (02-007) completed alongside pipeline; runbook `docs/ops/concelier-certbund-operations.md` captures locale guidance and offline packaging. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Kisa/TASKS.md | DONE (2025-10-14) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-KISA-02-001 … 02-007 | Connector, tests, and telemetry/docs (02-006) finalized; localisation notes in `docs/dev/kisa_connector_notes.md` complete rollout. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Kisa/TASKS.md | DONE (2025-10-14) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-KISA-02-001 … 02-007 | Connector, tests, and telemetry/docs (02-006) finalized; localisation notes in `docs/dev/kisa_connector_notes.md` complete rollout. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Ru.Bdu/TASKS.md | DONE (2025-10-14) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-RUBDU-02-001 … 02-008 | Fetch/parser/mapper refinements, regression fixtures, telemetry/docs, access options, and trusted root packaging all landed; README documents offline access strategy. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Ru.Bdu/TASKS.md | DONE (2025-10-14) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-RUBDU-02-001 … 02-008 | Fetch/parser/mapper refinements, regression fixtures, telemetry/docs, access options, and trusted root packaging all landed; README documents offline access strategy. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Ru.Nkcki/TASKS.md | DONE (2025-10-13) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-NKCKI-02-001 … 02-008 | Listing fetch, parser, mapper, fixtures, telemetry/docs, and archive plan finished; Mongo2Go/libcrypto dependency resolved via bundled OpenSSL noted in ops guide. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Ru.Nkcki/TASKS.md | DONE (2025-10-13) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-NKCKI-02-001 … 02-008 | Listing fetch, parser, mapper, fixtures, telemetry/docs, and archive plan finished; Mongo2Go/libcrypto dependency resolved via bundled OpenSSL noted in ops guide. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Ics.Cisa/TASKS.md | DONE (2025-10-16) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-ICSCISA-02-001 … 02-011 | Feed parser attachment fixes, SemVer exact values, regression suites, telemetry/docs updates, and handover complete; ops runbook now details attachment verification + proxy usage. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Ics.Cisa/TASKS.md | DONE (2025-10-16) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-ICSCISA-02-001 … 02-011 | Feed parser attachment fixes, SemVer exact values, regression suites, telemetry/docs updates, and handover complete; ops runbook now details attachment verification + proxy usage. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Vndr.Cisco/TASKS.md | DONE (2025-10-14) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CISCO-02-001 … 02-007 | OAuth fetch pipeline, DTO/mapping, tests, and telemetry/docs shipped; monitoring/export integration follow-ups recorded in Ops docs and exporter backlog (completed). |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Vndr.Cisco/TASKS.md | DONE (2025-10-14) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CISCO-02-001 … 02-007 | OAuth fetch pipeline, DTO/mapping, tests, and telemetry/docs shipped; monitoring/export integration follow-ups recorded in Ops docs and exporter backlog (completed). |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Vndr.Msrc/TASKS.md | DONE (2025-10-15) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-MSRC-02-001 … 02-008 | Azure AD onboarding (02-008) unblocked fetch/parse/map pipeline; fixtures, telemetry/docs, and Offline Kit guidance published in `docs/ops/feedser-msrc-operations.md`. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Vndr.Msrc/TASKS.md | DONE (2025-10-15) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-MSRC-02-001 … 02-008 | Azure AD onboarding (02-008) unblocked fetch/parse/map pipeline; fixtures, telemetry/docs, and Offline Kit guidance published in `docs/ops/concelier-msrc-operations.md`. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Cve/TASKS.md | DONE (2025-10-15) | Team Connector Support & Monitoring | FEEDCONN-CVE-02-001 … 02-002 | CVE data-source selection, fetch pipeline, and docs landed 2025-10-10. 2025-10-15: smoke verified using the seeded mirror fallback; connector now logs a warning and pulls from `seed-data/cve/` until live CVE Services credentials arrive. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Cve/TASKS.md | DONE (2025-10-15) | Team Connector Support & Monitoring | FEEDCONN-CVE-02-001 … 02-002 | CVE data-source selection, fetch pipeline, and docs landed 2025-10-10. 2025-10-15: smoke verified using the seeded mirror fallback; connector now logs a warning and pulls from `seed-data/cve/` until live CVE Services credentials arrive. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Kev/TASKS.md | DONE (2025-10-12) | Team Connector Support & Monitoring | FEEDCONN-KEV-02-001 … 02-002 | KEV catalog ingestion, fixtures, telemetry, and schema validation completed 2025-10-12; ops dashboard published. |
|
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Concelier.Source.Kev/TASKS.md | DONE (2025-10-12) | Team Connector Support & Monitoring | FEEDCONN-KEV-02-001 … 02-002 | KEV catalog ingestion, fixtures, telemetry, and schema validation completed 2025-10-12; ops dashboard published. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | docs/TASKS.md | DONE (2025-10-11) | Team Docs & Knowledge Base | FEEDDOCS-DOCS-01-001 | Canonical schema docs refresh<br>Updated canonical schema + provenance guides with SemVer style, normalized version rules, decision reason change log, and migration notes. |
|
| Sprint 2 | Connector & Data Implementation Wave | docs/TASKS.md | DONE (2025-10-11) | Team Docs & Knowledge Base | FEEDDOCS-DOCS-01-001 | Canonical schema docs refresh<br>Updated canonical schema + provenance guides with SemVer style, normalized version rules, decision reason change log, and migration notes. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | docs/TASKS.md | DONE (2025-10-11) | Team Docs & Knowledge Base | FEEDDOCS-DOCS-02-001 | Feedser-SemVer Playbook<br>Published merge playbook covering mapper patterns, dedupe flow, indexes, and rollout checklist. |
|
| Sprint 2 | Connector & Data Implementation Wave | docs/TASKS.md | DONE (2025-10-11) | Team Docs & Knowledge Base | FEEDDOCS-DOCS-02-001 | Concelier-SemVer Playbook<br>Published merge playbook covering mapper patterns, dedupe flow, indexes, and rollout checklist. |
|
||||||
| Sprint 2 | Connector & Data Implementation Wave | docs/TASKS.md | DONE (2025-10-11) | Team Docs & Knowledge Base | FEEDDOCS-DOCS-02-002 | Normalized versions query guide<br>Delivered Mongo index/query addendum with `$unwind` recipes, dedupe checks, and operational checklist.<br>Instructions to work:<br>DONE Read ./AGENTS.md and docs/AGENTS.md. Document every schema/index/query change produced in Sprint 1-2 leveraging ./src/FASTER_MODELING_AND_NORMALIZATION.md. |
|
| Sprint 2 | Connector & Data Implementation Wave | docs/TASKS.md | DONE (2025-10-11) | Team Docs & Knowledge Base | FEEDDOCS-DOCS-02-002 | Normalized versions query guide<br>Delivered Mongo index/query addendum with `$unwind` recipes, dedupe checks, and operational checklist.<br>Instructions to work:<br>DONE Read ./AGENTS.md and docs/AGENTS.md. Document every schema/index/query change produced in Sprint 1-2 leveraging ./src/FASTER_MODELING_AND_NORMALIZATION.md. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Core/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-03-001 | Canonical merger implementation<br>`CanonicalMerger` ships with freshness/tie-breaker logic, provenance, and unit coverage feeding Merge. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Core/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-03-001 | Canonical merger implementation<br>`CanonicalMerger` ships with freshness/tie-breaker logic, provenance, and unit coverage feeding Merge. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Core/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-03-002 | Field precedence and tie-breaker map<br>Field precedence tables and tie-breaker metrics wired into the canonical merge flow; docs/tests updated.<br>Instructions to work:<br>Read ./AGENTS.md and core AGENTS. Implement the conflict resolver exactly as specified in ./src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md, coordinating with Merge and Storage teammates. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Core/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-03-002 | Field precedence and tie-breaker map<br>Field precedence tables and tie-breaker metrics wired into the canonical merge flow; docs/tests updated.<br>Instructions to work:<br>Read ./AGENTS.md and core AGENTS. Implement the conflict resolver exactly as specified in ./src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md, coordinating with Merge and Storage teammates. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDSTORAGE-DATA-03-001 | Merge event provenance audit prep<br>Merge events now persist `fieldDecisions` and analytics-ready provenance snapshots. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDSTORAGE-DATA-03-001 | Merge event provenance audit prep<br>Merge events now persist `fieldDecisions` and analytics-ready provenance snapshots. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDSTORAGE-DATA-02-001 | Normalized range dual-write + backfill<br>Dual-write/backfill flag delivered; migration + options validated in tests. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDSTORAGE-DATA-02-001 | Normalized range dual-write + backfill<br>Dual-write/backfill flag delivered; migration + options validated in tests. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDSTORAGE-TESTS-02-004 | Restore AdvisoryStore build after normalized versions refactor<br>Storage tests adjusted for normalized versions/decision reasons.<br>Instructions to work:<br>Read ./AGENTS.md and storage AGENTS. Extend merge events with decision reasons and analytics views to support the conflict rules, and deliver the dual-write/backfill for `NormalizedVersions` + `decisionReason` so connectors can roll out safely. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | DONE (2025-10-11) | Team Core Engine & Storage Analytics | FEEDSTORAGE-TESTS-02-004 | Restore AdvisoryStore build after normalized versions refactor<br>Storage tests adjusted for normalized versions/decision reasons.<br>Instructions to work:<br>Read ./AGENTS.md and storage AGENTS. Extend merge events with decision reasons and analytics views to support the conflict rules, and deliver the dual-write/backfill for `NormalizedVersions` + `decisionReason` so connectors can roll out safely. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Merge/TASKS.md | DONE (2025-10-11) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-001 | GHSA/NVD/OSV conflict rules<br>Merge pipeline consumes `CanonicalMerger` output prior to precedence merge. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Merge/TASKS.md | DONE (2025-10-11) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-001 | GHSA/NVD/OSV conflict rules<br>Merge pipeline consumes `CanonicalMerger` output prior to precedence merge. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Merge/TASKS.md | DONE (2025-10-11) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-002 | Override metrics instrumentation<br>Merge events capture per-field decisions; counters/logs align with conflict rules. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Merge/TASKS.md | DONE (2025-10-11) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-002 | Override metrics instrumentation<br>Merge events capture per-field decisions; counters/logs align with conflict rules. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Merge/TASKS.md | DONE (2025-10-11) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-003 | Reference & credit union pipeline<br>Canonical merge preserves unions with updated tests. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Merge/TASKS.md | DONE (2025-10-11) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-003 | Reference & credit union pipeline<br>Canonical merge preserves unions with updated tests. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Merge/TASKS.md | DONE (2025-10-11) | Team Merge & QA Enforcement | FEEDMERGE-QA-04-001 | End-to-end conflict regression suite<br>Added regression tests (`AdvisoryMergeServiceTests`) covering canonical + precedence flow.<br>Instructions to work:<br>Read ./AGENTS.md and merge AGENTS. Integrate the canonical merger, instrument metrics, and deliver comprehensive regression tests following ./src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Merge/TASKS.md | DONE (2025-10-11) | Team Merge & QA Enforcement | FEEDMERGE-QA-04-001 | End-to-end conflict regression suite<br>Added regression tests (`AdvisoryMergeServiceTests`) covering canonical + precedence flow.<br>Instructions to work:<br>Read ./AGENTS.md and merge AGENTS. Integrate the canonical merger, instrument metrics, and deliver comprehensive regression tests following ./src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Regression Fixtures | FEEDCONN-GHSA-04-002 | GHSA conflict regression fixtures |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Source.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Regression Fixtures | FEEDCONN-GHSA-04-002 | GHSA conflict regression fixtures |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Source.Nvd/TASKS.md | DONE (2025-10-12) | Team Connector Regression Fixtures | FEEDCONN-NVD-04-002 | NVD conflict regression fixtures |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Source.Nvd/TASKS.md | DONE (2025-10-12) | Team Connector Regression Fixtures | FEEDCONN-NVD-04-002 | NVD conflict regression fixtures |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Regression Fixtures | FEEDCONN-OSV-04-002 | OSV conflict regression fixtures<br>Instructions to work:<br>Read ./AGENTS.md and module AGENTS. Produce fixture triples supporting the precedence/tie-breaker paths defined in ./src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md and hand them to Merge QA. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | src/StellaOps.Concelier.Source.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Regression Fixtures | FEEDCONN-OSV-04-002 | OSV conflict regression fixtures<br>Instructions to work:<br>Read ./AGENTS.md and module AGENTS. Produce fixture triples supporting the precedence/tie-breaker paths defined in ./src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md and hand them to Merge QA. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | docs/TASKS.md | DONE (2025-10-11) | Team Documentation Guild – Conflict Guidance | FEEDDOCS-DOCS-05-001 | Feedser Conflict Rules<br>Runbook published at `docs/ops/feedser-conflict-resolution.md`; metrics/log guidance aligned with Sprint 3 merge counters. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | docs/TASKS.md | DONE (2025-10-11) | Team Documentation Guild – Conflict Guidance | FEEDDOCS-DOCS-05-001 | Concelier Conflict Rules<br>Runbook published at `docs/ops/concelier-conflict-resolution.md`; metrics/log guidance aligned with Sprint 3 merge counters. |
|
||||||
| Sprint 3 | Conflict Resolution Integration & Communications | docs/TASKS.md | DONE (2025-10-16) | Team Documentation Guild – Conflict Guidance | FEEDDOCS-DOCS-05-002 | Conflict runbook ops rollout<br>Ops review completed, alert thresholds applied, and change log appended in `docs/ops/feedser-conflict-resolution.md`; task closed after connector signals verified. |
|
| Sprint 3 | Conflict Resolution Integration & Communications | docs/TASKS.md | DONE (2025-10-16) | Team Documentation Guild – Conflict Guidance | FEEDDOCS-DOCS-05-002 | Conflict runbook ops rollout<br>Ops review completed, alert thresholds applied, and change log appended in `docs/ops/concelier-conflict-resolution.md`; task closed after connector signals verified. |
|
||||||
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Feedser.Models/TASKS.md | DONE (2025-10-15) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-04-001 | Advisory schema parity (description/CWE/canonical metric)<br>Extend `Advisory` and related records with description text, CWE collection, and canonical metric pointer; refresh validation + serializer determinism tests. |
|
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Concelier.Models/TASKS.md | DONE (2025-10-15) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-04-001 | Advisory schema parity (description/CWE/canonical metric)<br>Extend `Advisory` and related records with description text, CWE collection, and canonical metric pointer; refresh validation + serializer determinism tests. |
|
||||||
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Feedser.Core/TASKS.md | DONE (2025-10-15) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-04-003 | Canonical merger parity for new fields<br>Teach `CanonicalMerger` to populate description, CWEResults, and canonical metric pointer with provenance + regression coverage. |
|
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Concelier.Core/TASKS.md | DONE (2025-10-15) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-04-003 | Canonical merger parity for new fields<br>Teach `CanonicalMerger` to populate description, CWEResults, and canonical metric pointer with provenance + regression coverage. |
|
||||||
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Feedser.Core/TASKS.md | DONE (2025-10-15) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-04-004 | Reference normalization & freshness instrumentation cleanup<br>Implement URL normalization for reference dedupe, align freshness-sensitive instrumentation, and add analytics tests. |
|
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Concelier.Core/TASKS.md | DONE (2025-10-15) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-04-004 | Reference normalization & freshness instrumentation cleanup<br>Implement URL normalization for reference dedupe, align freshness-sensitive instrumentation, and add analytics tests. |
|
||||||
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Feedser.Merge/TASKS.md | DONE (2025-10-15) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-004 | Merge pipeline parity for new advisory fields<br>Ensure merge service + merge events surface description/CWE/canonical metric decisions with updated metrics/tests. |
|
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Concelier.Merge/TASKS.md | DONE (2025-10-15) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-004 | Merge pipeline parity for new advisory fields<br>Ensure merge service + merge events surface description/CWE/canonical metric decisions with updated metrics/tests. |
|
||||||
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Feedser.Merge/TASKS.md | DONE (2025-10-15) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-005 | Connector coordination for new advisory fields<br>GHSA/NVD/OSV connectors now ship description, CWE, and canonical metric data with refreshed fixtures; merge coordination log updated and exporters notified. |
|
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Concelier.Merge/TASKS.md | DONE (2025-10-15) | Team Merge & QA Enforcement | FEEDMERGE-ENGINE-04-005 | Connector coordination for new advisory fields<br>GHSA/NVD/OSV connectors now ship description, CWE, and canonical metric data with refreshed fixtures; merge coordination log updated and exporters notified. |
|
||||||
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Feedser.Exporter.Json/TASKS.md | DONE (2025-10-15) | Team Exporters – JSON | FEEDEXPORT-JSON-04-001 | Surface new advisory fields in JSON exporter<br>Update schemas/offline bundle + fixtures once model/core parity lands.<br>2025-10-15: `dotnet test src/StellaOps.Feedser.Exporter.Json.Tests` validated canonical metric/CWE emission. |
|
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Concelier.Exporter.Json/TASKS.md | DONE (2025-10-15) | Team Exporters – JSON | FEEDEXPORT-JSON-04-001 | Surface new advisory fields in JSON exporter<br>Update schemas/offline bundle + fixtures once model/core parity lands.<br>2025-10-15: `dotnet test src/StellaOps.Concelier.Exporter.Json.Tests` validated canonical metric/CWE emission. |
|
||||||
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Feedser.Exporter.TrivyDb/TASKS.md | DONE (2025-10-15) | Team Exporters – Trivy DB | FEEDEXPORT-TRIVY-04-001 | Propagate new advisory fields into Trivy DB package<br>Extend Bolt builder, metadata, and regression tests for the expanded schema.<br>2025-10-15: `dotnet test src/StellaOps.Feedser.Exporter.TrivyDb.Tests` confirmed canonical metric/CWE propagation. |
|
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Concelier.Exporter.TrivyDb/TASKS.md | DONE (2025-10-15) | Team Exporters – Trivy DB | FEEDEXPORT-TRIVY-04-001 | Propagate new advisory fields into Trivy DB package<br>Extend Bolt builder, metadata, and regression tests for the expanded schema.<br>2025-10-15: `dotnet test src/StellaOps.Concelier.Exporter.TrivyDb.Tests` confirmed canonical metric/CWE propagation. |
|
||||||
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Feedser.Source.Ghsa/TASKS.md | DONE (2025-10-16) | Team Connector Regression Fixtures | FEEDCONN-GHSA-04-004 | Harden CVSS fallback so canonical metric ids persist when GitHub omits vectors; extend fixtures and document severity precedence hand-off to Merge. |
|
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Concelier.Source.Ghsa/TASKS.md | DONE (2025-10-16) | Team Connector Regression Fixtures | FEEDCONN-GHSA-04-004 | Harden CVSS fallback so canonical metric ids persist when GitHub omits vectors; extend fixtures and document severity precedence hand-off to Merge. |
|
||||||
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-16) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-04-005 | Map OSV advisories lacking CVSS vectors to canonical metric ids/notes and document CWE provenance quirks; schedule parity fixture updates. |
|
| Sprint 4 | Schema Parity & Freshness Alignment | src/StellaOps.Concelier.Source.Osv/TASKS.md | DONE (2025-10-16) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-04-005 | Map OSV advisories lacking CVSS vectors to canonical metric ids/notes and document CWE provenance quirks; schedule parity fixture updates. |
|
||||||
| Sprint 5 | Excititor Core Foundations | src/StellaOps.Excititor.Core/TASKS.md | DONE (2025-10-15) | Team Excititor Core & Policy | EXCITITOR-CORE-01-001 | Stand up canonical VEX claim/consensus records with deterministic serializers so Storage/Exports share a stable contract. |
|
| Sprint 5 | Excititor Core Foundations | src/StellaOps.Excititor.Core/TASKS.md | DONE (2025-10-15) | Team Excititor Core & Policy | EXCITITOR-CORE-01-001 | Stand up canonical VEX claim/consensus records with deterministic serializers so Storage/Exports share a stable contract. |
|
||||||
| Sprint 5 | Excititor Core Foundations | src/StellaOps.Excititor.Core/TASKS.md | DONE (2025-10-15) | Team Excititor Core & Policy | EXCITITOR-CORE-01-002 | Implement trust-weighted consensus resolver with baseline policy weights, justification gates, telemetry output, and majority/tie handling. |
|
| Sprint 5 | Excititor Core Foundations | src/StellaOps.Excititor.Core/TASKS.md | DONE (2025-10-15) | Team Excititor Core & Policy | EXCITITOR-CORE-01-002 | Implement trust-weighted consensus resolver with baseline policy weights, justification gates, telemetry output, and majority/tie handling. |
|
||||||
| Sprint 5 | Excititor Core Foundations | src/StellaOps.Excititor.Core/TASKS.md | DONE (2025-10-15) | Team Excititor Core & Policy | EXCITITOR-CORE-01-003 | Publish shared connector/exporter/attestation abstractions and deterministic query signature utilities for cache/attestation workflows. |
|
| Sprint 5 | Excititor Core Foundations | src/StellaOps.Excititor.Core/TASKS.md | DONE (2025-10-15) | Team Excititor Core & Policy | EXCITITOR-CORE-01-003 | Publish shared connector/exporter/attestation abstractions and deterministic query signature utilities for cache/attestation workflows. |
|
||||||
@@ -147,10 +147,10 @@
|
|||||||
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Excititor.Attestation/TASKS.md | DONE (2025-10-16) | Team Excititor Attestation | EXCITITOR-ATTEST-01-002 | Rekor v2 client integration – ship transparency log client with retries and offline queue. |
|
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Excititor.Attestation/TASKS.md | DONE (2025-10-16) | Team Excititor Attestation | EXCITITOR-ATTEST-01-002 | Rekor v2 client integration – ship transparency log client with retries and offline queue. |
|
||||||
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Excititor.Worker/TASKS.md | TODO | Team Excititor Worker | EXCITITOR-WORKER-01-004 | TTL refresh & stability damper – schedule re-resolve loops and guard against status flapping. |
|
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Excititor.Worker/TASKS.md | TODO | Team Excititor Worker | EXCITITOR-WORKER-01-004 | TTL refresh & stability damper – schedule re-resolve loops and guard against status flapping. |
|
||||||
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Excititor.Export/TASKS.md | TODO | Team Excititor Export | EXCITITOR-EXPORT-01-005 | Score & resolve envelope surfaces – include signed consensus/score artifacts in exports. |
|
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Excititor.Export/TASKS.md | TODO | Team Excititor Export | EXCITITOR-EXPORT-01-005 | Score & resolve envelope surfaces – include signed consensus/score artifacts in exports. |
|
||||||
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Feedser.Core/TASKS.md | TODO | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-07-001 | Advisory event log & asOf queries – surface immutable statements and replay capability. |
|
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Concelier.Core/TASKS.md | TODO | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-07-001 | Advisory event log & asOf queries – surface immutable statements and replay capability. |
|
||||||
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Feedser.Core/TASKS.md | TODO | Team Core Engine & Data Science | FEEDCORE-ENGINE-07-002 | Noise prior computation service – learn false-positive priors and expose deterministic summaries. |
|
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Concelier.Core/TASKS.md | TODO | Team Core Engine & Data Science | FEEDCORE-ENGINE-07-002 | Noise prior computation service – learn false-positive priors and expose deterministic summaries. |
|
||||||
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | TODO | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-07-001 | Advisory statement & conflict collections – provision Mongo schema/indexes for event-sourced merge. |
|
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | TODO | Team Normalization & Storage Backbone | FEEDSTORAGE-DATA-07-001 | Advisory statement & conflict collections – provision Mongo schema/indexes for event-sourced merge. |
|
||||||
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Feedser.Merge/TASKS.md | TODO | BE-Merge | FEEDMERGE-ENGINE-07-001 | Conflict sets & explainers – persist conflict materialization and replay hashes for merge decisions. |
|
| Sprint 7 | Contextual Truth Foundations | src/StellaOps.Concelier.Merge/TASKS.md | TODO | BE-Merge | FEEDMERGE-ENGINE-07-001 | Conflict sets & explainers – persist conflict materialization and replay hashes for merge decisions. |
|
||||||
| Sprint 8 | Mongo strengthening | src/StellaOps.Feedser.Storage.Mongo/TASKS.md | TODO | Team Normalization & Storage Backbone | FEEDSTORAGE-MONGO-08-001 | Causal-consistent Feedser storage sessions<br>Ensure `AddMongoStorage` registers a scoped session facilitator (causal consistency + majority concerns), update repositories to accept optional session handles, and add integration coverage proving read-your-write and monotonic reads across a replica set/election scenario. |
|
| Sprint 8 | Mongo strengthening | src/StellaOps.Concelier.Storage.Mongo/TASKS.md | TODO | Team Normalization & Storage Backbone | FEEDSTORAGE-MONGO-08-001 | Causal-consistent Concelier storage sessions<br>Ensure `AddMongoStorage` registers a scoped session facilitator (causal consistency + majority concerns), update repositories to accept optional session handles, and add integration coverage proving read-your-write and monotonic reads across a replica set/election scenario. |
|
||||||
| Sprint 8 | Mongo strengthening | src/StellaOps.Authority/TASKS.md | TODO | Authority Core & Storage Guild | AUTHSTORAGE-MONGO-08-001 | Harden Authority Mongo usage<br>Introduce scoped MongoDB sessions with `writeConcern`/`readConcern` majority defaults, flow the session through stores used in mutations + follow-up reads, and document middleware pattern for web/API & GraphQL layers. |
|
| Sprint 8 | Mongo strengthening | src/StellaOps.Authority/TASKS.md | TODO | Authority Core & Storage Guild | AUTHSTORAGE-MONGO-08-001 | Harden Authority Mongo usage<br>Introduce scoped MongoDB sessions with `writeConcern`/`readConcern` majority defaults, flow the session through stores used in mutations + follow-up reads, and document middleware pattern for web/API & GraphQL layers. |
|
||||||
| Sprint 8 | Mongo strengthening | src/StellaOps.Excititor.Storage.Mongo/TASKS.md | TODO | Team Excititor Storage | EXCITITOR-STORAGE-MONGO-08-001 | Causal consistency for Excititor repositories<br>Register Mongo options with majority defaults, push session-aware overloads through raw/export/consensus/cache stores, and extend migration/tests to validate causal reads after writes (including GridFS-backed content) under replica-set failover. |
|
| Sprint 8 | Mongo strengthening | src/StellaOps.Excititor.Storage.Mongo/TASKS.md | TODO | Team Excititor Storage | EXCITITOR-STORAGE-MONGO-08-001 | Causal consistency for Excititor repositories<br>Register Mongo options with majority defaults, push session-aware overloads through raw/export/consensus/cache stores, and extend migration/tests to validate causal reads after writes (including GridFS-backed content) under replica-set failover. |
|
||||||
|
|||||||
2
TODOS.md
2
TODOS.md
@@ -4,7 +4,7 @@
|
|||||||
|FEEDCONN-CERTCC-02-005 Deterministic fixtures/tests|DONE (2025-10-11)|Snapshot regression for summary/detail fetch landed; fixtures regenerate via `UPDATE_CERTCC_FIXTURES`.|
|
|FEEDCONN-CERTCC-02-005 Deterministic fixtures/tests|DONE (2025-10-11)|Snapshot regression for summary/detail fetch landed; fixtures regenerate via `UPDATE_CERTCC_FIXTURES`.|
|
||||||
|FEEDCONN-CERTCC-02-008 Snapshot coverage handoff|DONE (2025-10-11)|Fixtures + README guidance shipped; QA can rerun with `UPDATE_CERTCC_FIXTURES=1` and share recorded-request diff with Merge.|
|
|FEEDCONN-CERTCC-02-008 Snapshot coverage handoff|DONE (2025-10-11)|Fixtures + README guidance shipped; QA can rerun with `UPDATE_CERTCC_FIXTURES=1` and share recorded-request diff with Merge.|
|
||||||
|FEEDCONN-CERTCC-02-007 Connector test harness remediation|DONE (2025-10-11)|Harness now resets time provider, wires Source.Common, and verifies VINCE canned responses across fetch→parse→map.|
|
|FEEDCONN-CERTCC-02-007 Connector test harness remediation|DONE (2025-10-11)|Harness now resets time provider, wires Source.Common, and verifies VINCE canned responses across fetch→parse→map.|
|
||||||
|FEEDCONN-CERTCC-02-009 Detail/map reintegration plan|DONE (2025-10-11)|Plan published in `src/StellaOps.Feedser.Source.CertCc/FEEDCONN-CERTCC-02-009_PLAN.md`; outlines staged enablement + rollback.|
|
|FEEDCONN-CERTCC-02-009 Detail/map reintegration plan|DONE (2025-10-11)|Plan published in `src/StellaOps.Concelier.Source.CertCc/FEEDCONN-CERTCC-02-009_PLAN.md`; outlines staged enablement + rollback.|
|
||||||
|
|
||||||
# Connector Apple Status
|
# Connector Apple Status
|
||||||
| Task | Status | Notes |
|
| Task | Status | Notes |
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ It **absorbs** all content from `components.md` so you have a single, authoritat
|
|||||||
| **Scanner.Worker** | `stellaops/scanner-worker` | Runs analyzers (OS, Lang: Java/Node/Python/Go/.NET/Rust, Native ELF/PE/Mach‑O, EntryTrace); emits per‑layer SBOMs and composes image SBOMs. | Horizontal; queue‑driven; sharded by layer digest. |
|
| **Scanner.Worker** | `stellaops/scanner-worker` | Runs analyzers (OS, Lang: Java/Node/Python/Go/.NET/Rust, Native ELF/PE/Mach‑O, EntryTrace); emits per‑layer SBOMs and composes image SBOMs. | Horizontal; queue‑driven; sharded by layer digest. |
|
||||||
| **Scanner.Sbomer.BuildXPlugin** | `stellaops/sbom-indexer` | BuildKit **generator** for build‑time SBOMs as OCI **referrers**. | CI‑side; ephemeral. |
|
| **Scanner.Sbomer.BuildXPlugin** | `stellaops/sbom-indexer` | BuildKit **generator** for build‑time SBOMs as OCI **referrers**. | CI‑side; ephemeral. |
|
||||||
| **Scanner.Sbomer.DockerImage** | `stellaops/scanner-cli` | CLI‑orchestrated scanner container for post‑build scans. | Local/CI; ephemeral. |
|
| **Scanner.Sbomer.DockerImage** | `stellaops/scanner-cli` | CLI‑orchestrated scanner container for post‑build scans. | Local/CI; ephemeral. |
|
||||||
| **Feedser.WebService** | `stellaops/feedser-web` | Vulnerability ingest/normalize/merge/export (JSON + Trivy DB). | HA via Mongo locks. |
|
| **Concelier.WebService** | `stellaops/concelier-web` | Vulnerability ingest/normalize/merge/export (JSON + Trivy DB). | HA via Mongo locks. |
|
||||||
| **Excititor.WebService** | `stellaops/excititor-web` | VEX ingest/normalize/consensus; conflict retention; exports. | HA via Mongo locks. |
|
| **Excititor.WebService** | `stellaops/excititor-web` | VEX ingest/normalize/consensus; conflict retention; exports. | HA via Mongo locks. |
|
||||||
| **Policy Engine** | (in `scanner-web`) | YAML DSL evaluator (waivers, vendor preferences, KEV/EPSS, license, usage‑gating); produces **policy digest**. | In‑process; cache per digest. |
|
| **Policy Engine** | (in `scanner-web`) | YAML DSL evaluator (waivers, vendor preferences, KEV/EPSS, license, usage‑gating); produces **policy digest**. | In‑process; cache per digest. |
|
||||||
| **Signer** | `stellaops/signer` | **Hard gate:** validates entitlement + release integrity; mints signing cert (Fulcio keyless) or uses KMS; signs DSSE. | Stateless; HPA by QPS. |
|
| **Signer** | `stellaops/signer` | **Hard gate:** validates entitlement + release integrity; mints signing cert (Fulcio keyless) or uses KMS; signs DSSE. | Stateless; HPA by QPS. |
|
||||||
@@ -71,7 +71,7 @@ flowchart LR
|
|||||||
Auth[Authority (OIDC)\nOpTok (DPoP/mTLS)]
|
Auth[Authority (OIDC)\nOpTok (DPoP/mTLS)]
|
||||||
SW[Scanner.WebService]
|
SW[Scanner.WebService]
|
||||||
WK[Scanner.Worker xN]
|
WK[Scanner.Worker xN]
|
||||||
FEED[Feedser]
|
FEED[Concelier]
|
||||||
VEX[Excititor]
|
VEX[Excititor]
|
||||||
POL[Policy Engine (in Scanner.Web)]
|
POL[Policy Engine (in Scanner.Web)]
|
||||||
SGN[Signer\n(entitlement + signing)]
|
SGN[Signer\n(entitlement + signing)]
|
||||||
@@ -177,7 +177,7 @@ LS --> IA: PoE (mTLS client cert or JWT with cnf=K_inst), CRL/OCSP/introspect
|
|||||||
|
|
||||||
## 4) Backend evaluation (decider)
|
## 4) Backend evaluation (decider)
|
||||||
|
|
||||||
### 4.1 Feedser (advisories)
|
### 4.1 Concelier (advisories)
|
||||||
|
|
||||||
* Ingests vendor, distro, OSS feeds; normalizes & merges; persists canonical advisories in Mongo; exports **deterministic JSON** and **Trivy DB**.
|
* Ingests vendor, distro, OSS feeds; normalizes & merges; persists canonical advisories in Mongo; exports **deterministic JSON** and **Trivy DB**.
|
||||||
* Offline kit bundles for air‑gapped sites.
|
* Offline kit bundles for air‑gapped sites.
|
||||||
@@ -194,7 +194,7 @@ LS --> IA: PoE (mTLS client cert or JWT with cnf=K_inst), CRL/OCSP/introspect
|
|||||||
|
|
||||||
### 4.4 PASS/FAIL flow
|
### 4.4 PASS/FAIL flow
|
||||||
|
|
||||||
1. SBOM (Inventory / Usage) → join with **Feedser** advisories.
|
1. SBOM (Inventory / Usage) → join with **Concelier** advisories.
|
||||||
2. Apply **Excititor** consensus (statuses & justifications).
|
2. Apply **Excititor** consensus (statuses & justifications).
|
||||||
3. Apply **Policy**; compute PASS/FAIL with waiver TTLs.
|
3. Apply **Policy**; compute PASS/FAIL with waiver TTLs.
|
||||||
4. Sign the **final report** (DSSE via **Signer**) and log to **Rekor v2** via **Attestor**.
|
4. Sign the **final report** (DSSE via **Signer**) and log to **Rekor v2** via **Attestor**.
|
||||||
@@ -349,9 +349,9 @@ services:
|
|||||||
image: stellaops/scanner-worker
|
image: stellaops/scanner-worker
|
||||||
deploy: { replicas: 4 }
|
deploy: { replicas: 4 }
|
||||||
depends_on: [scanner-web]
|
depends_on: [scanner-web]
|
||||||
feedser: { image: stellaops/feedser-web, depends_on: [mongo] }
|
concelier: { image: stellaops/concelier-web, depends_on: [mongo] }
|
||||||
excititor: { image: stellaops/excititor-web, depends_on: [mongo] }
|
excititor: { image: stellaops/excititor-web, depends_on: [mongo] }
|
||||||
ui: { image: stellaops/ui, depends_on: [scanner-web, feedser, excititor] }
|
ui: { image: stellaops/ui, depends_on: [scanner-web, concelier, excititor] }
|
||||||
```
|
```
|
||||||
|
|
||||||
* **Backups:** Mongo dumps; MinIO versioned buckets & replication; Rekor v2 DB snapshots; JWKS/Fulcio/KMS key rotation.
|
* **Backups:** Mongo dumps; MinIO versioned buckets & replication; Rekor v2 DB snapshots; JWKS/Fulcio/KMS key rotation.
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ Returns `202 Accepted` and `Location: /attest/{id}` for async verify.
|
|||||||
|
|
||||||
## 3 StellaOps CLI (`stellaops-cli`)
|
## 3 StellaOps CLI (`stellaops-cli`)
|
||||||
|
|
||||||
The new CLI is built on **System.CommandLine 2.0.0‑beta5** and mirrors the Feedser backend REST API.
|
The new CLI is built on **System.CommandLine 2.0.0‑beta5** and mirrors the Concelier backend REST API.
|
||||||
Configuration follows the same precedence chain everywhere:
|
Configuration follows the same precedence chain everywhere:
|
||||||
|
|
||||||
1. Environment variables (e.g. `API_KEY`, `STELLAOPS_BACKEND_URL`, `StellaOps:ApiKey`)
|
1. Environment variables (e.g. `API_KEY`, `STELLAOPS_BACKEND_URL`, `StellaOps:ApiKey`)
|
||||||
@@ -250,7 +250,7 @@ When running on an interactive terminal without explicit override flags, the CLI
|
|||||||
- Downloads are verified against the `X-StellaOps-Digest` header (SHA-256). When `StellaOps:ScannerSignaturePublicKeyPath` points to a PEM-encoded RSA key, the optional `X-StellaOps-Signature` header is validated as well.
|
- Downloads are verified against the `X-StellaOps-Digest` header (SHA-256). When `StellaOps:ScannerSignaturePublicKeyPath` points to a PEM-encoded RSA key, the optional `X-StellaOps-Signature` header is validated as well.
|
||||||
- Metadata for each bundle is written alongside the artefact (`*.metadata.json`) with digest, signature, source URL, and timestamps.
|
- Metadata for each bundle is written alongside the artefact (`*.metadata.json`) with digest, signature, source URL, and timestamps.
|
||||||
- Retry behaviour is controlled via `StellaOps:ScannerDownloadAttempts` (default **3** with exponential backoff).
|
- Retry behaviour is controlled via `StellaOps:ScannerDownloadAttempts` (default **3** with exponential backoff).
|
||||||
- Successful `scan run` executions create timestamped JSON artefacts inside `ResultsDirectory` plus a `scan-run-*.json` metadata envelope documenting the runner, arguments, timing, and stdout/stderr. The artefact is posted back to Feedser automatically.
|
- Successful `scan run` executions create timestamped JSON artefacts inside `ResultsDirectory` plus a `scan-run-*.json` metadata envelope documenting the runner, arguments, timing, and stdout/stderr. The artefact is posted back to Concelier automatically.
|
||||||
|
|
||||||
#### Trivy DB export metadata (`metadata.json`)
|
#### Trivy DB export metadata (`metadata.json`)
|
||||||
|
|
||||||
@@ -265,18 +265,18 @@ When running on an interactive terminal without explicit override flags, the CLI
|
|||||||
| `treeDigest` | string | Canonical SHA-256 digest of the JSON tree used to build the database. |
|
| `treeDigest` | string | Canonical SHA-256 digest of the JSON tree used to build the database. |
|
||||||
| `treeBytes` | number | Total bytes across exported JSON files. |
|
| `treeBytes` | number | Total bytes across exported JSON files. |
|
||||||
| `advisoryCount` | number | Count of advisories included in the export. |
|
| `advisoryCount` | number | Count of advisories included in the export. |
|
||||||
| `exporterVersion` | string | Version stamp of `StellaOps.Feedser.Exporter.TrivyDb`. |
|
| `exporterVersion` | string | Version stamp of `StellaOps.Concelier.Exporter.TrivyDb`. |
|
||||||
| `builder` | object? | Raw metadata emitted by `trivy-db build` (version, update cadence, etc.). |
|
| `builder` | object? | Raw metadata emitted by `trivy-db build` (version, update cadence, etc.). |
|
||||||
| `delta.changedFiles[]` | array | Present when `mode = delta`. Each entry lists `{ "path": "<relative json>", "length": <bytes>, "digest": "sha256:..." }`. |
|
| `delta.changedFiles[]` | array | Present when `mode = delta`. Each entry lists `{ "path": "<relative json>", "length": <bytes>, "digest": "sha256:..." }`. |
|
||||||
| `delta.removedPaths[]` | array | Paths that existed in the previous manifest but were removed in the new run. |
|
| `delta.removedPaths[]` | array | Paths that existed in the previous manifest but were removed in the new run. |
|
||||||
|
|
||||||
When the planner opts for a delta run, the exporter copies unmodified blobs from the baseline layout identified by `baseManifestDigest`. Consumers that cache OCI blobs only need to fetch the `changedFiles` and the new manifest/metadata unless `resetBaseline` is true.
|
When the planner opts for a delta run, the exporter copies unmodified blobs from the baseline layout identified by `baseManifestDigest`. Consumers that cache OCI blobs only need to fetch the `changedFiles` and the new manifest/metadata unless `resetBaseline` is true.
|
||||||
When pushing to ORAS, set `feedser:exporters:trivyDb:oras:publishFull` / `publishDelta` to control whether full or delta runs are copied to the registry. Offline bundles follow the analogous `includeFull` / `includeDelta` switches under `offlineBundle`.
|
When pushing to ORAS, set `concelier:exporters:trivyDb:oras:publishFull` / `publishDelta` to control whether full or delta runs are copied to the registry. Offline bundles follow the analogous `includeFull` / `includeDelta` switches under `offlineBundle`.
|
||||||
|
|
||||||
Example configuration (`appsettings.yaml`):
|
Example configuration (`appsettings.yaml`):
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
exporters:
|
exporters:
|
||||||
trivyDb:
|
trivyDb:
|
||||||
oras:
|
oras:
|
||||||
@@ -293,7 +293,7 @@ feedser:
|
|||||||
**Authentication**
|
**Authentication**
|
||||||
|
|
||||||
- API key is sent as `Authorization: Bearer <token>` automatically when configured.
|
- API key is sent as `Authorization: Bearer <token>` automatically when configured.
|
||||||
- Anonymous operation is permitted only when Feedser runs with
|
- Anonymous operation is permitted only when Concelier runs with
|
||||||
`authority.allowAnonymousFallback: true`. This flag is temporary—plan to disable
|
`authority.allowAnonymousFallback: true`. This flag is temporary—plan to disable
|
||||||
it before **2025-12-31 UTC** so bearer tokens become mandatory.
|
it before **2025-12-31 UTC** so bearer tokens become mandatory.
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ Authority-backed auth workflow:
|
|||||||
3. Execute CLI commands as normal—the backend client injects the cached bearer token automatically and retries on transient 401/403 responses with operator guidance.
|
3. Execute CLI commands as normal—the backend client injects the cached bearer token automatically and retries on transient 401/403 responses with operator guidance.
|
||||||
4. Inspect the cache with `stellaops-cli auth status` (shows expiry, scope, mode) or clear it via `stellaops-cli auth logout`.
|
4. Inspect the cache with `stellaops-cli auth status` (shows expiry, scope, mode) or clear it via `stellaops-cli auth logout`.
|
||||||
5. Run `stellaops-cli auth whoami` to dump token subject, audience, issuer, scopes, and remaining lifetime (verbose mode prints additional claims).
|
5. Run `stellaops-cli auth whoami` to dump token subject, audience, issuer, scopes, and remaining lifetime (verbose mode prints additional claims).
|
||||||
6. Expect Feedser to emit audit logs for each `/jobs*` request showing `subject`,
|
6. Expect Concelier to emit audit logs for each `/jobs*` request showing `subject`,
|
||||||
`clientId`, `scopes`, `status`, and whether network bypass rules were applied.
|
`clientId`, `scopes`, `status`, and whether network bypass rules were applied.
|
||||||
|
|
||||||
Tokens live in `~/.stellaops/tokens` unless `StellaOps:Authority:TokenCacheDirectory` overrides it. Cached tokens are reused offline until they expire; the CLI surfaces clear errors if refresh fails.
|
Tokens live in `~/.stellaops/tokens` unless `StellaOps:Authority:TokenCacheDirectory` overrides it. Cached tokens are reused offline until they expire; the CLI surfaces clear errors if refresh fails.
|
||||||
@@ -314,7 +314,7 @@ Tokens live in `~/.stellaops/tokens` unless `StellaOps:Authority:TokenCacheDirec
|
|||||||
{
|
{
|
||||||
"StellaOps": {
|
"StellaOps": {
|
||||||
"ApiKey": "your-api-token",
|
"ApiKey": "your-api-token",
|
||||||
"BackendUrl": "https://feedser.example.org",
|
"BackendUrl": "https://concelier.example.org",
|
||||||
"ScannerCacheDirectory": "scanners",
|
"ScannerCacheDirectory": "scanners",
|
||||||
"ResultsDirectory": "results",
|
"ResultsDirectory": "results",
|
||||||
"DefaultRunner": "docker",
|
"DefaultRunner": "docker",
|
||||||
@@ -322,11 +322,11 @@ Tokens live in `~/.stellaops/tokens` unless `StellaOps:Authority:TokenCacheDirec
|
|||||||
"ScannerDownloadAttempts": 3,
|
"ScannerDownloadAttempts": 3,
|
||||||
"Authority": {
|
"Authority": {
|
||||||
"Url": "https://authority.example.org",
|
"Url": "https://authority.example.org",
|
||||||
"ClientId": "feedser-cli",
|
"ClientId": "concelier-cli",
|
||||||
"ClientSecret": "REDACTED",
|
"ClientSecret": "REDACTED",
|
||||||
"Username": "",
|
"Username": "",
|
||||||
"Password": "",
|
"Password": "",
|
||||||
"Scope": "feedser.jobs.trigger",
|
"Scope": "concelier.jobs.trigger",
|
||||||
"TokenCacheDirectory": ""
|
"TokenCacheDirectory": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 10 · Feedser + CLI Quickstart
|
# 10 · Concelier + CLI Quickstart
|
||||||
|
|
||||||
This guide walks through configuring the Feedser web service and the `stellaops-cli`
|
This guide walks through configuring the Concelier web service and the `stellaops-cli`
|
||||||
tool so an operator can ingest advisories, merge them, and publish exports from a
|
tool so an operator can ingest advisories, merge them, and publish exports from a
|
||||||
single workstation. It focuses on deployment-facing surfaces only (configuration,
|
single workstation. It focuses on deployment-facing surfaces only (configuration,
|
||||||
runtime wiring, CLI usage) and leaves connector/internal customization for later.
|
runtime wiring, CLI usage) and leaves connector/internal customization for later.
|
||||||
@@ -16,39 +16,39 @@ runtime wiring, CLI usage) and leaves connector/internal customization for later
|
|||||||
- Optional: Docker/Podman runtime if you plan to run scanners locally
|
- Optional: Docker/Podman runtime if you plan to run scanners locally
|
||||||
|
|
||||||
> **Tip** – air-gapped installs should preload `trivy-db` and `oras` binaries into the
|
> **Tip** – air-gapped installs should preload `trivy-db` and `oras` binaries into the
|
||||||
> runner image since Feedser never fetches them dynamically.
|
> runner image since Concelier never fetches them dynamically.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1 · Configure Feedser
|
## 1 · Configure Concelier
|
||||||
|
|
||||||
1. Copy the sample config to the expected location (CI/CD pipelines can stamp values
|
1. Copy the sample config to the expected location (CI/CD pipelines can stamp values
|
||||||
into this file during deployment—see the “Deployment automation” note below):
|
into this file during deployment—see the “Deployment automation” note below):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p etc
|
mkdir -p etc
|
||||||
cp etc/feedser.yaml.sample etc/feedser.yaml
|
cp etc/concelier.yaml.sample etc/concelier.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Edit `etc/feedser.yaml` and update the MongoDB DSN (and optional database name).
|
2. Edit `etc/concelier.yaml` and update the MongoDB DSN (and optional database name).
|
||||||
The default template configures plug-in discovery to look in `PluginBinaries/`
|
The default template configures plug-in discovery to look in `PluginBinaries/`
|
||||||
and disables remote telemetry exporters by default.
|
and disables remote telemetry exporters by default.
|
||||||
|
|
||||||
3. (Optional) Override settings via environment variables. All keys are prefixed with
|
3. (Optional) Override settings via environment variables. All keys are prefixed with
|
||||||
`FEEDSER_`. Example:
|
`CONCELIER_`. Example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export FEEDSER_STORAGE__DSN="mongodb://user:pass@mongo:27017/feedser"
|
export CONCELIER_STORAGE__DSN="mongodb://user:pass@mongo:27017/concelier"
|
||||||
export FEEDSER_TELEMETRY__ENABLETRACING=false
|
export CONCELIER_TELEMETRY__ENABLETRACING=false
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Start the web service from the repository root:
|
4. Start the web service from the repository root:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dotnet run --project src/StellaOps.Feedser.WebService
|
dotnet run --project src/StellaOps.Concelier.WebService
|
||||||
```
|
```
|
||||||
|
|
||||||
On startup Feedser validates the options, boots MongoDB indexes, loads plug-ins,
|
On startup Concelier validates the options, boots MongoDB indexes, loads plug-ins,
|
||||||
and exposes:
|
and exposes:
|
||||||
|
|
||||||
- `GET /health` – returns service status and telemetry settings
|
- `GET /health` – returns service status and telemetry settings
|
||||||
@@ -90,7 +90,7 @@ defaults live in `src/StellaOps.Cli/appsettings.json` and expect overrides at ru
|
|||||||
|
|
||||||
| Setting | Environment variable | Default | Purpose |
|
| Setting | Environment variable | Default | Purpose |
|
||||||
| ------- | -------------------- | ------- | ------- |
|
| ------- | -------------------- | ------- | ------- |
|
||||||
| `BackendUrl` | `STELLAOPS_BACKEND_URL` | _empty_ | Base URL of the Feedser web service |
|
| `BackendUrl` | `STELLAOPS_BACKEND_URL` | _empty_ | Base URL of the Concelier web service |
|
||||||
| `ApiKey` | `API_KEY` | _empty_ | Reserved for legacy key auth; leave empty when using Authority |
|
| `ApiKey` | `API_KEY` | _empty_ | Reserved for legacy key auth; leave empty when using Authority |
|
||||||
| `ScannerCacheDirectory` | `STELLAOPS_SCANNER_CACHE_DIRECTORY` | `scanners` | Local cache folder |
|
| `ScannerCacheDirectory` | `STELLAOPS_SCANNER_CACHE_DIRECTORY` | `scanners` | Local cache folder |
|
||||||
| `ResultsDirectory` | `STELLAOPS_RESULTS_DIRECTORY` | `results` | Where scan outputs are written |
|
| `ResultsDirectory` | `STELLAOPS_RESULTS_DIRECTORY` | `results` | Where scan outputs are written |
|
||||||
@@ -99,7 +99,7 @@ defaults live in `src/StellaOps.Cli/appsettings.json` and expect overrides at ru
|
|||||||
| `Authority.ClientSecret` | `STELLAOPS_AUTHORITY_CLIENT_SECRET` | _empty_ | Client secret (omit when using username/password grant) |
|
| `Authority.ClientSecret` | `STELLAOPS_AUTHORITY_CLIENT_SECRET` | _empty_ | Client secret (omit when using username/password grant) |
|
||||||
| `Authority.Username` | `STELLAOPS_AUTHORITY_USERNAME` | _empty_ | Username for password grant flows |
|
| `Authority.Username` | `STELLAOPS_AUTHORITY_USERNAME` | _empty_ | Username for password grant flows |
|
||||||
| `Authority.Password` | `STELLAOPS_AUTHORITY_PASSWORD` | _empty_ | Password for password grant flows |
|
| `Authority.Password` | `STELLAOPS_AUTHORITY_PASSWORD` | _empty_ | Password for password grant flows |
|
||||||
| `Authority.Scope` | `STELLAOPS_AUTHORITY_SCOPE` | `feedser.jobs.trigger` | OAuth scope requested for backend operations |
|
| `Authority.Scope` | `STELLAOPS_AUTHORITY_SCOPE` | `concelier.jobs.trigger` | OAuth scope requested for backend operations |
|
||||||
| `Authority.TokenCacheDirectory` | `STELLAOPS_AUTHORITY_TOKEN_CACHE_DIR` | `~/.stellaops/tokens` | Directory that persists cached tokens |
|
| `Authority.TokenCacheDirectory` | `STELLAOPS_AUTHORITY_TOKEN_CACHE_DIR` | `~/.stellaops/tokens` | Directory that persists cached tokens |
|
||||||
| `Authority.Resilience.EnableRetries` | `STELLAOPS_AUTHORITY_ENABLE_RETRIES` | `true` | Toggle Polly retry handler for Authority HTTP calls |
|
| `Authority.Resilience.EnableRetries` | `STELLAOPS_AUTHORITY_ENABLE_RETRIES` | `true` | Toggle Polly retry handler for Authority HTTP calls |
|
||||||
| `Authority.Resilience.RetryDelays` | `STELLAOPS_AUTHORITY_RETRY_DELAYS` | `1s,2s,5s` | Comma- or space-separated backoff delays (hh:mm:ss) |
|
| `Authority.Resilience.RetryDelays` | `STELLAOPS_AUTHORITY_RETRY_DELAYS` | `1s,2s,5s` | Comma- or space-separated backoff delays (hh:mm:ss) |
|
||||||
@@ -112,7 +112,7 @@ Example bootstrap:
|
|||||||
export STELLAOPS_BACKEND_URL="http://localhost:5000"
|
export STELLAOPS_BACKEND_URL="http://localhost:5000"
|
||||||
export STELLAOPS_RESULTS_DIRECTORY="$HOME/.stellaops/results"
|
export STELLAOPS_RESULTS_DIRECTORY="$HOME/.stellaops/results"
|
||||||
export STELLAOPS_AUTHORITY_URL="https://authority.local"
|
export STELLAOPS_AUTHORITY_URL="https://authority.local"
|
||||||
export STELLAOPS_AUTHORITY_CLIENT_ID="feedser-cli"
|
export STELLAOPS_AUTHORITY_CLIENT_ID="concelier-cli"
|
||||||
export STELLAOPS_AUTHORITY_CLIENT_SECRET="s3cr3t"
|
export STELLAOPS_AUTHORITY_CLIENT_SECRET="s3cr3t"
|
||||||
dotnet run --project src/StellaOps.Cli -- db merge
|
dotnet run --project src/StellaOps.Cli -- db merge
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ rely on environment variables for ephemeral runners.
|
|||||||
dotnet run --project src/StellaOps.Cli -- db export --format trivy-db --delta
|
dotnet run --project src/StellaOps.Cli -- db export --format trivy-db --delta
|
||||||
```
|
```
|
||||||
|
|
||||||
Feedser always produces a deterministic OCI layout. The first run after a clean
|
Concelier always produces a deterministic OCI layout. The first run after a clean
|
||||||
bootstrap emits a **full** baseline; subsequent `--delta` runs reuse the previous
|
bootstrap emits a **full** baseline; subsequent `--delta` runs reuse the previous
|
||||||
baseline’s blobs when only JSON manifests change. If the exporter detects that a
|
baseline’s blobs when only JSON manifests change. If the exporter detects that a
|
||||||
prior delta is still active (i.e., `LastDeltaDigest` is recorded) it automatically
|
prior delta is still active (i.e., `LastDeltaDigest` is recorded) it automatically
|
||||||
@@ -175,7 +175,7 @@ rely on environment variables for ephemeral runners.
|
|||||||
while reusing the previous layer blob.
|
while reusing the previous layer blob.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export_root=${FEEDSER_EXPORT_ROOT:-exports/trivy}
|
export_root=${CONCELIER_EXPORT_ROOT:-exports/trivy}
|
||||||
base=$(ls -1d "$export_root"/* | sort | tail -n2 | head -n1)
|
base=$(ls -1d "$export_root"/* | sort | tail -n2 | head -n1)
|
||||||
delta=$(ls -1d "$export_root"/* | sort | tail -n1)
|
delta=$(ls -1d "$export_root"/* | sort | tail -n1)
|
||||||
|
|
||||||
@@ -209,10 +209,10 @@ a problem document.
|
|||||||
|
|
||||||
## 4 · Verification Checklist
|
## 4 · Verification Checklist
|
||||||
|
|
||||||
- Feedser `/health` returns `"status":"healthy"` and Storage bootstrap is marked
|
- Concelier `/health` returns `"status":"healthy"` and Storage bootstrap is marked
|
||||||
complete after startup.
|
complete after startup.
|
||||||
- CLI commands return HTTP 202 with a `Location` header (job tracking URL) when
|
- CLI commands return HTTP 202 with a `Location` header (job tracking URL) when
|
||||||
triggering Feedser jobs.
|
triggering Concelier jobs.
|
||||||
- Export artefacts are materialised under the configured output directories and
|
- Export artefacts are materialised under the configured output directories and
|
||||||
their manifests record digests.
|
their manifests record digests.
|
||||||
- MongoDB contains the expected `document`, `dto`, `advisory`, and `export_state`
|
- MongoDB contains the expected `document`, `dto`, `advisory`, and `export_state`
|
||||||
@@ -222,7 +222,7 @@ a problem document.
|
|||||||
|
|
||||||
## 5 · Deployment Automation
|
## 5 · Deployment Automation
|
||||||
|
|
||||||
- Treat `etc/feedser.yaml.sample` as the canonical template. CI/CD should copy it to
|
- Treat `etc/concelier.yaml.sample` as the canonical template. CI/CD should copy it to
|
||||||
the deployment artifact and replace placeholders (DSN, telemetry endpoints, cron
|
the deployment artifact and replace placeholders (DSN, telemetry endpoints, cron
|
||||||
overrides) with environment-specific secrets.
|
overrides) with environment-specific secrets.
|
||||||
- Keep secret material (Mongo credentials, OTLP tokens) outside of the repository;
|
- Keep secret material (Mongo credentials, OTLP tokens) outside of the repository;
|
||||||
@@ -238,15 +238,15 @@ a problem document.
|
|||||||
`authority.enabled: true` while keeping `authority.allowAnonymousFallback: true`
|
`authority.enabled: true` while keeping `authority.allowAnonymousFallback: true`
|
||||||
to observe logs, then flip it to `false` before 2025-12-31 UTC to enforce tokens.
|
to observe logs, then flip it to `false` before 2025-12-31 UTC to enforce tokens.
|
||||||
- Automate the workflow above via CI/CD (compose stack or Kubernetes CronJobs).
|
- Automate the workflow above via CI/CD (compose stack or Kubernetes CronJobs).
|
||||||
- Pair with the Feedser connector teams when enabling additional sources so their
|
- Pair with the Concelier connector teams when enabling additional sources so their
|
||||||
module-specific requirements are pulled in safely.
|
module-specific requirements are pulled in safely.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6 · Authority Integration
|
## 6 · Authority Integration
|
||||||
|
|
||||||
- Feedser now authenticates callers through StellaOps Authority using OAuth 2.0
|
- Concelier now authenticates callers through StellaOps Authority using OAuth 2.0
|
||||||
resource server flows. Populate the `authority` block in `feedser.yaml`:
|
resource server flows. Populate the `authority` block in `concelier.yaml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
authority:
|
authority:
|
||||||
@@ -254,20 +254,20 @@ a problem document.
|
|||||||
allowAnonymousFallback: false # keep true only during the staged rollout window
|
allowAnonymousFallback: false # keep true only during the staged rollout window
|
||||||
issuer: "https://authority.example.org"
|
issuer: "https://authority.example.org"
|
||||||
audiences:
|
audiences:
|
||||||
- "api://feedser"
|
- "api://concelier"
|
||||||
requiredScopes:
|
requiredScopes:
|
||||||
- "feedser.jobs.trigger"
|
- "concelier.jobs.trigger"
|
||||||
clientId: "feedser-jobs"
|
clientId: "concelier-jobs"
|
||||||
clientSecretFile: "../secrets/feedser-jobs.secret"
|
clientSecretFile: "../secrets/concelier-jobs.secret"
|
||||||
clientScopes:
|
clientScopes:
|
||||||
- "feedser.jobs.trigger"
|
- "concelier.jobs.trigger"
|
||||||
bypassNetworks:
|
bypassNetworks:
|
||||||
- "127.0.0.1/32"
|
- "127.0.0.1/32"
|
||||||
- "::1/128"
|
- "::1/128"
|
||||||
```
|
```
|
||||||
|
|
||||||
- Store the client secret outside of source control. Either provide it via
|
- Store the client secret outside of source control. Either provide it via
|
||||||
`authority.clientSecret` (environment variable `FEEDSER_AUTHORITY__CLIENTSECRET`)
|
`authority.clientSecret` (environment variable `CONCELIER_AUTHORITY__CLIENTSECRET`)
|
||||||
or point `authority.clientSecretFile` to a file mounted at runtime.
|
or point `authority.clientSecretFile` to a file mounted at runtime.
|
||||||
- Cron jobs running on the same host can keep using the API thanks to the loopback
|
- Cron jobs running on the same host can keep using the API thanks to the loopback
|
||||||
bypass mask. Add additional CIDR ranges as needed; every bypass is logged.
|
bypass mask. Add additional CIDR ranges as needed; every bypass is logged.
|
||||||
@@ -275,15 +275,15 @@ a problem document.
|
|||||||
variables such as:
|
variables such as:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export FEEDSER_AUTHORITY__ENABLED=true
|
export CONCELIER_AUTHORITY__ENABLED=true
|
||||||
export FEEDSER_AUTHORITY__ALLOWANONYMOUSFALLBACK=false
|
export CONCELIER_AUTHORITY__ALLOWANONYMOUSFALLBACK=false
|
||||||
export FEEDSER_AUTHORITY__ISSUER="https://authority.example.org"
|
export CONCELIER_AUTHORITY__ISSUER="https://authority.example.org"
|
||||||
export FEEDSER_AUTHORITY__CLIENTID="feedser-jobs"
|
export CONCELIER_AUTHORITY__CLIENTID="concelier-jobs"
|
||||||
export FEEDSER_AUTHORITY__CLIENTSECRETFILE="/var/run/secrets/feedser/authority-client"
|
export CONCELIER_AUTHORITY__CLIENTSECRETFILE="/var/run/secrets/concelier/authority-client"
|
||||||
```
|
```
|
||||||
|
|
||||||
- CLI commands already pass `Authorization` headers when credentials are supplied.
|
- CLI commands already pass `Authorization` headers when credentials are supplied.
|
||||||
Configure the CLI with matching Authority settings (`docs/09_API_CLI_REFERENCE.md`)
|
Configure the CLI with matching Authority settings (`docs/09_API_CLI_REFERENCE.md`)
|
||||||
so that automation can obtain tokens with the same client credentials. Feedser
|
so that automation can obtain tokens with the same client credentials. Concelier
|
||||||
logs every job request with the client ID, subject (if present), scopes, and
|
logs every job request with the client ID, subject (if present), scopes, and
|
||||||
a `bypass` flag so operators can audit cron traffic.
|
a `bypass` flag so operators can audit cron traffic.
|
||||||
@@ -3,14 +3,14 @@
|
|||||||
> **Status:** Drafted 2025-10-12 (CORE5B.DOC / DOC1.AUTH) – aligns with Authority revocation store, JWKS rotation, and bootstrap endpoints delivered in Sprint 1.
|
> **Status:** Drafted 2025-10-12 (CORE5B.DOC / DOC1.AUTH) – aligns with Authority revocation store, JWKS rotation, and bootstrap endpoints delivered in Sprint 1.
|
||||||
|
|
||||||
## 1. Purpose
|
## 1. Purpose
|
||||||
The **StellaOps Authority** service issues OAuth2/OIDC tokens for every StellaOps module (Feedser, Backend, Agent, Zastava) and exposes the policy controls required in sovereign/offline environments. Authority is built as a minimal ASP.NET host that:
|
The **StellaOps Authority** service issues OAuth2/OIDC tokens for every StellaOps module (Concelier, Backend, Agent, Zastava) and exposes the policy controls required in sovereign/offline environments. Authority is built as a minimal ASP.NET host that:
|
||||||
|
|
||||||
- brokers password, client-credentials, and device-code flows through pluggable identity providers;
|
- brokers password, client-credentials, and device-code flows through pluggable identity providers;
|
||||||
- persists access/refresh/device tokens in MongoDB with deterministic schemas for replay analysis and air-gapped audit copies;
|
- persists access/refresh/device tokens in MongoDB with deterministic schemas for replay analysis and air-gapped audit copies;
|
||||||
- distributes revocation bundles and JWKS material so downstream services can enforce lockouts without direct database access;
|
- distributes revocation bundles and JWKS material so downstream services can enforce lockouts without direct database access;
|
||||||
- offers bootstrap APIs for first-run provisioning and key rotation without redeploying binaries.
|
- offers bootstrap APIs for first-run provisioning and key rotation without redeploying binaries.
|
||||||
|
|
||||||
Authority is deployed alongside Feedser in air-gapped environments and never requires outbound internet access. All trusted metadata (OpenIddict discovery, JWKS, revocation bundles) is cacheable, signed, and reproducible.
|
Authority is deployed alongside Concelier in air-gapped environments and never requires outbound internet access. All trusted metadata (OpenIddict discovery, JWKS, revocation bundles) is cacheable, signed, and reproducible.
|
||||||
|
|
||||||
## 2. Component Architecture
|
## 2. Component Architecture
|
||||||
Authority is composed of five cooperating subsystems:
|
Authority is composed of five cooperating subsystems:
|
||||||
@@ -46,7 +46,7 @@ Authority persists every issued token in MongoDB so operators can audit or revok
|
|||||||
- **Expiry maintenance:** `AuthorityTokenStore.DeleteExpiredAsync` prunes non-revoked tokens past their `expiresAt` timestamp. Operators should schedule this in maintenance windows if large volumes of tokens are issued.
|
- **Expiry maintenance:** `AuthorityTokenStore.DeleteExpiredAsync` prunes non-revoked tokens past their `expiresAt` timestamp. Operators should schedule this in maintenance windows if large volumes of tokens are issued.
|
||||||
|
|
||||||
### Expectations for resource servers
|
### Expectations for resource servers
|
||||||
Resource servers (Feedser WebService, Backend, Agent) **must not** assume in-memory caches are authoritative. They should:
|
Resource servers (Concelier WebService, Backend, Agent) **must not** assume in-memory caches are authoritative. They should:
|
||||||
|
|
||||||
- cache `/jwks` and `/revocations/export` responses within configured lifetimes;
|
- cache `/jwks` and `/revocations/export` responses within configured lifetimes;
|
||||||
- honour `revokedReason` metadata when shaping audit trails;
|
- honour `revokedReason` metadata when shaping audit trails;
|
||||||
@@ -73,7 +73,7 @@ Authority centralises revocation in `authority_revocations` with deterministic c
|
|||||||
|
|
||||||
**Consumer guidance:**
|
**Consumer guidance:**
|
||||||
|
|
||||||
1. Mirror `revocation-bundle.json*` alongside Feedser exports. Offline agents fetch both over the existing update channel.
|
1. Mirror `revocation-bundle.json*` alongside Concelier exports. Offline agents fetch both over the existing update channel.
|
||||||
2. Use bundle `sequence` and `bundleId` to detect replay or monotonicity regressions. Ignore bundles with older sequence numbers unless `bundleId` changes and `issuedAt` advances.
|
2. Use bundle `sequence` and `bundleId` to detect replay or monotonicity regressions. Ignore bundles with older sequence numbers unless `bundleId` changes and `issuedAt` advances.
|
||||||
3. Treat `revokedReason` taxonomy as machine-friendly codes (`compromised`, `rotation`, `policy`, `lifecycle`). Translating to human-readable logs is the consumer’s responsibility.
|
3. Treat `revokedReason` taxonomy as machine-friendly codes (`compromised`, `rotation`, `policy`, `lifecycle`). Translating to human-readable logs is the consumer’s responsibility.
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ All administrative calls emit `AuthEventRecord` entries enriched with correlatio
|
|||||||
|
|
||||||
## 9. Operational Checklist
|
## 9. Operational Checklist
|
||||||
- [ ] Protect the bootstrap API key and disable bootstrap endpoints (`bootstrap.enabled: false`) once initial setup is complete.
|
- [ ] Protect the bootstrap API key and disable bootstrap endpoints (`bootstrap.enabled: false`) once initial setup is complete.
|
||||||
- [ ] Schedule `stella auth revoke export` (or `/internal/revocations/export`) at the same cadence as Feedser exports so bundles remain in lockstep.
|
- [ ] Schedule `stella auth revoke export` (or `/internal/revocations/export`) at the same cadence as Concelier exports so bundles remain in lockstep.
|
||||||
- [ ] Rotate signing keys before expiration; keep at least one retired key until all cached bundles/tokens signed with it have expired.
|
- [ ] Rotate signing keys before expiration; keep at least one retired key until all cached bundles/tokens signed with it have expired.
|
||||||
- [ ] Monitor `/health` and `/ready` plus rate-limiter metrics to detect plugin outages early.
|
- [ ] Monitor `/health` and `/ready` plus rate-limiter metrics to detect plugin outages early.
|
||||||
- [ ] Ensure downstream services cache JWKS and revocation bundles within tolerances; stale caches risk accepting revoked tokens.
|
- [ ] Ensure downstream services cache JWKS and revocation bundles within tolerances; stale caches risk accepting revoked tokens.
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ cosign verify \
|
|||||||
|
|
||||||
## 5 · Private‑feed mirrors 🌐
|
## 5 · Private‑feed mirrors 🌐
|
||||||
|
|
||||||
The **Feedser (vulnerability ingest/merge/export service)** provides signed JSON and Trivy DB snapshots that merge:
|
The **Concelier (vulnerability ingest/merge/export service)** provides signed JSON and Trivy DB snapshots that merge:
|
||||||
|
|
||||||
* OSV + GHSA
|
* OSV + GHSA
|
||||||
* (optional) NVD 2.0, CNNVD, CNVD, ENISA, JVN and BDU regionals
|
* (optional) NVD 2.0, CNNVD, CNVD, ENISA, JVN and BDU regionals
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ open a PR and append it alphabetically.*
|
|||||||
| **ADR** | *Architecture Decision Record* – lightweight Markdown file that captures one irreversible design decision. | ADR template lives at `/docs/adr/` |
|
| **ADR** | *Architecture Decision Record* – lightweight Markdown file that captures one irreversible design decision. | ADR template lives at `/docs/adr/` |
|
||||||
| **AIRE** | *AI Risk Evaluator* – optional Plus/Pro plug‑in that suggests mute rules using an ONNX model. | Commercial feature |
|
| **AIRE** | *AI Risk Evaluator* – optional Plus/Pro plug‑in that suggests mute rules using an ONNX model. | Commercial feature |
|
||||||
| **Azure‑Pipelines** | CI/CD service in Microsoft Azure DevOps. | Recipe in Pipeline Library |
|
| **Azure‑Pipelines** | CI/CD service in Microsoft Azure DevOps. | Recipe in Pipeline Library |
|
||||||
| **BDU** | Russian (FSTEC) national vulnerability database: *База данных уязвимостей*. | Merged with NVD by Feedser (vulnerability ingest/merge/export service) |
|
| **BDU** | Russian (FSTEC) national vulnerability database: *База данных уязвимостей*. | Merged with NVD by Concelier (vulnerability ingest/merge/export service) |
|
||||||
| **BuildKit** | Modern Docker build engine with caching and concurrency. | Needed for layer cache patterns |
|
| **BuildKit** | Modern Docker build engine with caching and concurrency. | Needed for layer cache patterns |
|
||||||
| **CI** | *Continuous Integration* – automated build/test pipeline. | Stella integrates via CLI |
|
| **CI** | *Continuous Integration* – automated build/test pipeline. | Stella integrates via CLI |
|
||||||
| **Cosign** | Open‑source Sigstore tool that signs & verifies container images **and files**. | Images & OUK tarballs |
|
| **Cosign** | Open‑source Sigstore tool that signs & verifies container images **and files**. | Images & OUK tarballs |
|
||||||
@@ -36,7 +36,7 @@ open a PR and append it alphabetically.*
|
|||||||
| **Digest (image)** | SHA‑256 hash uniquely identifying a container image or layer. | Pin digests for reproducible builds |
|
| **Digest (image)** | SHA‑256 hash uniquely identifying a container image or layer. | Pin digests for reproducible builds |
|
||||||
| **Docker‑in‑Docker (DinD)** | Running Docker daemon inside a CI container. | Used in GitHub / GitLab recipes |
|
| **Docker‑in‑Docker (DinD)** | Running Docker daemon inside a CI container. | Used in GitHub / GitLab recipes |
|
||||||
| **DTO** | *Data Transfer Object* – C# record serialised to JSON. | Schemas in doc 11 |
|
| **DTO** | *Data Transfer Object* – C# record serialised to JSON. | Schemas in doc 11 |
|
||||||
| **Feedser** | Vulnerability ingest/merge/export service consolidating OVN, GHSA, NVD 2.0, CNNVD, CNVD, ENISA, JVN and BDU feeds into the canonical MongoDB store and export artifacts. | Cron default `0 1 * * *` |
|
| **Concelier** | Vulnerability ingest/merge/export service consolidating OVN, GHSA, NVD 2.0, CNNVD, CNVD, ENISA, JVN and BDU feeds into the canonical MongoDB store and export artifacts. | Cron default `0 1 * * *` |
|
||||||
| **FSTEC** | Russian regulator issuing SOBIT certificates. | Pro GA target |
|
| **FSTEC** | Russian regulator issuing SOBIT certificates. | Pro GA target |
|
||||||
| **Gitea** | Self‑hosted Git service – mirrors GitHub repo. | OSS hosting |
|
| **Gitea** | Self‑hosted Git service – mirrors GitHub repo. | OSS hosting |
|
||||||
| **GOST TLS** | TLS cipher‑suites defined by Russian GOST R 34.10‑2012 / 34.11‑2012. | Provided by `OpenSslGost` or CryptoPro |
|
| **GOST TLS** | TLS cipher‑suites defined by Russian GOST R 34.10‑2012 / 34.11‑2012. | Provided by `OpenSslGost` or CryptoPro |
|
||||||
|
|||||||
@@ -145,28 +145,28 @@ cosign verify ghcr.io/stellaops/backend@sha256:<DIGEST> \
|
|||||||
| Audit events | Redis stream audit; export daily to SIEM |
|
| Audit events | Redis stream audit; export daily to SIEM |
|
||||||
| Alert rules | Feed age ≥ 48 h, P95 wall‑time > 5 s, Redis used memory > 75 % |
|
| Alert rules | Feed age ≥ 48 h, P95 wall‑time > 5 s, Redis used memory > 75 % |
|
||||||
|
|
||||||
### 7.1 Feedser authorization audits
|
### 7.1 Concelier authorization audits
|
||||||
|
|
||||||
- Enable the Authority integration for Feedser (`authority.enabled=true`). Keep
|
- Enable the Authority integration for Concelier (`authority.enabled=true`). Keep
|
||||||
`authority.allowAnonymousFallback` set to `true` only during migration and plan
|
`authority.allowAnonymousFallback` set to `true` only during migration and plan
|
||||||
to disable it before **2025-12-31 UTC** so the `/jobs*` surface always demands
|
to disable it before **2025-12-31 UTC** so the `/jobs*` surface always demands
|
||||||
a bearer token.
|
a bearer token.
|
||||||
- Store the Authority client secret using Docker/Kubernetes secrets and point
|
- Store the Authority client secret using Docker/Kubernetes secrets and point
|
||||||
`authority.clientSecretFile` at the mounted path; the value is read at startup
|
`authority.clientSecretFile` at the mounted path; the value is read at startup
|
||||||
and never logged.
|
and never logged.
|
||||||
- Watch the `Feedser.Authorization.Audit` logger. Each entry contains the HTTP
|
- Watch the `Concelier.Authorization.Audit` logger. Each entry contains the HTTP
|
||||||
status, subject, client ID, scopes, remote IP, and a boolean `bypass` flag
|
status, subject, client ID, scopes, remote IP, and a boolean `bypass` flag
|
||||||
showing whether a network bypass CIDR allowed the request. Configure your SIEM
|
showing whether a network bypass CIDR allowed the request. Configure your SIEM
|
||||||
to alert when unauthenticated requests (`status=401`) appear with
|
to alert when unauthenticated requests (`status=401`) appear with
|
||||||
`bypass=true`, or when unexpected scopes invoke job triggers.
|
`bypass=true`, or when unexpected scopes invoke job triggers.
|
||||||
Detailed monitoring and response guidance lives in `docs/ops/feedser-authority-audit-runbook.md`.
|
Detailed monitoring and response guidance lives in `docs/ops/concelier-authority-audit-runbook.md`.
|
||||||
|
|
||||||
## 8 Update & patch strategy
|
## 8 Update & patch strategy
|
||||||
|
|
||||||
| Layer | Cadence | Method |
|
| Layer | Cadence | Method |
|
||||||
| -------------------- | -------------------------------------------------------- | ------------------------------ |
|
| -------------------- | -------------------------------------------------------- | ------------------------------ |
|
||||||
| Backend & CLI images | Monthly or CVE‑driven docker pull + docker compose up -d |
|
| Backend & CLI images | Monthly or CVE‑driven docker pull + docker compose up -d |
|
||||||
| Trivy DB | 24 h scheduler via Feedser (vulnerability ingest/merge/export service) | configurable via Feedser scheduler options |
|
| Trivy DB | 24 h scheduler via Concelier (vulnerability ingest/merge/export service) | configurable via Concelier scheduler options |
|
||||||
| Docker Engine | vendor LTS | distro package manager |
|
| Docker Engine | vendor LTS | distro package manager |
|
||||||
| Host OS | security repos enabled | unattended‑upgrades |
|
| Host OS | security repos enabled | unattended‑upgrades |
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ contributors who need to extend coverage or diagnose failures.
|
|||||||
| **1. Unit** | `xUnit` (<code>dotnet test</code>) | `*.Tests.csproj` | per PR / push |
|
| **1. Unit** | `xUnit` (<code>dotnet test</code>) | `*.Tests.csproj` | per PR / push |
|
||||||
| **2. Property‑based** | `FsCheck` | `SbomPropertyTests` | per PR |
|
| **2. Property‑based** | `FsCheck` | `SbomPropertyTests` | per PR |
|
||||||
| **3. Integration (API)** | `Testcontainers` suite | `test/Api.Integration` | per PR + nightly |
|
| **3. Integration (API)** | `Testcontainers` suite | `test/Api.Integration` | per PR + nightly |
|
||||||
| **4. Integration (DB-merge)** | in-memory Mongo + Redis | `Feedser.Integration` (vulnerability ingest/merge/export service) | per PR |
|
| **4. Integration (DB-merge)** | in-memory Mongo + Redis | `Concelier.Integration` (vulnerability ingest/merge/export service) | per PR |
|
||||||
| **5. Contract (gRPC)** | `Buf breaking` | `buf.yaml` files | per PR |
|
| **5. Contract (gRPC)** | `Buf breaking` | `buf.yaml` files | per PR |
|
||||||
| **6. Front‑end unit** | `Jest` | `ui/src/**/*.spec.ts` | per PR |
|
| **6. Front‑end unit** | `Jest` | `ui/src/**/*.spec.ts` | per PR |
|
||||||
| **7. Front‑end E2E** | `Playwright` | `ui/e2e/**` | nightly |
|
| **7. Front‑end E2E** | `Playwright` | `ui/e2e/**` | nightly |
|
||||||
@@ -59,17 +59,17 @@ The script spins up MongoDB/Redis via Testcontainers and requires:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Feedser OSV↔GHSA parity fixtures
|
### Concelier OSV↔GHSA parity fixtures
|
||||||
|
|
||||||
The Feedser connector suite includes a regression test (`OsvGhsaParityRegressionTests`)
|
The Concelier connector suite includes a regression test (`OsvGhsaParityRegressionTests`)
|
||||||
that checks a curated set of GHSA identifiers against OSV responses. The fixture
|
that checks a curated set of GHSA identifiers against OSV responses. The fixture
|
||||||
snapshots live in `src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/` and are kept
|
snapshots live in `src/StellaOps.Concelier.Source.Osv.Tests/Fixtures/` and are kept
|
||||||
deterministic so the parity report remains reproducible.
|
deterministic so the parity report remains reproducible.
|
||||||
|
|
||||||
To refresh the fixtures when GHSA/OSV payloads change:
|
To refresh the fixtures when GHSA/OSV payloads change:
|
||||||
|
|
||||||
1. Ensure outbound HTTPS access to `https://api.osv.dev` and `https://api.github.com`.
|
1. Ensure outbound HTTPS access to `https://api.osv.dev` and `https://api.github.com`.
|
||||||
2. Run `UPDATE_PARITY_FIXTURES=1 dotnet test src/StellaOps.Feedser.Source.Osv.Tests/StellaOps.Feedser.Source.Osv.Tests.csproj`.
|
2. Run `UPDATE_PARITY_FIXTURES=1 dotnet test src/StellaOps.Concelier.Source.Osv.Tests/StellaOps.Concelier.Source.Osv.Tests.csproj`.
|
||||||
3. Commit the regenerated `osv-ghsa.*.json` files that the test emits (raw snapshots and canonical advisories).
|
3. Commit the regenerated `osv-ghsa.*.json` files that the test emits (raw snapshots and canonical advisories).
|
||||||
|
|
||||||
The regen flow logs `[Parity]` messages and normalises `recordedAt` timestamps so the
|
The regen flow logs `[Parity]` messages and normalises `recordedAt` timestamps so the
|
||||||
@@ -88,7 +88,7 @@ flowchart LR
|
|||||||
I1 --> FE[Jest]
|
I1 --> FE[Jest]
|
||||||
FE --> E2E[Playwright]
|
FE --> E2E[Playwright]
|
||||||
E2E --> Lighthouse
|
E2E --> Lighthouse
|
||||||
Lighthouse --> INTEG2[Feedser]
|
Lighthouse --> INTEG2[Concelier]
|
||||||
INTEG2 --> LOAD[k6]
|
INTEG2 --> LOAD[k6]
|
||||||
LOAD --> CHAOS[pumba]
|
LOAD --> CHAOS[pumba]
|
||||||
CHAOS --> RELEASE[Attestation diff]
|
CHAOS --> RELEASE[Attestation diff]
|
||||||
|
|||||||
@@ -76,51 +76,51 @@ UI: [https://\<host\>:8443](https://<host>:8443) (self‑signed cert
|
|||||||
> `stella-ops:latest` with the immutable digest printed by
|
> `stella-ops:latest` with the immutable digest printed by
|
||||||
> `docker images --digests`.
|
> `docker images --digests`.
|
||||||
|
|
||||||
### 1.1 · Feedser authority configuration
|
### 1.1 · Concelier authority configuration
|
||||||
|
|
||||||
The Feedser container reads configuration from `etc/feedser.yaml` plus
|
The Concelier container reads configuration from `etc/concelier.yaml` plus
|
||||||
`FEEDSER_` environment variables. To enable the new Authority integration:
|
`CONCELIER_` environment variables. To enable the new Authority integration:
|
||||||
|
|
||||||
1. Add the following keys to `.env` (replace values for your environment):
|
1. Add the following keys to `.env` (replace values for your environment):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
FEEDSER_AUTHORITY__ENABLED=true
|
CONCELIER_AUTHORITY__ENABLED=true
|
||||||
FEEDSER_AUTHORITY__ALLOWANONYMOUSFALLBACK=true # temporary rollout only
|
CONCELIER_AUTHORITY__ALLOWANONYMOUSFALLBACK=true # temporary rollout only
|
||||||
FEEDSER_AUTHORITY__ISSUER="https://authority.internal"
|
CONCELIER_AUTHORITY__ISSUER="https://authority.internal"
|
||||||
FEEDSER_AUTHORITY__AUDIENCES__0="api://feedser"
|
CONCELIER_AUTHORITY__AUDIENCES__0="api://concelier"
|
||||||
FEEDSER_AUTHORITY__REQUIREDSCOPES__0="feedser.jobs.trigger"
|
CONCELIER_AUTHORITY__REQUIREDSCOPES__0="concelier.jobs.trigger"
|
||||||
FEEDSER_AUTHORITY__CLIENTID="feedser-jobs"
|
CONCELIER_AUTHORITY__CLIENTID="concelier-jobs"
|
||||||
FEEDSER_AUTHORITY__CLIENTSECRETFILE="/run/secrets/feedser_authority_client"
|
CONCELIER_AUTHORITY__CLIENTSECRETFILE="/run/secrets/concelier_authority_client"
|
||||||
FEEDSER_AUTHORITY__BYPASSNETWORKS__0="127.0.0.1/32"
|
CONCELIER_AUTHORITY__BYPASSNETWORKS__0="127.0.0.1/32"
|
||||||
FEEDSER_AUTHORITY__BYPASSNETWORKS__1="::1/128"
|
CONCELIER_AUTHORITY__BYPASSNETWORKS__1="::1/128"
|
||||||
FEEDSER_AUTHORITY__RESILIENCE__ENABLERETRIES=true
|
CONCELIER_AUTHORITY__RESILIENCE__ENABLERETRIES=true
|
||||||
FEEDSER_AUTHORITY__RESILIENCE__RETRYDELAYS__0="00:00:01"
|
CONCELIER_AUTHORITY__RESILIENCE__RETRYDELAYS__0="00:00:01"
|
||||||
FEEDSER_AUTHORITY__RESILIENCE__RETRYDELAYS__1="00:00:02"
|
CONCELIER_AUTHORITY__RESILIENCE__RETRYDELAYS__1="00:00:02"
|
||||||
FEEDSER_AUTHORITY__RESILIENCE__RETRYDELAYS__2="00:00:05"
|
CONCELIER_AUTHORITY__RESILIENCE__RETRYDELAYS__2="00:00:05"
|
||||||
FEEDSER_AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK=true
|
CONCELIER_AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK=true
|
||||||
FEEDSER_AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE="00:10:00"
|
CONCELIER_AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE="00:10:00"
|
||||||
```
|
```
|
||||||
|
|
||||||
Store the client secret outside source control (Docker secrets, mounted file,
|
Store the client secret outside source control (Docker secrets, mounted file,
|
||||||
or Kubernetes Secret). Feedser loads the secret during post-configuration, so
|
or Kubernetes Secret). Concelier loads the secret during post-configuration, so
|
||||||
the value never needs to appear in the YAML template.
|
the value never needs to appear in the YAML template.
|
||||||
|
|
||||||
Connected sites can keep the retry ladder short (1 s, 2 s, 5 s) so job triggers fail fast when Authority is down. For air‑gapped or intermittently connected deployments, extend `RESILIENCE__OFFLINECACHETOLERANCE` (e.g. `00:30:00`) so cached discovery/JWKS data remains valid while the Offline Kit synchronises upstream changes.
|
Connected sites can keep the retry ladder short (1 s, 2 s, 5 s) so job triggers fail fast when Authority is down. For air‑gapped or intermittently connected deployments, extend `RESILIENCE__OFFLINECACHETOLERANCE` (e.g. `00:30:00`) so cached discovery/JWKS data remains valid while the Offline Kit synchronises upstream changes.
|
||||||
|
|
||||||
2. Redeploy Feedser:
|
2. Redeploy Concelier:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose --env-file .env -f docker-compose.stella-ops.yml up -d feedser
|
docker compose --env-file .env -f docker-compose.stella-ops.yml up -d concelier
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Tail the logs: `docker compose logs -f feedser`. Successful `/jobs*` calls now
|
3. Tail the logs: `docker compose logs -f concelier`. Successful `/jobs*` calls now
|
||||||
emit `Feedser.Authorization.Audit` entries with `route`, `status`, `subject`,
|
emit `Concelier.Authorization.Audit` entries with `route`, `status`, `subject`,
|
||||||
`clientId`, `scopes`, `bypass`, and `remote` fields. 401 denials keep the same
|
`clientId`, `scopes`, `bypass`, and `remote` fields. 401 denials keep the same
|
||||||
shape—watch for `bypass=True`, which indicates a bypass CIDR accepted an anonymous
|
shape—watch for `bypass=True`, which indicates a bypass CIDR accepted an anonymous
|
||||||
call. See `docs/ops/feedser-authority-audit-runbook.md` for a full audit/alerting checklist.
|
call. See `docs/ops/concelier-authority-audit-runbook.md` for a full audit/alerting checklist.
|
||||||
|
|
||||||
> **Enforcement deadline** – keep `FEEDSER_AUTHORITY__ALLOWANONYMOUSFALLBACK=true`
|
> **Enforcement deadline** – keep `CONCELIER_AUTHORITY__ALLOWANONYMOUSFALLBACK=true`
|
||||||
> only while validating the rollout. Set it to `false` (and restart Feedser)
|
> only while validating the rollout. Set it to `false` (and restart Concelier)
|
||||||
> before **2025-12-31 UTC** to require tokens in production.
|
> before **2025-12-31 UTC** to require tokens in production.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ completely isolated network:
|
|||||||
| **Attested manifest** | `offline-manifest.json` + detached JWS covering bundle metadata, signed during export. |
|
| **Attested manifest** | `offline-manifest.json` + detached JWS covering bundle metadata, signed during export. |
|
||||||
| **Delta patches** | Daily diff bundles keep size \< 350 MB |
|
| **Delta patches** | Daily diff bundles keep size \< 350 MB |
|
||||||
|
|
||||||
**RU BDU note:** ship the official Russian Trusted Root/Sub CA bundle (`certificates/russian_trusted_bundle.pem`) inside the kit so `feedser:httpClients:source.bdu:trustedRootPaths` can resolve it when the service runs in an air‑gapped network. Drop the most recent `vulxml.zip` alongside the kit if operators need a cold-start cache.
|
**RU BDU note:** ship the official Russian Trusted Root/Sub CA bundle (`certificates/russian_trusted_bundle.pem`) inside the kit so `concelier:httpClients:source.bdu:trustedRootPaths` can resolve it when the service runs in an air‑gapped network. Drop the most recent `vulxml.zip` alongside the kit if operators need a cold-start cache.
|
||||||
|
|
||||||
*Scanner core:* C# 12 on **.NET {{ dotnet }}**.
|
*Scanner core:* C# 12 on **.NET {{ dotnet }}**.
|
||||||
*Imports are idempotent and atomic — no service downtime.*
|
*Imports are idempotent and atomic — no service downtime.*
|
||||||
@@ -110,4 +110,4 @@ See the detailed rules in
|
|||||||
* **Install guide:** `/install/#air-gapped`
|
* **Install guide:** `/install/#air-gapped`
|
||||||
* **Sovereign mode rationale:** `/sovereign/`
|
* **Sovereign mode rationale:** `/sovereign/`
|
||||||
* **Security policy:** `/security/#reporting-a-vulnerability`
|
* **Security policy:** `/security/#reporting-a-vulnerability`
|
||||||
* **CERT-Bund snapshots:** `python tools/certbund_offline_snapshot.py --help` (see `docs/ops/feedser-certbund-operations.md`)
|
* **CERT-Bund snapshots:** `python tools/certbund_offline_snapshot.py --help` (see `docs/ops/concelier-certbund-operations.md`)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ why the system leans *monolith‑plus‑plug‑ins*, and where extension points
|
|||||||
graph TD
|
graph TD
|
||||||
A(API Gateway)
|
A(API Gateway)
|
||||||
B1(Scanner Core<br/>.NET latest LTS)
|
B1(Scanner Core<br/>.NET latest LTS)
|
||||||
B2(Feedser service\n(vuln ingest/merge/export))
|
B2(Concelier service\n(vuln ingest/merge/export))
|
||||||
B3(Policy Engine OPA)
|
B3(Policy Engine OPA)
|
||||||
C1(Redis 7)
|
C1(Redis 7)
|
||||||
C2(MongoDB 7)
|
C2(MongoDB 7)
|
||||||
@@ -53,7 +53,7 @@ graph TD
|
|||||||
| ---------------------------- | --------------------- | ---------------------------------------------------- |
|
| ---------------------------- | --------------------- | ---------------------------------------------------- |
|
||||||
| **API Gateway** | ASP.NET Minimal API | Auth (JWT), quotas, request routing |
|
| **API Gateway** | ASP.NET Minimal API | Auth (JWT), quotas, request routing |
|
||||||
| **Scanner Core** | C# 12, Polly | Layer diffing, SBOM generation, vuln correlation |
|
| **Scanner Core** | C# 12, Polly | Layer diffing, SBOM generation, vuln correlation |
|
||||||
| **Feedser (vulnerability ingest/merge/export service)** | C# source-gen workers | Consolidate NVD + regional CVE feeds into the canonical MongoDB store and drive JSON / Trivy DB exports |
|
| **Concelier (vulnerability ingest/merge/export service)** | C# source-gen workers | Consolidate NVD + regional CVE feeds into the canonical MongoDB store and drive JSON / Trivy DB exports |
|
||||||
| **Policy Engine** | OPA (Rego) | admission decisions, custom org rules |
|
| **Policy Engine** | OPA (Rego) | admission decisions, custom org rules |
|
||||||
| **Redis 7** | Key‑DB compatible | LRU cache, quota counters |
|
| **Redis 7** | Key‑DB compatible | LRU cache, quota counters |
|
||||||
| **MongoDB 7** | WiredTiger | SBOM & findings storage |
|
| **MongoDB 7** | WiredTiger | SBOM & findings storage |
|
||||||
@@ -121,7 +121,7 @@ Hot‑plugging is deferred until after v 1.0 for security review.
|
|||||||
Although the default deployment is a single container, each sub‑service can be
|
Although the default deployment is a single container, each sub‑service can be
|
||||||
extracted:
|
extracted:
|
||||||
|
|
||||||
* Feedser → standalone cron pod.
|
* Concelier → standalone cron pod.
|
||||||
* Policy Engine → side‑car (OPA) with gRPC contract.
|
* Policy Engine → side‑car (OPA) with gRPC contract.
|
||||||
* ResultSink → queue worker (RabbitMQ or Azure Service Bus).
|
* ResultSink → queue worker (RabbitMQ or Azure Service Bus).
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Produce and maintain offline-friendly documentation for StellaOps modules, cover
|
|||||||
|
|
||||||
## Scope Highlights
|
## Scope Highlights
|
||||||
- Authority docs (`docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, upcoming `docs/11_AUTHORITY.md`).
|
- Authority docs (`docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, upcoming `docs/11_AUTHORITY.md`).
|
||||||
- Feedser quickstarts, CLI guides, Offline Kit manuals.
|
- Concelier quickstarts, CLI guides, Offline Kit manuals.
|
||||||
- Release notes and migration playbooks.
|
- Release notes and migration playbooks.
|
||||||
|
|
||||||
## Operating Principles
|
## Operating Principles
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
## 0) Mission & boundaries
|
## 0) Mission & boundaries
|
||||||
|
|
||||||
**Mission.** Provide **fast, local, verifiable** authentication for Stella Ops microservices and tools by minting **very short‑lived** OAuth2/OIDC tokens that are **sender‑constrained** (DPoP or mTLS‑bound). Support RBAC scopes, multi‑tenant claims, and deterministic validation for APIs (Scanner, Signer, Attestor, Excititor, Feedser, UI, CLI, Zastava).
|
**Mission.** Provide **fast, local, verifiable** authentication for Stella Ops microservices and tools by minting **very short‑lived** OAuth2/OIDC tokens that are **sender‑constrained** (DPoP or mTLS‑bound). Support RBAC scopes, multi‑tenant claims, and deterministic validation for APIs (Scanner, Signer, Attestor, Excititor, Concelier, UI, CLI, Zastava).
|
||||||
|
|
||||||
**Boundaries.**
|
**Boundaries.**
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
```
|
```
|
||||||
iss = https://authority.<domain>
|
iss = https://authority.<domain>
|
||||||
sub = <client_id or user_id>
|
sub = <client_id or user_id>
|
||||||
aud = <service audience: signer|scanner|attestor|feedser|excititor|ui|zastava>
|
aud = <service audience: signer|scanner|attestor|concelier|excititor|ui|zastava>
|
||||||
exp = <unix ts> (<= 300 s from iat)
|
exp = <unix ts> (<= 300 s from iat)
|
||||||
iat = <unix ts>
|
iat = <unix ts>
|
||||||
nbf = iat - 30
|
nbf = iat - 30
|
||||||
@@ -140,7 +140,7 @@ plan? = <plan name> // optional hint for UIs; not used for e
|
|||||||
### 4.1 Audiences
|
### 4.1 Audiences
|
||||||
|
|
||||||
* `signer` — only the **Signer** service should accept tokens with `aud=signer`.
|
* `signer` — only the **Signer** service should accept tokens with `aud=signer`.
|
||||||
* `attestor`, `scanner`, `feedser`, `excititor`, `ui`, `zastava` similarly.
|
* `attestor`, `scanner`, `concelier`, `excititor`, `ui`, `zastava` similarly.
|
||||||
|
|
||||||
Services **must** verify `aud` and **sender constraint** (DPoP/mTLS) per their policy.
|
Services **must** verify `aud` and **sender constraint** (DPoP/mTLS) per their policy.
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ Services **must** verify `aud` and **sender constraint** (DPoP/mTLS) per their p
|
|||||||
| `scanner.export` | Scanner.WebService | Export SBOMs |
|
| `scanner.export` | Scanner.WebService | Export SBOMs |
|
||||||
| `scanner.read` | Scanner.WebService | Read catalog/SBOMs |
|
| `scanner.read` | Scanner.WebService | Read catalog/SBOMs |
|
||||||
| `vex.read` / `vex.admin` | Excititor | Query/operate |
|
| `vex.read` / `vex.admin` | Excititor | Query/operate |
|
||||||
| `feedser.read` / `feedser.export` | Feedser | Query/exports |
|
| `concelier.read` / `concelier.export` | Concelier | Query/exports |
|
||||||
| `ui.read` / `ui.admin` | UI | View/admin |
|
| `ui.read` / `ui.admin` | UI | View/admin |
|
||||||
| `zastava.emit` / `zastava.enforce` | Scanner/Zastava | Runtime events / admission |
|
| `zastava.emit` / `zastava.enforce` | Scanner/Zastava | Runtime events / admission |
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# component_architecture_cli.md — **Stella Ops CLI** (2025Q4)
|
# component_architecture_cli.md — **Stella Ops CLI** (2025Q4)
|
||||||
|
|
||||||
> **Scope.** Implementation‑ready architecture for **Stella Ops CLI**: command surface, process model, auth (Authority/DPoP), integration with Scanner/Excititor/Feedser/Signer/Attestor, Buildx plug‑in management, offline kit behavior, packaging, observability, security posture, and CI ergonomics.
|
> **Scope.** Implementation‑ready architecture for **Stella Ops CLI**: command surface, process model, auth (Authority/DPoP), integration with Scanner/Excititor/Concelier/Signer/Attestor, Buildx plug‑in management, offline kit behavior, packaging, observability, security posture, and CI ergonomics.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
* CLI **never** signs; it only calls **Signer**/**Attestor** via backend APIs when needed (e.g., `report --attest`).
|
* CLI **never** signs; it only calls **Signer**/**Attestor** via backend APIs when needed (e.g., `report --attest`).
|
||||||
* CLI **does not** store long‑lived credentials beyond OS keychain; tokens are **short** (Authority OpToks).
|
* CLI **does not** store long‑lived credentials beyond OS keychain; tokens are **short** (Authority OpToks).
|
||||||
* Heavy work (scanning, merging, policy) is executed **server‑side** (Scanner/Excititor/Feedser).
|
* Heavy work (scanning, merging, policy) is executed **server‑side** (Scanner/Excititor/Concelier).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ src/
|
|||||||
### 2.4 Policy & data
|
### 2.4 Policy & data
|
||||||
|
|
||||||
* `policy get/set/apply` — fetch active policy, apply staged policy, compute digest.
|
* `policy get/set/apply` — fetch active policy, apply staged policy, compute digest.
|
||||||
* `feedser export` — trigger/export canonical JSON or Trivy DB (admin).
|
* `concelier export` — trigger/export canonical JSON or Trivy DB (admin).
|
||||||
* `excititor export` — trigger/export consensus/raw claims (admin).
|
* `excititor export` — trigger/export consensus/raw claims (admin).
|
||||||
|
|
||||||
### 2.5 Verification
|
### 2.5 Verification
|
||||||
@@ -91,8 +91,8 @@ src/
|
|||||||
|
|
||||||
### 2.7 Offline kit
|
### 2.7 Offline kit
|
||||||
|
|
||||||
* `offline kit pull` — fetch latest **Feedser JSON + Trivy DB + Excititor exports** as a tarball from a mirror.
|
* `offline kit pull` — fetch latest **Concelier JSON + Trivy DB + Excititor exports** as a tarball from a mirror.
|
||||||
* `offline kit import <tar>` — upload the kit to on‑prem services (Feedser/Excititor).
|
* `offline kit import <tar>` — upload the kit to on‑prem services (Concelier/Excititor).
|
||||||
* `offline kit status` — list current seed versions.
|
* `offline kit status` — list current seed versions.
|
||||||
|
|
||||||
### 2.8 Utilities
|
### 2.8 Utilities
|
||||||
@@ -122,7 +122,7 @@ src/
|
|||||||
* `scanner` for scan/export/report/diff
|
* `scanner` for scan/export/report/diff
|
||||||
* `signer` (indirect; usually backend calls Signer)
|
* `signer` (indirect; usually backend calls Signer)
|
||||||
* `attestor` for verify
|
* `attestor` for verify
|
||||||
* `feedser`/`excititor` for admin verbs
|
* `concelier`/`excititor` for admin verbs
|
||||||
|
|
||||||
CLI rejects verbs if required scopes are missing.
|
CLI rejects verbs if required scopes are missing.
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ cli:
|
|||||||
backend:
|
backend:
|
||||||
scanner: "https://scanner-web.internal"
|
scanner: "https://scanner-web.internal"
|
||||||
attestor: "https://attestor.internal"
|
attestor: "https://attestor.internal"
|
||||||
feedser: "https://feedser-web.internal"
|
concelier: "https://concelier-web.internal"
|
||||||
excititor: "https://excititor-web.internal"
|
excititor: "https://excititor-web.internal"
|
||||||
auth:
|
auth:
|
||||||
audienceDefault: "scanner"
|
audienceDefault: "scanner"
|
||||||
@@ -263,7 +263,7 @@ Exit code: 2
|
|||||||
|
|
||||||
## 13) Admin & advanced flags
|
## 13) Admin & advanced flags
|
||||||
|
|
||||||
* `--authority`, `--scanner`, `--attestor`, `--feedser`, `--excititor` override config URLs.
|
* `--authority`, `--scanner`, `--attestor`, `--concelier`, `--excititor` override config URLs.
|
||||||
* `--no-color`, `--quiet`, `--json`.
|
* `--no-color`, `--quiet`, `--json`.
|
||||||
* `--timeout`, `--retries`, `--retry-backoff-ms`.
|
* `--timeout`, `--retries`, `--retry-backoff-ms`.
|
||||||
* `--ca-bundle`, `--insecure` (dev only; prints warning).
|
* `--ca-bundle`, `--insecure` (dev only; prints warning).
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# component_architecture_feedser.md — **Stella Ops Feedser** (2025Q4)
|
# component_architecture_concelier.md — **Stella Ops Concelier** (2025Q4)
|
||||||
|
|
||||||
> **Scope.** Implementation‑ready architecture for **Feedser**: the vulnerability ingest/normalize/merge/export subsystem that produces deterministic advisory data for the Scanner + Policy + Excititor pipeline. Covers domain model, connectors, merge rules, storage schema, exports, APIs, performance, security, and test matrices.
|
> **Scope.** Implementation‑ready architecture for **Concelier**: the vulnerability ingest/normalize/merge/export subsystem that produces deterministic advisory data for the Scanner + Policy + Excititor pipeline. Covers domain model, connectors, merge rules, storage schema, exports, APIs, performance, security, and test matrices.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -10,15 +10,15 @@
|
|||||||
|
|
||||||
**Boundaries.**
|
**Boundaries.**
|
||||||
|
|
||||||
* Feedser **does not** sign with private keys. When attestation is required, the export artifact is handed to the **Signer**/**Attestor** pipeline (out‑of‑process).
|
* Concelier **does not** sign with private keys. When attestation is required, the export artifact is handed to the **Signer**/**Attestor** pipeline (out‑of‑process).
|
||||||
* Feedser **does not** decide PASS/FAIL; it provides data to the **Policy** engine.
|
* Concelier **does not** decide PASS/FAIL; it provides data to the **Policy** engine.
|
||||||
* Online operation is **allowlist‑only**; air‑gapped deployments use the **Offline Kit**.
|
* Online operation is **allowlist‑only**; air‑gapped deployments use the **Offline Kit**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1) Topology & processes
|
## 1) Topology & processes
|
||||||
|
|
||||||
**Process shape:** single ASP.NET Core service `StellaOps.Feedser.WebService` hosting:
|
**Process shape:** single ASP.NET Core service `StellaOps.Concelier.WebService` hosting:
|
||||||
|
|
||||||
* **Scheduler** with distributed locks (Mongo backed).
|
* **Scheduler** with distributed locks (Mongo backed).
|
||||||
* **Connectors** (fetch/parse/map).
|
* **Connectors** (fetch/parse/map).
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
## 2) Canonical domain model
|
## 2) Canonical domain model
|
||||||
|
|
||||||
> Stored in MongoDB (database `feedser`), serialized with a **canonical JSON** writer (stable order, camelCase, normalized timestamps).
|
> Stored in MongoDB (database `concelier`), serialized with a **canonical JSON** writer (stable order, camelCase, normalized timestamps).
|
||||||
|
|
||||||
### 2.1 Core entities
|
### 2.1 Core entities
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ public interface IFeedConnector {
|
|||||||
|
|
||||||
### 5.1 Keying & identity
|
### 5.1 Keying & identity
|
||||||
|
|
||||||
* Identity graph: **CVE** is primary node; vendor/distro IDs resolved via **Alias** edges (from connectors and Feedser’s alias tables).
|
* Identity graph: **CVE** is primary node; vendor/distro IDs resolved via **Alias** edges (from connectors and Concelier’s alias tables).
|
||||||
* `advisoryKey` is the canonical primary key (CVE if present, else vendor/distro key).
|
* `advisoryKey` is the canonical primary key (CVE if present, else vendor/distro key).
|
||||||
|
|
||||||
### 5.2 Merge algorithm (deterministic)
|
### 5.2 Merge algorithm (deterministic)
|
||||||
@@ -255,14 +255,14 @@ public interface IFeedConnector {
|
|||||||
|
|
||||||
### 7.3 Hand‑off to Signer/Attestor (optional)
|
### 7.3 Hand‑off to Signer/Attestor (optional)
|
||||||
|
|
||||||
* On export completion, if `attest: true` is set in job args, Feedser **posts** the artifact metadata to **Signer**/**Attestor**; Feedser itself **does not** hold signing keys.
|
* On export completion, if `attest: true` is set in job args, Concelier **posts** the artifact metadata to **Signer**/**Attestor**; Concelier itself **does not** hold signing keys.
|
||||||
* Export record stores returned `{ uuid, index, url }` from **Rekor v2**.
|
* Export record stores returned `{ uuid, index, url }` from **Rekor v2**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8) REST APIs
|
## 8) REST APIs
|
||||||
|
|
||||||
All under `/api/v1/feedser`.
|
All under `/api/v1/concelier`.
|
||||||
|
|
||||||
**Health & status**
|
**Health & status**
|
||||||
|
|
||||||
@@ -296,18 +296,18 @@ GET /advisories?scheme=CVE&value=CVE-2025-12345
|
|||||||
GET /affected?productKey=pkg:rpm/openssl&limit=100
|
GET /affected?productKey=pkg:rpm/openssl&limit=100
|
||||||
```
|
```
|
||||||
|
|
||||||
**AuthN/Z:** Authority tokens (OpTok) with roles: `feedser.read`, `feedser.admin`, `feedser.export`.
|
**AuthN/Z:** Authority tokens (OpTok) with roles: `concelier.read`, `concelier.admin`, `concelier.export`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9) Configuration (YAML)
|
## 9) Configuration (YAML)
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
mongo: { uri: "mongodb://mongo/feedser" }
|
mongo: { uri: "mongodb://mongo/concelier" }
|
||||||
s3:
|
s3:
|
||||||
endpoint: "http://minio:9000"
|
endpoint: "http://minio:9000"
|
||||||
bucket: "stellaops-feedser"
|
bucket: "stellaops-concelier"
|
||||||
scheduler:
|
scheduler:
|
||||||
windowSeconds: 30
|
windowSeconds: 30
|
||||||
maxParallelSources: 4
|
maxParallelSources: 4
|
||||||
@@ -337,14 +337,14 @@ feedser:
|
|||||||
exporters:
|
exporters:
|
||||||
json:
|
json:
|
||||||
enabled: true
|
enabled: true
|
||||||
output: s3://stellaops-feedser/json/
|
output: s3://stellaops-concelier/json/
|
||||||
trivy:
|
trivy:
|
||||||
enabled: true
|
enabled: true
|
||||||
mode: full
|
mode: full
|
||||||
output: s3://stellaops-feedser/trivy/
|
output: s3://stellaops-concelier/trivy/
|
||||||
oras:
|
oras:
|
||||||
enabled: false
|
enabled: false
|
||||||
repo: ghcr.io/org/feedser
|
repo: ghcr.io/org/concelier
|
||||||
precedence:
|
precedence:
|
||||||
vendorWinsOverDistro: true
|
vendorWinsOverDistro: true
|
||||||
distroWinsOverOsv: true
|
distroWinsOverOsv: true
|
||||||
@@ -372,7 +372,7 @@ feedser:
|
|||||||
* **Export**: 1M advisories JSON in ≤ 90 s (streamed, zstd), Trivy DB in ≤ 60 s on 8 cores.
|
* **Export**: 1M advisories JSON in ≤ 90 s (streamed, zstd), Trivy DB in ≤ 60 s on 8 cores.
|
||||||
* **Memory**: hard cap per job; chunked streaming writers; backpressure to avoid GC spikes.
|
* **Memory**: hard cap per job; chunked streaming writers; backpressure to avoid GC spikes.
|
||||||
|
|
||||||
**Scale pattern**: add Feedser replicas; Mongo scaling via indices and read/write concerns; GridFS only for oversized docs.
|
**Scale pattern**: add Concelier replicas; Mongo scaling via indices and read/write concerns; GridFS only for oversized docs.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -380,13 +380,13 @@ feedser:
|
|||||||
|
|
||||||
* **Metrics**
|
* **Metrics**
|
||||||
|
|
||||||
* `feedser.fetch.docs_total{source}`
|
* `concelier.fetch.docs_total{source}`
|
||||||
* `feedser.fetch.bytes_total{source}`
|
* `concelier.fetch.bytes_total{source}`
|
||||||
* `feedser.parse.failures_total{source}`
|
* `concelier.parse.failures_total{source}`
|
||||||
* `feedser.map.affected_total{source}`
|
* `concelier.map.affected_total{source}`
|
||||||
* `feedser.merge.changed_total`
|
* `concelier.merge.changed_total`
|
||||||
* `feedser.export.bytes{kind}`
|
* `concelier.export.bytes{kind}`
|
||||||
* `feedser.export.duration_seconds{kind}`
|
* `concelier.export.duration_seconds{kind}`
|
||||||
* **Tracing** around fetch/parse/map/merge/export.
|
* **Tracing** around fetch/parse/map/merge/export.
|
||||||
* **Logs**: structured with `source`, `uri`, `docDigest`, `advisoryKey`, `exportId`.
|
* **Logs**: structured with `source`, `uri`, `docDigest`, `advisoryKey`, `exportId`.
|
||||||
|
|
||||||
@@ -415,11 +415,11 @@ feedser:
|
|||||||
|
|
||||||
## 15) Operator runbook (quick)
|
## 15) Operator runbook (quick)
|
||||||
|
|
||||||
* **Trigger all sources:** `POST /api/v1/feedser/sources/*/trigger`
|
* **Trigger all sources:** `POST /api/v1/concelier/sources/*/trigger`
|
||||||
* **Force full export JSON:** `POST /api/v1/feedser/exports/json { "full": true, "force": true }`
|
* **Force full export JSON:** `POST /api/v1/concelier/exports/json { "full": true, "force": true }`
|
||||||
* **Force Trivy DB delta publish:** `POST /api/v1/feedser/exports/trivy { "full": false, "publish": true }`
|
* **Force Trivy DB delta publish:** `POST /api/v1/concelier/exports/trivy { "full": false, "publish": true }`
|
||||||
* **Inspect advisory:** `GET /api/v1/feedser/advisories?scheme=CVE&value=CVE-2025-12345`
|
* **Inspect advisory:** `GET /api/v1/concelier/advisories?scheme=CVE&value=CVE-2025-12345`
|
||||||
* **Pause noisy source:** `POST /api/v1/feedser/sources/osv/pause`
|
* **Pause noisy source:** `POST /api/v1/concelier/sources/osv/pause`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ Semantic core + calendar tag:
|
|||||||
A release is a **bundle** of image digests + charts + manifests. All services in a bundle are **wire‑compatible**. Mixed minor versions are allowed within a bounded skew:
|
A release is a **bundle** of image digests + charts + manifests. All services in a bundle are **wire‑compatible**. Mixed minor versions are allowed within a bounded skew:
|
||||||
|
|
||||||
* **Web UI ↔ backend**: `±1 minor`.
|
* **Web UI ↔ backend**: `±1 minor`.
|
||||||
* **Scanner ↔ Policy/Excititor/Feedser**: `±1 minor`.
|
* **Scanner ↔ Policy/Excititor/Concelier**: `±1 minor`.
|
||||||
* **Authority/Signer/Attestor triangle**: **must** be same minor (crypto and DPoP/mTLS binding rules).
|
* **Authority/Signer/Attestor triangle**: **must** be same minor (crypto and DPoP/mTLS binding rules).
|
||||||
|
|
||||||
At startup, services **self‑advertise** their semver & channel; the UI surfaces **mismatch warnings**.
|
At startup, services **self‑advertise** their semver & channel; the UI surfaces **mismatch warnings**.
|
||||||
@@ -75,7 +75,7 @@ At startup, services **self‑advertise** their semver & channel; the UI surface
|
|||||||
* **Static**: linters, codegen checks, protobuf API freeze (backward‑compat tests).
|
* **Static**: linters, codegen checks, protobuf API freeze (backward‑compat tests).
|
||||||
* **Unit/integration**: per‑component, plus **end‑to‑end** flows (scan→vex→policy→sign→attest).
|
* **Unit/integration**: per‑component, plus **end‑to‑end** flows (scan→vex→policy→sign→attest).
|
||||||
* **Perf SLOs**: hot paths (SBOM compose, diff, export) measured against budgets.
|
* **Perf SLOs**: hot paths (SBOM compose, diff, export) measured against budgets.
|
||||||
* **Security**: dependency audit vs Feedser export; container hardening tests; minimal caps.
|
* **Security**: dependency audit vs Concelier export; container hardening tests; minimal caps.
|
||||||
* **Canary cohort**: internal staging + selected customers; one week on **edge** before **stable** tag.
|
* **Canary cohort**: internal staging + selected customers; one week on **edge** before **stable** tag.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -90,7 +90,7 @@ At startup, services **self‑advertise** their semver & channel; the UI surface
|
|||||||
|
|
||||||
**Gating policy**:
|
**Gating policy**:
|
||||||
|
|
||||||
* **Core images** (Authority, Scanner, Feedser, Excititor, Attestor, UI): public **read**.
|
* **Core images** (Authority, Scanner, Concelier, Excititor, Attestor, UI): public **read**.
|
||||||
* **Enterprise add‑ons** (if any) and **pre‑release**: private repos via OAuth2 token service.
|
* **Enterprise add‑ons** (if any) and **pre‑release**: private repos via OAuth2 token service.
|
||||||
|
|
||||||
> Monetization lever is **signing** (PoE gate), not image pulls, so the core remains simple to consume.
|
> Monetization lever is **signing** (PoE gate), not image pulls, so the core remains simple to consume.
|
||||||
@@ -115,7 +115,7 @@ At startup, services **self‑advertise** their semver & channel; the UI surface
|
|||||||
/attest/ DSSE bundles + Rekor proofs
|
/attest/ DSSE bundles + Rekor proofs
|
||||||
/charts/ Helm charts + values templates
|
/charts/ Helm charts + values templates
|
||||||
/compose/ docker-compose.yml + .env template
|
/compose/ docker-compose.yml + .env template
|
||||||
/plugins/ Feedser/Excititor connectors (restart-time)
|
/plugins/ Concelier/Excititor connectors (restart-time)
|
||||||
/policy/ example policies
|
/policy/ example policies
|
||||||
/manifest/ release.yaml (see §6.1)
|
/manifest/ release.yaml (see §6.1)
|
||||||
```
|
```
|
||||||
@@ -169,7 +169,7 @@ helm install stella stellaops/platform \
|
|||||||
--set authority.issuer=https://authority.stella.local \
|
--set authority.issuer=https://authority.stella.local \
|
||||||
--set scanner.minio.endpoint=http://minio.stella.local:9000 \
|
--set scanner.minio.endpoint=http://minio.stella.local:9000 \
|
||||||
--set scanner.mongo.uri=mongodb://mongo/scanner \
|
--set scanner.mongo.uri=mongodb://mongo/scanner \
|
||||||
--set feedser.mongo.uri=mongodb://mongo/feedser \
|
--set concelier.mongo.uri=mongodb://mongo/concelier \
|
||||||
--set excititor.mongo.uri=mongodb://mongo/excititor
|
--set excititor.mongo.uri=mongodb://mongo/excititor
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ helm install stella stellaops/platform \
|
|||||||
1. Authority (stateless, dual‑key rotation ready)
|
1. Authority (stateless, dual‑key rotation ready)
|
||||||
2. Signer/Attestor (same minor)
|
2. Signer/Attestor (same minor)
|
||||||
3. Scanner WebService & Workers
|
3. Scanner WebService & Workers
|
||||||
4. Feedser, then Excititor (schema migrations are expand/contract)
|
4. Concelier, then Excititor (schema migrations are expand/contract)
|
||||||
5. UI last
|
5. UI last
|
||||||
|
|
||||||
* **DB migrations** are **expand/contract**:
|
* **DB migrations** are **expand/contract**:
|
||||||
@@ -263,7 +263,7 @@ s3://stellaops/
|
|||||||
images/<imgDigest>/usage.cdx.pb
|
images/<imgDigest>/usage.cdx.pb
|
||||||
diffs/<old>_<new>/diff.json.zst
|
diffs/<old>_<new>/diff.json.zst
|
||||||
attest/<artifactSha256>.dsse.json
|
attest/<artifactSha256>.dsse.json
|
||||||
feedser/
|
concelier/
|
||||||
json/<exportId>/...
|
json/<exportId>/...
|
||||||
trivy/<exportId>/...
|
trivy/<exportId>/...
|
||||||
excititor/
|
excititor/
|
||||||
@@ -289,14 +289,14 @@ s3://stellaops/
|
|||||||
### 7.4 Mongo retention
|
### 7.4 Mongo retention
|
||||||
|
|
||||||
* **Scanner**: `runtime.events` use TTL (e.g., 30–90 days); **catalog** permanent.
|
* **Scanner**: `runtime.events` use TTL (e.g., 30–90 days); **catalog** permanent.
|
||||||
* **Feedser/Excititor**: raw docs keep **last N windows**; canonical stores permanent.
|
* **Concelier/Excititor**: raw docs keep **last N windows**; canonical stores permanent.
|
||||||
* **Attestor**: `entries` permanent; `dedupe` TTL 24–48h.
|
* **Attestor**: `entries` permanent; `dedupe` TTL 24–48h.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8) Observability & SLOs (operations)
|
## 8) Observability & SLOs (operations)
|
||||||
|
|
||||||
* **Uptime SLO**: 99.9% for Signer/Authority/Attestor; 99.5% for Scanner WebService; Excititor/Feedser 99.0%.
|
* **Uptime SLO**: 99.9% for Signer/Authority/Attestor; 99.5% for Scanner WebService; Excititor/Concelier 99.0%.
|
||||||
* **Error budgets**: tracked per month; dashboards show burn rates.
|
* **Error budgets**: tracked per month; dashboards show burn rates.
|
||||||
* **Golden signals**:
|
* **Golden signals**:
|
||||||
|
|
||||||
@@ -324,7 +324,7 @@ Prometheus + OTLP; Grafana dashboards ship in the charts.
|
|||||||
|
|
||||||
* **Vulnerability response**:
|
* **Vulnerability response**:
|
||||||
|
|
||||||
* Feedser red‑flag advisories trigger accelerated **stable** patch rollout; UI/CLI “security patch available” notice.
|
* Concelier red‑flag advisories trigger accelerated **stable** patch rollout; UI/CLI “security patch available” notice.
|
||||||
|
|
||||||
* **Backups/DR**:
|
* **Backups/DR**:
|
||||||
|
|
||||||
@@ -408,8 +408,8 @@ services:
|
|||||||
scanner-worker:
|
scanner-worker:
|
||||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:...
|
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:...
|
||||||
deploy: { replicas: 4 }
|
deploy: { replicas: 4 }
|
||||||
feedser:
|
concelier:
|
||||||
image: registry.stella-ops.org/stellaops/feedser@sha256:...
|
image: registry.stella-ops.org/stellaops/concelier@sha256:...
|
||||||
excititor:
|
excititor:
|
||||||
image: registry.stella-ops.org/stellaops/excititor@sha256:...
|
image: registry.stella-ops.org/stellaops/excititor@sha256:...
|
||||||
web-ui:
|
web-ui:
|
||||||
@@ -446,7 +446,7 @@ services:
|
|||||||
* `signer.requests_total{result="success"}/minute` > 0 (when scans occur).
|
* `signer.requests_total{result="success"}/minute` > 0 (when scans occur).
|
||||||
* `attestor.submit_latency_seconds{quantile=0.95}` < 0.3.
|
* `attestor.submit_latency_seconds{quantile=0.95}` < 0.3.
|
||||||
* `scanner.scan_latency_seconds{quantile=0.95}` < target per image size.
|
* `scanner.scan_latency_seconds{quantile=0.95}` < target per image size.
|
||||||
* `feedser.export.duration_seconds` stable; `excititor.consensus.conflicts_total` not exploding after policy changes.
|
* `concelier.export.duration_seconds` stable; `excititor.consensus.conflicts_total` not exploding after policy changes.
|
||||||
* MinIO `s3_requests_errors_total` near zero; Mongo `opcounters` hit expected baseline.
|
* MinIO `s3_requests_errors_total` near zero; Mongo `opcounters` hit expected baseline.
|
||||||
|
|
||||||
### Appendix B — Upgrade safety checklist
|
### Appendix B — Upgrade safety checklist
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# component_architecture_excititor.md — **Stella Ops Excititor** (2025Q4)
|
# component_architecture_excititor.md — **Stella Ops Excititor** (2025Q4)
|
||||||
|
|
||||||
> **Scope.** This document specifies the **Excititor** service: its purpose, trust model, data structures, APIs, plug‑in contracts, storage schema, normalization/consensus algorithms, performance budgets, testing matrix, and how it integrates with Scanner, Policy, Feedser, and the attestation chain. It is implementation‑ready.
|
> **Scope.** This document specifies the **Excititor** service: its purpose, trust model, data structures, APIs, plug‑in contracts, storage schema, normalization/consensus algorithms, performance budgets, testing matrix, and how it integrates with Scanner, Policy, Concelier, and the attestation chain. It is implementation‑ready.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ All exports are **deterministic**, and (optionally) **attested** via DSSE and lo
|
|||||||
### 2.1 Vuln identity
|
### 2.1 Vuln identity
|
||||||
|
|
||||||
* Accepts **CVE**, **GHSA**, vendor IDs (MSRC, RHSA…), distro IDs (DSA/USN/RHSA…) — normalized to `vulnId` with alias sets.
|
* Accepts **CVE**, **GHSA**, vendor IDs (MSRC, RHSA…), distro IDs (DSA/USN/RHSA…) — normalized to `vulnId` with alias sets.
|
||||||
* **Alias graph** maintained (from Feedser) to map vendor/distro IDs → CVE (primary) and to **GHSA** where applicable.
|
* **Alias graph** maintained (from Concelier) to map vendor/distro IDs → CVE (primary) and to **GHSA** where applicable.
|
||||||
|
|
||||||
### 2.2 Product identity (`productKey`)
|
### 2.2 Product identity (`productKey`)
|
||||||
|
|
||||||
@@ -427,7 +427,7 @@ excititor:
|
|||||||
## 14) Integration points
|
## 14) Integration points
|
||||||
|
|
||||||
* **Backend Policy Engine** (in Scanner.WebService): calls `POST /resolve` with batched `(purl, vulnId)` pairs to fetch `rollupStatus + sources`.
|
* **Backend Policy Engine** (in Scanner.WebService): calls `POST /resolve` with batched `(purl, vulnId)` pairs to fetch `rollupStatus + sources`.
|
||||||
* **Feedser**: provides alias graph (CVE↔vendor IDs) and may supply VEX‑adjacent metadata (e.g., KEV flag) for policy escalation.
|
* **Concelier**: provides alias graph (CVE↔vendor IDs) and may supply VEX‑adjacent metadata (e.g., KEV flag) for policy escalation.
|
||||||
* **UI**: VEX explorer screens use `/claims/search` and `/consensus/search`; show conflicts & provenance.
|
* **UI**: VEX explorer screens use `/claims/search` and `/consensus/search`; show conflicts & provenance.
|
||||||
* **CLI**: `stellaops vex export --consensus --since 7d --out vex.json` for audits.
|
* **CLI**: `stellaops vex export --consensus --since 7d --out vex.json` for audits.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# component_architecture_scanner.md — **Stella Ops Scanner** (2025Q4)
|
# component_architecture_scanner.md — **Stella Ops Scanner** (2025Q4)
|
||||||
|
|
||||||
> **Scope.** Implementation‑ready architecture for the **Scanner** subsystem: WebService, Workers, analyzers, SBOM assembly (inventory & usage), per‑layer caching, three‑way diffs, artifact catalog (MinIO+Mongo), attestation hand‑off, and scale/security posture. This document is the contract between the scanning plane and everything else (Policy, Excititor, Feedser, UI, CLI).
|
> **Scope.** Implementation‑ready architecture for the **Scanner** subsystem: WebService, Workers, analyzers, SBOM assembly (inventory & usage), per‑layer caching, three‑way diffs, artifact catalog (MinIO+Mongo), attestation hand‑off, and scale/security posture. This document is the contract between the scanning plane and everything else (Policy, Excititor, Concelier, UI, CLI).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
**Boundaries.**
|
**Boundaries.**
|
||||||
|
|
||||||
* Scanner **does not** produce PASS/FAIL. The backend (Policy + Excititor + Feedser) decides presentation and verdicts.
|
* Scanner **does not** produce PASS/FAIL. The backend (Policy + Excititor + Concelier) decides presentation and verdicts.
|
||||||
* Scanner **does not** keep third‑party SBOM warehouses. It may **bind** to existing attestations for exact hashes.
|
* Scanner **does not** keep third‑party SBOM warehouses. It may **bind** to existing attestations for exact hashes.
|
||||||
* Core analyzers are **deterministic** (no fuzzy identity). Optional heuristic plug‑ins (e.g., patch‑presence) run under explicit flags and never contaminate the core SBOM.
|
* Core analyzers are **deterministic** (no fuzzy identity). Optional heuristic plug‑ins (e.g., patch‑presence) run under explicit flags and never contaminate the core SBOM.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# component_architecture_web_ui.md — **Stella Ops Web UI** (2025Q4)
|
# component_architecture_web_ui.md — **Stella Ops Web UI** (2025Q4)
|
||||||
|
|
||||||
> **Scope.** Implementation‑ready architecture for the **Angular SPA** that operators and developers use to drive Stella Ops. This document defines UX surfaces, module boundaries, data flows, auth, RBAC, real‑time updates, performance targets, i18n/a11y, security headers, testing and deployment. The UI is a *consumer* of backend APIs (Scanner, Policy, Excititor, Feedser, Attestor, Authority) and never performs scanning, merging, or signing on its own.
|
> **Scope.** Implementation‑ready architecture for the **Angular SPA** that operators and developers use to drive Stella Ops. This document defines UX surfaces, module boundaries, data flows, auth, RBAC, real‑time updates, performance targets, i18n/a11y, security headers, testing and deployment. The UI is a *consumer* of backend APIs (Scanner, Policy, Excititor, Concelier, Attestor, Authority) and never performs scanning, merging, or signing on its own.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
* Scans (status, SBOMs, diffs, EntryTrace, attestation).
|
* Scans (status, SBOMs, diffs, EntryTrace, attestation).
|
||||||
* Policy management (rules, exemptions, VEX consumption view).
|
* Policy management (rules, exemptions, VEX consumption view).
|
||||||
* Vulnerability intel (Feedser status), VEX consensus exploration (Excititor).
|
* Vulnerability intel (Concelier status), VEX consensus exploration (Excititor).
|
||||||
* Runtime posture (Zastava observer + admission).
|
* Runtime posture (Zastava observer + admission).
|
||||||
* Admin operations (tenants, tokens, quotas, licensing posture).
|
* Admin operations (tenants, tokens, quotas, licensing posture).
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
├─ runtime/ # Zastava posture, drift events, admission decisions
|
├─ runtime/ # Zastava posture, drift events, admission decisions
|
||||||
├─ policy/ # rules editor (YAML/Rego), exemptions, previews
|
├─ policy/ # rules editor (YAML/Rego), exemptions, previews
|
||||||
├─ vex/ # VEX explorer (claims, consensus, conflicts)
|
├─ vex/ # VEX explorer (claims, consensus, conflicts)
|
||||||
├─ feedser/ # source health, export cursors, rebuild/export triggers
|
├─ concelier/ # source health, export cursors, rebuild/export triggers
|
||||||
├─ attest/ # attestation proofs, verification bundles, Rekor links
|
├─ attest/ # attestation proofs, verification bundles, Rekor links
|
||||||
├─ admin/ # tenants, roles, clients, quotas, licensing posture
|
├─ admin/ # tenants, roles, clients, quotas, licensing posture
|
||||||
└─ plugins/ # route plug-ins (lazy remote modules, governed)
|
└─ plugins/ # route plug-ins (lazy remote modules, governed)
|
||||||
@@ -92,7 +92,7 @@ Each feature folder builds as a **standalone route** (lazy loaded). All HTTP sha
|
|||||||
* **Consensus view**: rollup per (vuln, product) with accepted/rejected sources, weights, timestamps.
|
* **Consensus view**: rollup per (vuln, product) with accepted/rejected sources, weights, timestamps.
|
||||||
* **Conflicts**: grid of top conflicts; filters for justification gates failed.
|
* **Conflicts**: grid of top conflicts; filters for justification gates failed.
|
||||||
|
|
||||||
### 3.6 Feedser
|
### 3.6 Concelier
|
||||||
|
|
||||||
* **Sources** table: staleness, last run, errors.
|
* **Sources** table: staleness, last run, errors.
|
||||||
* **Advisory search**: by CVE/alias; show normalized affected ranges.
|
* **Advisory search**: by CVE/alias; show normalized affected ranges.
|
||||||
@@ -136,7 +136,7 @@ Each feature folder builds as a **standalone route** (lazy loaded). All HTTP sha
|
|||||||
|
|
||||||
* **`core/http/api-client.ts`** centralizes:
|
* **`core/http/api-client.ts`** centralizes:
|
||||||
|
|
||||||
* Base URLs (Scanner, Excititor, Feedser, Attestor).
|
* Base URLs (Scanner, Excititor, Concelier, Attestor).
|
||||||
* **Retry** policies on idempotent GETs (backoff + jitter).
|
* **Retry** policies on idempotent GETs (backoff + jitter).
|
||||||
* **Problem+JSON** parser → uniform error toasts with correlation ID.
|
* **Problem+JSON** parser → uniform error toasts with correlation ID.
|
||||||
* **SSE** helper (EventSource) with auto‑reconnect & backpressure.
|
* **SSE** helper (EventSource) with auto‑reconnect & backpressure.
|
||||||
@@ -144,7 +144,7 @@ Each feature folder builds as a **standalone route** (lazy loaded). All HTTP sha
|
|||||||
|
|
||||||
* Typed API clients (DTOs in `core/api/models.ts`):
|
* Typed API clients (DTOs in `core/api/models.ts`):
|
||||||
|
|
||||||
* `ScannerApi`, `PolicyApi`, `ExcititorApi`, `FeedserApi`, `AttestorApi`, `AuthorityApi`.
|
* `ScannerApi`, `PolicyApi`, `ExcititorApi`, `ConcelierApi`, `AttestorApi`, `AuthorityApi`.
|
||||||
|
|
||||||
**DTO examples (abbrev):**
|
**DTO examples (abbrev):**
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ export interface VexConsensus {
|
|||||||
|
|
||||||
* **Huge tables** rendered with **virtual scrolling** (CDK Virtual Scroll); sort/filter performed client‑side for ≤ 20k rows; beyond that, server‑side queries via BOM‑Index endpoints.
|
* **Huge tables** rendered with **virtual scrolling** (CDK Virtual Scroll); sort/filter performed client‑side for ≤ 20k rows; beyond that, server‑side queries via BOM‑Index endpoints.
|
||||||
* **Component row** shows purl, version, origin (OS pkg / metadata / linker / attested), licenses, and **used** badge (Usage view).
|
* **Component row** shows purl, version, origin (OS pkg / metadata / linker / attested), licenses, and **used** badge (Usage view).
|
||||||
* **Diff**: compact heatmap per layer; clicking opens a right‑pane with evidence: introducing paths, file hashes, VEX notes (from Excititor consensus) and links to advisories (Feedser).
|
* **Diff**: compact heatmap per layer; clicking opens a right‑pane with evidence: introducing paths, file hashes, VEX notes (from Excititor consensus) and links to advisories (Concelier).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ This document tracks the future-looking risk scoring model for Excititor. The ca
|
|||||||
|
|
||||||
* **Gate(VEX_status)**: `affected`/`under_investigation` → 1, `not_affected`/`fixed` → 0. A trusted “not affected” or “fixed” still zeroes the score.
|
* **Gate(VEX_status)**: `affected`/`under_investigation` → 1, `not_affected`/`fixed` → 0. A trusted “not affected” or “fixed” still zeroes the score.
|
||||||
* **W_trust(source)**: normalized policy weight (baseline 0‒1). Policies may opt into >1 boosts for signed vendor feeds once Phase 1 closes.
|
* **W_trust(source)**: normalized policy weight (baseline 0‒1). Policies may opt into >1 boosts for signed vendor feeds once Phase 1 closes.
|
||||||
* **Severity_base**: canonical numeric severity from Feedser (CVSS or org-defined scale).
|
* **Severity_base**: canonical numeric severity from Concelier (CVSS or org-defined scale).
|
||||||
* **KEV flag**: 0/1 boost when CISA Known Exploited Vulnerabilities applies.
|
* **KEV flag**: 0/1 boost when CISA Known Exploited Vulnerabilities applies.
|
||||||
* **EPSS**: probability [0,1]; bounded multiplier.
|
* **EPSS**: probability [0,1]; bounded multiplier.
|
||||||
* **α, β**: configurable coefficients (default α=0.25, β=0.5) stored in policy.
|
* **α, β**: configurable coefficients (default α=0.25, β=0.5) stored in policy.
|
||||||
@@ -19,9 +19,9 @@ Safeguards: freeze boosts when product identity is unknown, clamp outputs ≥0,
|
|||||||
|
|
||||||
| Phase | Scope | Artifacts |
|
| Phase | Scope | Artifacts |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| **Phase 1 – Schema foundations** | Extend Excititor consensus/claims and Feedser canonical advisories with severity, KEV, EPSS, and expose α/β + weight ceilings in policy. | Sprint 7 tasks `EXCITITOR-CORE-02-001`, `EXCITITOR-POLICY-02-001`, `EXCITITOR-STORAGE-02-001`, `FEEDCORE-ENGINE-07-001`. |
|
| **Phase 1 – Schema foundations** | Extend Excititor consensus/claims and Concelier canonical advisories with severity, KEV, EPSS, and expose α/β + weight ceilings in policy. | Sprint 7 tasks `EXCITITOR-CORE-02-001`, `EXCITITOR-POLICY-02-001`, `EXCITITOR-STORAGE-02-001`, `FEEDCORE-ENGINE-07-001`. |
|
||||||
| **Phase 2 – Deterministic score engine** | Implement a scoring component that executes alongside consensus and persists score envelopes with hashes. | Planned task `EXCITITOR-CORE-02-002` (backlog). |
|
| **Phase 2 – Deterministic score engine** | Implement a scoring component that executes alongside consensus and persists score envelopes with hashes. | Planned task `EXCITITOR-CORE-02-002` (backlog). |
|
||||||
| **Phase 3 – Surfacing & enforcement** | Expose scores via WebService/CLI, integrate with Feedser noise priors, and enforce policy-based suppressions. | To be scheduled after Phase 2. |
|
| **Phase 3 – Surfacing & enforcement** | Expose scores via WebService/CLI, integrate with Concelier noise priors, and enforce policy-based suppressions. | To be scheduled after Phase 2. |
|
||||||
|
|
||||||
## Data model (after Phase 1)
|
## Data model (after Phase 1)
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ Safeguards: freeze boosts when product identity is unknown, clamp outputs ≥0,
|
|||||||
|
|
||||||
## Operational guidance
|
## Operational guidance
|
||||||
|
|
||||||
* **Inputs**: Feedser delivers severity/KEV/EPSS via the advisory event log; Excititor connectors load VEX statements. Policy owns trust tiers and coefficients.
|
* **Inputs**: Concelier delivers severity/KEV/EPSS via the advisory event log; Excititor connectors load VEX statements. Policy owns trust tiers and coefficients.
|
||||||
* **Processing**: the scoring engine (Phase 2) runs next to consensus, storing results with deterministic hashes so exports and attestations can reference them.
|
* **Processing**: the scoring engine (Phase 2) runs next to consensus, storing results with deterministic hashes so exports and attestations can reference them.
|
||||||
* **Consumption**: WebService/CLI will return consensus plus score; scanners may suppress findings only when policy-authorized VEX gating and signed score envelopes agree.
|
* **Consumption**: WebService/CLI will return consensus plus score; scanners may suppress findings only when policy-authorized VEX gating and signed score envelopes agree.
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ Everything here is open‑source and versioned — when you check out a git ta
|
|||||||
- **07 – [High‑Level Architecture](07_HIGH_LEVEL_ARCHITECTURE.md)**
|
- **07 – [High‑Level Architecture](07_HIGH_LEVEL_ARCHITECTURE.md)**
|
||||||
- **08 – Module Architecture Dossiers**
|
- **08 – Module Architecture Dossiers**
|
||||||
- [Scanner](ARCHITECTURE_SCANNER.md)
|
- [Scanner](ARCHITECTURE_SCANNER.md)
|
||||||
- [Feedser](ARCHITECTURE_FEEDSER.md)
|
- [Concelier](ARCHITECTURE_CONCELIER.md)
|
||||||
- [Excititor](ARCHITECTURE_EXCITITOR.md)
|
- [Excititor](ARCHITECTURE_EXCITITOR.md)
|
||||||
- [Signer](ARCHITECTURE_SIGNER.md)
|
- [Signer](ARCHITECTURE_SIGNER.md)
|
||||||
- [Attestor](ARCHITECTURE_ATTESTOR.md)
|
- [Attestor](ARCHITECTURE_ATTESTOR.md)
|
||||||
@@ -47,7 +47,7 @@ Everything here is open‑source and versioned — when you check out a git ta
|
|||||||
- [Release & Operations](ARCHITECTURE_DEVOPS.md)
|
- [Release & Operations](ARCHITECTURE_DEVOPS.md)
|
||||||
- **09 – [API & CLI Reference](09_API_CLI_REFERENCE.md)**
|
- **09 – [API & CLI Reference](09_API_CLI_REFERENCE.md)**
|
||||||
- **10 – [Plug‑in SDK Guide](10_PLUGIN_SDK_GUIDE.md)**
|
- **10 – [Plug‑in SDK Guide](10_PLUGIN_SDK_GUIDE.md)**
|
||||||
- **10 – [Feedser CLI Quickstart](10_FEEDSER_CLI_QUICKSTART.md)**
|
- **10 – [Concelier CLI Quickstart](10_CONCELIER_CLI_QUICKSTART.md)**
|
||||||
- **30 – [Excititor Connector Packaging Guide](dev/30_EXCITITOR_CONNECTOR_GUIDE.md)**
|
- **30 – [Excititor Connector Packaging Guide](dev/30_EXCITITOR_CONNECTOR_GUIDE.md)**
|
||||||
- **30 – Developer Templates**
|
- **30 – Developer Templates**
|
||||||
- [Excititor Connector Skeleton](dev/templates/excititor-connector/)
|
- [Excititor Connector Skeleton](dev/templates/excititor-connector/)
|
||||||
@@ -67,12 +67,12 @@ Everything here is open‑source and versioned — when you check out a git ta
|
|||||||
- **22 – [CI/CD Recipes Library](ci/20_CI_RECIPES.md)**
|
- **22 – [CI/CD Recipes Library](ci/20_CI_RECIPES.md)**
|
||||||
- **23 – [FAQ](23_FAQ_MATRIX.md)**
|
- **23 – [FAQ](23_FAQ_MATRIX.md)**
|
||||||
- **24 – [Offline Update Kit Admin Guide](24_OFFLINE_KIT.md)**
|
- **24 – [Offline Update Kit Admin Guide](24_OFFLINE_KIT.md)**
|
||||||
- **25 – [Feedser Apple Connector Operations](ops/feedser-apple-operations.md)**
|
- **25 – [Concelier Apple Connector Operations](ops/concelier-apple-operations.md)**
|
||||||
- **26 – [Authority Key Rotation Playbook](ops/authority-key-rotation.md)**
|
- **26 – [Authority Key Rotation Playbook](ops/authority-key-rotation.md)**
|
||||||
- **27 – [Feedser CCCS Connector Operations](ops/feedser-cccs-operations.md)**
|
- **27 – [Concelier CCCS Connector Operations](ops/concelier-cccs-operations.md)**
|
||||||
- **28 – [Feedser CISA ICS Connector Operations](ops/feedser-icscisa-operations.md)**
|
- **28 – [Concelier CISA ICS Connector Operations](ops/concelier-icscisa-operations.md)**
|
||||||
- **29 – [Feedser CERT-Bund Connector Operations](ops/feedser-certbund-operations.md)**
|
- **29 – [Concelier CERT-Bund Connector Operations](ops/concelier-certbund-operations.md)**
|
||||||
- **30 – [Feedser MSRC Connector – AAD Onboarding](ops/feedser-msrc-operations.md)**
|
- **30 – [Concelier MSRC Connector – AAD Onboarding](ops/concelier-msrc-operations.md)**
|
||||||
|
|
||||||
### Legal & licence
|
### Legal & licence
|
||||||
- **31 – [Legal & Quota FAQ](29_LEGAL_FAQ_QUOTA.md)**
|
- **31 – [Legal & Quota FAQ](29_LEGAL_FAQ_QUOTA.md)**
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
| DOC7.README-INDEX | DONE (2025-10-17) | Docs Guild | — | Refresh index docs (docs/README.md + root README) after architecture dossier split and Offline Kit overhaul. | ✅ ToC reflects new component architecture docs; ✅ root README highlights updated doc set; ✅ Offline Kit guide linked correctly. |
|
| DOC7.README-INDEX | DONE (2025-10-17) | Docs Guild | — | Refresh index docs (docs/README.md + root README) after architecture dossier split and Offline Kit overhaul. | ✅ ToC reflects new component architecture docs; ✅ root README highlights updated doc set; ✅ Offline Kit guide linked correctly. |
|
||||||
| DOC4.AUTH-PDG | REVIEW | Docs Guild, Plugin Team | PLG6.DOC | Copy-edit `docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, export lifecycle diagram, add LDAP RFC cross-link. | ✅ PR merged with polish; ✅ Diagram committed; ✅ Slack handoff posted. |
|
| DOC4.AUTH-PDG | REVIEW | Docs Guild, Plugin Team | PLG6.DOC | Copy-edit `docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, export lifecycle diagram, add LDAP RFC cross-link. | ✅ PR merged with polish; ✅ Diagram committed; ✅ Slack handoff posted. |
|
||||||
| DOC1.AUTH | DONE (2025-10-12) | Docs Guild, Authority Core | CORE5B.DOC | Draft `docs/11_AUTHORITY.md` covering architecture, configuration, bootstrap flows. | ✅ Architecture + config sections approved by Core; ✅ Samples reference latest options; ✅ Offline note added. |
|
| DOC1.AUTH | DONE (2025-10-12) | Docs Guild, Authority Core | CORE5B.DOC | Draft `docs/11_AUTHORITY.md` covering architecture, configuration, bootstrap flows. | ✅ Architecture + config sections approved by Core; ✅ Samples reference latest options; ✅ Offline note added. |
|
||||||
| DOC3.Feedser-Authority | DONE (2025-10-12) | Docs Guild, DevEx | FSR4 | Polish operator/runbook sections (DOC3/DOC5) to document Feedser authority rollout, bypass logging, and enforcement checklist. | ✅ DOC3/DOC5 updated with audit runbook references; ✅ enforcement deadline highlighted; ✅ Docs guild sign-off. |
|
| DOC3.Concelier-Authority | DONE (2025-10-12) | Docs Guild, DevEx | FSR4 | Polish operator/runbook sections (DOC3/DOC5) to document Concelier authority rollout, bypass logging, and enforcement checklist. | ✅ DOC3/DOC5 updated with audit runbook references; ✅ enforcement deadline highlighted; ✅ Docs guild sign-off. |
|
||||||
| DOC5.Feedser-Runbook | DONE (2025-10-12) | Docs Guild | DOC3.Feedser-Authority | Produce dedicated Feedser authority audit runbook covering log fields, monitoring recommendations, and troubleshooting steps. | ✅ Runbook published; ✅ linked from DOC3/DOC5; ✅ alerting guidance included. |
|
| DOC5.Concelier-Runbook | DONE (2025-10-12) | Docs Guild | DOC3.Concelier-Authority | Produce dedicated Concelier authority audit runbook covering log fields, monitoring recommendations, and troubleshooting steps. | ✅ Runbook published; ✅ linked from DOC3/DOC5; ✅ alerting guidance included. |
|
||||||
| FEEDDOCS-DOCS-05-001 | DONE (2025-10-11) | Docs Guild | FEEDMERGE-ENGINE-04-001, FEEDMERGE-ENGINE-04-002 | Publish Feedser conflict resolution runbook covering precedence workflow, merge-event auditing, and Sprint 3 metrics. | ✅ `docs/ops/feedser-conflict-resolution.md` committed; ✅ metrics/log tables align with latest merge code; ✅ Ops alert guidance handed to Feedser team. |
|
| FEEDDOCS-DOCS-05-001 | DONE (2025-10-11) | Docs Guild | FEEDMERGE-ENGINE-04-001, FEEDMERGE-ENGINE-04-002 | Publish Concelier conflict resolution runbook covering precedence workflow, merge-event auditing, and Sprint 3 metrics. | ✅ `docs/ops/concelier-conflict-resolution.md` committed; ✅ metrics/log tables align with latest merge code; ✅ Ops alert guidance handed to Concelier team. |
|
||||||
| FEEDDOCS-DOCS-05-002 | DONE (2025-10-16) | Docs Guild, Feedser Ops | FEEDDOCS-DOCS-05-001 | Ops sign-off captured: conflict runbook circulated, alert thresholds tuned, and rollout decisions documented in change log. | ✅ Ops review recorded; ✅ alert thresholds finalised using `docs/ops/feedser-authority-audit-runbook.md`; ✅ change-log entry linked from runbook once GHSA/NVD/OSV regression fixtures land. |
|
| FEEDDOCS-DOCS-05-002 | DONE (2025-10-16) | Docs Guild, Concelier Ops | FEEDDOCS-DOCS-05-001 | Ops sign-off captured: conflict runbook circulated, alert thresholds tuned, and rollout decisions documented in change log. | ✅ Ops review recorded; ✅ alert thresholds finalised using `docs/ops/concelier-authority-audit-runbook.md`; ✅ change-log entry linked from runbook once GHSA/NVD/OSV regression fixtures land. |
|
||||||
|
|
||||||
> Update statuses (TODO/DOING/REVIEW/DONE/BLOCKED) as progress changes. Keep guides in sync with configuration samples under `etc/`.
|
> Update statuses (TODO/DOING/REVIEW/DONE/BLOCKED) as progress changes. Keep guides in sync with configuration samples under `etc/`.
|
||||||
|
|
||||||
|
|||||||
@@ -101,5 +101,5 @@
|
|||||||
|
|
||||||
<!-- Notes -->
|
<!-- Notes -->
|
||||||
<text class="note" x="40" y="210">429 path → add `authority.client_id`, `authority.remote_ip` tags for dashboards.</text>
|
<text class="note" x="40" y="210">429 path → add `authority.client_id`, `authority.remote_ip` tags for dashboards.</text>
|
||||||
<text class="note" x="40" y="240">Lockout path → reuse precedence strategy from Feedser dedup (see DEDUP_CONFLICTS_RESOLUTION_ALGO.md).</text>
|
<text class="note" x="40" y="240">Lockout path → reuse precedence strategy from Concelier dedup (see DEDUP_CONFLICTS_RESOLUTION_ALGO.md).</text>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
@@ -1,4 +1,4 @@
|
|||||||
# Feedser Connector Research – 2025-10-11
|
# Concelier Connector Research – 2025-10-11
|
||||||
|
|
||||||
Snapshot of direct network checks performed on 2025-10-11 (UTC) for the national/vendor connectors in scope. Use alongside each module’s `TASKS.md` notes.
|
Snapshot of direct network checks performed on 2025-10-11 (UTC) for the national/vendor connectors in scope. Use alongside each module’s `TASKS.md` notes.
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ Snapshot of direct network checks performed on 2025-10-11 (UTC) for the national
|
|||||||
|
|
||||||
## CCCS (Canada)
|
## CCCS (Canada)
|
||||||
- JSON endpoint (`https://www.cyber.gc.ca/api/cccs/threats/v1/get?lang=<lang>&content_type=cccs_threat`) returns ~5 100 records per language; `page=<n>` still works for segmented pulls and the earliest `date_created` seen is 2018‑06‑08 (EN) / 2018‑06‑08 (FR). Use an explicit `User-Agent` to avoid 403 responses.
|
- JSON endpoint (`https://www.cyber.gc.ca/api/cccs/threats/v1/get?lang=<lang>&content_type=cccs_threat`) returns ~5 100 records per language; `page=<n>` still works for segmented pulls and the earliest `date_created` seen is 2018‑06‑08 (EN) / 2018‑06‑08 (FR). Use an explicit `User-Agent` to avoid 403 responses.
|
||||||
- Follow-up: telemetry, sanitiser coverage, and backfill procedures are documented in `docs/ops/feedser-cccs-operations.md` (2025‑10‑15). Adjust `maxEntriesPerFetch` when performing historical sweeps so cursor state remains responsive.
|
- Follow-up: telemetry, sanitiser coverage, and backfill procedures are documented in `docs/ops/concelier-cccs-operations.md` (2025‑10‑15). Adjust `maxEntriesPerFetch` when performing historical sweeps so cursor state remains responsive.
|
||||||
|
|
||||||
## CERT-Bund (Germany)
|
## CERT-Bund (Germany)
|
||||||
- `https://wid.cert-bund.de/content/public/securityAdvisory/rss` responds 200 without cookies (≈250-item window, German taxonomy). Detail links load an Angular SPA that fetches JSON behind the bootstrap session.
|
- `https://wid.cert-bund.de/content/public/securityAdvisory/rss` responds 200 without cookies (≈250-item window, German taxonomy). Detail links load an Angular SPA that fetches JSON behind the bootstrap session.
|
||||||
@@ -16,7 +16,7 @@ Snapshot of direct network checks performed on 2025-10-11 (UTC) for the national
|
|||||||
- Historical advisories accessible through the SPA search/export endpoints once the `XSRF-TOKEN` cookie (exposed via `GET /portal/api/security/csrf`) is supplied with the `X-XSRF-TOKEN` header:
|
- Historical advisories accessible through the SPA search/export endpoints once the `XSRF-TOKEN` cookie (exposed via `GET /portal/api/security/csrf`) is supplied with the `X-XSRF-TOKEN` header:
|
||||||
- `POST /portal/api/securityadvisory/search` (`{"page":N,"size":100,"sort":["published,desc"]}`) pages data back to 2014.
|
- `POST /portal/api/securityadvisory/search` (`{"page":N,"size":100,"sort":["published,desc"]}`) pages data back to 2014.
|
||||||
- `GET /portal/api/securityadvisory/export?format=json&from=YYYY-MM-DD` emits JSON bundles suitable for Offline Kit mirrors.
|
- `GET /portal/api/securityadvisory/export?format=json&from=YYYY-MM-DD` emits JSON bundles suitable for Offline Kit mirrors.
|
||||||
- Locale note: content is German-only; Feedser preserves `language=de` and Docs will publish a CERT-Bund glossary so operators can bridge terminology without machine translation.
|
- Locale note: content is German-only; Concelier preserves `language=de` and Docs will publish a CERT-Bund glossary so operators can bridge terminology without machine translation.
|
||||||
|
|
||||||
## KISA / KNVD (Korea)
|
## KISA / KNVD (Korea)
|
||||||
- `https://knvd.krcert.or.kr/rss/securityInfo.do` and `/rss/securityNotice.do` return UTF-8 RSS (10-item window) with `detailDos.do?IDX=` links. No cookies required for feed fetch.
|
- `https://knvd.krcert.or.kr/rss/securityInfo.do` and `/rss/securityNotice.do` return UTF-8 RSS (10-item window) with `detailDos.do?IDX=` links. No cookies required for feed fetch.
|
||||||
@@ -24,11 +24,11 @@ Snapshot of direct network checks performed on 2025-10-11 (UTC) for the national
|
|||||||
|
|
||||||
## BDU (Russia / FSTEC)
|
## BDU (Russia / FSTEC)
|
||||||
- Candidate endpoints (`https://bdu.fstec.ru/component/rsform/form/7-bdu?format=xml/json`) return 403/404; TLS chain requires Russian Trusted Sub CA and WAF expects additional headers.
|
- Candidate endpoints (`https://bdu.fstec.ru/component/rsform/form/7-bdu?format=xml/json`) return 403/404; TLS chain requires Russian Trusted Sub CA and WAF expects additional headers.
|
||||||
- Next actions: acquire official PEM chain, point `feedser:httpClients:source.bdu:trustedRootPaths` (or `feedser:sources:bdu:http:trustedRootPaths`) at the Offline Kit PEM, keep `allowInvalidCertificates=false`, script session bootstrap, then capture RSS/HTML schema for parser work.
|
- Next actions: acquire official PEM chain, point `concelier:httpClients:source.bdu:trustedRootPaths` (or `concelier:sources:bdu:http:trustedRootPaths`) at the Offline Kit PEM, keep `allowInvalidCertificates=false`, script session bootstrap, then capture RSS/HTML schema for parser work.
|
||||||
|
|
||||||
## NKTsKI / cert.gov.ru (Russia)
|
## NKTsKI / cert.gov.ru (Russia)
|
||||||
- `https://cert.gov.ru/rss/advisories.xml` served via Bitrix returns 403/404 even with `Accept-Language: ru-RU`; TLS chain also requires Russian trust anchors.
|
- `https://cert.gov.ru/rss/advisories.xml` served via Bitrix returns 403/404 even with `Accept-Language: ru-RU`; TLS chain also requires Russian trust anchors.
|
||||||
- Next actions: source trust store, configure `feedser:httpClients:source.nkcki:trustedRootPaths` (Offline Kit root via `feedser:offline:root`), prepare proxy fallback, and once accessible document taxonomy/retention plus attachment handling.
|
- Next actions: source trust store, configure `concelier:httpClients:source.nkcki:trustedRootPaths` (Offline Kit root via `concelier:offline:root`), prepare proxy fallback, and once accessible document taxonomy/retention plus attachment handling.
|
||||||
|
|
||||||
## CISA ICS (United States)
|
## CISA ICS (United States)
|
||||||
- `curl -I https://www.cisa.gov/cybersecurity-advisories/ics-advisories.xml` returns HTTP 403 + `x-reference-error` (Akamai). Same for legacy feed paths.
|
- `curl -I https://www.cisa.gov/cybersecurity-advisories/ics-advisories.xml` returns HTTP 403 + `x-reference-error` (Akamai). Same for legacy feed paths.
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
> **Status:** Updated 2025-10-11 (AUTHPLUG-DOCS-01-001) with lifecycle + limiter diagrams and refreshed rate-limit guidance aligned to PLG6 acceptance criteria.
|
> **Status:** Updated 2025-10-11 (AUTHPLUG-DOCS-01-001) with lifecycle + limiter diagrams and refreshed rate-limit guidance aligned to PLG6 acceptance criteria.
|
||||||
|
|
||||||
## 1. Overview
|
## 1. Overview
|
||||||
Authority plug-ins extend the **StellaOps Authority** service with custom identity providers, credential stores, and client-management logic. Unlike Feedser plug-ins (which ingest or export advisories), Authority plug-ins participate directly in authentication flows:
|
Authority plug-ins extend the **StellaOps Authority** service with custom identity providers, credential stores, and client-management logic. Unlike Concelier plug-ins (which ingest or export advisories), Authority plug-ins participate directly in authentication flows:
|
||||||
|
|
||||||
- **Use cases:** integrate corporate directories (LDAP/AD), delegate to external IDPs, enforce bespoke password/lockout policies, or add client provisioning automation.
|
- **Use cases:** integrate corporate directories (LDAP/AD), delegate to external IDPs, enforce bespoke password/lockout policies, or add client provisioning automation.
|
||||||
- **Constraints:** plug-ins load only during service start (no hot-reload), must function without outbound internet access, and must emit deterministic results for identical configuration and input data.
|
- **Constraints:** plug-ins load only during service start (no hot-reload), must function without outbound internet access, and must emit deterministic results for identical configuration and input data.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# StellaOps Auth Client — Integration Guide
|
# StellaOps Auth Client — Integration Guide
|
||||||
|
|
||||||
> **Status:** Drafted 2025-10-10 as part of LIB5. Consumer teams (Feedser, CLI, Agent) should review before wiring the new options into their configuration surfaces.
|
> **Status:** Drafted 2025-10-10 as part of LIB5. Consumer teams (Concelier, CLI, Agent) should review before wiring the new options into their configuration surfaces.
|
||||||
|
|
||||||
The `StellaOps.Auth.Client` library provides a resilient OpenID Connect client for services and tools that talk to **StellaOps Authority**. LIB5 introduced configurable HTTP retry/backoff policies and an offline-fallback window so downstream components stay deterministic even when Authority is briefly unavailable.
|
The `StellaOps.Auth.Client` library provides a resilient OpenID Connect client for services and tools that talk to **StellaOps Authority**. LIB5 introduced configurable HTTP retry/backoff policies and an offline-fallback window so downstream components stay deterministic even when Authority is briefly unavailable.
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ services.AddStellaOpsAuthClient(options =>
|
|||||||
options.Authority = configuration["StellaOps:Authority:Url"]!;
|
options.Authority = configuration["StellaOps:Authority:Url"]!;
|
||||||
options.ClientId = configuration["StellaOps:Authority:ClientId"]!;
|
options.ClientId = configuration["StellaOps:Authority:ClientId"]!;
|
||||||
options.ClientSecret = configuration["StellaOps:Authority:ClientSecret"];
|
options.ClientSecret = configuration["StellaOps:Authority:ClientSecret"];
|
||||||
options.DefaultScopes.Add("feedser.jobs.trigger");
|
options.DefaultScopes.Add("concelier.jobs.trigger");
|
||||||
|
|
||||||
options.EnableRetries = true;
|
options.EnableRetries = true;
|
||||||
options.RetryDelays.Clear();
|
options.RetryDelays.Clear();
|
||||||
@@ -53,7 +53,7 @@ Suggested configuration keys (coordinate with consuming teams before finalising)
|
|||||||
StellaOps:
|
StellaOps:
|
||||||
Authority:
|
Authority:
|
||||||
Url: "https://authority.stella-ops.local"
|
Url: "https://authority.stella-ops.local"
|
||||||
ClientId: "feedser"
|
ClientId: "concelier"
|
||||||
ClientSecret: "change-me"
|
ClientSecret: "change-me"
|
||||||
AuthClient:
|
AuthClient:
|
||||||
EnableRetries: true
|
EnableRetries: true
|
||||||
@@ -72,7 +72,7 @@ STELLAOPS__AUTHORITY__AUTHCLIENT__RETRYDELAYS__0=00:00:02
|
|||||||
STELLAOPS__AUTHORITY__AUTHCLIENT__OFFLINECACHETOLERANCE=00:05:00
|
STELLAOPS__AUTHORITY__AUTHCLIENT__OFFLINECACHETOLERANCE=00:05:00
|
||||||
```
|
```
|
||||||
|
|
||||||
CLI and Feedser teams should expose these knobs once they adopt the auth client.
|
CLI and Concelier teams should expose these knobs once they adopt the auth client.
|
||||||
|
|
||||||
## 4. Testing recommendations
|
## 4. Testing recommendations
|
||||||
|
|
||||||
@@ -88,4 +88,4 @@ CLI and Feedser teams should expose these knobs once they adopt the auth client.
|
|||||||
- [ ] Extend smoke tests to cover Authority outage scenarios.
|
- [ ] Extend smoke tests to cover Authority outage scenarios.
|
||||||
- [ ] Coordinate with Docs Guild so user-facing quickstarts reference the new knobs.
|
- [ ] Coordinate with Docs Guild so user-facing quickstarts reference the new knobs.
|
||||||
|
|
||||||
Once Feedser and CLI integrate these changes, we can mark LIB5 **DONE**; further packaging work is deferred until the backlog reintroduces it.
|
Once Concelier and CLI integrate these changes, we can mark LIB5 **DONE**; further packaging work is deferred until the backlog reintroduces it.
|
||||||
|
|||||||
@@ -1,45 +1,45 @@
|
|||||||
# Feedser Fixture Maintenance
|
# Concelier Fixture Maintenance
|
||||||
|
|
||||||
Feedser uses a handful of deterministic fixtures to keep connector regressions in check. This guide lists the
|
Concelier uses a handful of deterministic fixtures to keep connector regressions in check. This guide lists the
|
||||||
fixture sets, where they live, and how to regenerate them safely.
|
fixture sets, where they live, and how to regenerate them safely.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## GHSA ↔ OSV parity fixtures
|
## GHSA ↔ OSV parity fixtures
|
||||||
|
|
||||||
- **Location:** `src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.*.json`
|
- **Location:** `src/StellaOps.Concelier.Source.Osv.Tests/Fixtures/osv-ghsa.*.json`
|
||||||
- **Purpose:** Exercised by `OsvGhsaParityRegressionTests` to ensure OSV + GHSA outputs stay aligned on aliases,
|
- **Purpose:** Exercised by `OsvGhsaParityRegressionTests` to ensure OSV + GHSA outputs stay aligned on aliases,
|
||||||
ranges, references, and credits.
|
ranges, references, and credits.
|
||||||
- **Regeneration:** Either run the test harness with online regeneration (`UPDATE_PARITY_FIXTURES=1 dotnet test src/StellaOps.Feedser.Source.Osv.Tests/StellaOps.Feedser.Source.Osv.Tests.csproj`)
|
- **Regeneration:** Either run the test harness with online regeneration (`UPDATE_PARITY_FIXTURES=1 dotnet test src/StellaOps.Concelier.Source.Osv.Tests/StellaOps.Concelier.Source.Osv.Tests.csproj`)
|
||||||
or execute the fixture updater (`dotnet run --project tools/FixtureUpdater/FixtureUpdater.csproj`). Both paths
|
or execute the fixture updater (`dotnet run --project tools/FixtureUpdater/FixtureUpdater.csproj`). Both paths
|
||||||
normalise timestamps and canonical ordering.
|
normalise timestamps and canonical ordering.
|
||||||
- **SemVer provenance:** The regenerated fixtures should show `normalizedVersions[].notes` in the
|
- **SemVer provenance:** The regenerated fixtures should show `normalizedVersions[].notes` in the
|
||||||
`osv:{ecosystem}:{advisoryId}:{identifier}` shape emitted by `SemVerRangeRuleBuilder`. Confirm the
|
`osv:{ecosystem}:{advisoryId}:{identifier}` shape emitted by `SemVerRangeRuleBuilder`. Confirm the
|
||||||
constraints and notes line up with GHSA/NVD composites before committing.
|
constraints and notes line up with GHSA/NVD composites before committing.
|
||||||
- **Verification:** Inspect the diff, then re-run `dotnet test src/StellaOps.Feedser.Source.Osv.Tests/StellaOps.Feedser.Source.Osv.Tests.csproj` to confirm parity.
|
- **Verification:** Inspect the diff, then re-run `dotnet test src/StellaOps.Concelier.Source.Osv.Tests/StellaOps.Concelier.Source.Osv.Tests.csproj` to confirm parity.
|
||||||
|
|
||||||
## GHSA credit parity fixtures
|
## GHSA credit parity fixtures
|
||||||
|
|
||||||
- **Location:** `src/StellaOps.Feedser.Source.Ghsa.Tests/Fixtures/credit-parity.{ghsa,osv,nvd}.json`
|
- **Location:** `src/StellaOps.Concelier.Source.Ghsa.Tests/Fixtures/credit-parity.{ghsa,osv,nvd}.json`
|
||||||
- **Purpose:** Exercised by `GhsaCreditParityRegressionTests` to guarantee GHSA/NVD/OSV acknowledgements remain in lockstep.
|
- **Purpose:** Exercised by `GhsaCreditParityRegressionTests` to guarantee GHSA/NVD/OSV acknowledgements remain in lockstep.
|
||||||
- **Regeneration:** `dotnet run --project tools/FixtureUpdater/FixtureUpdater.csproj` rewrites all three canonical snapshots.
|
- **Regeneration:** `dotnet run --project tools/FixtureUpdater/FixtureUpdater.csproj` rewrites all three canonical snapshots.
|
||||||
- **Verification:** `dotnet test src/StellaOps.Feedser.Source.Ghsa.Tests/StellaOps.Feedser.Source.Ghsa.Tests.csproj`.
|
- **Verification:** `dotnet test src/StellaOps.Concelier.Source.Ghsa.Tests/StellaOps.Concelier.Source.Ghsa.Tests.csproj`.
|
||||||
|
|
||||||
> Always commit fixture changes together with the code that motivated them and reference the regression test that guards the behaviour.
|
> Always commit fixture changes together with the code that motivated them and reference the regression test that guards the behaviour.
|
||||||
|
|
||||||
## Apple security update fixtures
|
## Apple security update fixtures
|
||||||
|
|
||||||
- **Location:** `src/StellaOps.Feedser.Source.Vndr.Apple.Tests/Apple/Fixtures/*.html` and `.expected.json`.
|
- **Location:** `src/StellaOps.Concelier.Source.Vndr.Apple.Tests/Apple/Fixtures/*.html` and `.expected.json`.
|
||||||
- **Purpose:** Exercised by `AppleLiveRegressionTests` to guarantee the Apple HTML parser and mapper stay deterministic while covering Rapid Security Responses and multi-device advisories.
|
- **Purpose:** Exercised by `AppleLiveRegressionTests` to guarantee the Apple HTML parser and mapper stay deterministic while covering Rapid Security Responses and multi-device advisories.
|
||||||
- **Regeneration:** Use the helper scripts (`scripts/update-apple-fixtures.sh` or `scripts/update-apple-fixtures.ps1`). They export `UPDATE_APPLE_FIXTURES=1`, propagate the flag through `WSLENV`, touch `.update-apple-fixtures`, and then run the Apple test project. This keeps WSL/VSCode test invocations in sync while the refresh workflow fetches live Apple support pages, sanitises them, and rewrites both the HTML and expected DTO snapshots with normalised ordering.
|
- **Regeneration:** Use the helper scripts (`scripts/update-apple-fixtures.sh` or `scripts/update-apple-fixtures.ps1`). They export `UPDATE_APPLE_FIXTURES=1`, propagate the flag through `WSLENV`, touch `.update-apple-fixtures`, and then run the Apple test project. This keeps WSL/VSCode test invocations in sync while the refresh workflow fetches live Apple support pages, sanitises them, and rewrites both the HTML and expected DTO snapshots with normalised ordering.
|
||||||
- **Verification:** Inspect the generated diffs and re-run `dotnet test src/StellaOps.Feedser.Source.Vndr.Apple.Tests/StellaOps.Feedser.Source.Vndr.Apple.Tests.csproj` without the env var to confirm determinism.
|
- **Verification:** Inspect the generated diffs and re-run `dotnet test src/StellaOps.Concelier.Source.Vndr.Apple.Tests/StellaOps.Concelier.Source.Vndr.Apple.Tests.csproj` without the env var to confirm determinism.
|
||||||
|
|
||||||
> **Tip for other connector owners:** mirror the sentinel + `WSLENV` pattern (`touch .update-<connector>-fixtures`, append the env var via `WSLENV`) when you add fixture refresh scripts so contributors running under WSL inherit the regeneration flag automatically.
|
> **Tip for other connector owners:** mirror the sentinel + `WSLENV` pattern (`touch .update-<connector>-fixtures`, append the env var via `WSLENV`) when you add fixture refresh scripts so contributors running under WSL inherit the regeneration flag automatically.
|
||||||
|
|
||||||
## KISA advisory fixtures
|
## KISA advisory fixtures
|
||||||
|
|
||||||
- **Location:** `src/StellaOps.Feedser.Source.Kisa.Tests/Fixtures/kisa-{feed,detail}.(xml|json)`
|
- **Location:** `src/StellaOps.Concelier.Source.Kisa.Tests/Fixtures/kisa-{feed,detail}.(xml|json)`
|
||||||
- **Purpose:** Used by `KisaConnectorTests` to verify Hangul-aware fetch → parse → map flows and to assert telemetry counters stay wired.
|
- **Purpose:** Used by `KisaConnectorTests` to verify Hangul-aware fetch → parse → map flows and to assert telemetry counters stay wired.
|
||||||
- **Regeneration:** `UPDATE_KISA_FIXTURES=1 dotnet test src/StellaOps.Feedser.Source.Kisa.Tests/StellaOps.Feedser.Source.Kisa.Tests.csproj`
|
- **Regeneration:** `UPDATE_KISA_FIXTURES=1 dotnet test src/StellaOps.Concelier.Source.Kisa.Tests/StellaOps.Concelier.Source.Kisa.Tests.csproj`
|
||||||
- **Verification:** Re-run the same test suite without the env var; confirm advisory content remains NFC-normalised and HTML is sanitised. Metrics assertions will fail if counters drift.
|
- **Verification:** Re-run the same test suite without the env var; confirm advisory content remains NFC-normalised and HTML is sanitised. Metrics assertions will fail if counters drift.
|
||||||
- **Localisation note:** RSS `category` values (e.g. `취약점정보`) remain in Hangul—do not translate them in fixtures; they feed directly into metrics/log tags.
|
- **Localisation note:** RSS `category` values (e.g. `취약점정보`) remain in Hangul—do not translate them in fixtures; they feed directly into metrics/log tags.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ The KISA/KNVD connector now ships with structured telemetry, richer logging, and
|
|||||||
|
|
||||||
## Telemetry counters
|
## Telemetry counters
|
||||||
|
|
||||||
All metrics are emitted from `KisaDiagnostics` (`Meter` name `StellaOps.Feedser.Source.Kisa`).
|
All metrics are emitted from `KisaDiagnostics` (`Meter` name `StellaOps.Concelier.Source.Kisa`).
|
||||||
|
|
||||||
| Metric | Description | Tags |
|
| Metric | Description | Tags |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
@@ -39,7 +39,7 @@ The messages use structured properties (`Idx`, `Category`, `DocumentId`, `Severi
|
|||||||
- Hangul fields (`title`, `summary`, `category`, `reference.label`, product vendor/name) are normalised to NFC before storage. Sample category `취약점정보` roughly translates to “vulnerability information”.
|
- Hangul fields (`title`, `summary`, `category`, `reference.label`, product vendor/name) are normalised to NFC before storage. Sample category `취약점정보` roughly translates to “vulnerability information”.
|
||||||
- Advisory HTML is sanitised via `HtmlContentSanitizer`, stripping script/style while preserving inline anchors for translation pipelines.
|
- Advisory HTML is sanitised via `HtmlContentSanitizer`, stripping script/style while preserving inline anchors for translation pipelines.
|
||||||
- Metrics carry Hangul `category` tags and logging keeps Hangul strings intact; this ensures air-gapped operators can validate native-language content without relying on MT.
|
- Metrics carry Hangul `category` tags and logging keeps Hangul strings intact; this ensures air-gapped operators can validate native-language content without relying on MT.
|
||||||
- Fixtures live under `src/StellaOps.Feedser.Source.Kisa.Tests/Fixtures/`. Regenerate with `UPDATE_KISA_FIXTURES=1 dotnet test src/StellaOps.Feedser.Source.Kisa.Tests/StellaOps.Feedser.Source.Kisa.Tests.csproj`.
|
- Fixtures live under `src/StellaOps.Concelier.Source.Kisa.Tests/Fixtures/`. Regenerate with `UPDATE_KISA_FIXTURES=1 dotnet test src/StellaOps.Concelier.Source.Kisa.Tests/StellaOps.Concelier.Source.Kisa.Tests.csproj`.
|
||||||
- The regression suite asserts canonical mapping, state cleanup, and telemetry counters (`KisaConnectorTests.Telemetry_RecordsMetrics`) so QA can track instrumentation drift.
|
- The regression suite asserts canonical mapping, state cleanup, and telemetry counters (`KisaConnectorTests.Telemetry_RecordsMetrics`) so QA can track instrumentation drift.
|
||||||
|
|
||||||
For operator docs, link to this brief when documenting Hangul handling or counter dashboards so localisation reviewers have a single reference point.
|
For operator docs, link to this brief when documenting Hangul handling or counter dashboards so localisation reviewers have a single reference point.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Feedser SemVer Merge Playbook (Sprint 1–2)
|
# Concelier SemVer Merge Playbook (Sprint 1–2)
|
||||||
|
|
||||||
This playbook describes how the merge layer and connector teams should emit the new SemVer primitives introduced in Sprint 1–2, how those primitives become normalized version rules, and how downstream jobs query them deterministically.
|
This playbook describes how the merge layer and connector teams should emit the new SemVer primitives introduced in Sprint 1–2, how those primitives become normalized version rules, and how downstream jobs query them deterministically.
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ This playbook describes how the merge layer and connector teams should emit the
|
|||||||
- `NormalizedVersionRule` documents the analytics-friendly projection of each `AffectedPackage` coverage entry and is persisted alongside legacy `versionRanges`.
|
- `NormalizedVersionRule` documents the analytics-friendly projection of each `AffectedPackage` coverage entry and is persisted alongside legacy `versionRanges`.
|
||||||
- `AdvisoryProvenance.decisionReason` records whether merge resolution favored precedence, freshness, or a tie-breaker comparison.
|
- `AdvisoryProvenance.decisionReason` records whether merge resolution favored precedence, freshness, or a tie-breaker comparison.
|
||||||
|
|
||||||
See `src/StellaOps.Feedser.Models/CANONICAL_RECORDS.md` for the full schema and field descriptions.
|
See `src/StellaOps.Concelier.Models/CANONICAL_RECORDS.md` for the full schema and field descriptions.
|
||||||
|
|
||||||
## 2. Mapper pattern
|
## 2. Mapper pattern
|
||||||
|
|
||||||
@@ -150,5 +150,5 @@ If a new scheme is required (for example, `apple.build` or `ios.semver`), raise
|
|||||||
|
|
||||||
## 9. Observability signals
|
## 9. Observability signals
|
||||||
|
|
||||||
- `feedser.merge.normalized_rules` (counter, tags: `package_type`, `scheme`) – increments once per normalized rule retained after precedence merge.
|
- `concelier.merge.normalized_rules` (counter, tags: `package_type`, `scheme`) – increments once per normalized rule retained after precedence merge.
|
||||||
- `feedser.merge.normalized_rules_missing` (counter, tags: `package_type`) – increments when a merged package still carries version ranges but no normalized rules; watch for spikes to catch connectors that have not emitted normalized arrays yet.
|
- `concelier.merge.normalized_rules_missing` (counter, tags: `package_type`) – increments when a merged package still carries version ranges but no normalized rules; watch for spikes to catch connectors that have not emitted normalized arrays yet.
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
This guide complements the Sprint 1–2 normalized versions rollout. It documents recommended indexes and aggregation patterns for querying `AffectedPackage.normalizedVersions`.
|
This guide complements the Sprint 1–2 normalized versions rollout. It documents recommended indexes and aggregation patterns for querying `AffectedPackage.normalizedVersions`.
|
||||||
|
|
||||||
For a field-by-field look at how normalized rules persist in MongoDB (including provenance metadata), see Section 8 of the [Feedser SemVer Merge Playbook](merge_semver_playbook.md).
|
For a field-by-field look at how normalized rules persist in MongoDB (including provenance metadata), see Section 8 of the [Concelier SemVer Merge Playbook](merge_semver_playbook.md).
|
||||||
|
|
||||||
## 1. Recommended indexes
|
## 1. Recommended indexes
|
||||||
|
|
||||||
When `feedser.storage.enableSemVerStyle` is enabled, advisories expose a flattened
|
When `concelier.storage.enableSemVerStyle` is enabled, advisories expose a flattened
|
||||||
`normalizedVersions` array at the document root. Create these indexes in `mongosh`
|
`normalizedVersions` array at the document root. Create these indexes in `mongosh`
|
||||||
after the migration completes (adjust collection name if you use a prefix):
|
after the migration completes (adjust collection name if you use a prefix):
|
||||||
|
|
||||||
@@ -105,4 +105,4 @@ Use this to confirm the merge dedupe logic keeps only one normalized rule per un
|
|||||||
- [ ] Notify downstream services that consume advisory snapshots about the new `normalizedVersions` array.
|
- [ ] Notify downstream services that consume advisory snapshots about the new `normalizedVersions` array.
|
||||||
- [ ] Update export fixtures once dedupe verification passes.
|
- [ ] Update export fixtures once dedupe verification passes.
|
||||||
|
|
||||||
Additional background and mapper examples live in [Feedser SemVer Merge Playbook](merge_semver_playbook.md).
|
Additional background and mapper examples live in [Concelier SemVer Merge Playbook](merge_semver_playbook.md).
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# Normalized Versions Rollout Dashboard (Sprint 2 – Feedser)
|
# Normalized Versions Rollout Dashboard (Sprint 2 – Concelier)
|
||||||
|
|
||||||
_Status date: 2025-10-12 17:05 UTC_
|
_Status date: 2025-10-12 17:05 UTC_
|
||||||
|
|
||||||
This dashboard tracks connector readiness for emitting `AffectedPackage.NormalizedVersions` arrays and highlights upcoming coordination checkpoints. Use it alongside:
|
This dashboard tracks connector readiness for emitting `AffectedPackage.NormalizedVersions` arrays and highlights upcoming coordination checkpoints. Use it alongside:
|
||||||
|
|
||||||
- [`src/StellaOps.Feedser.Merge/RANGE_PRIMITIVES_COORDINATION.md`](../../src/StellaOps.Feedser.Merge/RANGE_PRIMITIVES_COORDINATION.md) for detailed guidance and timelines.
|
- [`src/StellaOps.Concelier.Merge/RANGE_PRIMITIVES_COORDINATION.md`](../../src/StellaOps.Concelier.Merge/RANGE_PRIMITIVES_COORDINATION.md) for detailed guidance and timelines.
|
||||||
- [Feedser SemVer Merge Playbook](merge_semver_playbook.md) §8 for persisted Mongo document shapes.
|
- [Concelier SemVer Merge Playbook](merge_semver_playbook.md) §8 for persisted Mongo document shapes.
|
||||||
- [Normalized Versions Query Guide](mongo_indices.md) for index/query validation steps.
|
- [Normalized Versions Query Guide](mongo_indices.md) for index/query validation steps.
|
||||||
|
|
||||||
## Key milestones
|
## Key milestones
|
||||||
@@ -18,28 +18,28 @@ This dashboard tracks connector readiness for emitting `AffectedPackage.Normaliz
|
|||||||
|
|
||||||
| Connector | Owner team | Normalized versions status | Last update | Next action / link |
|
| Connector | Owner team | Normalized versions status | Last update | Next action / link |
|
||||||
|-----------|------------|---------------------------|-------------|--------------------|
|
|-----------|------------|---------------------------|-------------|--------------------|
|
||||||
| Acsc | BE-Conn-ACSC | ❌ Not started – mapper pending | 2025-10-11 | Design DTOs + mapper with normalized rule array; see `src/StellaOps.Feedser.Source.Acsc/TASKS.md`. |
|
| Acsc | BE-Conn-ACSC | ❌ Not started – mapper pending | 2025-10-11 | Design DTOs + mapper with normalized rule array; see `src/StellaOps.Concelier.Source.Acsc/TASKS.md`. |
|
||||||
| Cccs | BE-Conn-CCCS | ❌ Not started – mapper pending | 2025-10-11 | Add normalized SemVer array in canonical mapper; coordinate fixtures per `TASKS.md`. |
|
| Cccs | BE-Conn-CCCS | ❌ Not started – mapper pending | 2025-10-11 | Add normalized SemVer array in canonical mapper; coordinate fixtures per `TASKS.md`. |
|
||||||
| CertBund | BE-Conn-CERTBUND | ✅ Canonical mapper emitting vendor ranges | 2025-10-14 | Normalized vendor range payloads landed alongside telemetry/docs updates; see `src/StellaOps.Feedser.Source.CertBund/TASKS.md`. |
|
| CertBund | BE-Conn-CERTBUND | ✅ Canonical mapper emitting vendor ranges | 2025-10-14 | Normalized vendor range payloads landed alongside telemetry/docs updates; see `src/StellaOps.Concelier.Source.CertBund/TASKS.md`. |
|
||||||
| CertCc | BE-Conn-CERTCC | ⚠️ In progress – fetch pipeline DOING | 2025-10-11 | Implement VINCE mapper with SemVer/NEVRA rules; unblock snapshot regeneration; `src/StellaOps.Feedser.Source.CertCc/TASKS.md`. |
|
| CertCc | BE-Conn-CERTCC | ⚠️ In progress – fetch pipeline DOING | 2025-10-11 | Implement VINCE mapper with SemVer/NEVRA rules; unblock snapshot regeneration; `src/StellaOps.Concelier.Source.CertCc/TASKS.md`. |
|
||||||
| Kev | BE-Conn-KEV | ✅ Normalized catalog/due-date rules verified | 2025-10-12 | Fixtures reconfirmed via `dotnet test src/StellaOps.Feedser.Source.Kev.Tests`; `src/StellaOps.Feedser.Source.Kev/TASKS.md`. |
|
| Kev | BE-Conn-KEV | ✅ Normalized catalog/due-date rules verified | 2025-10-12 | Fixtures reconfirmed via `dotnet test src/StellaOps.Concelier.Source.Kev.Tests`; `src/StellaOps.Concelier.Source.Kev/TASKS.md`. |
|
||||||
| Cve | BE-Conn-CVE | ✅ Normalized SemVer rules verified | 2025-10-12 | Snapshot parity green (`dotnet test src/StellaOps.Feedser.Source.Cve.Tests`); `src/StellaOps.Feedser.Source.Cve/TASKS.md`. |
|
| Cve | BE-Conn-CVE | ✅ Normalized SemVer rules verified | 2025-10-12 | Snapshot parity green (`dotnet test src/StellaOps.Concelier.Source.Cve.Tests`); `src/StellaOps.Concelier.Source.Cve/TASKS.md`. |
|
||||||
| Ghsa | BE-Conn-GHSA | ⚠️ DOING – normalized rollout task active | 2025-10-11 18:45 UTC | Wire `SemVerRangeRuleBuilder` + refresh fixtures; `src/StellaOps.Feedser.Source.Ghsa/TASKS.md`. |
|
| Ghsa | BE-Conn-GHSA | ⚠️ DOING – normalized rollout task active | 2025-10-11 18:45 UTC | Wire `SemVerRangeRuleBuilder` + refresh fixtures; `src/StellaOps.Concelier.Source.Ghsa/TASKS.md`. |
|
||||||
| Osv | BE-Conn-OSV | ✅ SemVer mapper & parity fixtures verified | 2025-10-12 | GHSA parity regression passing (`dotnet test src/StellaOps.Feedser.Source.Osv.Tests`); `src/StellaOps.Feedser.Source.Osv/TASKS.md`. |
|
| Osv | BE-Conn-OSV | ✅ SemVer mapper & parity fixtures verified | 2025-10-12 | GHSA parity regression passing (`dotnet test src/StellaOps.Concelier.Source.Osv.Tests`); `src/StellaOps.Concelier.Source.Osv/TASKS.md`. |
|
||||||
| Ics.Cisa | BE-Conn-ICS-CISA | ❌ Not started – mapper TODO | 2025-10-11 | Plan SemVer/firmware scheme selection; `src/StellaOps.Feedser.Source.Ics.Cisa/TASKS.md`. |
|
| Ics.Cisa | BE-Conn-ICS-CISA | ❌ Not started – mapper TODO | 2025-10-11 | Plan SemVer/firmware scheme selection; `src/StellaOps.Concelier.Source.Ics.Cisa/TASKS.md`. |
|
||||||
| Kisa | BE-Conn-KISA | ✅ Landed 2025-10-14 (mapper + telemetry) | 2025-10-11 | Hangul-aware mapper emits normalized rules; see `docs/dev/kisa_connector_notes.md` for localisation/metric details. |
|
| Kisa | BE-Conn-KISA | ✅ Landed 2025-10-14 (mapper + telemetry) | 2025-10-11 | Hangul-aware mapper emits normalized rules; see `docs/dev/kisa_connector_notes.md` for localisation/metric details. |
|
||||||
| Ru.Bdu | BE-Conn-BDU | ✅ Raw scheme emitted | 2025-10-14 | Mapper now writes `ru-bdu.raw` normalized rules with provenance + telemetry; `src/StellaOps.Feedser.Source.Ru.Bdu/TASKS.md`. |
|
| Ru.Bdu | BE-Conn-BDU | ✅ Raw scheme emitted | 2025-10-14 | Mapper now writes `ru-bdu.raw` normalized rules with provenance + telemetry; `src/StellaOps.Concelier.Source.Ru.Bdu/TASKS.md`. |
|
||||||
| Ru.Nkcki | BE-Conn-Nkcki | ❌ Not started – mapper TODO | 2025-10-11 | Similar to BDU; ensure Cyrillic provenance preserved; `src/StellaOps.Feedser.Source.Ru.Nkcki/TASKS.md`. |
|
| Ru.Nkcki | BE-Conn-Nkcki | ❌ Not started – mapper TODO | 2025-10-11 | Similar to BDU; ensure Cyrillic provenance preserved; `src/StellaOps.Concelier.Source.Ru.Nkcki/TASKS.md`. |
|
||||||
| Vndr.Apple | BE-Conn-Apple | ✅ Shipped – emitting normalized arrays | 2025-10-11 | Continue fixture/tooling work; `src/StellaOps.Feedser.Source.Vndr.Apple/TASKS.md`. |
|
| Vndr.Apple | BE-Conn-Apple | ✅ Shipped – emitting normalized arrays | 2025-10-11 | Continue fixture/tooling work; `src/StellaOps.Concelier.Source.Vndr.Apple/TASKS.md`. |
|
||||||
| Vndr.Cisco | BE-Conn-Cisco | ✅ SemVer + vendor extensions emitted | 2025-10-14 | Connector outputs SemVer primitives with `cisco.productId` notes; see `CiscoMapper` and fixtures for coverage. |
|
| Vndr.Cisco | BE-Conn-Cisco | ✅ SemVer + vendor extensions emitted | 2025-10-14 | Connector outputs SemVer primitives with `cisco.productId` notes; see `CiscoMapper` and fixtures for coverage. |
|
||||||
| Vndr.Msrc | BE-Conn-MSRC | ✅ Map + normalized build rules landed | 2025-10-15 | `MsrcMapper` emits `msrc.build` normalized rules with CVRF references; see `src/StellaOps.Feedser.Source.Vndr.Msrc/TASKS.md`. |
|
| Vndr.Msrc | BE-Conn-MSRC | ✅ Map + normalized build rules landed | 2025-10-15 | `MsrcMapper` emits `msrc.build` normalized rules with CVRF references; see `src/StellaOps.Concelier.Source.Vndr.Msrc/TASKS.md`. |
|
||||||
| Nvd | BE-Conn-NVD | ⚠️ Needs follow-up – mapper complete but normalized array MR pending | 2025-10-11 | Align CVE notes + normalized payload flag; `src/StellaOps.Feedser.Source.Nvd/TASKS.md`. |
|
| Nvd | BE-Conn-NVD | ⚠️ Needs follow-up – mapper complete but normalized array MR pending | 2025-10-11 | Align CVE notes + normalized payload flag; `src/StellaOps.Concelier.Source.Nvd/TASKS.md`. |
|
||||||
|
|
||||||
Legend: ✅ complete, ⚠️ in progress/partial, ❌ not started.
|
Legend: ✅ complete, ⚠️ in progress/partial, ❌ not started.
|
||||||
|
|
||||||
## Monitoring
|
## Monitoring
|
||||||
|
|
||||||
- Merge now emits `feedser.merge.normalized_rules` (tags: `package_type`, `scheme`) and `feedser.merge.normalized_rules_missing` (tags: `package_type`). Track these counters to confirm normalized arrays land as connectors roll out.
|
- Merge now emits `concelier.merge.normalized_rules` (tags: `package_type`, `scheme`) and `concelier.merge.normalized_rules_missing` (tags: `package_type`). Track these counters to confirm normalized arrays land as connectors roll out.
|
||||||
- Expect `normalized_rules_missing` to trend toward zero as each connector flips on normalized output. Investigate any sustained counts by checking the corresponding module `TASKS.md`.
|
- Expect `normalized_rules_missing` to trend toward zero as each connector flips on normalized output. Investigate any sustained counts by checking the corresponding module `TASKS.md`.
|
||||||
|
|
||||||
## Implementation tips
|
## Implementation tips
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Feedser Apple Security Update Connector Operations
|
# Concelier Apple Security Update Connector Operations
|
||||||
|
|
||||||
This runbook covers staging and production rollout for the Apple security updates connector (`source:vndr-apple:*`), including observability checks and fixture maintenance.
|
This runbook covers staging and production rollout for the Apple security updates connector (`source:vndr-apple:*`), including observability checks and fixture maintenance.
|
||||||
|
|
||||||
@@ -6,10 +6,10 @@ This runbook covers staging and production rollout for the Apple security update
|
|||||||
|
|
||||||
- Network egress (or mirrored cache) for `https://gdmf.apple.com/v2/pmv` and the Apple Support domain (`https://support.apple.com/`).
|
- Network egress (or mirrored cache) for `https://gdmf.apple.com/v2/pmv` and the Apple Support domain (`https://support.apple.com/`).
|
||||||
- Optional: corporate proxy exclusions for the Apple hosts if outbound traffic is normally filtered.
|
- Optional: corporate proxy exclusions for the Apple hosts if outbound traffic is normally filtered.
|
||||||
- Updated configuration (environment variables or `feedser.yaml`) with an `apple` section. Example baseline:
|
- Updated configuration (environment variables or `concelier.yaml`) with an `apple` section. Example baseline:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
sources:
|
sources:
|
||||||
apple:
|
apple:
|
||||||
softwareLookupUri: "https://gdmf.apple.com/v2/pmv"
|
softwareLookupUri: "https://gdmf.apple.com/v2/pmv"
|
||||||
@@ -21,23 +21,23 @@ feedser:
|
|||||||
failureBackoff: "00:05:00"
|
failureBackoff: "00:05:00"
|
||||||
```
|
```
|
||||||
|
|
||||||
> ℹ️ `softwareLookupUri` and `advisoryBaseUri` must stay absolute and aligned with the HTTP allow-list; Feedser automatically adds both hosts to the connector HttpClient.
|
> ℹ️ `softwareLookupUri` and `advisoryBaseUri` must stay absolute and aligned with the HTTP allow-list; Concelier automatically adds both hosts to the connector HttpClient.
|
||||||
|
|
||||||
## 2. Staging Smoke Test
|
## 2. Staging Smoke Test
|
||||||
|
|
||||||
1. Deploy the configuration and restart the Feedser workers to ensure the Apple connector options are bound.
|
1. Deploy the configuration and restart the Concelier workers to ensure the Apple connector options are bound.
|
||||||
2. Trigger a full connector cycle:
|
2. Trigger a full connector cycle:
|
||||||
- CLI: `stella db jobs run source:vndr-apple:fetch --and-then source:vndr-apple:parse --and-then source:vndr-apple:map`
|
- CLI: `stella db jobs run source:vndr-apple:fetch --and-then source:vndr-apple:parse --and-then source:vndr-apple:map`
|
||||||
- REST: `POST /jobs/run { "kind": "source:vndr-apple:fetch", "chain": ["source:vndr-apple:parse", "source:vndr-apple:map"] }`
|
- REST: `POST /jobs/run { "kind": "source:vndr-apple:fetch", "chain": ["source:vndr-apple:parse", "source:vndr-apple:map"] }`
|
||||||
3. Validate metrics exported under meter `StellaOps.Feedser.Source.Vndr.Apple`:
|
3. Validate metrics exported under meter `StellaOps.Concelier.Source.Vndr.Apple`:
|
||||||
- `apple.fetch.items` (documents fetched)
|
- `apple.fetch.items` (documents fetched)
|
||||||
- `apple.fetch.failures`
|
- `apple.fetch.failures`
|
||||||
- `apple.fetch.unchanged`
|
- `apple.fetch.unchanged`
|
||||||
- `apple.parse.failures`
|
- `apple.parse.failures`
|
||||||
- `apple.map.affected.count` (histogram of affected package counts)
|
- `apple.map.affected.count` (histogram of affected package counts)
|
||||||
4. Cross-check the shared HTTP counters:
|
4. Cross-check the shared HTTP counters:
|
||||||
- `feedser.source.http.requests_total{feedser_source="vndr-apple"}` should increase for both index and detail phases.
|
- `concelier.source.http.requests_total{concelier_source="vndr-apple"}` should increase for both index and detail phases.
|
||||||
- `feedser.source.http.failures_total{feedser_source="vndr-apple"}` should remain flat (0) during a healthy run.
|
- `concelier.source.http.failures_total{concelier_source="vndr-apple"}` should remain flat (0) during a healthy run.
|
||||||
5. Inspect the info logs:
|
5. Inspect the info logs:
|
||||||
- `Apple software index fetch … processed=X newDocuments=Y`
|
- `Apple software index fetch … processed=X newDocuments=Y`
|
||||||
- `Apple advisory parse complete … aliases=… affected=…`
|
- `Apple advisory parse complete … aliases=… affected=…`
|
||||||
@@ -50,28 +50,28 @@ feedser:
|
|||||||
|
|
||||||
## 3. Production Monitoring
|
## 3. Production Monitoring
|
||||||
|
|
||||||
- **Dashboards** – Add the following expressions to your Feedser Grafana board (OTLP/Prometheus naming assumed):
|
- **Dashboards** – Add the following expressions to your Concelier Grafana board (OTLP/Prometheus naming assumed):
|
||||||
- `rate(apple_fetch_items_total[15m])` vs `rate(feedser_source_http_requests_total{feedser_source="vndr-apple"}[15m])`
|
- `rate(apple_fetch_items_total[15m])` vs `rate(concelier_source_http_requests_total{concelier_source="vndr-apple"}[15m])`
|
||||||
- `rate(apple_fetch_failures_total[5m])` for error spikes (`severity=warning` at `>0`)
|
- `rate(apple_fetch_failures_total[5m])` for error spikes (`severity=warning` at `>0`)
|
||||||
- `histogram_quantile(0.95, rate(apple_map_affected_count_bucket[1h]))` to watch affected-package fan-out
|
- `histogram_quantile(0.95, rate(apple_map_affected_count_bucket[1h]))` to watch affected-package fan-out
|
||||||
- `increase(apple_parse_failures_total[6h])` to catch parser drift (alerts at `>0`)
|
- `increase(apple_parse_failures_total[6h])` to catch parser drift (alerts at `>0`)
|
||||||
- **Alerts** – Page if `rate(apple_fetch_items_total[2h]) == 0` during business hours while other connectors are active. This often indicates lookup feed failures or misconfigured allow-lists.
|
- **Alerts** – Page if `rate(apple_fetch_items_total[2h]) == 0` during business hours while other connectors are active. This often indicates lookup feed failures or misconfigured allow-lists.
|
||||||
- **Logs** – Surface warnings `Apple document {DocumentId} missing GridFS payload` or `Apple parse failed`—repeated hits imply storage issues or HTML regressions.
|
- **Logs** – Surface warnings `Apple document {DocumentId} missing GridFS payload` or `Apple parse failed`—repeated hits imply storage issues or HTML regressions.
|
||||||
- **Telemetry pipeline** – `StellaOps.Feedser.WebService` now exports `StellaOps.Feedser.Source.Vndr.Apple` alongside existing Feedser meters; ensure your OTEL collector or Prometheus scraper includes it.
|
- **Telemetry pipeline** – `StellaOps.Concelier.WebService` now exports `StellaOps.Concelier.Source.Vndr.Apple` alongside existing Concelier meters; ensure your OTEL collector or Prometheus scraper includes it.
|
||||||
|
|
||||||
## 4. Fixture Maintenance
|
## 4. Fixture Maintenance
|
||||||
|
|
||||||
Regression fixtures live under `src/StellaOps.Feedser.Source.Vndr.Apple.Tests/Apple/Fixtures`. Refresh them whenever Apple reshapes the HT layout or when new platforms appear.
|
Regression fixtures live under `src/StellaOps.Concelier.Source.Vndr.Apple.Tests/Apple/Fixtures`. Refresh them whenever Apple reshapes the HT layout or when new platforms appear.
|
||||||
|
|
||||||
1. Run the helper script matching your platform:
|
1. Run the helper script matching your platform:
|
||||||
- Bash: `./scripts/update-apple-fixtures.sh`
|
- Bash: `./scripts/update-apple-fixtures.sh`
|
||||||
- PowerShell: `./scripts/update-apple-fixtures.ps1`
|
- PowerShell: `./scripts/update-apple-fixtures.ps1`
|
||||||
2. Each script exports `UPDATE_APPLE_FIXTURES=1`, updates the `WSLENV` passthrough, and touches `.update-apple-fixtures` so WSL+VS Code test runs observe the flag. The subsequent test execution fetches the live HT articles listed in `AppleFixtureManager`, sanitises the HTML, and rewrites the `.expected.json` DTO snapshots.
|
2. Each script exports `UPDATE_APPLE_FIXTURES=1`, updates the `WSLENV` passthrough, and touches `.update-apple-fixtures` so WSL+VS Code test runs observe the flag. The subsequent test execution fetches the live HT articles listed in `AppleFixtureManager`, sanitises the HTML, and rewrites the `.expected.json` DTO snapshots.
|
||||||
3. Review the diff for localisation or nav noise. Once satisfied, re-run the tests without the env var (`dotnet test src/StellaOps.Feedser.Source.Vndr.Apple.Tests/StellaOps.Feedser.Source.Vndr.Apple.Tests.csproj`) to verify determinism.
|
3. Review the diff for localisation or nav noise. Once satisfied, re-run the tests without the env var (`dotnet test src/StellaOps.Concelier.Source.Vndr.Apple.Tests/StellaOps.Concelier.Source.Vndr.Apple.Tests.csproj`) to verify determinism.
|
||||||
4. Commit fixture updates together with any parser/mapping changes that motivated them.
|
4. Commit fixture updates together with any parser/mapping changes that motivated them.
|
||||||
|
|
||||||
## 5. Known Issues & Follow-up Tasks
|
## 5. Known Issues & Follow-up Tasks
|
||||||
|
|
||||||
- Apple occasionally throttles anonymous requests after bursts. The connector backs off automatically, but persistent `apple.fetch.failures` spikes might require mirroring the HT content or scheduling wider fetch windows.
|
- Apple occasionally throttles anonymous requests after bursts. The connector backs off automatically, but persistent `apple.fetch.failures` spikes might require mirroring the HT content or scheduling wider fetch windows.
|
||||||
- Rapid Security Responses may appear before the general patch notes surface in the lookup JSON. When that happens, the fetch run will log `detailFailures>0`. Collect sample HTML and refresh fixtures to confirm parser coverage.
|
- Rapid Security Responses may appear before the general patch notes surface in the lookup JSON. When that happens, the fetch run will log `detailFailures>0`. Collect sample HTML and refresh fixtures to confirm parser coverage.
|
||||||
- Multi-locale content is still under regression sweep (`src/StellaOps.Feedser.Source.Vndr.Apple/TASKS.md`). Capture non-`en-us` snapshots once the fixture tooling stabilises.
|
- Multi-locale content is still under regression sweep (`src/StellaOps.Concelier.Source.Vndr.Apple/TASKS.md`). Capture non-`en-us` snapshots once the fixture tooling stabilises.
|
||||||
@@ -1,32 +1,32 @@
|
|||||||
# Feedser Authority Audit Runbook
|
# Concelier Authority Audit Runbook
|
||||||
|
|
||||||
_Last updated: 2025-10-12_
|
_Last updated: 2025-10-12_
|
||||||
|
|
||||||
This runbook helps operators verify and monitor the StellaOps Feedser ⇆ Authority integration. It focuses on the `/jobs*` surface, which now requires StellaOps Authority tokens, and the corresponding audit/metric signals that expose authentication and bypass activity.
|
This runbook helps operators verify and monitor the StellaOps Concelier ⇆ Authority integration. It focuses on the `/jobs*` surface, which now requires StellaOps Authority tokens, and the corresponding audit/metric signals that expose authentication and bypass activity.
|
||||||
|
|
||||||
## 1. Prerequisites
|
## 1. Prerequisites
|
||||||
|
|
||||||
- Authority integration is enabled in `feedser.yaml` (or via `FEEDSER_AUTHORITY__*` environment variables) with a valid `clientId`, secret, audience, and required scopes.
|
- Authority integration is enabled in `concelier.yaml` (or via `CONCELIER_AUTHORITY__*` environment variables) with a valid `clientId`, secret, audience, and required scopes.
|
||||||
- OTLP metrics/log exporters are configured (`feedser.telemetry.*`) or container stdout is shipped to your SIEM.
|
- OTLP metrics/log exporters are configured (`concelier.telemetry.*`) or container stdout is shipped to your SIEM.
|
||||||
- Operators have access to the Feedser job trigger endpoints via CLI or REST for smoke tests.
|
- Operators have access to the Concelier job trigger endpoints via CLI or REST for smoke tests.
|
||||||
|
|
||||||
### Configuration snippet
|
### Configuration snippet
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
authority:
|
authority:
|
||||||
enabled: true
|
enabled: true
|
||||||
allowAnonymousFallback: false # keep true only during initial rollout
|
allowAnonymousFallback: false # keep true only during initial rollout
|
||||||
issuer: "https://authority.internal"
|
issuer: "https://authority.internal"
|
||||||
audiences:
|
audiences:
|
||||||
- "api://feedser"
|
- "api://concelier"
|
||||||
requiredScopes:
|
requiredScopes:
|
||||||
- "feedser.jobs.trigger"
|
- "concelier.jobs.trigger"
|
||||||
bypassNetworks:
|
bypassNetworks:
|
||||||
- "127.0.0.1/32"
|
- "127.0.0.1/32"
|
||||||
- "::1/128"
|
- "::1/128"
|
||||||
clientId: "feedser-jobs"
|
clientId: "concelier-jobs"
|
||||||
clientSecretFile: "/run/secrets/feedser_authority_client"
|
clientSecretFile: "/run/secrets/concelier_authority_client"
|
||||||
tokenClockSkewSeconds: 60
|
tokenClockSkewSeconds: 60
|
||||||
resilience:
|
resilience:
|
||||||
enableRetries: true
|
enableRetries: true
|
||||||
@@ -38,22 +38,22 @@ feedser:
|
|||||||
offlineCacheTolerance: "00:10:00"
|
offlineCacheTolerance: "00:10:00"
|
||||||
```
|
```
|
||||||
|
|
||||||
> Store secrets outside source control. Feedser reads `clientSecretFile` on startup; rotate by updating the mounted file and restarting the service.
|
> Store secrets outside source control. Concelier reads `clientSecretFile` on startup; rotate by updating the mounted file and restarting the service.
|
||||||
|
|
||||||
### Resilience tuning
|
### Resilience tuning
|
||||||
|
|
||||||
- **Connected sites:** keep the default 1 s / 2 s / 5 s retry ladder so Feedser retries transient Authority hiccups but still surfaces outages quickly. Leave `allowOfflineCacheFallback=true` so cached discovery/JWKS data can bridge short Pathfinder restarts.
|
- **Connected sites:** keep the default 1 s / 2 s / 5 s retry ladder so Concelier retries transient Authority hiccups but still surfaces outages quickly. Leave `allowOfflineCacheFallback=true` so cached discovery/JWKS data can bridge short Pathfinder restarts.
|
||||||
- **Air-gapped/Offline Kit installs:** extend `offlineCacheTolerance` (15–30 minutes) to keep the cached metadata valid between manual synchronisations. You can also disable retries (`enableRetries=false`) if infrastructure teams prefer to handle exponential backoff at the network layer; Feedser will fail fast but keep deterministic logs.
|
- **Air-gapped/Offline Kit installs:** extend `offlineCacheTolerance` (15–30 minutes) to keep the cached metadata valid between manual synchronisations. You can also disable retries (`enableRetries=false`) if infrastructure teams prefer to handle exponential backoff at the network layer; Concelier will fail fast but keep deterministic logs.
|
||||||
- Feedser resolves these knobs through `IOptionsMonitor<StellaOpsAuthClientOptions>`. Edits to `feedser.yaml` are applied on configuration reload; restart the container if you change environment variables or do not have file-watch reloads enabled.
|
- Concelier resolves these knobs through `IOptionsMonitor<StellaOpsAuthClientOptions>`. Edits to `concelier.yaml` are applied on configuration reload; restart the container if you change environment variables or do not have file-watch reloads enabled.
|
||||||
|
|
||||||
## 2. Key Signals
|
## 2. Key Signals
|
||||||
|
|
||||||
### 2.1 Audit log channel
|
### 2.1 Audit log channel
|
||||||
|
|
||||||
Feedser emits structured audit entries via the `Feedser.Authorization.Audit` logger for every `/jobs*` request once Authority enforcement is active.
|
Concelier emits structured audit entries via the `Concelier.Authorization.Audit` logger for every `/jobs*` request once Authority enforcement is active.
|
||||||
|
|
||||||
```
|
```
|
||||||
Feedser authorization audit route=/jobs/definitions status=200 subject=ops@example.com clientId=feedser-cli scopes=feedser.jobs.trigger bypass=False remote=10.1.4.7
|
Concelier authorization audit route=/jobs/definitions status=200 subject=ops@example.com clientId=concelier-cli scopes=concelier.jobs.trigger bypass=False remote=10.1.4.7
|
||||||
```
|
```
|
||||||
|
|
||||||
| Field | Sample value | Meaning |
|
| Field | Sample value | Meaning |
|
||||||
@@ -61,8 +61,8 @@ Feedser authorization audit route=/jobs/definitions status=200 subject=ops@examp
|
|||||||
| `route` | `/jobs/definitions` | Endpoint that processed the request. |
|
| `route` | `/jobs/definitions` | Endpoint that processed the request. |
|
||||||
| `status` | `200` / `401` / `409` | Final HTTP status code returned to the caller. |
|
| `status` | `200` / `401` / `409` | Final HTTP status code returned to the caller. |
|
||||||
| `subject` | `ops@example.com` | User or service principal subject (falls back to `(anonymous)` when unauthenticated). |
|
| `subject` | `ops@example.com` | User or service principal subject (falls back to `(anonymous)` when unauthenticated). |
|
||||||
| `clientId` | `feedser-cli` | OAuth client ID provided by Authority ( `(none)` if the token lacked the claim). |
|
| `clientId` | `concelier-cli` | OAuth client ID provided by Authority ( `(none)` if the token lacked the claim). |
|
||||||
| `scopes` | `feedser.jobs.trigger` | Normalised scope list extracted from token claims; `(none)` if the token carried none. |
|
| `scopes` | `concelier.jobs.trigger` | Normalised scope list extracted from token claims; `(none)` if the token carried none. |
|
||||||
| `bypass` | `True` / `False` | Indicates whether the request succeeded because its source IP matched a bypass CIDR. |
|
| `bypass` | `True` / `False` | Indicates whether the request succeeded because its source IP matched a bypass CIDR. |
|
||||||
| `remote` | `10.1.4.7` | Remote IP recorded from the connection / forwarded header test hooks. |
|
| `remote` | `10.1.4.7` | Remote IP recorded from the connection / forwarded header test hooks. |
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ Use your logging backend (e.g., Loki) to index the logger name and filter for su
|
|||||||
|
|
||||||
### 2.2 Metrics
|
### 2.2 Metrics
|
||||||
|
|
||||||
Feedser publishes counters under the OTEL meter `StellaOps.Feedser.WebService.Jobs`. Tags: `job.kind`, `job.trigger`, `job.outcome`.
|
Concelier publishes counters under the OTEL meter `StellaOps.Concelier.WebService.Jobs`. Tags: `job.kind`, `job.trigger`, `job.outcome`.
|
||||||
|
|
||||||
| Metric name | Description | PromQL example |
|
| Metric name | Description | PromQL example |
|
||||||
|-------------------------------|----------------------------------------------------|----------------|
|
|-------------------------------|----------------------------------------------------|----------------|
|
||||||
@@ -84,42 +84,42 @@ Feedser publishes counters under the OTEL meter `StellaOps.Feedser.WebService.Jo
|
|||||||
|
|
||||||
> Prometheus/OTEL collectors typically surface counters with `_total` suffix. Adjust queries to match your pipeline’s generated metric names.
|
> Prometheus/OTEL collectors typically surface counters with `_total` suffix. Adjust queries to match your pipeline’s generated metric names.
|
||||||
|
|
||||||
Correlate audit logs with the following global meter exported via `Feedser.SourceDiagnostics`:
|
Correlate audit logs with the following global meter exported via `Concelier.SourceDiagnostics`:
|
||||||
|
|
||||||
- `feedser.source.http.requests_total{feedser_source="jobs-run"}` – ensures REST/manual triggers route through Authority.
|
- `concelier.source.http.requests_total{concelier_source="jobs-run"}` – ensures REST/manual triggers route through Authority.
|
||||||
- If Grafana dashboards are deployed, extend the “Feedser Jobs” board with the above counters plus a table of recent audit log entries.
|
- If Grafana dashboards are deployed, extend the “Concelier Jobs” board with the above counters plus a table of recent audit log entries.
|
||||||
|
|
||||||
## 3. Alerting Guidance
|
## 3. Alerting Guidance
|
||||||
|
|
||||||
1. **Unauthorized bypass attempt**
|
1. **Unauthorized bypass attempt**
|
||||||
- Query: `sum(rate(log_messages_total{logger="Feedser.Authorization.Audit", status="401", bypass="True"}[5m])) > 0`
|
- Query: `sum(rate(log_messages_total{logger="Concelier.Authorization.Audit", status="401", bypass="True"}[5m])) > 0`
|
||||||
- Action: verify `bypassNetworks` list; confirm expected maintenance windows; rotate credentials if suspicious.
|
- Action: verify `bypassNetworks` list; confirm expected maintenance windows; rotate credentials if suspicious.
|
||||||
|
|
||||||
2. **Missing scopes**
|
2. **Missing scopes**
|
||||||
- Query: `sum(rate(log_messages_total{logger="Feedser.Authorization.Audit", scopes="(none)", status="200"}[5m])) > 0`
|
- Query: `sum(rate(log_messages_total{logger="Concelier.Authorization.Audit", scopes="(none)", status="200"}[5m])) > 0`
|
||||||
- Action: audit Authority client registration; ensure `requiredScopes` includes `feedser.jobs.trigger`.
|
- Action: audit Authority client registration; ensure `requiredScopes` includes `concelier.jobs.trigger`.
|
||||||
|
|
||||||
3. **Trigger failure surge**
|
3. **Trigger failure surge**
|
||||||
- Query: `sum(rate(web_jobs_trigger_failed_total[10m])) > 0` with severity `warning` if sustained for 10 minutes.
|
- Query: `sum(rate(web_jobs_trigger_failed_total[10m])) > 0` with severity `warning` if sustained for 10 minutes.
|
||||||
- Action: inspect correlated audit entries and `Feedser.Telemetry` traces for job execution errors.
|
- Action: inspect correlated audit entries and `Concelier.Telemetry` traces for job execution errors.
|
||||||
|
|
||||||
4. **Conflict spike**
|
4. **Conflict spike**
|
||||||
- Query: `sum(rate(web_jobs_trigger_conflict_total[10m])) > 5` (tune threshold).
|
- Query: `sum(rate(web_jobs_trigger_conflict_total[10m])) > 5` (tune threshold).
|
||||||
- Action: downstream scheduling may be firing repetitive triggers; ensure precedence is configured properly.
|
- Action: downstream scheduling may be firing repetitive triggers; ensure precedence is configured properly.
|
||||||
|
|
||||||
5. **Authority offline**
|
5. **Authority offline**
|
||||||
- Watch `Feedser.Authorization.Audit` logs for `status=503` or `status=500` along with `clientId="(none)"`. Investigate Authority availability before re-enabling anonymous fallback.
|
- Watch `Concelier.Authorization.Audit` logs for `status=503` or `status=500` along with `clientId="(none)"`. Investigate Authority availability before re-enabling anonymous fallback.
|
||||||
|
|
||||||
## 4. Rollout & Verification Procedure
|
## 4. Rollout & Verification Procedure
|
||||||
|
|
||||||
1. **Pre-checks**
|
1. **Pre-checks**
|
||||||
- Confirm `allowAnonymousFallback` is `false` in production; keep `true` only during staged validation.
|
- Confirm `allowAnonymousFallback` is `false` in production; keep `true` only during staged validation.
|
||||||
- Validate Authority issuer metadata is reachable from Feedser (`curl https://authority.internal/.well-known/openid-configuration` from the host).
|
- Validate Authority issuer metadata is reachable from Concelier (`curl https://authority.internal/.well-known/openid-configuration` from the host).
|
||||||
|
|
||||||
2. **Smoke test with valid token**
|
2. **Smoke test with valid token**
|
||||||
- Obtain a token via CLI: `stella auth login --scope feedser.jobs.trigger`.
|
- Obtain a token via CLI: `stella auth login --scope concelier.jobs.trigger`.
|
||||||
- Trigger a read-only endpoint: `curl -H "Authorization: Bearer $TOKEN" https://feedser.internal/jobs/definitions`.
|
- Trigger a read-only endpoint: `curl -H "Authorization: Bearer $TOKEN" https://concelier.internal/jobs/definitions`.
|
||||||
- Expect HTTP 200/202 and an audit log with `bypass=False`, `scopes=feedser.jobs.trigger`.
|
- Expect HTTP 200/202 and an audit log with `bypass=False`, `scopes=concelier.jobs.trigger`.
|
||||||
|
|
||||||
3. **Negative test without token**
|
3. **Negative test without token**
|
||||||
- Call the same endpoint without a token. Expect HTTP 401, `bypass=False`.
|
- Call the same endpoint without a token. Expect HTTP 401, `bypass=False`.
|
||||||
@@ -130,21 +130,21 @@ Correlate audit logs with the following global meter exported via `Feedser.Sourc
|
|||||||
|
|
||||||
5. **Metrics validation**
|
5. **Metrics validation**
|
||||||
- Ensure `web.jobs.triggered` counter increments during accepted runs.
|
- Ensure `web.jobs.triggered` counter increments during accepted runs.
|
||||||
- Exporters should show corresponding spans (`feedser.job.trigger`) if tracing is enabled.
|
- Exporters should show corresponding spans (`concelier.job.trigger`) if tracing is enabled.
|
||||||
|
|
||||||
## 5. Troubleshooting
|
## 5. Troubleshooting
|
||||||
|
|
||||||
| Symptom | Probable cause | Remediation |
|
| Symptom | Probable cause | Remediation |
|
||||||
|---------|----------------|-------------|
|
|---------|----------------|-------------|
|
||||||
| Audit log shows `clientId=(none)` for all requests | Authority not issuing `client_id` claim or CLI outdated | Update StellaOps Authority configuration (`StellaOpsAuthorityOptions.Token.Claims.ClientId`), or upgrade the CLI token acquisition flow. |
|
| Audit log shows `clientId=(none)` for all requests | Authority not issuing `client_id` claim or CLI outdated | Update StellaOps Authority configuration (`StellaOpsAuthorityOptions.Token.Claims.ClientId`), or upgrade the CLI token acquisition flow. |
|
||||||
| Requests succeed with `bypass=True` unexpectedly | Local network added to `bypassNetworks` or fallback still enabled | Remove/adjust the CIDR list, disable anonymous fallback, restart Feedser. |
|
| Requests succeed with `bypass=True` unexpectedly | Local network added to `bypassNetworks` or fallback still enabled | Remove/adjust the CIDR list, disable anonymous fallback, restart Concelier. |
|
||||||
| HTTP 401 with valid token | `requiredScopes` missing from client registration or token audience mismatch | Verify Authority client scopes (`feedser.jobs.trigger`) and ensure the token audience matches `audiences` config. |
|
| HTTP 401 with valid token | `requiredScopes` missing from client registration or token audience mismatch | Verify Authority client scopes (`concelier.jobs.trigger`) and ensure the token audience matches `audiences` config. |
|
||||||
| Metrics missing from Prometheus | Telemetry exporters disabled or filter missing OTEL meter | Set `feedser.telemetry.enableMetrics=true`, ensure collector includes `StellaOps.Feedser.WebService.Jobs` meter. |
|
| Metrics missing from Prometheus | Telemetry exporters disabled or filter missing OTEL meter | Set `concelier.telemetry.enableMetrics=true`, ensure collector includes `StellaOps.Concelier.WebService.Jobs` meter. |
|
||||||
| Sudden spike in `web.jobs.trigger.failed` | Downstream job failure or Authority timeout mid-request | Inspect Feedser job logs, re-run with tracing enabled, validate Authority latency. |
|
| Sudden spike in `web.jobs.trigger.failed` | Downstream job failure or Authority timeout mid-request | Inspect Concelier job logs, re-run with tracing enabled, validate Authority latency. |
|
||||||
|
|
||||||
## 6. References
|
## 6. References
|
||||||
|
|
||||||
- `docs/21_INSTALL_GUIDE.md` – Authority configuration quick start.
|
- `docs/21_INSTALL_GUIDE.md` – Authority configuration quick start.
|
||||||
- `docs/17_SECURITY_HARDENING_GUIDE.md` – Security guardrails and enforcement deadlines.
|
- `docs/17_SECURITY_HARDENING_GUIDE.md` – Security guardrails and enforcement deadlines.
|
||||||
- `docs/ops/authority-monitoring.md` – Authority-side monitoring and alerting playbook.
|
- `docs/ops/authority-monitoring.md` – Authority-side monitoring and alerting playbook.
|
||||||
- `StellaOps.Feedser.WebService/Filters/JobAuthorizationAuditFilter.cs` – source of audit log fields.
|
- `StellaOps.Concelier.WebService/Filters/JobAuthorizationAuditFilter.cs` – source of audit log fields.
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
# Feedser CCCS Connector Operations
|
# Concelier CCCS Connector Operations
|
||||||
|
|
||||||
This runbook covers day‑to‑day operation of the Canadian Centre for Cyber Security (`source:cccs:*`) connector, including configuration, telemetry, and historical backfill guidance for English/French advisories.
|
This runbook covers day‑to‑day operation of the Canadian Centre for Cyber Security (`source:cccs:*`) connector, including configuration, telemetry, and historical backfill guidance for English/French advisories.
|
||||||
|
|
||||||
## 1. Configuration Checklist
|
## 1. Configuration Checklist
|
||||||
|
|
||||||
- Network egress (or mirrored cache) for `https://www.cyber.gc.ca/` and the JSON API endpoints under `/api/cccs/`.
|
- Network egress (or mirrored cache) for `https://www.cyber.gc.ca/` and the JSON API endpoints under `/api/cccs/`.
|
||||||
- Set the Feedser options before restarting workers. Example `feedser.yaml` snippet:
|
- Set the Concelier options before restarting workers. Example `concelier.yaml` snippet:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
sources:
|
sources:
|
||||||
cccs:
|
cccs:
|
||||||
feeds:
|
feeds:
|
||||||
@@ -27,15 +27,15 @@ feedser:
|
|||||||
|
|
||||||
## 2. Telemetry & Logging
|
## 2. Telemetry & Logging
|
||||||
|
|
||||||
- **Metrics (Meter `StellaOps.Feedser.Source.Cccs`):**
|
- **Metrics (Meter `StellaOps.Concelier.Source.Cccs`):**
|
||||||
- `cccs.fetch.attempts`, `cccs.fetch.success`, `cccs.fetch.failures`
|
- `cccs.fetch.attempts`, `cccs.fetch.success`, `cccs.fetch.failures`
|
||||||
- `cccs.fetch.documents`, `cccs.fetch.unchanged`
|
- `cccs.fetch.documents`, `cccs.fetch.unchanged`
|
||||||
- `cccs.parse.success`, `cccs.parse.failures`, `cccs.parse.quarantine`
|
- `cccs.parse.success`, `cccs.parse.failures`, `cccs.parse.quarantine`
|
||||||
- `cccs.map.success`, `cccs.map.failures`
|
- `cccs.map.success`, `cccs.map.failures`
|
||||||
- **Shared HTTP metrics** via `SourceDiagnostics`:
|
- **Shared HTTP metrics** via `SourceDiagnostics`:
|
||||||
- `feedser.source.http.requests{feedser.source="cccs"}`
|
- `concelier.source.http.requests{concelier.source="cccs"}`
|
||||||
- `feedser.source.http.failures{feedser.source="cccs"}`
|
- `concelier.source.http.failures{concelier.source="cccs"}`
|
||||||
- `feedser.source.http.duration{feedser.source="cccs"}`
|
- `concelier.source.http.duration{concelier.source="cccs"}`
|
||||||
- **Structured logs**
|
- **Structured logs**
|
||||||
- `CCCS fetch completed feeds=… items=… newDocuments=… pendingDocuments=…`
|
- `CCCS fetch completed feeds=… items=… newDocuments=… pendingDocuments=…`
|
||||||
- `CCCS parse completed parsed=… failures=…`
|
- `CCCS parse completed parsed=… failures=…`
|
||||||
@@ -45,13 +45,13 @@ feedser:
|
|||||||
Suggested Grafana alerts:
|
Suggested Grafana alerts:
|
||||||
- `increase(cccs.fetch.failures_total[15m]) > 0`
|
- `increase(cccs.fetch.failures_total[15m]) > 0`
|
||||||
- `rate(cccs.map.success_total[1h]) == 0` while other connectors are active
|
- `rate(cccs.map.success_total[1h]) == 0` while other connectors are active
|
||||||
- `histogram_quantile(0.95, rate(feedser_source_http_duration_bucket{feedser_source="cccs"}[1h])) > 5s`
|
- `histogram_quantile(0.95, rate(concelier_source_http_duration_bucket{concelier_source="cccs"}[1h])) > 5s`
|
||||||
|
|
||||||
## 3. Historical Backfill Plan
|
## 3. Historical Backfill Plan
|
||||||
|
|
||||||
1. **Snapshot the source** – the API accepts `page=<n>` and `lang=<en|fr>` query parameters. `page=0` returns the full dataset (observed earliest `date_created`: 2018‑06‑08 for EN, 2018‑06‑08 for FR). Mirror those responses into Offline Kit storage when operating air‑gapped.
|
1. **Snapshot the source** – the API accepts `page=<n>` and `lang=<en|fr>` query parameters. `page=0` returns the full dataset (observed earliest `date_created`: 2018‑06‑08 for EN, 2018‑06‑08 for FR). Mirror those responses into Offline Kit storage when operating air‑gapped.
|
||||||
2. **Stage ingestion**:
|
2. **Stage ingestion**:
|
||||||
- Temporarily raise `maxEntriesPerFetch` (e.g. 500) and restart Feedser workers.
|
- Temporarily raise `maxEntriesPerFetch` (e.g. 500) and restart Concelier workers.
|
||||||
- Run chained jobs until `pendingDocuments` drains:
|
- Run chained jobs until `pendingDocuments` drains:
|
||||||
`stella db jobs run source:cccs:fetch --and-then source:cccs:parse --and-then source:cccs:map`
|
`stella db jobs run source:cccs:fetch --and-then source:cccs:parse --and-then source:cccs:map`
|
||||||
- Monitor `cccs.fetch.unchanged` growth; once it approaches dataset size the backfill is complete.
|
- Monitor `cccs.fetch.unchanged` growth; once it approaches dataset size the backfill is complete.
|
||||||
@@ -67,6 +67,6 @@ Suggested Grafana alerts:
|
|||||||
|
|
||||||
## 5. Fixture Maintenance
|
## 5. Fixture Maintenance
|
||||||
|
|
||||||
- Regression fixtures live in `src/StellaOps.Feedser.Source.Cccs.Tests/Fixtures`.
|
- Regression fixtures live in `src/StellaOps.Concelier.Source.Cccs.Tests/Fixtures`.
|
||||||
- Refresh via `UPDATE_CCCS_FIXTURES=1 dotnet test src/StellaOps.Feedser.Source.Cccs.Tests/StellaOps.Feedser.Source.Cccs.Tests.csproj`.
|
- Refresh via `UPDATE_CCCS_FIXTURES=1 dotnet test src/StellaOps.Concelier.Source.Cccs.Tests/StellaOps.Concelier.Source.Cccs.Tests.csproj`.
|
||||||
- Fixtures capture both EN/FR advisories with nested lists to guard against sanitiser regressions; review diffs for heading/list changes before committing.
|
- Fixtures capture both EN/FR advisories with nested lists to guard against sanitiser regressions; review diffs for heading/list changes before committing.
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# Feedser CERT-Bund Connector Operations
|
# Concelier CERT-Bund Connector Operations
|
||||||
|
|
||||||
_Last updated: 2025-10-17_
|
_Last updated: 2025-10-17_
|
||||||
|
|
||||||
Germany’s Federal Office for Information Security (BSI) operates the Warn- und Informationsdienst (WID) portal. The Feedser CERT-Bund connector (`source:cert-bund:*`) ingests the public RSS feed, hydrates the portal’s JSON detail endpoint, and maps the result into canonical advisories while preserving the original German content.
|
Germany’s Federal Office for Information Security (BSI) operates the Warn- und Informationsdienst (WID) portal. The Concelier CERT-Bund connector (`source:cert-bund:*`) ingests the public RSS feed, hydrates the portal’s JSON detail endpoint, and maps the result into canonical advisories while preserving the original German content.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -14,10 +14,10 @@ Germany’s Federal Office for Information Security (BSI) operates the Warn- und
|
|||||||
- `https://wid.cert-bund.de/portal/api/securityadvisory` (detail/search/export JSON)
|
- `https://wid.cert-bund.de/portal/api/securityadvisory` (detail/search/export JSON)
|
||||||
- Ensure the HTTP client reuses a cookie container (the connector’s dependency injection wiring already sets this up).
|
- Ensure the HTTP client reuses a cookie container (the connector’s dependency injection wiring already sets this up).
|
||||||
|
|
||||||
Example `feedser.yaml` fragment:
|
Example `concelier.yaml` fragment:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
sources:
|
sources:
|
||||||
cert-bund:
|
cert-bund:
|
||||||
feedUri: "https://wid.cert-bund.de/content/public/securityAdvisory/rss"
|
feedUri: "https://wid.cert-bund.de/content/public/securityAdvisory/rss"
|
||||||
@@ -36,7 +36,7 @@ feedser:
|
|||||||
|
|
||||||
## 2. Telemetry & Logging
|
## 2. Telemetry & Logging
|
||||||
|
|
||||||
- **Meter**: `StellaOps.Feedser.Source.CertBund`
|
- **Meter**: `StellaOps.Concelier.Source.CertBund`
|
||||||
- **Counters / histograms**:
|
- **Counters / histograms**:
|
||||||
- `certbund.feed.fetch.attempts|success|failures`
|
- `certbund.feed.fetch.attempts|success|failures`
|
||||||
- `certbund.feed.items.count`
|
- `certbund.feed.items.count`
|
||||||
@@ -47,7 +47,7 @@ feedser:
|
|||||||
- `certbund.parse.products.count`, `certbund.parse.cve.count`
|
- `certbund.parse.products.count`, `certbund.parse.cve.count`
|
||||||
- `certbund.map.success|failures{reason}`
|
- `certbund.map.success|failures{reason}`
|
||||||
- `certbund.map.affected.count`, `certbund.map.aliases.count`
|
- `certbund.map.affected.count`, `certbund.map.aliases.count`
|
||||||
- Shared HTTP metrics remain available through `feedser.source.http.*`.
|
- Shared HTTP metrics remain available through `concelier.source.http.*`.
|
||||||
|
|
||||||
**Structured logs** (all emitted at information level when work occurs):
|
**Structured logs** (all emitted at information level when work occurs):
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ Alerting ideas:
|
|||||||
|
|
||||||
1. `increase(certbund.detail.fetch.failures_total[10m]) > 0`
|
1. `increase(certbund.detail.fetch.failures_total[10m]) > 0`
|
||||||
2. `rate(certbund.map.success_total[30m]) == 0`
|
2. `rate(certbund.map.success_total[30m]) == 0`
|
||||||
3. `histogram_quantile(0.95, rate(feedser_source_http_duration_bucket{feedser_source="cert-bund"}[15m])) > 5s`
|
3. `histogram_quantile(0.95, rate(concelier_source_http_duration_bucket{concelier_source="cert-bund"}[15m])) > 5s`
|
||||||
|
|
||||||
The WebService now registers the meter so metrics surface automatically once OpenTelemetry metrics are enabled.
|
The WebService now registers the meter so metrics surface automatically once OpenTelemetry metrics are enabled.
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ The helper stores yearly exports under `seed-data/cert-bund/export/`,
|
|||||||
captures paginated search snapshots in `seed-data/cert-bund/search/`,
|
captures paginated search snapshots in `seed-data/cert-bund/search/`,
|
||||||
and generates the manifest + SHA files in `seed-data/cert-bund/manifest/`.
|
and generates the manifest + SHA files in `seed-data/cert-bund/manifest/`.
|
||||||
Split ranges according to your compliance window (default: one file per
|
Split ranges according to your compliance window (default: one file per
|
||||||
calendar year). Feedser can ingest these JSON payloads directly when
|
calendar year). Concelier can ingest these JSON payloads directly when
|
||||||
operating offline.
|
operating offline.
|
||||||
|
|
||||||
> When automatic bootstrap fails (e.g. portal introduces CAPTCHA), run the
|
> When automatic bootstrap fails (e.g. portal introduces CAPTCHA), run the
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
# Feedser Cisco PSIRT Connector – OAuth Provisioning SOP
|
# Concelier Cisco PSIRT Connector – OAuth Provisioning SOP
|
||||||
|
|
||||||
_Last updated: 2025-10-14_
|
_Last updated: 2025-10-14_
|
||||||
|
|
||||||
## 1. Scope
|
## 1. Scope
|
||||||
|
|
||||||
This runbook describes how Ops provisions, rotates, and distributes Cisco PSIRT openVuln OAuth client credentials for the Feedser Cisco connector. It covers online and air-gapped (Offline Kit) environments, quota-aware execution, and escalation paths.
|
This runbook describes how Ops provisions, rotates, and distributes Cisco PSIRT openVuln OAuth client credentials for the Concelier Cisco connector. It covers online and air-gapped (Offline Kit) environments, quota-aware execution, and escalation paths.
|
||||||
|
|
||||||
## 2. Prerequisites
|
## 2. Prerequisites
|
||||||
|
|
||||||
- Active Cisco.com (CCO) account with access to the Cisco API Console.
|
- Active Cisco.com (CCO) account with access to the Cisco API Console.
|
||||||
- Cisco PSIRT openVuln API entitlement (visible under “My Apps & Keys” once granted).citeturn3search0
|
- Cisco PSIRT openVuln API entitlement (visible under “My Apps & Keys” once granted).citeturn3search0
|
||||||
- Feedser configuration location (typically `/etc/stella/feedser.yaml` in production) or Offline Kit secret bundle staging directory.
|
- Concelier configuration location (typically `/etc/stella/concelier.yaml` in production) or Offline Kit secret bundle staging directory.
|
||||||
|
|
||||||
## 3. Provisioning workflow
|
## 3. Provisioning workflow
|
||||||
|
|
||||||
@@ -29,11 +29,11 @@ This runbook describes how Ops provisions, rotates, and distributes Cisco PSIRT
|
|||||||
```
|
```
|
||||||
- Confirm HTTP 200 and an `expires_in` value of 3600 seconds (tokens live for one hour).citeturn3search0turn3search7
|
- Confirm HTTP 200 and an `expires_in` value of 3600 seconds (tokens live for one hour).citeturn3search0turn3search7
|
||||||
- Preserve the response only long enough to validate syntax; do **not** persist tokens.
|
- Preserve the response only long enough to validate syntax; do **not** persist tokens.
|
||||||
3. **Authorize Feedser runtime**
|
3. **Authorize Concelier runtime**
|
||||||
- Update `feedser:sources:cisco:auth` (or the module-specific secret template) with the stored credentials.
|
- Update `concelier:sources:cisco:auth` (or the module-specific secret template) with the stored credentials.
|
||||||
- For Offline Kit delivery, export encrypted secrets into `offline-kit/secrets/cisco-openvuln.json` using the platform’s sealed secret format.
|
- For Offline Kit delivery, export encrypted secrets into `offline-kit/secrets/cisco-openvuln.json` using the platform’s sealed secret format.
|
||||||
4. **Connectivity validation**
|
4. **Connectivity validation**
|
||||||
- From the Feedser control plane, run `stella db jobs run source:vndr-cisco:fetch --dry-run`.
|
- From the Concelier control plane, run `stella db jobs run source:vndr-cisco:fetch --dry-run`.
|
||||||
- Ensure the Source HTTP diagnostics record `Bearer` authorization headers and no 401/403 responses.
|
- Ensure the Source HTTP diagnostics record `Bearer` authorization headers and no 401/403 responses.
|
||||||
|
|
||||||
## 4. Rotation SOP
|
## 4. Rotation SOP
|
||||||
@@ -42,12 +42,12 @@ This runbook describes how Ops provisions, rotates, and distributes Cisco PSIRT
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| 1. Schedule rotation | Ops (monthly board) | Rotate every 90 days or immediately after suspected credential exposure. |
|
| 1. Schedule rotation | Ops (monthly board) | Rotate every 90 days or immediately after suspected credential exposure. |
|
||||||
| 2. Create replacement app | Ops | Repeat §3.1 with “-next” suffix; verify token issuance. |
|
| 2. Create replacement app | Ops | Repeat §3.1 with “-next” suffix; verify token issuance. |
|
||||||
| 3. Stage dual credentials | Ops + Feedser On-Call | Publish new credentials to secret store alongside current pair. |
|
| 3. Stage dual credentials | Ops + Concelier On-Call | Publish new credentials to secret store alongside current pair. |
|
||||||
| 4. Cut over | Feedser On-Call | Restart connector workers during a low-traffic window (<10 min) to pick up the new secret. |
|
| 4. Cut over | Concelier On-Call | Restart connector workers during a low-traffic window (<10 min) to pick up the new secret. |
|
||||||
| 5. Deactivate legacy app | Ops | Delete prior app in Cisco API Console once telemetry confirms successful fetch/parse cycles for 2 consecutive hours. |
|
| 5. Deactivate legacy app | Ops | Delete prior app in Cisco API Console once telemetry confirms successful fetch/parse cycles for 2 consecutive hours. |
|
||||||
|
|
||||||
**Automation hooks**
|
**Automation hooks**
|
||||||
- Rotation reminders are tracked in OpsRunbookOps board (`OPS-RUN-KEYS` swim lane); add checklist items for Feedser Cisco when opening a rotation task.
|
- Rotation reminders are tracked in OpsRunbookOps board (`OPS-RUN-KEYS` swim lane); add checklist items for Concelier Cisco when opening a rotation task.
|
||||||
- Use the secret management pipeline (`ops/secrets/rotate.sh --connector cisco`) to template vault updates; the script renders a redacted diff for audit.
|
- Use the secret management pipeline (`ops/secrets/rotate.sh --connector cisco`) to template vault updates; the script renders a redacted diff for audit.
|
||||||
|
|
||||||
## 5. Offline Kit packaging
|
## 5. Offline Kit packaging
|
||||||
@@ -61,19 +61,19 @@ This runbook describes how Ops provisions, rotates, and distributes Cisco PSIRT
|
|||||||
## 6. Quota and throttling guidance
|
## 6. Quota and throttling guidance
|
||||||
|
|
||||||
- Cisco enforces combined limits of 5 requests/second, 30 requests/minute, and 5 000 requests/day per application.citeturn0search0turn3search6
|
- Cisco enforces combined limits of 5 requests/second, 30 requests/minute, and 5 000 requests/day per application.citeturn0search0turn3search6
|
||||||
- Feedser fetch jobs must respect `Retry-After` headers on HTTP 429 responses; Ops should monitor for sustained quota saturation and consider paging window adjustments.
|
- Concelier fetch jobs must respect `Retry-After` headers on HTTP 429 responses; Ops should monitor for sustained quota saturation and consider paging window adjustments.
|
||||||
- Telemetry to watch: `feedser.source.http.requests{feedser.source="vndr-cisco"}`, `feedser.source.http.failures{...}`, and connector-specific metrics once implemented.
|
- Telemetry to watch: `concelier.source.http.requests{concelier.source="vndr-cisco"}`, `concelier.source.http.failures{...}`, and connector-specific metrics once implemented.
|
||||||
|
|
||||||
## 7. Telemetry & Monitoring
|
## 7. Telemetry & Monitoring
|
||||||
|
|
||||||
- **Metrics (Meter `StellaOps.Feedser.Source.Vndr.Cisco`)**
|
- **Metrics (Meter `StellaOps.Concelier.Source.Vndr.Cisco`)**
|
||||||
- `cisco.fetch.documents`, `cisco.fetch.failures`, `cisco.fetch.unchanged`
|
- `cisco.fetch.documents`, `cisco.fetch.failures`, `cisco.fetch.unchanged`
|
||||||
- `cisco.parse.success`, `cisco.parse.failures`
|
- `cisco.parse.success`, `cisco.parse.failures`
|
||||||
- `cisco.map.success`, `cisco.map.failures`, `cisco.map.affected.packages`
|
- `cisco.map.success`, `cisco.map.failures`, `cisco.map.affected.packages`
|
||||||
- **Shared HTTP metrics** via `SourceDiagnostics`:
|
- **Shared HTTP metrics** via `SourceDiagnostics`:
|
||||||
- `feedser.source.http.requests{feedser.source="vndr-cisco"}`
|
- `concelier.source.http.requests{concelier.source="vndr-cisco"}`
|
||||||
- `feedser.source.http.failures{feedser.source="vndr-cisco"}`
|
- `concelier.source.http.failures{concelier.source="vndr-cisco"}`
|
||||||
- `feedser.source.http.duration{feedser.source="vndr-cisco"}`
|
- `concelier.source.http.duration{concelier.source="vndr-cisco"}`
|
||||||
- **Structured logs**
|
- **Structured logs**
|
||||||
- `Cisco fetch completed date=… pages=… added=…` (info)
|
- `Cisco fetch completed date=… pages=… added=…` (info)
|
||||||
- `Cisco parse completed parsed=… failures=…` (info)
|
- `Cisco parse completed parsed=… failures=…` (info)
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
# Feedser Conflict Resolution Runbook (Sprint 3)
|
# Concelier Conflict Resolution Runbook (Sprint 3)
|
||||||
|
|
||||||
This runbook equips Feedser operators to detect, triage, and resolve advisory conflicts now that the Sprint 3 merge engine landed (`AdvisoryPrecedenceMerger`, merge-event hashing, and telemetry counters). It builds on the canonical rules defined in `src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md` and the metrics/logging instrumentation delivered this sprint.
|
This runbook equips Concelier operators to detect, triage, and resolve advisory conflicts now that the Sprint 3 merge engine landed (`AdvisoryPrecedenceMerger`, merge-event hashing, and telemetry counters). It builds on the canonical rules defined in `src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md` and the metrics/logging instrumentation delivered this sprint.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Precedence Model (recap)
|
## 1. Precedence Model (recap)
|
||||||
|
|
||||||
- **Default ranking:** `GHSA -> NVD -> OSV`, with distro/vendor PSIRTs outranking ecosystem feeds (`AdvisoryPrecedenceDefaults`). Use `feedser:merge:precedence:ranks` to override per source when incident response requires it.
|
- **Default ranking:** `GHSA -> NVD -> OSV`, with distro/vendor PSIRTs outranking ecosystem feeds (`AdvisoryPrecedenceDefaults`). Use `concelier:merge:precedence:ranks` to override per source when incident response requires it.
|
||||||
- **Freshness override:** if a lower-ranked source is >= 48 hours newer for a freshness-sensitive field (title, summary, affected ranges, references, credits), it wins. Every override stamps `provenance[].decisionReason = freshness`.
|
- **Freshness override:** if a lower-ranked source is >= 48 hours newer for a freshness-sensitive field (title, summary, affected ranges, references, credits), it wins. Every override stamps `provenance[].decisionReason = freshness`.
|
||||||
- **Tie-breakers:** when precedence and freshness tie, the engine falls back to (1) primary source order, (2) shortest normalized text, (3) lowest stable hash. Merge-generated provenance records set `decisionReason = tie-breaker`.
|
- **Tie-breakers:** when precedence and freshness tie, the engine falls back to (1) primary source order, (2) shortest normalized text, (3) lowest stable hash. Merge-generated provenance records set `decisionReason = tie-breaker`.
|
||||||
- **Audit trail:** each merged advisory receives a `merge` provenance entry listing the participating sources plus a `merge_event` record with canonical before/after SHA-256 hashes.
|
- **Audit trail:** each merged advisory receives a `merge` provenance entry listing the participating sources plus a `merge_event` record with canonical before/after SHA-256 hashes.
|
||||||
@@ -17,41 +17,41 @@ This runbook equips Feedser operators to detect, triage, and resolve advisory co
|
|||||||
|
|
||||||
| Instrument | Type | Key Tags | Purpose |
|
| Instrument | Type | Key Tags | Purpose |
|
||||||
|------------|------|----------|---------|
|
|------------|------|----------|---------|
|
||||||
| `feedser.merge.operations` | Counter | `inputs` | Total precedence merges executed. |
|
| `concelier.merge.operations` | Counter | `inputs` | Total precedence merges executed. |
|
||||||
| `feedser.merge.overrides` | Counter | `primary_source`, `suppressed_source`, `primary_rank`, `suppressed_rank` | Field-level overrides chosen by precedence. |
|
| `concelier.merge.overrides` | Counter | `primary_source`, `suppressed_source`, `primary_rank`, `suppressed_rank` | Field-level overrides chosen by precedence. |
|
||||||
| `feedser.merge.range_overrides` | Counter | `advisory_key`, `package_type`, `primary_source`, `suppressed_source`, `primary_range_count`, `suppressed_range_count` | Package range overrides emitted by `AffectedPackagePrecedenceResolver`. |
|
| `concelier.merge.range_overrides` | Counter | `advisory_key`, `package_type`, `primary_source`, `suppressed_source`, `primary_range_count`, `suppressed_range_count` | Package range overrides emitted by `AffectedPackagePrecedenceResolver`. |
|
||||||
| `feedser.merge.conflicts` | Counter | `type` (`severity`, `precedence_tie`), `reason` (`mismatch`, `primary_missing`, `equal_rank`) | Conflicts requiring operator review. |
|
| `concelier.merge.conflicts` | Counter | `type` (`severity`, `precedence_tie`), `reason` (`mismatch`, `primary_missing`, `equal_rank`) | Conflicts requiring operator review. |
|
||||||
| `feedser.merge.identity_conflicts` | Counter | `scheme`, `alias_value`, `advisory_count` | Alias collisions surfaced by the identity graph. |
|
| `concelier.merge.identity_conflicts` | Counter | `scheme`, `alias_value`, `advisory_count` | Alias collisions surfaced by the identity graph. |
|
||||||
|
|
||||||
### Structured logs
|
### Structured logs
|
||||||
|
|
||||||
- `AdvisoryOverride` (EventId 1000) - logs merge suppressions with alias/provenance counts.
|
- `AdvisoryOverride` (EventId 1000) - logs merge suppressions with alias/provenance counts.
|
||||||
- `PackageRangeOverride` (EventId 1001) - logs package-level precedence decisions.
|
- `PackageRangeOverride` (EventId 1001) - logs package-level precedence decisions.
|
||||||
- `PrecedenceConflict` (EventId 1002) - logs mismatched severity or equal-rank scenarios.
|
- `PrecedenceConflict` (EventId 1002) - logs mismatched severity or equal-rank scenarios.
|
||||||
- `Alias collision ...` (no EventId) - emitted when `feedser.merge.identity_conflicts` increments.
|
- `Alias collision ...` (no EventId) - emitted when `concelier.merge.identity_conflicts` increments.
|
||||||
|
|
||||||
Expect all logs at `Information`. Ensure OTEL exporters include the scope `StellaOps.Feedser.Merge`.
|
Expect all logs at `Information`. Ensure OTEL exporters include the scope `StellaOps.Concelier.Merge`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Detection & Alerting
|
## 3. Detection & Alerting
|
||||||
|
|
||||||
1. **Dashboard panels**
|
1. **Dashboard panels**
|
||||||
- `feedser.merge.conflicts` - table grouped by `type/reason`. Alert when > 0 in a 15 minute window.
|
- `concelier.merge.conflicts` - table grouped by `type/reason`. Alert when > 0 in a 15 minute window.
|
||||||
- `feedser.merge.range_overrides` - stacked bar by `package_type`. Spikes highlight vendor PSIRT overrides over registry data.
|
- `concelier.merge.range_overrides` - stacked bar by `package_type`. Spikes highlight vendor PSIRT overrides over registry data.
|
||||||
- `feedser.merge.overrides` with `primary_source|suppressed_source` - catches unexpected precedence flips (e.g., OSV overtaking GHSA).
|
- `concelier.merge.overrides` with `primary_source|suppressed_source` - catches unexpected precedence flips (e.g., OSV overtaking GHSA).
|
||||||
- `feedser.merge.identity_conflicts` - single-stat; alert when alias collisions occur more than once per day.
|
- `concelier.merge.identity_conflicts` - single-stat; alert when alias collisions occur more than once per day.
|
||||||
2. **Log based alerts**
|
2. **Log based alerts**
|
||||||
- `eventId=1002` with `reason="equal_rank"` - indicates precedence table gaps; page merge owners.
|
- `eventId=1002` with `reason="equal_rank"` - indicates precedence table gaps; page merge owners.
|
||||||
- `eventId=1002` with `reason="mismatch"` - severity disagreement; open connector bug if sustained.
|
- `eventId=1002` with `reason="mismatch"` - severity disagreement; open connector bug if sustained.
|
||||||
3. **Job health**
|
3. **Job health**
|
||||||
- `stellaops-cli db merge` exit code `1` signifies unresolved conflicts. Pipe to automation that captures logs and notifies #feedser-ops.
|
- `stellaops-cli db merge` exit code `1` signifies unresolved conflicts. Pipe to automation that captures logs and notifies #concelier-ops.
|
||||||
|
|
||||||
### Threshold updates (2025-10-12)
|
### Threshold updates (2025-10-12)
|
||||||
|
|
||||||
- `feedser.merge.conflicts` – Page only when ≥ 2 events fire within 30 minutes; the synthetic conflict fixture run produces 0 conflicts, so the first event now routes to Slack for manual review instead of paging.
|
- `concelier.merge.conflicts` – Page only when ≥ 2 events fire within 30 minutes; the synthetic conflict fixture run produces 0 conflicts, so the first event now routes to Slack for manual review instead of paging.
|
||||||
- `feedser.merge.overrides` – Raise a warning when the 30-minute sum exceeds 10 (canonical triple yields exactly 1 summary override with `primary_source=osv`, `suppressed_source=ghsa`).
|
- `concelier.merge.overrides` – Raise a warning when the 30-minute sum exceeds 10 (canonical triple yields exactly 1 summary override with `primary_source=osv`, `suppressed_source=ghsa`).
|
||||||
- `feedser.merge.range_overrides` – Maintain the 15-minute alert at ≥ 3 but annotate dashboards that the regression triple emits a single `package_type=semver` override so ops can spot unexpected spikes.
|
- `concelier.merge.range_overrides` – Maintain the 15-minute alert at ≥ 3 but annotate dashboards that the regression triple emits a single `package_type=semver` override so ops can spot unexpected spikes.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -60,16 +60,16 @@ Expect all logs at `Information`. Ensure OTEL exporters include the scope `Stell
|
|||||||
1. **Confirm job context**
|
1. **Confirm job context**
|
||||||
- `stellaops-cli db merge` (CLI) or `POST /jobs/merge:reconcile` (API) to rehydrate the merge job. Use `--verbose` to stream structured logs during triage.
|
- `stellaops-cli db merge` (CLI) or `POST /jobs/merge:reconcile` (API) to rehydrate the merge job. Use `--verbose` to stream structured logs during triage.
|
||||||
2. **Inspect metrics**
|
2. **Inspect metrics**
|
||||||
- Correlate spikes in `feedser.merge.conflicts` with `primary_source`/`suppressed_source` tags from `feedser.merge.overrides`.
|
- Correlate spikes in `concelier.merge.conflicts` with `primary_source`/`suppressed_source` tags from `concelier.merge.overrides`.
|
||||||
3. **Pull structured logs**
|
3. **Pull structured logs**
|
||||||
- Example (vector output):
|
- Example (vector output):
|
||||||
```
|
```
|
||||||
jq 'select(.EventId.Name=="PrecedenceConflict") | {advisory: .State[0].Value, type: .ConflictType, reason: .Reason, primary: .PrimarySources, suppressed: .SuppressedSources}' stellaops-feedser.log
|
jq 'select(.EventId.Name=="PrecedenceConflict") | {advisory: .State[0].Value, type: .ConflictType, reason: .Reason, primary: .PrimarySources, suppressed: .SuppressedSources}' stellaops-concelier.log
|
||||||
```
|
```
|
||||||
4. **Review merge events**
|
4. **Review merge events**
|
||||||
- `mongosh`:
|
- `mongosh`:
|
||||||
```javascript
|
```javascript
|
||||||
use feedser;
|
use concelier;
|
||||||
db.merge_event.find({ advisoryKey: "CVE-2025-1234" }).sort({ mergedAt: -1 }).limit(5);
|
db.merge_event.find({ advisoryKey: "CVE-2025-1234" }).sort({ mergedAt: -1 }).limit(5);
|
||||||
```
|
```
|
||||||
- Compare `beforeHash` vs `afterHash` to confirm the merge actually changed canonical output.
|
- Compare `beforeHash` vs `afterHash` to confirm the merge actually changed canonical output.
|
||||||
@@ -85,9 +85,9 @@ Expect all logs at `Information`. Ensure OTEL exporters include the scope `Stell
|
|||||||
|--------|--------------|------------------|
|
|--------|--------------|------------------|
|
||||||
| `reason="mismatch"` with `type="severity"` | Upstream feeds disagree on CVSS vector/severity. | Verify which feed is freshest; if correctness is known, adjust connector mapping or precedence override. |
|
| `reason="mismatch"` with `type="severity"` | Upstream feeds disagree on CVSS vector/severity. | Verify which feed is freshest; if correctness is known, adjust connector mapping or precedence override. |
|
||||||
| `reason="primary_missing"` | Higher-ranked source lacks the field entirely. | Backfill connector data or temporarily allow lower-ranked source via precedence override. |
|
| `reason="primary_missing"` | Higher-ranked source lacks the field entirely. | Backfill connector data or temporarily allow lower-ranked source via precedence override. |
|
||||||
| `reason="equal_rank"` | Two feeds share the same precedence rank (custom config or missing entry). | Update `feedser:merge:precedence:ranks` to break the tie; restart merge job. |
|
| `reason="equal_rank"` | Two feeds share the same precedence rank (custom config or missing entry). | Update `concelier:merge:precedence:ranks` to break the tie; restart merge job. |
|
||||||
| Rising `feedser.merge.range_overrides` for a package type | Vendor PSIRT now supplies richer ranges. | Validate connectors emit `decisionReason="precedence"` and update dashboards to treat registry ranges as fallback. |
|
| Rising `concelier.merge.range_overrides` for a package type | Vendor PSIRT now supplies richer ranges. | Validate connectors emit `decisionReason="precedence"` and update dashboards to treat registry ranges as fallback. |
|
||||||
| `feedser.merge.identity_conflicts` > 0 | Alias scheme mapping produced collisions (duplicate CVE <-> advisory pairs). | Inspect `Alias collision` log payload; reconcile the alias graph by adjusting connector alias output. |
|
| `concelier.merge.identity_conflicts` > 0 | Alias scheme mapping produced collisions (duplicate CVE <-> advisory pairs). | Inspect `Alias collision` log payload; reconcile the alias graph by adjusting connector alias output. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -97,16 +97,16 @@ Expect all logs at `Information`. Ensure OTEL exporters include the scope `Stell
|
|||||||
- Re-run the offending connector stages (`stellaops-cli db fetch --source ghsa --stage map` etc.).
|
- Re-run the offending connector stages (`stellaops-cli db fetch --source ghsa --stage map` etc.).
|
||||||
- Once fixed, rerun merge and verify `decisionReason` reflects `freshness` or `precedence` as expected.
|
- Once fixed, rerun merge and verify `decisionReason` reflects `freshness` or `precedence` as expected.
|
||||||
2. **Temporary precedence override**
|
2. **Temporary precedence override**
|
||||||
- Edit `etc/feedser.yaml`:
|
- Edit `etc/concelier.yaml`:
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
merge:
|
merge:
|
||||||
precedence:
|
precedence:
|
||||||
ranks:
|
ranks:
|
||||||
osv: 1
|
osv: 1
|
||||||
ghsa: 0
|
ghsa: 0
|
||||||
```
|
```
|
||||||
- Restart Feedser workers; confirm tags in `feedser.merge.overrides` show the new ranks.
|
- Restart Concelier workers; confirm tags in `concelier.merge.overrides` show the new ranks.
|
||||||
- Document the override with expiry in the change log.
|
- Document the override with expiry in the change log.
|
||||||
3. **Alias remediation**
|
3. **Alias remediation**
|
||||||
- Update connector mapping rules to weed out duplicate aliases (e.g., skip GHSA aliases that mirror CVE IDs).
|
- Update connector mapping rules to weed out duplicate aliases (e.g., skip GHSA aliases that mirror CVE IDs).
|
||||||
@@ -119,7 +119,7 @@ Expect all logs at `Information`. Ensure OTEL exporters include the scope `Stell
|
|||||||
## 7. Validation Checklist
|
## 7. Validation Checklist
|
||||||
|
|
||||||
- [ ] Merge job rerun returns exit code `0`.
|
- [ ] Merge job rerun returns exit code `0`.
|
||||||
- [ ] `feedser.merge.conflicts` baseline returns to zero after corrective action.
|
- [ ] `concelier.merge.conflicts` baseline returns to zero after corrective action.
|
||||||
- [ ] Latest `merge_event` entry shows expected hash delta.
|
- [ ] Latest `merge_event` entry shows expected hash delta.
|
||||||
- [ ] Affected advisory document shows updated `provenance[].decisionReason`.
|
- [ ] Affected advisory document shows updated `provenance[].decisionReason`.
|
||||||
- [ ] Ops change log updated with incident summary, config overrides, and rollback plan.
|
- [ ] Ops change log updated with incident summary, config overrides, and rollback plan.
|
||||||
@@ -129,9 +129,9 @@ Expect all logs at `Information`. Ensure OTEL exporters include the scope `Stell
|
|||||||
## 8. Reference Material
|
## 8. Reference Material
|
||||||
|
|
||||||
- Canonical conflict rules: `src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md`.
|
- Canonical conflict rules: `src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md`.
|
||||||
- Merge engine internals: `src/StellaOps.Feedser.Merge/Services/AdvisoryPrecedenceMerger.cs`.
|
- Merge engine internals: `src/StellaOps.Concelier.Merge/Services/AdvisoryPrecedenceMerger.cs`.
|
||||||
- Metrics definitions: `src/StellaOps.Feedser.Merge/Services/AdvisoryMergeService.cs` (identity conflicts) and `AdvisoryPrecedenceMerger`.
|
- Metrics definitions: `src/StellaOps.Concelier.Merge/Services/AdvisoryMergeService.cs` (identity conflicts) and `AdvisoryPrecedenceMerger`.
|
||||||
- Storage audit trail: `src/StellaOps.Feedser.Merge/Services/MergeEventWriter.cs`, `src/StellaOps.Feedser.Storage.Mongo/MergeEvents`.
|
- Storage audit trail: `src/StellaOps.Concelier.Merge/Services/MergeEventWriter.cs`, `src/StellaOps.Concelier.Storage.Mongo/MergeEvents`.
|
||||||
|
|
||||||
Keep this runbook synchronized with future sprint notes and update alert thresholds as baseline volumes change.
|
Keep this runbook synchronized with future sprint notes and update alert thresholds as baseline volumes change.
|
||||||
|
|
||||||
@@ -139,17 +139,17 @@ Keep this runbook synchronized with future sprint notes and update alert thresho
|
|||||||
|
|
||||||
## 9. Synthetic Regression Fixtures
|
## 9. Synthetic Regression Fixtures
|
||||||
|
|
||||||
- **Locations** – Canonical conflict snapshots now live at `src/StellaOps.Feedser.Source.Ghsa.Tests/Fixtures/conflict-ghsa.canonical.json`, `src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/conflict-nvd.canonical.json`, and `src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/conflict-osv.canonical.json`.
|
- **Locations** – Canonical conflict snapshots now live at `src/StellaOps.Concelier.Source.Ghsa.Tests/Fixtures/conflict-ghsa.canonical.json`, `src/StellaOps.Concelier.Source.Nvd.Tests/Nvd/Fixtures/conflict-nvd.canonical.json`, and `src/StellaOps.Concelier.Source.Osv.Tests/Fixtures/conflict-osv.canonical.json`.
|
||||||
- **Validation commands** – To regenerate and verify the fixtures offline, run:
|
- **Validation commands** – To regenerate and verify the fixtures offline, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dotnet test src/StellaOps.Feedser.Source.Ghsa.Tests/StellaOps.Feedser.Source.Ghsa.Tests.csproj --filter GhsaConflictFixtureTests
|
dotnet test src/StellaOps.Concelier.Source.Ghsa.Tests/StellaOps.Concelier.Source.Ghsa.Tests.csproj --filter GhsaConflictFixtureTests
|
||||||
dotnet test src/StellaOps.Feedser.Source.Nvd.Tests/StellaOps.Feedser.Source.Nvd.Tests.csproj --filter NvdConflictFixtureTests
|
dotnet test src/StellaOps.Concelier.Source.Nvd.Tests/StellaOps.Concelier.Source.Nvd.Tests.csproj --filter NvdConflictFixtureTests
|
||||||
dotnet test src/StellaOps.Feedser.Source.Osv.Tests/StellaOps.Feedser.Source.Osv.Tests.csproj --filter OsvConflictFixtureTests
|
dotnet test src/StellaOps.Concelier.Source.Osv.Tests/StellaOps.Concelier.Source.Osv.Tests.csproj --filter OsvConflictFixtureTests
|
||||||
dotnet test src/StellaOps.Feedser.Merge.Tests/StellaOps.Feedser.Merge.Tests.csproj --filter MergeAsync_AppliesCanonicalRulesAndPersistsDecisions
|
dotnet test src/StellaOps.Concelier.Merge.Tests/StellaOps.Concelier.Merge.Tests.csproj --filter MergeAsync_AppliesCanonicalRulesAndPersistsDecisions
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Expected signals** – The triple produces one freshness-driven summary override (`primary_source=osv`, `suppressed_source=ghsa`) and one range override for the npm SemVer package while leaving `feedser.merge.conflicts` at zero. Use these values as the baseline when tuning dashboards or load-testing alert pipelines.
|
- **Expected signals** – The triple produces one freshness-driven summary override (`primary_source=osv`, `suppressed_source=ghsa`) and one range override for the npm SemVer package while leaving `concelier.merge.conflicts` at zero. Use these values as the baseline when tuning dashboards or load-testing alert pipelines.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -157,4 +157,4 @@ dotnet test src/StellaOps.Feedser.Merge.Tests/StellaOps.Feedser.Merge.Tests.cspr
|
|||||||
|
|
||||||
| Date (UTC) | Change | Notes |
|
| Date (UTC) | Change | Notes |
|
||||||
|------------|--------|-------|
|
|------------|--------|-------|
|
||||||
| 2025-10-16 | Ops review signed off after connector expansion (CCCS, CERT-Bund, KISA, ICS CISA, MSRC) landed. Alert thresholds from §3 reaffirmed; dashboards updated to watch attachment signals emitted by ICS CISA connector. | Ops sign-off recorded by Feedser Ops Guild; no additional overrides required. |
|
| 2025-10-16 | Ops review signed off after connector expansion (CCCS, CERT-Bund, KISA, ICS CISA, MSRC) landed. Alert thresholds from §3 reaffirmed; dashboards updated to watch attachment signals emitted by ICS CISA connector. | Ops sign-off recorded by Concelier Ops Guild; no additional overrides required. |
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"title": "Feedser CVE & KEV Observability",
|
"title": "Concelier CVE & KEV Observability",
|
||||||
"uid": "feedser-cve-kev",
|
"uid": "concelier-cve-kev",
|
||||||
"schemaVersion": 38,
|
"schemaVersion": 38,
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"editable": true,
|
"editable": true,
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Feedser CVE & KEV Connector Operations
|
# Concelier CVE & KEV Connector Operations
|
||||||
|
|
||||||
This playbook equips operators with the steps required to roll out and monitor the CVE Services and CISA KEV connectors across environments.
|
This playbook equips operators with the steps required to roll out and monitor the CVE Services and CISA KEV connectors across environments.
|
||||||
|
|
||||||
@@ -7,17 +7,17 @@ This playbook equips operators with the steps required to roll out and monitor t
|
|||||||
### 1.1 Prerequisites
|
### 1.1 Prerequisites
|
||||||
|
|
||||||
- CVE Services API credentials (organisation ID, user ID, API key) with access to the JSON 5 API.
|
- CVE Services API credentials (organisation ID, user ID, API key) with access to the JSON 5 API.
|
||||||
- Network egress to `https://cveawg.mitre.org` (or a mirrored endpoint) from the Feedser workers.
|
- Network egress to `https://cveawg.mitre.org` (or a mirrored endpoint) from the Concelier workers.
|
||||||
- Updated `feedser.yaml` (or the matching environment variables) with the following section:
|
- Updated `concelier.yaml` (or the matching environment variables) with the following section:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
sources:
|
sources:
|
||||||
cve:
|
cve:
|
||||||
baseEndpoint: "https://cveawg.mitre.org/api/"
|
baseEndpoint: "https://cveawg.mitre.org/api/"
|
||||||
apiOrg: "ORG123"
|
apiOrg: "ORG123"
|
||||||
apiUser: "user@example.org"
|
apiUser: "user@example.org"
|
||||||
apiKeyFile: "/var/run/secrets/feedser/cve-api-key"
|
apiKeyFile: "/var/run/secrets/concelier/cve-api-key"
|
||||||
seedDirectory: "./seed-data/cve"
|
seedDirectory: "./seed-data/cve"
|
||||||
pageSize: 200
|
pageSize: 200
|
||||||
maxPagesPerFetch: 5
|
maxPagesPerFetch: 5
|
||||||
@@ -26,44 +26,44 @@ feedser:
|
|||||||
failureBackoff: "00:10:00"
|
failureBackoff: "00:10:00"
|
||||||
```
|
```
|
||||||
|
|
||||||
> ℹ️ Store the API key outside source control. When using `apiKeyFile`, mount the secret file into the container/host; alternatively supply `apiKey` via `FEEDSER_SOURCES__CVE__APIKEY`.
|
> ℹ️ Store the API key outside source control. When using `apiKeyFile`, mount the secret file into the container/host; alternatively supply `apiKey` via `CONCELIER_SOURCES__CVE__APIKEY`.
|
||||||
|
|
||||||
> 🪙 When credentials are not yet available, configure `seedDirectory` to point at mirrored CVE JSON (for example, the repo’s `seed-data/cve/` bundle). The connector will ingest those records and log a warning instead of failing the job; live fetching resumes automatically once `apiOrg` / `apiUser` / `apiKey` are supplied.
|
> 🪙 When credentials are not yet available, configure `seedDirectory` to point at mirrored CVE JSON (for example, the repo’s `seed-data/cve/` bundle). The connector will ingest those records and log a warning instead of failing the job; live fetching resumes automatically once `apiOrg` / `apiUser` / `apiKey` are supplied.
|
||||||
|
|
||||||
### 1.2 Smoke Test (staging)
|
### 1.2 Smoke Test (staging)
|
||||||
|
|
||||||
1. Deploy the updated configuration and restart the Feedser service so the connector picks up the credentials.
|
1. Deploy the updated configuration and restart the Concelier service so the connector picks up the credentials.
|
||||||
2. Trigger one end-to-end cycle:
|
2. Trigger one end-to-end cycle:
|
||||||
- Feedser CLI: `stella db jobs run source:cve:fetch --and-then source:cve:parse --and-then source:cve:map`
|
- Concelier CLI: `stella db jobs run source:cve:fetch --and-then source:cve:parse --and-then source:cve:map`
|
||||||
- REST fallback: `POST /jobs/run { "kind": "source:cve:fetch", "chain": ["source:cve:parse", "source:cve:map"] }`
|
- REST fallback: `POST /jobs/run { "kind": "source:cve:fetch", "chain": ["source:cve:parse", "source:cve:map"] }`
|
||||||
3. Observe the following metrics (exported via OTEL meter `StellaOps.Feedser.Source.Cve`):
|
3. Observe the following metrics (exported via OTEL meter `StellaOps.Concelier.Source.Cve`):
|
||||||
- `cve.fetch.attempts`, `cve.fetch.success`, `cve.fetch.documents`, `cve.fetch.failures`, `cve.fetch.unchanged`
|
- `cve.fetch.attempts`, `cve.fetch.success`, `cve.fetch.documents`, `cve.fetch.failures`, `cve.fetch.unchanged`
|
||||||
- `cve.parse.success`, `cve.parse.failures`, `cve.parse.quarantine`
|
- `cve.parse.success`, `cve.parse.failures`, `cve.parse.quarantine`
|
||||||
- `cve.map.success`
|
- `cve.map.success`
|
||||||
4. Verify Prometheus shows matching `feedser.source.http.requests_total{feedser_source="cve"}` deltas (list vs detail phases) while `feedser.source.http.failures_total{feedser_source="cve"}` stays flat.
|
4. Verify Prometheus shows matching `concelier.source.http.requests_total{concelier_source="cve"}` deltas (list vs detail phases) while `concelier.source.http.failures_total{concelier_source="cve"}` stays flat.
|
||||||
5. Confirm the info-level summary log `CVEs fetch window … pages=X detailDocuments=Y detailFailures=Z` appears once per fetch run and shows `detailFailures=0`.
|
5. Confirm the info-level summary log `CVEs fetch window … pages=X detailDocuments=Y detailFailures=Z` appears once per fetch run and shows `detailFailures=0`.
|
||||||
6. Verify the MongoDB advisory store contains fresh CVE advisories (`advisoryKey` prefix `cve/`) and that the source cursor (`source_states` collection) advanced.
|
6. Verify the MongoDB advisory store contains fresh CVE advisories (`advisoryKey` prefix `cve/`) and that the source cursor (`source_states` collection) advanced.
|
||||||
|
|
||||||
### 1.3 Production Monitoring
|
### 1.3 Production Monitoring
|
||||||
|
|
||||||
- **Dashboards** – Plot `rate(cve_fetch_success_total[5m])`, `rate(cve_fetch_failures_total[5m])`, and `rate(cve_fetch_documents_total[5m])` alongside `feedser_source_http_requests_total{feedser_source="cve"}` to confirm HTTP and connector counters stay aligned. Keep `feedser.range.primitives{scheme=~"semver|vendor"}` on the same board for range coverage. Example alerts:
|
- **Dashboards** – Plot `rate(cve_fetch_success_total[5m])`, `rate(cve_fetch_failures_total[5m])`, and `rate(cve_fetch_documents_total[5m])` alongside `concelier_source_http_requests_total{concelier_source="cve"}` to confirm HTTP and connector counters stay aligned. Keep `concelier.range.primitives{scheme=~"semver|vendor"}` on the same board for range coverage. Example alerts:
|
||||||
- `rate(cve_fetch_failures_total[5m]) > 0` for 10 minutes (`severity=warning`)
|
- `rate(cve_fetch_failures_total[5m]) > 0` for 10 minutes (`severity=warning`)
|
||||||
- `rate(cve_map_success_total[15m]) == 0` while `rate(cve_fetch_success_total[15m]) > 0` (`severity=critical`)
|
- `rate(cve_map_success_total[15m]) == 0` while `rate(cve_fetch_success_total[15m]) > 0` (`severity=critical`)
|
||||||
- `sum_over_time(cve_parse_quarantine_total[1h]) > 0` to catch schema anomalies
|
- `sum_over_time(cve_parse_quarantine_total[1h]) > 0` to catch schema anomalies
|
||||||
- **Logs** – Monitor warnings such as `Failed fetching CVE record {CveId}` and `Malformed CVE JSON`, and surface the summary info log `CVEs fetch window … detailFailures=0 detailUnchanged=0` on dashboards. A non-zero `detailFailures` usually indicates rate-limit or auth issues on detail requests.
|
- **Logs** – Monitor warnings such as `Failed fetching CVE record {CveId}` and `Malformed CVE JSON`, and surface the summary info log `CVEs fetch window … detailFailures=0 detailUnchanged=0` on dashboards. A non-zero `detailFailures` usually indicates rate-limit or auth issues on detail requests.
|
||||||
- **Grafana pack** – Import `docs/ops/feedser-cve-kev-grafana-dashboard.json` and filter by panel legend (`CVE`, `KEV`) to reuse the canned layout.
|
- **Grafana pack** – Import `docs/ops/concelier-cve-kev-grafana-dashboard.json` and filter by panel legend (`CVE`, `KEV`) to reuse the canned layout.
|
||||||
- **Backfill window** – Operators can tighten or widen `initialBackfill` / `maxPagesPerFetch` after validating throughput. Update config and restart Feedser to apply changes.
|
- **Backfill window** – Operators can tighten or widen `initialBackfill` / `maxPagesPerFetch` after validating throughput. Update config and restart Concelier to apply changes.
|
||||||
|
|
||||||
### 1.4 Staging smoke log (2025-10-15)
|
### 1.4 Staging smoke log (2025-10-15)
|
||||||
|
|
||||||
While Ops finalises long-lived CVE Services credentials, we validated the connector end-to-end against the recorded CVE-2024-0001 payloads used in regression tests:
|
While Ops finalises long-lived CVE Services credentials, we validated the connector end-to-end against the recorded CVE-2024-0001 payloads used in regression tests:
|
||||||
|
|
||||||
- Command: `dotnet test src/StellaOps.Feedser.Source.Cve.Tests/StellaOps.Feedser.Source.Cve.Tests.csproj -l "console;verbosity=detailed"`
|
- Command: `dotnet test src/StellaOps.Concelier.Source.Cve.Tests/StellaOps.Concelier.Source.Cve.Tests.csproj -l "console;verbosity=detailed"`
|
||||||
- Summary log emitted by the connector:
|
- Summary log emitted by the connector:
|
||||||
```
|
```
|
||||||
CVEs fetch window 2024-09-01T00:00:00Z->2024-10-01T00:00:00Z pages=1 listSuccess=1 detailDocuments=1 detailFailures=0 detailUnchanged=0 pendingDocuments=0->1 pendingMappings=0->1 hasMorePages=False nextWindowStart=2024-09-15T12:00:00Z nextWindowEnd=(none) nextPage=1
|
CVEs fetch window 2024-09-01T00:00:00Z->2024-10-01T00:00:00Z pages=1 listSuccess=1 detailDocuments=1 detailFailures=0 detailUnchanged=0 pendingDocuments=0->1 pendingMappings=0->1 hasMorePages=False nextWindowStart=2024-09-15T12:00:00Z nextWindowEnd=(none) nextPage=1
|
||||||
```
|
```
|
||||||
- Telemetry captured by `Meter` `StellaOps.Feedser.Source.Cve`:
|
- Telemetry captured by `Meter` `StellaOps.Concelier.Source.Cve`:
|
||||||
| Metric | Value |
|
| Metric | Value |
|
||||||
|--------|-------|
|
|--------|-------|
|
||||||
| `cve.fetch.attempts` | 1 |
|
| `cve.fetch.attempts` | 1 |
|
||||||
@@ -72,7 +72,7 @@ While Ops finalises long-lived CVE Services credentials, we validated the connec
|
|||||||
| `cve.parse.success` | 1 |
|
| `cve.parse.success` | 1 |
|
||||||
| `cve.map.success` | 1 |
|
| `cve.map.success` | 1 |
|
||||||
|
|
||||||
The Grafana pack `docs/ops/feedser-cve-kev-grafana-dashboard.json` has been imported into staging so the panels referenced above render against these counters once the live API keys are in place.
|
The Grafana pack `docs/ops/concelier-cve-kev-grafana-dashboard.json` has been imported into staging so the panels referenced above render against these counters once the live API keys are in place.
|
||||||
|
|
||||||
## 2. CISA KEV Connector (`source:kev:*`)
|
## 2. CISA KEV Connector (`source:kev:*`)
|
||||||
|
|
||||||
@@ -80,10 +80,10 @@ The Grafana pack `docs/ops/feedser-cve-kev-grafana-dashboard.json` has been impo
|
|||||||
|
|
||||||
- Network egress (or mirrored content) for `https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json`.
|
- Network egress (or mirrored content) for `https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json`.
|
||||||
- No credentials are required, but the HTTP allow-list must include `www.cisa.gov`.
|
- No credentials are required, but the HTTP allow-list must include `www.cisa.gov`.
|
||||||
- Confirm the following snippet in `feedser.yaml` (defaults shown; tune as needed):
|
- Confirm the following snippet in `concelier.yaml` (defaults shown; tune as needed):
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
sources:
|
sources:
|
||||||
kev:
|
kev:
|
||||||
feedUri: "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
|
feedUri: "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
|
||||||
@@ -105,15 +105,15 @@ Treat repeated schema failures or growing anomaly counts as an upstream regressi
|
|||||||
|
|
||||||
### 2.3 Smoke Test (staging)
|
### 2.3 Smoke Test (staging)
|
||||||
|
|
||||||
1. Deploy the configuration and restart Feedser.
|
1. Deploy the configuration and restart Concelier.
|
||||||
2. Trigger a pipeline run:
|
2. Trigger a pipeline run:
|
||||||
- CLI: `stella db jobs run source:kev:fetch --and-then source:kev:parse --and-then source:kev:map`
|
- CLI: `stella db jobs run source:kev:fetch --and-then source:kev:parse --and-then source:kev:map`
|
||||||
- REST: `POST /jobs/run { "kind": "source:kev:fetch", "chain": ["source:kev:parse", "source:kev:map"] }`
|
- REST: `POST /jobs/run { "kind": "source:kev:fetch", "chain": ["source:kev:parse", "source:kev:map"] }`
|
||||||
3. Verify the metrics exposed by meter `StellaOps.Feedser.Source.Kev`:
|
3. Verify the metrics exposed by meter `StellaOps.Concelier.Source.Kev`:
|
||||||
- `kev.fetch.attempts`, `kev.fetch.success`, `kev.fetch.unchanged`, `kev.fetch.failures`
|
- `kev.fetch.attempts`, `kev.fetch.success`, `kev.fetch.unchanged`, `kev.fetch.failures`
|
||||||
- `kev.parse.entries` (tag `catalogVersion`), `kev.parse.failures`, `kev.parse.anomalies` (tag `reason`)
|
- `kev.parse.entries` (tag `catalogVersion`), `kev.parse.failures`, `kev.parse.anomalies` (tag `reason`)
|
||||||
- `kev.map.advisories` (tag `catalogVersion`)
|
- `kev.map.advisories` (tag `catalogVersion`)
|
||||||
4. Confirm `feedser.source.http.requests_total{feedser_source="kev"}` increments once per fetch and that the paired `feedser.source.http.failures_total` stays flat (zero increase).
|
4. Confirm `concelier.source.http.requests_total{concelier_source="kev"}` increments once per fetch and that the paired `concelier.source.http.failures_total` stays flat (zero increase).
|
||||||
5. Inspect the info logs `Fetched KEV catalog document … pendingDocuments=…` and `Parsed KEV catalog document … entries=…`—they should appear exactly once per run and `Mapped X/Y… skipped=0` should match the `kev.map.advisories` delta.
|
5. Inspect the info logs `Fetched KEV catalog document … pendingDocuments=…` and `Parsed KEV catalog document … entries=…`—they should appear exactly once per run and `Mapped X/Y… skipped=0` should match the `kev.map.advisories` delta.
|
||||||
6. Confirm MongoDB documents exist for the catalog JSON (`raw_documents` & `dtos`) and that advisories with prefix `kev/` are written.
|
6. Confirm MongoDB documents exist for the catalog JSON (`raw_documents` & `dtos`) and that advisories with prefix `kev/` are written.
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ Treat repeated schema failures or growing anomaly counts as an upstream regressi
|
|||||||
|
|
||||||
### 2.5 Known good dashboard tiles
|
### 2.5 Known good dashboard tiles
|
||||||
|
|
||||||
Add the following panels to the Feedser observability board:
|
Add the following panels to the Concelier observability board:
|
||||||
|
|
||||||
| Metric | Recommended visualisation |
|
| Metric | Recommended visualisation |
|
||||||
|--------|---------------------------|
|
|--------|---------------------------|
|
||||||
@@ -140,4 +140,4 @@ Add the following panels to the Feedser observability board:
|
|||||||
- Record staging/production smoke test results (date, catalog version, advisory counts) in your team’s change log.
|
- Record staging/production smoke test results (date, catalog version, advisory counts) in your team’s change log.
|
||||||
- Add the CVE/KEV job kinds to the standard maintenance checklist so operators can manually trigger them after planned downtime.
|
- Add the CVE/KEV job kinds to the standard maintenance checklist so operators can manually trigger them after planned downtime.
|
||||||
- Keep this document in sync with future connector changes (for example, new anomaly reasons or additional metrics).
|
- Keep this document in sync with future connector changes (for example, new anomaly reasons or additional metrics).
|
||||||
- Version-control dashboard tweaks alongside `docs/ops/feedser-cve-kev-grafana-dashboard.json` so operations can re-import the observability pack during restores.
|
- Version-control dashboard tweaks alongside `docs/ops/concelier-cve-kev-grafana-dashboard.json` so operations can re-import the observability pack during restores.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Feedser GHSA Connector – Operations Runbook
|
# Concelier GHSA Connector – Operations Runbook
|
||||||
|
|
||||||
_Last updated: 2025-10-16_
|
_Last updated: 2025-10-16_
|
||||||
|
|
||||||
@@ -32,9 +32,9 @@ When GitHub reports zero remaining calls, the connector logs and sleeps for the
|
|||||||
|
|
||||||
After the quota recovers above the warning threshold the connector writes an informational log with the refreshed remaining/headroom, letting operators clear alerts quickly.
|
After the quota recovers above the warning threshold the connector writes an informational log with the refreshed remaining/headroom, letting operators clear alerts quickly.
|
||||||
|
|
||||||
## 4. Configuration knobs (`feedser.yaml`)
|
## 4. Configuration knobs (`concelier.yaml`)
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
sources:
|
sources:
|
||||||
ghsa:
|
ghsa:
|
||||||
apiToken: "${GITHUB_PAT}"
|
apiToken: "${GITHUB_PAT}"
|
||||||
@@ -58,18 +58,18 @@ feedser:
|
|||||||
| `source:ghsa:parse` | `3,13,23,33,43,53 * * * *` | 5 minutes | 4 minutes |
|
| `source:ghsa:parse` | `3,13,23,33,43,53 * * * *` | 5 minutes | 4 minutes |
|
||||||
| `source:ghsa:map` | `5,15,25,35,45,55 * * * *` | 5 minutes | 4 minutes |
|
| `source:ghsa:map` | `5,15,25,35,45,55 * * * *` | 5 minutes | 4 minutes |
|
||||||
|
|
||||||
These defaults spread GHSA stages across the hour so fetch completes before parse/map fire. Override them via `feedser.jobs.definitions[...]` when coordinating multiple connectors on the same runner.
|
These defaults spread GHSA stages across the hour so fetch completes before parse/map fire. Override them via `concelier.jobs.definitions[...]` when coordinating multiple connectors on the same runner.
|
||||||
|
|
||||||
## 5. Provisioning credentials
|
## 5. Provisioning credentials
|
||||||
|
|
||||||
Feedser requires a GitHub personal access token (classic) with the **`read:org`** and **`security_events`** scopes to pull GHSA data. Store it as a secret and reference it via `feedser.sources.ghsa.apiToken`.
|
Concelier requires a GitHub personal access token (classic) with the **`read:org`** and **`security_events`** scopes to pull GHSA data. Store it as a secret and reference it via `concelier.sources.ghsa.apiToken`.
|
||||||
|
|
||||||
### Docker Compose (stack operators)
|
### Docker Compose (stack operators)
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
feedser:
|
concelier:
|
||||||
environment:
|
environment:
|
||||||
FEEDSER__SOURCES__GHSA__APITOKEN: /run/secrets/ghsa_pat
|
CONCELIER__SOURCES__GHSA__APITOKEN: /run/secrets/ghsa_pat
|
||||||
secrets:
|
secrets:
|
||||||
- ghsa_pat
|
- ghsa_pat
|
||||||
|
|
||||||
@@ -80,25 +80,25 @@ secrets:
|
|||||||
|
|
||||||
### Helm values (cluster operators)
|
### Helm values (cluster operators)
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
extraEnv:
|
extraEnv:
|
||||||
- name: FEEDSER__SOURCES__GHSA__APITOKEN
|
- name: CONCELIER__SOURCES__GHSA__APITOKEN
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: feedser-ghsa
|
name: concelier-ghsa
|
||||||
key: apiToken
|
key: apiToken
|
||||||
|
|
||||||
extraSecrets:
|
extraSecrets:
|
||||||
feedser-ghsa:
|
concelier-ghsa:
|
||||||
apiToken: "<paste PAT here or source from external secret store>"
|
apiToken: "<paste PAT here or source from external secret store>"
|
||||||
```
|
```
|
||||||
|
|
||||||
After rotating the PAT, restart the Feedser workers (or run `kubectl rollout restart deployment/feedser`) to ensure the configuration reloads.
|
After rotating the PAT, restart the Concelier workers (or run `kubectl rollout restart deployment/concelier`) to ensure the configuration reloads.
|
||||||
|
|
||||||
When enabling GHSA the first time, run a staged backfill:
|
When enabling GHSA the first time, run a staged backfill:
|
||||||
|
|
||||||
1. Trigger `source:ghsa:fetch` manually (CLI or API) outside of peak hours.
|
1. Trigger `source:ghsa:fetch` manually (CLI or API) outside of peak hours.
|
||||||
2. Watch `feedser.jobs.health` for the GHSA jobs until they report `healthy`.
|
2. Watch `concelier.jobs.health` for the GHSA jobs until they report `healthy`.
|
||||||
3. Allow the scheduled cron cadence to resume once the initial backlog drains (typically < 30 minutes).
|
3. Allow the scheduled cron cadence to resume once the initial backlog drains (typically < 30 minutes).
|
||||||
|
|
||||||
## 6. Runbook steps when throttled
|
## 6. Runbook steps when throttled
|
||||||
@@ -107,7 +107,7 @@ When enabling GHSA the first time, run a staged backfill:
|
|||||||
3. If rate limits stay exhausted:
|
3. If rate limits stay exhausted:
|
||||||
- Verify no other jobs are sharing the PAT.
|
- Verify no other jobs are sharing the PAT.
|
||||||
- Temporarily reduce `MaxPagesPerFetch` or `PageSize` to shrink burst size.
|
- Temporarily reduce `MaxPagesPerFetch` or `PageSize` to shrink burst size.
|
||||||
- Consider provisioning a dedicated PAT (GHSA permissions only) for Feedser.
|
- Consider provisioning a dedicated PAT (GHSA permissions only) for Concelier.
|
||||||
4. After the quota resets, reset `rateLimitWarningThreshold`/`requestDelay` to their normal values and monitor the histograms for at least one hour.
|
4. After the quota resets, reset `rateLimitWarningThreshold`/`requestDelay` to their normal values and monitor the histograms for at least one hour.
|
||||||
|
|
||||||
## 7. Alert integration quick reference
|
## 7. Alert integration quick reference
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Feedser CISA ICS Connector Operations
|
# Concelier CISA ICS Connector Operations
|
||||||
|
|
||||||
This runbook documents how to provision, rotate, and validate credentials for the CISA Industrial Control Systems (ICS) connector (`source:ics-cisa:*`). Follow it before enabling the connector in staging or offline installations.
|
This runbook documents how to provision, rotate, and validate credentials for the CISA Industrial Control Systems (ICS) connector (`source:ics-cisa:*`). Follow it before enabling the connector in staging or offline installations.
|
||||||
|
|
||||||
@@ -10,16 +10,16 @@ This runbook documents how to provision, rotate, and validate credentials for th
|
|||||||
- `USDHSCISA_19` — ICS medical advisories (`ICSMA-YY-###`).
|
- `USDHSCISA_19` — ICS medical advisories (`ICSMA-YY-###`).
|
||||||
- `USDHSCISA_17` — ICS alerts (`IR-ALERT-YY-###`) for completeness.
|
- `USDHSCISA_17` — ICS alerts (`IR-ALERT-YY-###`) for completeness.
|
||||||
3. Complete the verification email. After confirmation, note the **personalised subscription code** included in the “Manage Preferences” link. It has the shape `code=AB12CD34EF`.
|
3. Complete the verification email. After confirmation, note the **personalised subscription code** included in the “Manage Preferences” link. It has the shape `code=AB12CD34EF`.
|
||||||
4. Store the code in the shared secret vault (or Offline Kit secrets bundle) as `feedser/sources/icscisa/govdelivery/code`.
|
4. Store the code in the shared secret vault (or Offline Kit secrets bundle) as `concelier/sources/icscisa/govdelivery/code`.
|
||||||
|
|
||||||
> ℹ️ GovDelivery does not expose a one-time API key; the personalised code is what authenticates the RSS pull. Never commit it to git.
|
> ℹ️ GovDelivery does not expose a one-time API key; the personalised code is what authenticates the RSS pull. Never commit it to git.
|
||||||
|
|
||||||
## 2. Feed Validation
|
## 2. Feed Validation
|
||||||
|
|
||||||
Use the following command to confirm the feed is reachable before wiring it into Feedser (substitute `<CODE>` with the personalised value):
|
Use the following command to confirm the feed is reachable before wiring it into Concelier (substitute `<CODE>` with the personalised value):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -H "User-Agent: StellaOpsFeedser/ics-cisa" \
|
curl -H "User-Agent: StellaOpsConcelier/ics-cisa" \
|
||||||
"https://content.govdelivery.com/accounts/USDHSCISA/topics/ICS-CERT/feed.rss?format=xml&code=<CODE>"
|
"https://content.govdelivery.com/accounts/USDHSCISA/topics/ICS-CERT/feed.rss?format=xml&code=<CODE>"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -27,14 +27,14 @@ If the endpoint returns HTTP 200 and an RSS payload, record the sample response
|
|||||||
|
|
||||||
## 3. Configuration Snippet
|
## 3. Configuration Snippet
|
||||||
|
|
||||||
Add the connector configuration to `feedser.yaml` (or equivalent environment variables):
|
Add the connector configuration to `concelier.yaml` (or equivalent environment variables):
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
sources:
|
sources:
|
||||||
icscisa:
|
icscisa:
|
||||||
govDelivery:
|
govDelivery:
|
||||||
code: "${FEEDSER_ICS_CISA_GOVDELIVERY_CODE}"
|
code: "${CONCELIER_ICS_CISA_GOVDELIVERY_CODE}"
|
||||||
topics:
|
topics:
|
||||||
- "USDHSCISA_16"
|
- "USDHSCISA_16"
|
||||||
- "USDHSCISA_19"
|
- "USDHSCISA_19"
|
||||||
@@ -47,10 +47,10 @@ feedser:
|
|||||||
Environment variable example:
|
Environment variable example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export FEEDSER_SOURCES_ICSCISA_GOVDELIVERY_CODE="AB12CD34EF"
|
export CONCELIER_SOURCES_ICSCISA_GOVDELIVERY_CODE="AB12CD34EF"
|
||||||
```
|
```
|
||||||
|
|
||||||
Feedser automatically register the host with the Source.Common HTTP allow-list when the connector assembly is loaded.
|
Concelier automatically register the host with the Source.Common HTTP allow-list when the connector assembly is loaded.
|
||||||
|
|
||||||
|
|
||||||
Optional tuning keys (set only when needed):
|
Optional tuning keys (set only when needed):
|
||||||
@@ -68,21 +68,21 @@ If credentials are still pending, populate the connector with the community CSV
|
|||||||
1. Run `./scripts/fetch-ics-cisa-seed.sh` (or `.ps1`) to download the latest `CISA_ICS_ADV_*.csv` files into `seed-data/ics-cisa/`.
|
1. Run `./scripts/fetch-ics-cisa-seed.sh` (or `.ps1`) to download the latest `CISA_ICS_ADV_*.csv` files into `seed-data/ics-cisa/`.
|
||||||
2. Copy the CSVs (and the generated `.sha256` files) into your Offline Kit staging area so they ship alongside the other feeds.
|
2. Copy the CSVs (and the generated `.sha256` files) into your Offline Kit staging area so they ship alongside the other feeds.
|
||||||
3. Import the kit as usual. The connector can parse the seed data for historical context, but **live GovDelivery credentials are still required** for fresh advisories.
|
3. Import the kit as usual. The connector can parse the seed data for historical context, but **live GovDelivery credentials are still required** for fresh advisories.
|
||||||
4. Once credentials arrive, update `feedser:sources:icscisa:govDelivery:code` and re-trigger `source:ics-cisa:fetch` so the connector switches to the authorised feed.
|
4. Once credentials arrive, update `concelier:sources:icscisa:govDelivery:code` and re-trigger `source:ics-cisa:fetch` so the connector switches to the authorised feed.
|
||||||
|
|
||||||
> The CSVs are licensed under ODbL 1.0 by the ICS Advisory Project. Preserve the attribution when redistributing them.
|
> The CSVs are licensed under ODbL 1.0 by the ICS Advisory Project. Preserve the attribution when redistributing them.
|
||||||
|
|
||||||
## 4. Integration Validation
|
## 4. Integration Validation
|
||||||
|
|
||||||
1. Ensure secrets are in place and restart the Feedser workers.
|
1. Ensure secrets are in place and restart the Concelier workers.
|
||||||
2. Run a dry-run fetch/parse/map chain against an Akamai-protected topic:
|
2. Run a dry-run fetch/parse/map chain against an Akamai-protected topic:
|
||||||
```bash
|
```bash
|
||||||
FEEDSER_SOURCES_ICSCISA_GOVDELIVERY_CODE=... \
|
CONCELIER_SOURCES_ICSCISA_GOVDELIVERY_CODE=... \
|
||||||
FEEDSER_SOURCES_ICSCISA_ENABLEDETAILSCRAPE=1 \
|
CONCELIER_SOURCES_ICSCISA_ENABLEDETAILSCRAPE=1 \
|
||||||
stella db jobs run source:ics-cisa:fetch --and-then source:ics-cisa:parse --and-then source:ics-cisa:map
|
stella db jobs run source:ics-cisa:fetch --and-then source:ics-cisa:parse --and-then source:ics-cisa:map
|
||||||
```
|
```
|
||||||
3. Confirm logs contain `ics-cisa detail fetch` entries and that new documents/DTOs include attachments (see `docs/artifacts/icscisa`). Canonical advisories should expose PDF links as `references.kind == "attachment"` and affected packages should surface `primitives.semVer.exactValue` for single-version hits.
|
3. Confirm logs contain `ics-cisa detail fetch` entries and that new documents/DTOs include attachments (see `docs/artifacts/icscisa`). Canonical advisories should expose PDF links as `references.kind == "attachment"` and affected packages should surface `primitives.semVer.exactValue` for single-version hits.
|
||||||
4. If Akamai blocks direct fetches, set `feedser:sources:icscisa:proxyUri` to your allow-listed egress proxy and rerun the dry-run.
|
4. If Akamai blocks direct fetches, set `concelier:sources:icscisa:proxyUri` to your allow-listed egress proxy and rerun the dry-run.
|
||||||
|
|
||||||
## 4. Rotation & Incident Response
|
## 4. Rotation & Incident Response
|
||||||
|
|
||||||
@@ -92,19 +92,19 @@ If credentials are still pending, populate the connector with the community CSV
|
|||||||
|
|
||||||
## 5. Offline Kit Handling
|
## 5. Offline Kit Handling
|
||||||
|
|
||||||
Include the personalised code in `offline-kit/secrets/feedser/icscisa.env`:
|
Include the personalised code in `offline-kit/secrets/concelier/icscisa.env`:
|
||||||
|
|
||||||
```
|
```
|
||||||
FEEDSER_SOURCES_ICSCISA_GOVDELIVERY_CODE=AB12CD34EF
|
CONCELIER_SOURCES_ICSCISA_GOVDELIVERY_CODE=AB12CD34EF
|
||||||
```
|
```
|
||||||
|
|
||||||
The Offline Kit deployment script copies this file into the container secret directory mounted at `/run/secrets/feedser`. Ensure permissions are `600` and ownership matches the Feedser runtime user.
|
The Offline Kit deployment script copies this file into the container secret directory mounted at `/run/secrets/concelier`. Ensure permissions are `600` and ownership matches the Concelier runtime user.
|
||||||
|
|
||||||
## 6. Telemetry & Monitoring
|
## 6. Telemetry & Monitoring
|
||||||
|
|
||||||
The connector emits metrics under the meter `StellaOps.Feedser.Source.Ics.Cisa`. They allow operators to track Akamai fallbacks, detail enrichment health, and advisory fan-out.
|
The connector emits metrics under the meter `StellaOps.Concelier.Source.Ics.Cisa`. They allow operators to track Akamai fallbacks, detail enrichment health, and advisory fan-out.
|
||||||
|
|
||||||
- `icscisa.fetch.*` – counters for `attempts`, `success`, `failures`, `not_modified`, and `fallbacks`, plus histogram `icscisa.fetch.documents` showing documents added per topic pull (tags: `feedser.source`, `icscisa.topic`).
|
- `icscisa.fetch.*` – counters for `attempts`, `success`, `failures`, `not_modified`, and `fallbacks`, plus histogram `icscisa.fetch.documents` showing documents added per topic pull (tags: `concelier.source`, `icscisa.topic`).
|
||||||
- `icscisa.parse.*` – counters for `success`/`failures` and histograms `icscisa.parse.advisories`, `icscisa.parse.attachments`, `icscisa.parse.detail_fetches` to monitor enrichment workload per feed document.
|
- `icscisa.parse.*` – counters for `success`/`failures` and histograms `icscisa.parse.advisories`, `icscisa.parse.attachments`, `icscisa.parse.detail_fetches` to monitor enrichment workload per feed document.
|
||||||
- `icscisa.detail.*` – counters `success` / `failures` per advisory (tagged with `icscisa.advisory`) to alert when Akamai blocks detail pages.
|
- `icscisa.detail.*` – counters `success` / `failures` per advisory (tagged with `icscisa.advisory`) to alert when Akamai blocks detail pages.
|
||||||
- `icscisa.map.*` – counters for `success`/`failures` and histograms `icscisa.map.references`, `icscisa.map.packages`, `icscisa.map.aliases` capturing canonical fan-out.
|
- `icscisa.map.*` – counters for `success`/`failures` and histograms `icscisa.map.references`, `icscisa.map.packages`, `icscisa.map.aliases` capturing canonical fan-out.
|
||||||
@@ -114,7 +114,7 @@ Suggested alerts:
|
|||||||
- `increase(icscisa.fetch.failures_total[15m]) > 0` or `increase(icscisa.fetch.fallbacks_total[15m]) > 5` — sustained Akamai or proxy issues.
|
- `increase(icscisa.fetch.failures_total[15m]) > 0` or `increase(icscisa.fetch.fallbacks_total[15m]) > 5` — sustained Akamai or proxy issues.
|
||||||
- `increase(icscisa.detail.failures_total[30m]) > 0` — detail enrichment breaking (potential HTML layout change).
|
- `increase(icscisa.detail.failures_total[30m]) > 0` — detail enrichment breaking (potential HTML layout change).
|
||||||
- `histogram_quantile(0.95, rate(icscisa.map.references_bucket[1h]))` trending sharply higher — sudden advisory reference explosion worth investigating.
|
- `histogram_quantile(0.95, rate(icscisa.map.references_bucket[1h]))` trending sharply higher — sudden advisory reference explosion worth investigating.
|
||||||
- Keep an eye on shared HTTP metrics (`feedser.source.http.*{feedser.source="ics-cisa"}`) for request latency and retry patterns.
|
- Keep an eye on shared HTTP metrics (`concelier.source.http.*{concelier.source="ics-cisa"}`) for request latency and retry patterns.
|
||||||
|
|
||||||
## 6. Related Tasks
|
## 6. Related Tasks
|
||||||
|
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
# Feedser KISA Connector Operations
|
# Concelier KISA Connector Operations
|
||||||
|
|
||||||
Operational guidance for the Korea Internet & Security Agency (KISA / KNVD) connector (`source:kisa:*`). Pair this with the engineering brief in `docs/dev/kisa_connector_notes.md`.
|
Operational guidance for the Korea Internet & Security Agency (KISA / KNVD) connector (`source:kisa:*`). Pair this with the engineering brief in `docs/dev/kisa_connector_notes.md`.
|
||||||
|
|
||||||
## 1. Prerequisites
|
## 1. Prerequisites
|
||||||
|
|
||||||
- Outbound HTTPS (or mirrored cache) for `https://knvd.krcert.or.kr/`.
|
- Outbound HTTPS (or mirrored cache) for `https://knvd.krcert.or.kr/`.
|
||||||
- Connector options defined under `feedser:sources:kisa`:
|
- Connector options defined under `concelier:sources:kisa`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
sources:
|
sources:
|
||||||
kisa:
|
kisa:
|
||||||
feedUri: "https://knvd.krcert.or.kr/rss/securityInfo.do"
|
feedUri: "https://knvd.krcert.or.kr/rss/securityInfo.do"
|
||||||
@@ -19,15 +19,15 @@ feedser:
|
|||||||
failureBackoff: "00:05:00"
|
failureBackoff: "00:05:00"
|
||||||
```
|
```
|
||||||
|
|
||||||
> Ensure the URIs stay absolute—Feedser adds the `feedUri`/`detailApiUri` hosts to the HttpClient allow-list automatically.
|
> Ensure the URIs stay absolute—Concelier adds the `feedUri`/`detailApiUri` hosts to the HttpClient allow-list automatically.
|
||||||
|
|
||||||
## 2. Staging Smoke Test
|
## 2. Staging Smoke Test
|
||||||
|
|
||||||
1. Restart the Feedser workers so the KISA options bind.
|
1. Restart the Concelier workers so the KISA options bind.
|
||||||
2. Run a full connector cycle:
|
2. Run a full connector cycle:
|
||||||
- CLI: `stella db jobs run source:kisa:fetch --and-then source:kisa:parse --and-then source:kisa:map`
|
- CLI: `stella db jobs run source:kisa:fetch --and-then source:kisa:parse --and-then source:kisa:map`
|
||||||
- REST: `POST /jobs/run { "kind": "source:kisa:fetch", "chain": ["source:kisa:parse", "source:kisa:map"] }`
|
- REST: `POST /jobs/run { "kind": "source:kisa:fetch", "chain": ["source:kisa:parse", "source:kisa:map"] }`
|
||||||
3. Confirm telemetry (Meter `StellaOps.Feedser.Source.Kisa`):
|
3. Confirm telemetry (Meter `StellaOps.Concelier.Source.Kisa`):
|
||||||
- `kisa.feed.success`, `kisa.feed.items`
|
- `kisa.feed.success`, `kisa.feed.items`
|
||||||
- `kisa.detail.success` / `.failures`
|
- `kisa.detail.success` / `.failures`
|
||||||
- `kisa.parse.success` / `.failures`
|
- `kisa.parse.success` / `.failures`
|
||||||
@@ -47,7 +47,7 @@ feedser:
|
|||||||
## 3. Production Monitoring
|
## 3. Production Monitoring
|
||||||
|
|
||||||
- **Dashboards** – Add the following Prometheus/OTEL expressions:
|
- **Dashboards** – Add the following Prometheus/OTEL expressions:
|
||||||
- `rate(kisa_feed_items_total[15m])` versus `rate(feedser_source_http_requests_total{feedser_source="kisa"}[15m])`
|
- `rate(kisa_feed_items_total[15m])` versus `rate(concelier_source_http_requests_total{concelier_source="kisa"}[15m])`
|
||||||
- `increase(kisa_detail_failures_total{reason!="empty-document"}[1h])` alert at `>0`
|
- `increase(kisa_detail_failures_total{reason!="empty-document"}[1h])` alert at `>0`
|
||||||
- `increase(kisa_parse_failures_total[1h])` for storage/JSON issues
|
- `increase(kisa_parse_failures_total[1h])` for storage/JSON issues
|
||||||
- `increase(kisa_map_failures_total[1h])` to flag schema drift
|
- `increase(kisa_map_failures_total[1h])` to flag schema drift
|
||||||
@@ -63,8 +63,8 @@ feedser:
|
|||||||
|
|
||||||
## 5. Fixture & Regression Maintenance
|
## 5. Fixture & Regression Maintenance
|
||||||
|
|
||||||
- Regression fixtures: `src/StellaOps.Feedser.Source.Kisa.Tests/Fixtures/kisa-feed.xml` and `kisa-detail.json`.
|
- Regression fixtures: `src/StellaOps.Concelier.Source.Kisa.Tests/Fixtures/kisa-feed.xml` and `kisa-detail.json`.
|
||||||
- Refresh via `UPDATE_KISA_FIXTURES=1 dotnet test src/StellaOps.Feedser.Source.Kisa.Tests/StellaOps.Feedser.Source.Kisa.Tests.csproj`.
|
- Refresh via `UPDATE_KISA_FIXTURES=1 dotnet test src/StellaOps.Concelier.Source.Kisa.Tests/StellaOps.Concelier.Source.Kisa.Tests.csproj`.
|
||||||
- The telemetry regression (`KisaConnectorTests.Telemetry_RecordsMetrics`) will fail if counters/log wiring drifts—treat failures as gating.
|
- The telemetry regression (`KisaConnectorTests.Telemetry_RecordsMetrics`) will fail if counters/log wiring drifts—treat failures as gating.
|
||||||
|
|
||||||
## 6. Known Issues
|
## 6. Known Issues
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Feedser MSRC Connector – Azure AD Onboarding Brief
|
# Concelier MSRC Connector – Azure AD Onboarding Brief
|
||||||
|
|
||||||
_Drafted: 2025-10-15_
|
_Drafted: 2025-10-15_
|
||||||
|
|
||||||
@@ -8,18 +8,18 @@ _Drafted: 2025-10-15_
|
|||||||
- **Application type**: confidential client (web/API) issuing client credentials.
|
- **Application type**: confidential client (web/API) issuing client credentials.
|
||||||
- **API permissions**: `api://api.msrc.microsoft.com/.default` (Application). Admin consent required once.
|
- **API permissions**: `api://api.msrc.microsoft.com/.default` (Application). Admin consent required once.
|
||||||
- **Token audience**: `https://api.msrc.microsoft.com/`.
|
- **Token audience**: `https://api.msrc.microsoft.com/`.
|
||||||
- **Grant type**: client credentials. Feedser will request tokens via `POST https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token`.
|
- **Grant type**: client credentials. Concelier will request tokens via `POST https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token`.
|
||||||
|
|
||||||
## 2. Secret/credential policy
|
## 2. Secret/credential policy
|
||||||
|
|
||||||
- Maintain two client secrets (primary + standby) rotating every 90 days.
|
- Maintain two client secrets (primary + standby) rotating every 90 days.
|
||||||
- Store secrets in the Feedser secrets vault; Offline Kit deployments must mirror the secret payloads in their encrypted store.
|
- Store secrets in the Concelier secrets vault; Offline Kit deployments must mirror the secret payloads in their encrypted store.
|
||||||
- Record rotation cadence in Ops runbook and update Feedser configuration (`FEEDSER__SOURCES__VNDR__MSRC__CLIENTSECRET`) ahead of expiry.
|
- Record rotation cadence in Ops runbook and update Concelier configuration (`CONCELIER__SOURCES__VNDR__MSRC__CLIENTSECRET`) ahead of expiry.
|
||||||
|
|
||||||
## 3. Feedser configuration sample
|
## 3. Concelier configuration sample
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
feedser:
|
concelier:
|
||||||
sources:
|
sources:
|
||||||
vndr.msrc:
|
vndr.msrc:
|
||||||
tenantId: "<azure-tenant-guid>"
|
tenantId: "<azure-tenant-guid>"
|
||||||
@@ -73,7 +73,7 @@ Run the helper:
|
|||||||
```bash
|
```bash
|
||||||
dotnet run --project tools/SourceStateSeeder -- \
|
dotnet run --project tools/SourceStateSeeder -- \
|
||||||
--connection-string "mongodb://localhost:27017" \
|
--connection-string "mongodb://localhost:27017" \
|
||||||
--database feedser \
|
--database concelier \
|
||||||
--input seeds/msrc-backfill.json
|
--input seeds/msrc-backfill.json
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ The NKCKI connector ingests JSON bulletin archives from cert.gov.ru, expanding e
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Key options exposed through `feedser:sources:ru-nkcki:http`:
|
Key options exposed through `concelier:sources:ru-nkcki:http`:
|
||||||
|
|
||||||
- `maxBulletinsPerFetch` – limits new bulletin downloads in a single run (default `5`).
|
- `maxBulletinsPerFetch` – limits new bulletin downloads in a single run (default `5`).
|
||||||
- `maxListingPagesPerFetch` – maximum listing pages visited during pagination (default `3`).
|
- `maxListingPagesPerFetch` – maximum listing pages visited during pagination (default `3`).
|
||||||
@@ -14,11 +14,11 @@ Key options exposed through `feedser:sources:ru-nkcki:http`:
|
|||||||
- `cacheDirectory` – optional path for persisted bulletin archives used during offline or failure scenarios.
|
- `cacheDirectory` – optional path for persisted bulletin archives used during offline or failure scenarios.
|
||||||
- `requestDelay` – delay inserted between bulletin downloads to respect upstream politeness.
|
- `requestDelay` – delay inserted between bulletin downloads to respect upstream politeness.
|
||||||
|
|
||||||
When operating in offline-first mode, set `cacheDirectory` to a writable path (e.g. `/var/lib/feedser/cache/ru-nkcki`) and pre-populate bulletin archives via the offline kit.
|
When operating in offline-first mode, set `cacheDirectory` to a writable path (e.g. `/var/lib/concelier/cache/ru-nkcki`) and pre-populate bulletin archives via the offline kit.
|
||||||
|
|
||||||
## Telemetry
|
## Telemetry
|
||||||
|
|
||||||
`RuNkckiDiagnostics` emits the following metrics under meter `StellaOps.Feedser.Source.Ru.Nkcki`:
|
`RuNkckiDiagnostics` emits the following metrics under meter `StellaOps.Concelier.Source.Ru.Nkcki`:
|
||||||
|
|
||||||
- `nkcki.listing.fetch.attempts` / `nkcki.listing.fetch.success` / `nkcki.listing.fetch.failures`
|
- `nkcki.listing.fetch.attempts` / `nkcki.listing.fetch.success` / `nkcki.listing.fetch.failures`
|
||||||
- `nkcki.listing.pages.visited` (histogram, `pages`)
|
- `nkcki.listing.pages.visited` (histogram, `pages`)
|
||||||
@@ -26,7 +26,7 @@ When operating in offline-first mode, set `cacheDirectory` to a writable path (e
|
|||||||
- `nkcki.bulletin.fetch.success` / `nkcki.bulletin.fetch.cached` / `nkcki.bulletin.fetch.failures`
|
- `nkcki.bulletin.fetch.success` / `nkcki.bulletin.fetch.cached` / `nkcki.bulletin.fetch.failures`
|
||||||
- `nkcki.entries.processed` (histogram, `entries`)
|
- `nkcki.entries.processed` (histogram, `entries`)
|
||||||
|
|
||||||
Integrate these counters into standard Feedser observability dashboards to track crawl coverage and cache hit rates.
|
Integrate these counters into standard Concelier observability dashboards to track crawl coverage and cache hit rates.
|
||||||
|
|
||||||
## Archive Backfill Strategy
|
## Archive Backfill Strategy
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ Bitrix pagination surfaces archives via `?PAGEN_1=n`. The connector now walks up
|
|||||||
1. Enumerate pages from newest to oldest, respecting `maxListingPagesPerFetch` and `listingCacheDuration` to avoid refetch storms.
|
1. Enumerate pages from newest to oldest, respecting `maxListingPagesPerFetch` and `listingCacheDuration` to avoid refetch storms.
|
||||||
2. Persist every `*.json.zip` attachment to the configured cache directory. This enables replay when listing access is temporarily blocked.
|
2. Persist every `*.json.zip` attachment to the configured cache directory. This enables replay when listing access is temporarily blocked.
|
||||||
3. During archive replay, `ProcessCachedBulletinsAsync` enqueues missing documents while respecting `maxVulnerabilitiesPerFetch`.
|
3. During archive replay, `ProcessCachedBulletinsAsync` enqueues missing documents while respecting `maxVulnerabilitiesPerFetch`.
|
||||||
4. For historical HTML-only advisories, collect page URLs and metadata while offline (future work: HTML and PDF extraction pipeline documented in `docs/feedser-connector-research-20251011.md`).
|
4. For historical HTML-only advisories, collect page URLs and metadata while offline (future work: HTML and PDF extraction pipeline documented in `docs/concelier-connector-research-20251011.md`).
|
||||||
|
|
||||||
For large migrations, seed caches with archived zip bundles, then run fetch/parse/map cycles in chronological order to maintain deterministic outputs.
|
For large migrations, seed caches with archived zip bundles, then run fetch/parse/map cycles in chronological order to maintain deterministic outputs.
|
||||||
|
|
||||||
@@ -45,4 +45,4 @@ For large migrations, seed caches with archived zip bundles, then run fetch/pars
|
|||||||
- Bulletin fetches fall back to cached copies before surfacing an error.
|
- Bulletin fetches fall back to cached copies before surfacing an error.
|
||||||
- Mongo integration tests rely on bundled OpenSSL 1.1 libraries (`tools/openssl/linux-x64`) to keep `Mongo2Go` operational on modern distros.
|
- Mongo integration tests rely on bundled OpenSSL 1.1 libraries (`tools/openssl/linux-x64`) to keep `Mongo2Go` operational on modern distros.
|
||||||
|
|
||||||
Refer to `ru-nkcki` entries in `src/StellaOps.Feedser.Source.Ru.Nkcki/TASKS.md` for outstanding items.
|
Refer to `ru-nkcki` entries in `src/StellaOps.Concelier.Source.Ru.Nkcki/TASKS.md` for outstanding items.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Feedser OSV Connector – Operations Notes
|
# Concelier OSV Connector – Operations Notes
|
||||||
|
|
||||||
_Last updated: 2025-10-16_
|
_Last updated: 2025-10-16_
|
||||||
|
|
||||||
@@ -20,5 +20,5 @@ The OSV connector ingests advisories from OSV.dev across OSS ecosystems. This no
|
|||||||
- Exporters already surface `canonicalMetricId`; no schema change is required, but ORAS/Trivy bundles should be spot-checked after deploying the connector update.
|
- Exporters already surface `canonicalMetricId`; no schema change is required, but ORAS/Trivy bundles should be spot-checked after deploying the connector update.
|
||||||
|
|
||||||
## 4. Runbook updates
|
## 4. Runbook updates
|
||||||
- Fixture parity suites (`osv-ghsa.*`) now assert the fallback id and provenance notes. Regenerate via `dotnet test src/StellaOps.Feedser.Source.Osv.Tests/StellaOps.Feedser.Source.Osv.Tests.csproj`.
|
- Fixture parity suites (`osv-ghsa.*`) now assert the fallback id and provenance notes. Regenerate via `dotnet test src/StellaOps.Concelier.Source.Osv.Tests/StellaOps.Concelier.Source.Osv.Tests.csproj`.
|
||||||
- When investigating merge severity conflicts, include the fallback counter and confirm OSV advisories carry the expected `osv:severity/<level>` id before raising connector bugs.
|
- When investigating merge severity conflicts, include the fallback counter and confirm OSV advisories carry the expected `osv:severity/<level>` id before raising connector bugs.
|
||||||
@@ -6,12 +6,12 @@ _Last updated: 2025-10-11_
|
|||||||
|
|
||||||
The SemVer style migration populates the new `normalizedVersions` field on advisory documents and ensures
|
The SemVer style migration populates the new `normalizedVersions` field on advisory documents and ensures
|
||||||
provenance `decisionReason` values are preserved during future reads. The migration is idempotent and only
|
provenance `decisionReason` values are preserved during future reads. The migration is idempotent and only
|
||||||
runs when the feature flag `feedser:storage:enableSemVerStyle` is enabled.
|
runs when the feature flag `concelier:storage:enableSemVerStyle` is enabled.
|
||||||
|
|
||||||
## Preconditions
|
## Preconditions
|
||||||
|
|
||||||
1. **Review configuration** – set `feedser.storage.enableSemVerStyle` to `true` on all Feedser services.
|
1. **Review configuration** – set `concelier.storage.enableSemVerStyle` to `true` on all Concelier services.
|
||||||
2. **Confirm batch size** – adjust `feedser.storage.backfillBatchSize` if you need smaller batches for older
|
2. **Confirm batch size** – adjust `concelier.storage.backfillBatchSize` if you need smaller batches for older
|
||||||
deployments (default: `250`).
|
deployments (default: `250`).
|
||||||
3. **Back up** – capture a fresh snapshot of the `advisory` collection or a full MongoDB backup.
|
3. **Back up** – capture a fresh snapshot of the `advisory` collection or a full MongoDB backup.
|
||||||
4. **Staging dry-run** – enable the flag in a staging environment and observe the migration output before
|
4. **Staging dry-run** – enable the flag in a staging environment and observe the migration output before
|
||||||
@@ -19,7 +19,7 @@ runs when the feature flag `feedser:storage:enableSemVerStyle` is enabled.
|
|||||||
|
|
||||||
## Execution
|
## Execution
|
||||||
|
|
||||||
No manual command is required. After deploying the configuration change, restart the Feedser WebService or
|
No manual command is required. After deploying the configuration change, restart the Concelier WebService or
|
||||||
any component that hosts the Mongo migration runner. During startup you will see log entries similar to:
|
any component that hosts the Mongo migration runner. During startup you will see log entries similar to:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -27,7 +27,7 @@ Applying Mongo migration 20251011-semver-style-backfill: Populate advisory.norma
|
|||||||
Mongo migration 20251011-semver-style-backfill applied
|
Mongo migration 20251011-semver-style-backfill applied
|
||||||
```
|
```
|
||||||
|
|
||||||
The migration reads advisories in batches (`feedser.storage.backfillBatchSize`) and writes flattened
|
The migration reads advisories in batches (`concelier.storage.backfillBatchSize`) and writes flattened
|
||||||
`normalizedVersions` arrays. Existing documents without SemVer ranges remain untouched.
|
`normalizedVersions` arrays. Existing documents without SemVer ranges remain untouched.
|
||||||
|
|
||||||
## Post-checks
|
## Post-checks
|
||||||
@@ -39,12 +39,12 @@ The migration reads advisories in batches (`feedser.storage.backfillBatchSize`)
|
|||||||
You should see `advisory_normalizedVersions_pkg_scheme_type` and `advisory_normalizedVersions_value`.
|
You should see `advisory_normalizedVersions_pkg_scheme_type` and `advisory_normalizedVersions_value`.
|
||||||
2. Spot check a few advisories to confirm the top-level `normalizedVersions` array exists and matches
|
2. Spot check a few advisories to confirm the top-level `normalizedVersions` array exists and matches
|
||||||
the embedded package data.
|
the embedded package data.
|
||||||
3. Run `dotnet test` for `StellaOps.Feedser.Storage.Mongo.Tests` (optional but recommended) in CI to confirm
|
3. Run `dotnet test` for `StellaOps.Concelier.Storage.Mongo.Tests` (optional but recommended) in CI to confirm
|
||||||
the storage suite passes with the feature flag enabled.
|
the storage suite passes with the feature flag enabled.
|
||||||
|
|
||||||
## Rollback
|
## Rollback
|
||||||
|
|
||||||
Set `feedser.storage.enableSemVerStyle` back to `false` and redeploy. The migration will be skipped on
|
Set `concelier.storage.enableSemVerStyle` back to `false` and redeploy. The migration will be skipped on
|
||||||
subsequent startups. You can leave the populated `normalizedVersions` arrays in place; they are ignored when
|
subsequent startups. You can leave the populated `normalizedVersions` arrays in place; they are ignored when
|
||||||
the feature flag is off. If you must remove them entirely, restore from the backup captured during
|
the feature flag is off. If you must remove them entirely, restore from the backup captured during
|
||||||
preparation.
|
preparation.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|-----------------|-------------|----------------|
|
|-----------------|-------------|----------------|
|
||||||
| Token issuance APIs (`/token`, `/authorize`) | OAuth/OIDC endpoints mediated by OpenIddict | CLI, UI, automation agents |
|
| Token issuance APIs (`/token`, `/authorize`) | OAuth/OIDC endpoints mediated by OpenIddict | CLI, UI, automation agents |
|
||||||
| Bootstrap channel | Initial admin invite + bootstrap CLI workflow | Platform operators |
|
| Bootstrap channel | Initial admin invite + bootstrap CLI workflow | Platform operators |
|
||||||
| Revocation bundle | Offline JSON + detached JWS consumed by agents | Feedser, Agents, Zastava |
|
| Revocation bundle | Offline JSON + detached JWS consumed by agents | Concelier, Agents, Zastava |
|
||||||
| Plug-in manifests | Standard plug-in configuration and password policy overrides | Operators, DevOps |
|
| Plug-in manifests | Standard plug-in configuration and password policy overrides | Operators, DevOps |
|
||||||
| Signing keys | ES256 signing keys backing tokens and revocation manifests | Security Guild, HSM/KeyOps |
|
| Signing keys | ES256 signing keys backing tokens and revocation manifests | Security Guild, HSM/KeyOps |
|
||||||
| Audit telemetry | Structured login/audit stream persisted to Mongo/observability stack | SOC, SecOps |
|
| Audit telemetry | Structured login/audit stream persisted to Mongo/observability stack | SOC, SecOps |
|
||||||
@@ -68,7 +68,7 @@ flowchart LR
|
|||||||
end
|
end
|
||||||
subgraph Distribution
|
subgraph Distribution
|
||||||
OFFKIT[Offline Kit Bundle]
|
OFFKIT[Offline Kit Bundle]
|
||||||
AGENT[Authorized Agent / Feedser]
|
AGENT[Authorized Agent / Concelier]
|
||||||
end
|
end
|
||||||
OPS -->|Bootstrap CLI (`stellaops auth bootstrap`)| AUTH
|
OPS -->|Bootstrap CLI (`stellaops auth bootstrap`)| AUTH
|
||||||
AUTH -->|One-time invite + Argon2 hash| STORE
|
AUTH -->|One-time invite + Argon2 hash| STORE
|
||||||
|
|||||||
@@ -12,14 +12,14 @@
|
|||||||
"id": "7ad4f3d2c21b461d9b3420e1151be9c4",
|
"id": "7ad4f3d2c21b461d9b3420e1151be9c4",
|
||||||
"category": "token",
|
"category": "token",
|
||||||
"tokenType": "access_token",
|
"tokenType": "access_token",
|
||||||
"clientId": "feedser-cli",
|
"clientId": "concelier-cli",
|
||||||
"subjectId": "user:ops-admin",
|
"subjectId": "user:ops-admin",
|
||||||
"reason": "compromised",
|
"reason": "compromised",
|
||||||
"reasonDescription": "Access token reported by SOC automation run R-2045.",
|
"reasonDescription": "Access token reported by SOC automation run R-2045.",
|
||||||
"revokedAt": "2025-10-12T14:32:05Z",
|
"revokedAt": "2025-10-12T14:32:05Z",
|
||||||
"scopes": [
|
"scopes": [
|
||||||
"feedser:export",
|
"concelier:export",
|
||||||
"feedser:jobs"
|
"concelier:jobs"
|
||||||
],
|
],
|
||||||
"fingerprint": "AD35E719C12204D7E7C92ED3F6DEBF0A44642D41AAF94233F9A47E183F4C5F18",
|
"fingerprint": "AD35E719C12204D7E7C92ED3F6DEBF0A44642D41AAF94233F9A47E183F4C5F18",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Authority Revocation Bundle
|
# Authority Revocation Bundle
|
||||||
|
|
||||||
The Authority service exports revocation information as an offline-friendly JSON document plus a detached JWS signature. Operators can mirror the bundle alongside Feedser exports to ensure air-gapped scanners receive the latest token, subject, and client revocations.
|
The Authority service exports revocation information as an offline-friendly JSON document plus a detached JWS signature. Operators can mirror the bundle alongside Concelier exports to ensure air-gapped scanners receive the latest token, subject, and client revocations.
|
||||||
|
|
||||||
## File layout
|
## File layout
|
||||||
|
|
||||||
@@ -88,4 +88,4 @@ The repository contains an [example bundle](revocation-bundle-example.json) demo
|
|||||||
- `stella auth revoke verify` validates a bundle using cached JWKS or an offline PEM key, honours the `provider` metadata embedded in the signature, and reports digest mismatches before distribution.
|
- `stella auth revoke verify` validates a bundle using cached JWKS or an offline PEM key, honours the `provider` metadata embedded in the signature, and reports digest mismatches before distribution.
|
||||||
- `POST /internal/revocations/export` provides the same payload for orchestrators that already talk to the bootstrap API.
|
- `POST /internal/revocations/export` provides the same payload for orchestrators that already talk to the bootstrap API.
|
||||||
- `POST /internal/signing/rotate` rotates JWKS material without downtime; always export a fresh bundle afterward so downstream mirrors receive signatures from the new `kid`.
|
- `POST /internal/signing/rotate` rotates JWKS material without downtime; always export a fresh bundle afterward so downstream mirrors receive signatures from the new `kid`.
|
||||||
- Offline Kit automation should mirror `revocation-bundle.json*` alongside Feedser exports so agents ingest revocations during the same sync pass.
|
- Offline Kit automation should mirror `revocation-bundle.json*` alongside Concelier exports so agents ingest revocations during the same sync pass.
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
# Feedser configuration template for StellaOps deployments.
|
# Concelier configuration template for StellaOps deployments.
|
||||||
# Copy to ../etc/feedser.yaml (relative to the web service content root)
|
# Copy to ../etc/concelier.yaml (relative to the web service content root)
|
||||||
# and adjust the values to match your environment. Environment variables
|
# and adjust the values to match your environment. Environment variables
|
||||||
# (prefixed with FEEDSER_) override these settings at runtime.
|
# (prefixed with CONCELIER_) override these settings at runtime.
|
||||||
|
|
||||||
storage:
|
storage:
|
||||||
driver: mongo
|
driver: mongo
|
||||||
# Mongo connection string. Use SRV URI or standard connection string.
|
# Mongo connection string. Use SRV URI or standard connection string.
|
||||||
dsn: "mongodb://feedser:feedser@mongo:27017/feedser?authSource=admin"
|
dsn: "mongodb://concelier:concelier@mongo:27017/concelier?authSource=admin"
|
||||||
# Optional database name; defaults to the name embedded in the DSN or 'feedser'.
|
# Optional database name; defaults to the name embedded in the DSN or 'concelier'.
|
||||||
database: "feedser"
|
database: "concelier"
|
||||||
# Mongo command timeout in seconds.
|
# Mongo command timeout in seconds.
|
||||||
commandTimeoutSeconds: 30
|
commandTimeoutSeconds: 30
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
# Feedser resolves plug-ins relative to the content root; override as needed.
|
# Concelier resolves plug-ins relative to the content root; override as needed.
|
||||||
baseDirectory: ".."
|
baseDirectory: ".."
|
||||||
directory: "PluginBinaries"
|
directory: "PluginBinaries"
|
||||||
searchPatterns:
|
searchPatterns:
|
||||||
- "StellaOps.Feedser.Plugin.*.dll"
|
- "StellaOps.Concelier.Plugin.*.dll"
|
||||||
|
|
||||||
telemetry:
|
telemetry:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -25,7 +25,7 @@ telemetry:
|
|||||||
enableMetrics: false
|
enableMetrics: false
|
||||||
enableLogging: true
|
enableLogging: true
|
||||||
minimumLogLevel: "Information"
|
minimumLogLevel: "Information"
|
||||||
serviceName: "stellaops-feedser"
|
serviceName: "stellaops-concelier"
|
||||||
# Configure OTLP endpoint when shipping traces/metrics/logs out-of-band.
|
# Configure OTLP endpoint when shipping traces/metrics/logs out-of-band.
|
||||||
otlpEndpoint: ""
|
otlpEndpoint: ""
|
||||||
# Optional headers for OTLP exporters, for example authentication tokens.
|
# Optional headers for OTLP exporters, for example authentication tokens.
|
||||||
@@ -38,7 +38,7 @@ telemetry:
|
|||||||
|
|
||||||
authority:
|
authority:
|
||||||
enabled: false
|
enabled: false
|
||||||
# Temporary rollout flag. When true, Feedser logs anonymous access but does not fail requests
|
# Temporary rollout flag. When true, Concelier logs anonymous access but does not fail requests
|
||||||
# without tokens. Set to false before 2025-12-31 UTC to enforce authentication fully.
|
# without tokens. Set to false before 2025-12-31 UTC to enforce authentication fully.
|
||||||
allowAnonymousFallback: true
|
allowAnonymousFallback: true
|
||||||
# Issuer advertised by StellaOps Authority (e.g. https://authority.stella-ops.local).
|
# Issuer advertised by StellaOps Authority (e.g. https://authority.stella-ops.local).
|
||||||
@@ -49,16 +49,16 @@ authority:
|
|||||||
backchannelTimeoutSeconds: 30
|
backchannelTimeoutSeconds: 30
|
||||||
tokenClockSkewSeconds: 60
|
tokenClockSkewSeconds: 60
|
||||||
audiences:
|
audiences:
|
||||||
- "api://feedser"
|
- "api://concelier"
|
||||||
requiredScopes:
|
requiredScopes:
|
||||||
- "feedser.jobs.trigger"
|
- "concelier.jobs.trigger"
|
||||||
# Outbound credentials Feedser can use to call Authority (client credentials flow).
|
# Outbound credentials Concelier can use to call Authority (client credentials flow).
|
||||||
clientId: "feedser-jobs"
|
clientId: "concelier-jobs"
|
||||||
# Prefer storing the secret outside of the config file. Provide either clientSecret or clientSecretFile.
|
# Prefer storing the secret outside of the config file. Provide either clientSecret or clientSecretFile.
|
||||||
clientSecret: ""
|
clientSecret: ""
|
||||||
clientSecretFile: ""
|
clientSecretFile: ""
|
||||||
clientScopes:
|
clientScopes:
|
||||||
- "feedser.jobs.trigger"
|
- "concelier.jobs.trigger"
|
||||||
resilience:
|
resilience:
|
||||||
# Enable deterministic retry/backoff when Authority is briefly unavailable.
|
# Enable deterministic retry/backoff when Authority is briefly unavailable.
|
||||||
enableRetries: true
|
enableRetries: true
|
||||||
@@ -10,9 +10,9 @@ $env:UPDATE_APPLE_FIXTURES = "1"
|
|||||||
|
|
||||||
Push-Location $rootDir
|
Push-Location $rootDir
|
||||||
try {
|
try {
|
||||||
$sentinel = Join-Path $rootDir "src/StellaOps.Feedser.Source.Vndr.Apple.Tests/Apple/Fixtures/.update-apple-fixtures"
|
$sentinel = Join-Path $rootDir "src/StellaOps.Concelier.Source.Vndr.Apple.Tests/Apple/Fixtures/.update-apple-fixtures"
|
||||||
New-Item -ItemType File -Path $sentinel -Force | Out-Null
|
New-Item -ItemType File -Path $sentinel -Force | Out-Null
|
||||||
dotnet test "src\StellaOps.Feedser.Source.Vndr.Apple.Tests\StellaOps.Feedser.Source.Vndr.Apple.Tests.csproj" @Args
|
dotnet test "src\StellaOps.Concelier.Source.Vndr.Apple.Tests\StellaOps.Concelier.Source.Vndr.Apple.Tests.csproj" @Args
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ else
|
|||||||
export WSLENV="UPDATE_APPLE_FIXTURES/up"
|
export WSLENV="UPDATE_APPLE_FIXTURES/up"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
touch "$ROOT_DIR/src/StellaOps.Feedser.Source.Vndr.Apple.Tests/Apple/Fixtures/.update-apple-fixtures"
|
touch "$ROOT_DIR/src/StellaOps.Concelier.Source.Vndr.Apple.Tests/Apple/Fixtures/.update-apple-fixtures"
|
||||||
( cd "$ROOT_DIR" && dotnet test "src/StellaOps.Feedser.Source.Vndr.Apple.Tests/StellaOps.Feedser.Source.Vndr.Apple.Tests.csproj" "$@" )
|
( cd "$ROOT_DIR" && dotnet test "src/StellaOps.Concelier.Source.Vndr.Apple.Tests/StellaOps.Concelier.Source.Vndr.Apple.Tests.csproj" "$@" )
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ Param(
|
|||||||
$Root = Split-Path -Parent $PSScriptRoot
|
$Root = Split-Path -Parent $PSScriptRoot
|
||||||
$env:UPDATE_GOLDENS = "1"
|
$env:UPDATE_GOLDENS = "1"
|
||||||
|
|
||||||
dotnet test (Join-Path $Root "src/StellaOps.Feedser.Models.Tests/StellaOps.Feedser.Models.Tests.csproj") @RestArgs
|
dotnet test (Join-Path $Root "src/StellaOps.Concelier.Models.Tests/StellaOps.Concelier.Models.Tests.csproj") @RestArgs
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|||||||
|
|
||||||
export UPDATE_GOLDENS=1
|
export UPDATE_GOLDENS=1
|
||||||
|
|
||||||
dotnet test "$ROOT_DIR/src/StellaOps.Feedser.Models.Tests/StellaOps.Feedser.Models.Tests.csproj" "$@"
|
dotnet test "$ROOT_DIR/src/StellaOps.Concelier.Models.Tests/StellaOps.Concelier.Models.Tests.csproj" "$@"
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ python tools/certbund_offline_snapshot.py --output seed-data/cert-bund
|
|||||||
```
|
```
|
||||||
|
|
||||||
See the connector operations guide
|
See the connector operations guide
|
||||||
(`docs/ops/feedser-certbund-operations.md`) for detailed usage,
|
(`docs/ops/concelier-certbund-operations.md`) for detailed usage,
|
||||||
including how to provide cookies/tokens when the portal requires manual
|
including how to provide cookies/tokens when the portal requires manual
|
||||||
authentication.
|
authentication.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
````markdown
|
````markdown
|
||||||
# Feedser Vulnerability Conflict Resolution Rules
|
# Concelier Vulnerability Conflict Resolution Rules
|
||||||
|
|
||||||
This document defines the canonical, deterministic conflict resolution strategy for merging vulnerability data from **NVD**, **GHSA**, and **OSV** in Feedser.
|
This document defines the canonical, deterministic conflict resolution strategy for merging vulnerability data from **NVD**, **GHSA**, and **OSV** in Concelier.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ return out
|
|||||||
|
|
||||||
## 🧰 Optional C# Helper Class
|
## 🧰 Optional C# Helper Class
|
||||||
|
|
||||||
`StellaOps.Feedser.Core/CanonicalMerger.cs`
|
`StellaOps.Concelier.Core/CanonicalMerger.cs`
|
||||||
|
|
||||||
Implements:
|
Implements:
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<FeedserPluginOutputRoot Condition="'$(FeedserPluginOutputRoot)' == ''">$(SolutionDir)PluginBinaries</FeedserPluginOutputRoot>
|
<ConcelierPluginOutputRoot Condition="'$(ConcelierPluginOutputRoot)' == ''">$(SolutionDir)PluginBinaries</ConcelierPluginOutputRoot>
|
||||||
<FeedserPluginOutputRoot Condition="'$(FeedserPluginOutputRoot)' == '' and '$(SolutionDir)' == ''">$(MSBuildThisFileDirectory)PluginBinaries</FeedserPluginOutputRoot>
|
<ConcelierPluginOutputRoot Condition="'$(ConcelierPluginOutputRoot)' == '' and '$(SolutionDir)' == ''">$(MSBuildThisFileDirectory)PluginBinaries</ConcelierPluginOutputRoot>
|
||||||
<AuthorityPluginOutputRoot Condition="'$(AuthorityPluginOutputRoot)' == ''">$(SolutionDir)PluginBinaries\Authority</AuthorityPluginOutputRoot>
|
<AuthorityPluginOutputRoot Condition="'$(AuthorityPluginOutputRoot)' == ''">$(SolutionDir)PluginBinaries\Authority</AuthorityPluginOutputRoot>
|
||||||
<AuthorityPluginOutputRoot Condition="'$(AuthorityPluginOutputRoot)' == '' and '$(SolutionDir)' == ''">$(MSBuildThisFileDirectory)PluginBinaries\Authority</AuthorityPluginOutputRoot>
|
<AuthorityPluginOutputRoot Condition="'$(AuthorityPluginOutputRoot)' == '' and '$(SolutionDir)' == ''">$(MSBuildThisFileDirectory)PluginBinaries\Authority</AuthorityPluginOutputRoot>
|
||||||
<IsFeedserPlugin Condition="'$(IsFeedserPlugin)' == '' and $([System.String]::Copy('$(MSBuildProjectName)').StartsWith('StellaOps.Feedser.Source.'))">true</IsFeedserPlugin>
|
<IsConcelierPlugin Condition="'$(IsConcelierPlugin)' == '' and $([System.String]::Copy('$(MSBuildProjectName)').StartsWith('StellaOps.Concelier.Source.'))">true</IsConcelierPlugin>
|
||||||
<IsFeedserPlugin Condition="'$(IsFeedserPlugin)' == '' and $([System.String]::Copy('$(MSBuildProjectName)').StartsWith('StellaOps.Feedser.Exporter.'))">true</IsFeedserPlugin>
|
<IsConcelierPlugin Condition="'$(IsConcelierPlugin)' == '' and $([System.String]::Copy('$(MSBuildProjectName)').StartsWith('StellaOps.Concelier.Exporter.'))">true</IsConcelierPlugin>
|
||||||
<IsAuthorityPlugin Condition="'$(IsAuthorityPlugin)' == '' and $([System.String]::Copy('$(MSBuildProjectName)').StartsWith('StellaOps.Authority.Plugin.'))">true</IsAuthorityPlugin>
|
<IsAuthorityPlugin Condition="'$(IsAuthorityPlugin)' == '' and $([System.String]::Copy('$(MSBuildProjectName)').StartsWith('StellaOps.Authority.Plugin.'))">true</IsAuthorityPlugin>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
@@ -24,10 +24,10 @@
|
|||||||
<PackageReference Include="xunit" Version="2.9.2" />
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" Version="8.4.0" />
|
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" Version="8.4.0" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)StellaOps.Feedser.Tests.Shared\AssemblyInfo.cs" Link="Shared\AssemblyInfo.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)StellaOps.Concelier.Tests.Shared\AssemblyInfo.cs" Link="Shared\AssemblyInfo.cs" />
|
||||||
<Compile Include="$(MSBuildThisFileDirectory)StellaOps.Feedser.Tests.Shared\MongoFixtureCollection.cs" Link="Shared\MongoFixtureCollection.cs" />
|
<Compile Include="$(MSBuildThisFileDirectory)StellaOps.Concelier.Tests.Shared\MongoFixtureCollection.cs" Link="Shared\MongoFixtureCollection.cs" />
|
||||||
<ProjectReference Include="$(MSBuildThisFileDirectory)StellaOps.Feedser.Testing\StellaOps.Feedser.Testing.csproj" />
|
<ProjectReference Include="$(MSBuildThisFileDirectory)StellaOps.Concelier.Testing\StellaOps.Concelier.Testing.csproj" />
|
||||||
<Using Include="StellaOps.Feedser.Testing" />
|
<Using Include="StellaOps.Concelier.Testing" />
|
||||||
<Using Include="Xunit" />
|
<Using Include="Xunit" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<Target Name="FeedserCopyPluginArtifacts" AfterTargets="Build" Condition="'$(IsFeedserPlugin)' == 'true'">
|
<Target Name="ConcelierCopyPluginArtifacts" AfterTargets="Build" Condition="'$(IsConcelierPlugin)' == 'true'">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<FeedserPluginOutputDirectory>$(FeedserPluginOutputRoot)\$(MSBuildProjectName)</FeedserPluginOutputDirectory>
|
<ConcelierPluginOutputDirectory>$(ConcelierPluginOutputRoot)\$(MSBuildProjectName)</ConcelierPluginOutputDirectory>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<MakeDir Directories="$(FeedserPluginOutputDirectory)" />
|
<MakeDir Directories="$(ConcelierPluginOutputDirectory)" />
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<FeedserPluginArtifacts Include="$(TargetPath)" />
|
<ConcelierPluginArtifacts Include="$(TargetPath)" />
|
||||||
<FeedserPluginArtifacts Include="$(TargetPath).deps.json" Condition="Exists('$(TargetPath).deps.json')" />
|
<ConcelierPluginArtifacts Include="$(TargetPath).deps.json" Condition="Exists('$(TargetPath).deps.json')" />
|
||||||
<FeedserPluginArtifacts Include="$(TargetDir)$(TargetName).pdb" Condition="Exists('$(TargetDir)$(TargetName).pdb')" />
|
<ConcelierPluginArtifacts Include="$(TargetDir)$(TargetName).pdb" Condition="Exists('$(TargetDir)$(TargetName).pdb')" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Copy SourceFiles="@(FeedserPluginArtifacts)" DestinationFolder="$(FeedserPluginOutputDirectory)" SkipUnchangedFiles="true" />
|
<Copy SourceFiles="@(ConcelierPluginArtifacts)" DestinationFolder="$(ConcelierPluginOutputDirectory)" SkipUnchangedFiles="true" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="AuthorityCopyPluginArtifacts" AfterTargets="Build" Condition="'$(IsAuthorityPlugin)' == 'true'">
|
<Target Name="AuthorityCopyPluginArtifacts" AfterTargets="Build" Condition="'$(IsAuthorityPlugin)' == 'true'">
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ public class StellaOpsPrincipalBuilderTests
|
|||||||
public void NormalizedScopes_AreSortedDeduplicatedLowerCased()
|
public void NormalizedScopes_AreSortedDeduplicatedLowerCased()
|
||||||
{
|
{
|
||||||
var builder = new StellaOpsPrincipalBuilder()
|
var builder = new StellaOpsPrincipalBuilder()
|
||||||
.WithScopes(new[] { "Feedser.Jobs.Trigger", " feedser.jobs.trigger ", "AUTHORITY.USERS.MANAGE" })
|
.WithScopes(new[] { "Concelier.Jobs.Trigger", " concelier.jobs.trigger ", "AUTHORITY.USERS.MANAGE" })
|
||||||
.WithAudiences(new[] { " api://feedser ", "api://cli", "api://feedser" });
|
.WithAudiences(new[] { " api://concelier ", "api://cli", "api://concelier" });
|
||||||
|
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
new[] { "authority.users.manage", "feedser.jobs.trigger" },
|
new[] { "authority.users.manage", "concelier.jobs.trigger" },
|
||||||
builder.NormalizedScopes);
|
builder.NormalizedScopes);
|
||||||
|
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
new[] { "api://cli", "api://feedser" },
|
new[] { "api://cli", "api://concelier" },
|
||||||
builder.Audiences);
|
builder.Audiences);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +38,8 @@ public class StellaOpsPrincipalBuilderTests
|
|||||||
.WithTokenId(Guid.NewGuid().ToString("N"))
|
.WithTokenId(Guid.NewGuid().ToString("N"))
|
||||||
.WithAuthenticationMethod("password")
|
.WithAuthenticationMethod("password")
|
||||||
.WithAuthenticationType(" custom ")
|
.WithAuthenticationType(" custom ")
|
||||||
.WithScopes(new[] { "Feedser.Jobs.Trigger", "AUTHORITY.USERS.MANAGE" })
|
.WithScopes(new[] { "Concelier.Jobs.Trigger", "AUTHORITY.USERS.MANAGE" })
|
||||||
.WithAudience(" api://feedser ")
|
.WithAudience(" api://concelier ")
|
||||||
.WithIssuedAt(now)
|
.WithIssuedAt(now)
|
||||||
.WithExpires(now.AddMinutes(5))
|
.WithExpires(now.AddMinutes(5))
|
||||||
.AddClaim(" custom ", " value ");
|
.AddClaim(" custom ", " value ");
|
||||||
@@ -57,13 +57,13 @@ public class StellaOpsPrincipalBuilderTests
|
|||||||
Assert.Equal("value", principal.FindFirstValue("custom"));
|
Assert.Equal("value", principal.FindFirstValue("custom"));
|
||||||
|
|
||||||
var scopeClaims = principal.Claims.Where(claim => claim.Type == StellaOpsClaimTypes.ScopeItem).Select(claim => claim.Value).ToArray();
|
var scopeClaims = principal.Claims.Where(claim => claim.Type == StellaOpsClaimTypes.ScopeItem).Select(claim => claim.Value).ToArray();
|
||||||
Assert.Equal(new[] { "authority.users.manage", "feedser.jobs.trigger" }, scopeClaims);
|
Assert.Equal(new[] { "authority.users.manage", "concelier.jobs.trigger" }, scopeClaims);
|
||||||
|
|
||||||
var scopeList = principal.FindFirstValue(StellaOpsClaimTypes.Scope);
|
var scopeList = principal.FindFirstValue(StellaOpsClaimTypes.Scope);
|
||||||
Assert.Equal("authority.users.manage feedser.jobs.trigger", scopeList);
|
Assert.Equal("authority.users.manage concelier.jobs.trigger", scopeList);
|
||||||
|
|
||||||
var audienceClaims = principal.Claims.Where(claim => claim.Type == StellaOpsClaimTypes.Audience).Select(claim => claim.Value).ToArray();
|
var audienceClaims = principal.Claims.Where(claim => claim.Type == StellaOpsClaimTypes.Audience).Select(claim => claim.Value).ToArray();
|
||||||
Assert.Equal(new[] { "api://feedser" }, audienceClaims);
|
Assert.Equal(new[] { "api://concelier" }, audienceClaims);
|
||||||
|
|
||||||
var issuedAt = principal.FindFirstValue("iat");
|
var issuedAt = principal.FindFirstValue("iat");
|
||||||
Assert.Equal(now.ToUnixTimeSeconds().ToString(), issuedAt);
|
Assert.Equal(now.ToUnixTimeSeconds().ToString(), issuedAt);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class StellaOpsProblemResultFactoryTests
|
|||||||
public void InsufficientScope_AddsScopeExtensions()
|
public void InsufficientScope_AddsScopeExtensions()
|
||||||
{
|
{
|
||||||
var result = StellaOpsProblemResultFactory.InsufficientScope(
|
var result = StellaOpsProblemResultFactory.InsufficientScope(
|
||||||
new[] { StellaOpsScopes.FeedserJobsTrigger },
|
new[] { StellaOpsScopes.ConcelierJobsTrigger },
|
||||||
new[] { StellaOpsScopes.AuthorityUsersManage },
|
new[] { StellaOpsScopes.AuthorityUsersManage },
|
||||||
instance: "/jobs/trigger");
|
instance: "/jobs/trigger");
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ public class StellaOpsProblemResultFactoryTests
|
|||||||
var details = Assert.IsType<ProblemDetails>(result.ProblemDetails);
|
var details = Assert.IsType<ProblemDetails>(result.ProblemDetails);
|
||||||
Assert.Equal("https://docs.stella-ops.org/problems/insufficient-scope", details.Type);
|
Assert.Equal("https://docs.stella-ops.org/problems/insufficient-scope", details.Type);
|
||||||
Assert.Equal("insufficient_scope", details.Extensions["error"]);
|
Assert.Equal("insufficient_scope", details.Extensions["error"]);
|
||||||
Assert.Equal(new[] { StellaOpsScopes.FeedserJobsTrigger }, Assert.IsType<string[]>(details.Extensions["required_scopes"]));
|
Assert.Equal(new[] { StellaOpsScopes.ConcelierJobsTrigger }, Assert.IsType<string[]>(details.Extensions["required_scopes"]));
|
||||||
Assert.Equal(new[] { StellaOpsScopes.AuthorityUsersManage }, Assert.IsType<string[]>(details.Extensions["granted_scopes"]));
|
Assert.Equal(new[] { StellaOpsScopes.AuthorityUsersManage }, Assert.IsType<string[]>(details.Extensions["granted_scopes"]));
|
||||||
Assert.Equal("/jobs/trigger", details.Instance);
|
Assert.Equal("/jobs/trigger", details.Instance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ namespace StellaOps.Auth.Abstractions;
|
|||||||
public static class StellaOpsScopes
|
public static class StellaOpsScopes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scope required to trigger Feedser jobs.
|
/// Scope required to trigger Concelier jobs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string FeedserJobsTrigger = "feedser.jobs.trigger";
|
public const string ConcelierJobsTrigger = "concelier.jobs.trigger";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scope required to manage Feedser merge operations.
|
/// Scope required to manage Concelier merge operations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string FeedserMerge = "feedser.merge";
|
public const string ConcelierMerge = "concelier.merge";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scope granting administrative access to Authority user management.
|
/// Scope granting administrative access to Authority user management.
|
||||||
@@ -40,8 +40,8 @@ public static class StellaOpsScopes
|
|||||||
|
|
||||||
private static readonly HashSet<string> KnownScopes = new(StringComparer.OrdinalIgnoreCase)
|
private static readonly HashSet<string> KnownScopes = new(StringComparer.OrdinalIgnoreCase)
|
||||||
{
|
{
|
||||||
FeedserJobsTrigger,
|
ConcelierJobsTrigger,
|
||||||
FeedserMerge,
|
ConcelierMerge,
|
||||||
AuthorityUsersManage,
|
AuthorityUsersManage,
|
||||||
AuthorityClientsManage,
|
AuthorityClientsManage,
|
||||||
AuthorityAuditRead,
|
AuthorityAuditRead,
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ public class StellaOpsAuthClientOptionsTests
|
|||||||
ClientId = "cli",
|
ClientId = "cli",
|
||||||
HttpTimeout = TimeSpan.FromSeconds(15)
|
HttpTimeout = TimeSpan.FromSeconds(15)
|
||||||
};
|
};
|
||||||
options.DefaultScopes.Add(" Feedser.Jobs.Trigger ");
|
options.DefaultScopes.Add(" Concelier.Jobs.Trigger ");
|
||||||
options.DefaultScopes.Add("feedser.jobs.trigger");
|
options.DefaultScopes.Add("concelier.jobs.trigger");
|
||||||
options.DefaultScopes.Add("AUTHORITY.USERS.MANAGE");
|
options.DefaultScopes.Add("AUTHORITY.USERS.MANAGE");
|
||||||
|
|
||||||
options.Validate();
|
options.Validate();
|
||||||
|
|
||||||
Assert.Equal(new[] { "authority.users.manage", "feedser.jobs.trigger" }, options.NormalizedScopes);
|
Assert.Equal(new[] { "authority.users.manage", "concelier.jobs.trigger" }, options.NormalizedScopes);
|
||||||
Assert.Equal(new Uri("https://authority.test"), options.AuthorityUri);
|
Assert.Equal(new Uri("https://authority.test"), options.AuthorityUri);
|
||||||
Assert.Equal<TimeSpan>(options.RetryDelays, options.NormalizedRetryDelays);
|
Assert.Equal<TimeSpan>(options.RetryDelays, options.NormalizedRetryDelays);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class StellaOpsTokenClientTests
|
|||||||
var timeProvider = new FakeTimeProvider(DateTimeOffset.Parse("2025-02-01T00:00:00Z"));
|
var timeProvider = new FakeTimeProvider(DateTimeOffset.Parse("2025-02-01T00:00:00Z"));
|
||||||
var responses = new Queue<HttpResponseMessage>();
|
var responses = new Queue<HttpResponseMessage>();
|
||||||
responses.Enqueue(CreateJsonResponse("{\"token_endpoint\":\"https://authority.test/connect/token\",\"jwks_uri\":\"https://authority.test/jwks\"}"));
|
responses.Enqueue(CreateJsonResponse("{\"token_endpoint\":\"https://authority.test/connect/token\",\"jwks_uri\":\"https://authority.test/jwks\"}"));
|
||||||
responses.Enqueue(CreateJsonResponse("{\"access_token\":\"abc\",\"token_type\":\"Bearer\",\"expires_in\":120,\"scope\":\"feedser.jobs.trigger\"}"));
|
responses.Enqueue(CreateJsonResponse("{\"access_token\":\"abc\",\"token_type\":\"Bearer\",\"expires_in\":120,\"scope\":\"concelier.jobs.trigger\"}"));
|
||||||
responses.Enqueue(CreateJsonResponse("{\"keys\":[]}"));
|
responses.Enqueue(CreateJsonResponse("{\"keys\":[]}"));
|
||||||
|
|
||||||
var handler = new StubHttpMessageHandler((request, cancellationToken) =>
|
var handler = new StubHttpMessageHandler((request, cancellationToken) =>
|
||||||
@@ -37,7 +37,7 @@ public class StellaOpsTokenClientTests
|
|||||||
Authority = "https://authority.test",
|
Authority = "https://authority.test",
|
||||||
ClientId = "cli"
|
ClientId = "cli"
|
||||||
};
|
};
|
||||||
options.DefaultScopes.Add("feedser.jobs.trigger");
|
options.DefaultScopes.Add("concelier.jobs.trigger");
|
||||||
options.Validate();
|
options.Validate();
|
||||||
|
|
||||||
var optionsMonitor = new TestOptionsMonitor<StellaOpsAuthClientOptions>(options);
|
var optionsMonitor = new TestOptionsMonitor<StellaOpsAuthClientOptions>(options);
|
||||||
@@ -49,7 +49,7 @@ public class StellaOpsTokenClientTests
|
|||||||
var result = await client.RequestPasswordTokenAsync("user", "pass");
|
var result = await client.RequestPasswordTokenAsync("user", "pass");
|
||||||
|
|
||||||
Assert.Equal("abc", result.AccessToken);
|
Assert.Equal("abc", result.AccessToken);
|
||||||
Assert.Contains("feedser.jobs.trigger", result.Scopes);
|
Assert.Contains("concelier.jobs.trigger", result.Scopes);
|
||||||
|
|
||||||
await client.CacheTokenAsync("key", result.ToCacheEntry());
|
await client.CacheTokenAsync("key", result.ToCacheEntry());
|
||||||
var cached = await client.GetCachedTokenAsync("key");
|
var cached = await client.GetCachedTokenAsync("key");
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ public class ServiceCollectionExtensionsTests
|
|||||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||||
{
|
{
|
||||||
["Authority:ResourceServer:Authority"] = "https://authority.example",
|
["Authority:ResourceServer:Authority"] = "https://authority.example",
|
||||||
["Authority:ResourceServer:Audiences:0"] = "api://feedser",
|
["Authority:ResourceServer:Audiences:0"] = "api://concelier",
|
||||||
["Authority:ResourceServer:RequiredScopes:0"] = "feedser.jobs.trigger",
|
["Authority:ResourceServer:RequiredScopes:0"] = "concelier.jobs.trigger",
|
||||||
["Authority:ResourceServer:BypassNetworks:0"] = "127.0.0.1/32"
|
["Authority:ResourceServer:BypassNetworks:0"] = "127.0.0.1/32"
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
@@ -37,8 +37,8 @@ public class ServiceCollectionExtensionsTests
|
|||||||
Assert.NotNull(jwtOptions.Authority);
|
Assert.NotNull(jwtOptions.Authority);
|
||||||
Assert.Equal(new Uri("https://authority.example/"), new Uri(jwtOptions.Authority!));
|
Assert.Equal(new Uri("https://authority.example/"), new Uri(jwtOptions.Authority!));
|
||||||
Assert.True(jwtOptions.TokenValidationParameters.ValidateAudience);
|
Assert.True(jwtOptions.TokenValidationParameters.ValidateAudience);
|
||||||
Assert.Contains("api://feedser", jwtOptions.TokenValidationParameters.ValidAudiences);
|
Assert.Contains("api://concelier", jwtOptions.TokenValidationParameters.ValidAudiences);
|
||||||
Assert.Equal(TimeSpan.FromSeconds(60), jwtOptions.TokenValidationParameters.ClockSkew);
|
Assert.Equal(TimeSpan.FromSeconds(60), jwtOptions.TokenValidationParameters.ClockSkew);
|
||||||
Assert.Equal(new[] { "feedser.jobs.trigger" }, resourceOptions.NormalizedScopes);
|
Assert.Equal(new[] { "concelier.jobs.trigger" }, resourceOptions.NormalizedScopes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ public class StellaOpsResourceServerOptionsTests
|
|||||||
TokenClockSkew = TimeSpan.FromSeconds(30)
|
TokenClockSkew = TimeSpan.FromSeconds(30)
|
||||||
};
|
};
|
||||||
|
|
||||||
options.Audiences.Add(" api://feedser ");
|
options.Audiences.Add(" api://concelier ");
|
||||||
options.Audiences.Add("api://feedser");
|
options.Audiences.Add("api://concelier");
|
||||||
options.Audiences.Add("api://feedser-admin");
|
options.Audiences.Add("api://concelier-admin");
|
||||||
|
|
||||||
options.RequiredScopes.Add(" Feedser.Jobs.Trigger ");
|
options.RequiredScopes.Add(" Concelier.Jobs.Trigger ");
|
||||||
options.RequiredScopes.Add("feedser.jobs.trigger");
|
options.RequiredScopes.Add("concelier.jobs.trigger");
|
||||||
options.RequiredScopes.Add("AUTHORITY.USERS.MANAGE");
|
options.RequiredScopes.Add("AUTHORITY.USERS.MANAGE");
|
||||||
|
|
||||||
options.BypassNetworks.Add("127.0.0.1/32");
|
options.BypassNetworks.Add("127.0.0.1/32");
|
||||||
@@ -32,8 +32,8 @@ public class StellaOpsResourceServerOptionsTests
|
|||||||
options.Validate();
|
options.Validate();
|
||||||
|
|
||||||
Assert.Equal(new Uri("https://authority.stella-ops.test"), options.AuthorityUri);
|
Assert.Equal(new Uri("https://authority.stella-ops.test"), options.AuthorityUri);
|
||||||
Assert.Equal(new[] { "api://feedser", "api://feedser-admin" }, options.Audiences);
|
Assert.Equal(new[] { "api://concelier", "api://concelier-admin" }, options.Audiences);
|
||||||
Assert.Equal(new[] { "authority.users.manage", "feedser.jobs.trigger" }, options.NormalizedScopes);
|
Assert.Equal(new[] { "authority.users.manage", "concelier.jobs.trigger" }, options.NormalizedScopes);
|
||||||
Assert.True(options.BypassMatcher.IsAllowed(IPAddress.Parse("127.0.0.1")));
|
Assert.True(options.BypassMatcher.IsAllowed(IPAddress.Parse("127.0.0.1")));
|
||||||
Assert.True(options.BypassMatcher.IsAllowed(IPAddress.IPv6Loopback));
|
Assert.True(options.BypassMatcher.IsAllowed(IPAddress.IPv6Loopback));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ public class StellaOpsScopeAuthorizationHandlerTests
|
|||||||
});
|
});
|
||||||
|
|
||||||
var (handler, accessor) = CreateHandler(optionsMonitor, remoteAddress: IPAddress.Parse("10.0.0.1"));
|
var (handler, accessor) = CreateHandler(optionsMonitor, remoteAddress: IPAddress.Parse("10.0.0.1"));
|
||||||
var requirement = new StellaOpsScopeRequirement(new[] { StellaOpsScopes.FeedserJobsTrigger });
|
var requirement = new StellaOpsScopeRequirement(new[] { StellaOpsScopes.ConcelierJobsTrigger });
|
||||||
var principal = new StellaOpsPrincipalBuilder()
|
var principal = new StellaOpsPrincipalBuilder()
|
||||||
.WithSubject("user-1")
|
.WithSubject("user-1")
|
||||||
.WithScopes(new[] { StellaOpsScopes.FeedserJobsTrigger })
|
.WithScopes(new[] { StellaOpsScopes.ConcelierJobsTrigger })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var context = new AuthorizationHandlerContext(new[] { requirement }, principal, accessor.HttpContext);
|
var context = new AuthorizationHandlerContext(new[] { requirement }, principal, accessor.HttpContext);
|
||||||
@@ -48,7 +48,7 @@ public class StellaOpsScopeAuthorizationHandlerTests
|
|||||||
});
|
});
|
||||||
|
|
||||||
var (handler, accessor) = CreateHandler(optionsMonitor, remoteAddress: IPAddress.Parse("127.0.0.1"));
|
var (handler, accessor) = CreateHandler(optionsMonitor, remoteAddress: IPAddress.Parse("127.0.0.1"));
|
||||||
var requirement = new StellaOpsScopeRequirement(new[] { StellaOpsScopes.FeedserJobsTrigger });
|
var requirement = new StellaOpsScopeRequirement(new[] { StellaOpsScopes.ConcelierJobsTrigger });
|
||||||
var principal = new ClaimsPrincipal(new ClaimsIdentity());
|
var principal = new ClaimsPrincipal(new ClaimsIdentity());
|
||||||
var context = new AuthorizationHandlerContext(new[] { requirement }, principal, accessor.HttpContext);
|
var context = new AuthorizationHandlerContext(new[] { requirement }, principal, accessor.HttpContext);
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ public class StellaOpsScopeAuthorizationHandlerTests
|
|||||||
});
|
});
|
||||||
|
|
||||||
var (handler, accessor) = CreateHandler(optionsMonitor, remoteAddress: IPAddress.Parse("203.0.113.10"));
|
var (handler, accessor) = CreateHandler(optionsMonitor, remoteAddress: IPAddress.Parse("203.0.113.10"));
|
||||||
var requirement = new StellaOpsScopeRequirement(new[] { StellaOpsScopes.FeedserJobsTrigger });
|
var requirement = new StellaOpsScopeRequirement(new[] { StellaOpsScopes.ConcelierJobsTrigger });
|
||||||
var principal = new ClaimsPrincipal(new ClaimsIdentity());
|
var principal = new ClaimsPrincipal(new ClaimsIdentity());
|
||||||
var context = new AuthorizationHandlerContext(new[] { requirement }, principal, accessor.HttpContext);
|
var context = new AuthorizationHandlerContext(new[] { requirement }, principal, accessor.HttpContext);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ ASP.NET Core helpers that enable resource servers to authenticate with **StellaO
|
|||||||
|
|
||||||
- `AddStellaOpsResourceServerAuthentication` extension for JWT bearer + scope policies.
|
- `AddStellaOpsResourceServerAuthentication` extension for JWT bearer + scope policies.
|
||||||
- Network bypass mask evaluation for on-host automation.
|
- Network bypass mask evaluation for on-host automation.
|
||||||
- Consistent `ProblemDetails` responses and policy helpers shared with Feedser/Backend services.
|
- Consistent `ProblemDetails` responses and policy helpers shared with Concelier/Backend services.
|
||||||
|
|
||||||
Pair this package with `StellaOps.Auth.Abstractions` and `StellaOps.Auth.Client` for end-to-end Authority integration.
|
Pair this package with `StellaOps.Auth.Abstractions` and `StellaOps.Auth.Client` for end-to-end Authority integration.
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ public class TokenValidationHandlersTests
|
|||||||
{
|
{
|
||||||
TokenId = "token-1",
|
TokenId = "token-1",
|
||||||
Status = "revoked",
|
Status = "revoked",
|
||||||
ClientId = "feedser"
|
ClientId = "concelier"
|
||||||
};
|
};
|
||||||
|
|
||||||
var metadataAccessor = new TestRateLimiterMetadataAccessor();
|
var metadataAccessor = new TestRateLimiterMetadataAccessor();
|
||||||
@@ -219,7 +219,7 @@ public class TokenValidationHandlersTests
|
|||||||
Request = new OpenIddictRequest()
|
Request = new OpenIddictRequest()
|
||||||
};
|
};
|
||||||
|
|
||||||
var principal = CreatePrincipal("feedser", "token-1", "standard");
|
var principal = CreatePrincipal("concelier", "token-1", "standard");
|
||||||
var context = new OpenIddictServerEvents.ValidateTokenContext(transaction)
|
var context = new OpenIddictServerEvents.ValidateTokenContext(transaction)
|
||||||
{
|
{
|
||||||
Principal = principal,
|
Principal = principal,
|
||||||
@@ -526,7 +526,7 @@ internal static class TestHelpers
|
|||||||
{
|
{
|
||||||
return new AuthorityClientDocument
|
return new AuthorityClientDocument
|
||||||
{
|
{
|
||||||
ClientId = "feedser",
|
ClientId = "concelier",
|
||||||
ClientType = clientType,
|
ClientType = clientType,
|
||||||
SecretHash = secret is null ? null : AuthoritySecretHasher.ComputeHash(secret),
|
SecretHash = secret is null ? null : AuthoritySecretHasher.ComputeHash(secret),
|
||||||
Plugin = "standard",
|
Plugin = "standard",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ using StellaOps.Authority.Storage.Mongo.Documents;
|
|||||||
using StellaOps.Authority.Storage.Mongo.Extensions;
|
using StellaOps.Authority.Storage.Mongo.Extensions;
|
||||||
using StellaOps.Authority.Storage.Mongo.Initialization;
|
using StellaOps.Authority.Storage.Mongo.Initialization;
|
||||||
using StellaOps.Authority.Storage.Mongo.Stores;
|
using StellaOps.Authority.Storage.Mongo.Stores;
|
||||||
using StellaOps.Feedser.Testing;
|
using StellaOps.Concelier.Testing;
|
||||||
using StellaOps.Authority.RateLimiting;
|
using StellaOps.Authority.RateLimiting;
|
||||||
using StellaOps.Cryptography.Audit;
|
using StellaOps.Cryptography.Audit;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ public class AuthorityRateLimiterIntegrationTests
|
|||||||
using var client = server.CreateClient();
|
using var client = server.CreateClient();
|
||||||
client.DefaultRequestHeaders.Add("X-Forwarded-For", "198.51.100.50");
|
client.DefaultRequestHeaders.Add("X-Forwarded-For", "198.51.100.50");
|
||||||
|
|
||||||
var firstResponse = await client.PostAsync("/token", CreateTokenForm("feedser"));
|
var firstResponse = await client.PostAsync("/token", CreateTokenForm("concelier"));
|
||||||
Assert.Equal(HttpStatusCode.OK, firstResponse.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, firstResponse.StatusCode);
|
||||||
|
|
||||||
var secondResponse = await client.PostAsync("/token", CreateTokenForm("feedser"));
|
var secondResponse = await client.PostAsync("/token", CreateTokenForm("concelier"));
|
||||||
Assert.Equal(HttpStatusCode.TooManyRequests, secondResponse.StatusCode);
|
Assert.Equal(HttpStatusCode.TooManyRequests, secondResponse.StatusCode);
|
||||||
Assert.NotNull(secondResponse.Headers.RetryAfter);
|
Assert.NotNull(secondResponse.Headers.RetryAfter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,17 +25,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Configuration", "
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Plugins.Abstractions.Tests", "StellaOps.Authority.Plugins.Abstractions.Tests\StellaOps.Authority.Plugins.Abstractions.Tests.csproj", "{EE97137B-22AF-4A84-9F65-9B4C6468B3CF}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Plugins.Abstractions.Tests", "StellaOps.Authority.Plugins.Abstractions.Tests\StellaOps.Authority.Plugins.Abstractions.Tests.csproj", "{EE97137B-22AF-4A84-9F65-9B4C6468B3CF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Feedser.Testing", "..\StellaOps.Feedser.Testing\StellaOps.Feedser.Testing.csproj", "{D48E48BF-80C8-43DA-8BE6-E2B9E769C49E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Concelier.Testing", "..\StellaOps.Concelier.Testing\StellaOps.Concelier.Testing.csproj", "{D48E48BF-80C8-43DA-8BE6-E2B9E769C49E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Feedser.Source.Common", "..\StellaOps.Feedser.Source.Common\StellaOps.Feedser.Source.Common.csproj", "{E0B9CD7A-C4FF-44EB-BE04-9B998C1C4166}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Concelier.Source.Common", "..\StellaOps.Concelier.Source.Common\StellaOps.Concelier.Source.Common.csproj", "{E0B9CD7A-C4FF-44EB-BE04-9B998C1C4166}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Feedser.Storage.Mongo", "..\StellaOps.Feedser.Storage.Mongo\StellaOps.Feedser.Storage.Mongo.csproj", "{67C85AC6-1670-4A0D-A81F-6015574F46C7}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Concelier.Storage.Mongo", "..\StellaOps.Concelier.Storage.Mongo\StellaOps.Concelier.Storage.Mongo.csproj", "{67C85AC6-1670-4A0D-A81F-6015574F46C7}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Feedser.Core", "..\StellaOps.Feedser.Core\StellaOps.Feedser.Core.csproj", "{17829125-C0F5-47E6-A16C-EC142BD58220}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Concelier.Core", "..\StellaOps.Concelier.Core\StellaOps.Concelier.Core.csproj", "{17829125-C0F5-47E6-A16C-EC142BD58220}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Feedser.Models", "..\StellaOps.Feedser.Models\StellaOps.Feedser.Models.csproj", "{9B4BA030-C979-4191-8B4F-7E2AD9F88A94}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Concelier.Models", "..\StellaOps.Concelier.Models\StellaOps.Concelier.Models.csproj", "{9B4BA030-C979-4191-8B4F-7E2AD9F88A94}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Feedser.Normalization", "..\StellaOps.Feedser.Normalization\StellaOps.Feedser.Normalization.csproj", "{26B58A9B-DB0B-4E3D-9827-3722859E5FB4}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Concelier.Normalization", "..\StellaOps.Concelier.Normalization\StellaOps.Concelier.Normalization.csproj", "{26B58A9B-DB0B-4E3D-9827-3722859E5FB4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Tests", "StellaOps.Authority.Tests\StellaOps.Authority.Tests.csproj", "{D719B01C-2424-4DAB-94B9-C9B6004F450B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.Authority.Tests", "StellaOps.Authority.Tests\StellaOps.Authority.Tests.csproj", "{D719B01C-2424-4DAB-94B9-C9B6004F450B}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
> Remark (2025-10-14): Background sweep emits invite expiry audits; integration test added.
|
> Remark (2025-10-14): Background sweep emits invite expiry audits; integration test added.
|
||||||
| SEC5.HOST-REPLAY | DONE (2025-10-14) | Security Guild, Zastava | SEC5.E | Persist token usage metadata and surface suspected replay heuristics. | ✅ Validation handlers record device metadata; ✅ Suspected replay flagged via audit/logs; ✅ Tests cover regression cases. |
|
| SEC5.HOST-REPLAY | DONE (2025-10-14) | Security Guild, Zastava | SEC5.E | Persist token usage metadata and surface suspected replay heuristics. | ✅ Validation handlers record device metadata; ✅ Suspected replay flagged via audit/logs; ✅ Tests cover regression cases. |
|
||||||
> Remark (2025-10-14): Token validation handler logs suspected replay audits with device metadata; coverage via unit/integration tests.
|
> Remark (2025-10-14): Token validation handler logs suspected replay audits with device metadata; coverage via unit/integration tests.
|
||||||
| SEC3.BUILD | DONE (2025-10-11) | Authority Core, Security Guild | SEC3.HOST, FEEDMERGE-COORD-02-900 | Track normalized-range dependency fallout and restore full test matrix once Feedser range primitives land. | ✅ Feedser normalized range libraries merged; ✅ Authority + Configuration test suites (`dotnet test src/StellaOps.Authority.sln`, `dotnet test src/StellaOps.Configuration.Tests/StellaOps.Configuration.Tests.csproj`) pass without Feedser compile failures; ✅ Status recorded here/Sprints (authority-core broadcast not available). |
|
| SEC3.BUILD | DONE (2025-10-11) | Authority Core, Security Guild | SEC3.HOST, FEEDMERGE-COORD-02-900 | Track normalized-range dependency fallout and restore full test matrix once Concelier range primitives land. | ✅ Concelier normalized range libraries merged; ✅ Authority + Configuration test suites (`dotnet test src/StellaOps.Authority.sln`, `dotnet test src/StellaOps.Configuration.Tests/StellaOps.Configuration.Tests.csproj`) pass without Concelier compile failures; ✅ Status recorded here/Sprints (authority-core broadcast not available). |
|
||||||
| AUTHCORE-BUILD-OPENIDDICT | DONE (2025-10-14) | Authority Core | SEC2.HOST | Adapt host/audit handlers for OpenIddict 6.4 API surface (no `OpenIddictServerTransaction`) and restore Authority solution build. | ✅ Build `dotnet build src/StellaOps.Authority.sln` succeeds; ✅ Audit correlation + tamper logging verified under new abstractions; ✅ Tests updated. |
|
| AUTHCORE-BUILD-OPENIDDICT | DONE (2025-10-14) | Authority Core | SEC2.HOST | Adapt host/audit handlers for OpenIddict 6.4 API surface (no `OpenIddictServerTransaction`) and restore Authority solution build. | ✅ Build `dotnet build src/StellaOps.Authority.sln` succeeds; ✅ Audit correlation + tamper logging verified under new abstractions; ✅ Tests updated. |
|
||||||
| AUTHCORE-STORAGE-DEVICE-TOKENS | DONE (2025-10-14) | Authority Core, Storage Guild | AUTHCORE-BUILD-OPENIDDICT | Reintroduce `AuthorityTokenDeviceDocument` + projections removed during refactor so storage layer compiles. | ✅ Document type restored with mappings/migrations; ✅ Storage tests cover device artifacts; ✅ Authority solution build green. |
|
| AUTHCORE-STORAGE-DEVICE-TOKENS | DONE (2025-10-14) | Authority Core, Storage Guild | AUTHCORE-BUILD-OPENIDDICT | Reintroduce `AuthorityTokenDeviceDocument` + projections removed during refactor so storage layer compiles. | ✅ Document type restored with mappings/migrations; ✅ Storage tests cover device artifacts; ✅ Authority solution build green. |
|
||||||
| AUTHCORE-BOOTSTRAP-INVITES | DONE (2025-10-14) | Authority Core, DevOps | AUTHCORE-STORAGE-DEVICE-TOKENS | Wire bootstrap invite cleanup service against restored document schema and re-enable lifecycle tests. | ✅ `BootstrapInviteCleanupService` passes integration tests; ✅ Operator guide updated if behavior changes; ✅ Build/test matrices green. |
|
| AUTHCORE-BOOTSTRAP-INVITES | DONE (2025-10-14) | Authority Core, DevOps | AUTHCORE-STORAGE-DEVICE-TOKENS | Wire bootstrap invite cleanup service against restored document schema and re-enable lifecycle tests. | ✅ `BootstrapInviteCleanupService` passes integration tests; ✅ Operator guide updated if behavior changes; ✅ Build/test matrices green. |
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ public sealed class CommandHandlersTests
|
|||||||
Url = "https://authority.example",
|
Url = "https://authority.example",
|
||||||
ClientId = "cli",
|
ClientId = "cli",
|
||||||
ClientSecret = "secret",
|
ClientSecret = "secret",
|
||||||
Scope = "feedser.jobs.trigger",
|
Scope = "concelier.jobs.trigger",
|
||||||
TokenCacheDirectory = tempDir.Path
|
TokenCacheDirectory = tempDir.Path
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -263,7 +263,7 @@ public sealed class CommandHandlersTests
|
|||||||
"token",
|
"token",
|
||||||
"Bearer",
|
"Bearer",
|
||||||
DateTimeOffset.UtcNow.AddMinutes(30),
|
DateTimeOffset.UtcNow.AddMinutes(30),
|
||||||
new[] { StellaOpsScopes.FeedserJobsTrigger });
|
new[] { StellaOpsScopes.ConcelierJobsTrigger });
|
||||||
|
|
||||||
var provider = BuildServiceProvider(new StubBackendClient(new JobTriggerResult(true, "ok", null, null)), options: options, tokenClient: tokenClient);
|
var provider = BuildServiceProvider(new StubBackendClient(new JobTriggerResult(true, "ok", null, null)), options: options, tokenClient: tokenClient);
|
||||||
|
|
||||||
@@ -331,13 +331,13 @@ public sealed class CommandHandlersTests
|
|||||||
tokenClient.CachedEntry = new StellaOpsTokenCacheEntry(
|
tokenClient.CachedEntry = new StellaOpsTokenCacheEntry(
|
||||||
CreateUnsignedJwt(
|
CreateUnsignedJwt(
|
||||||
("sub", "cli-user"),
|
("sub", "cli-user"),
|
||||||
("aud", "feedser"),
|
("aud", "concelier"),
|
||||||
("iss", "https://authority.example"),
|
("iss", "https://authority.example"),
|
||||||
("iat", 1_700_000_000),
|
("iat", 1_700_000_000),
|
||||||
("nbf", 1_700_000_000)),
|
("nbf", 1_700_000_000)),
|
||||||
"Bearer",
|
"Bearer",
|
||||||
DateTimeOffset.UtcNow.AddMinutes(30),
|
DateTimeOffset.UtcNow.AddMinutes(30),
|
||||||
new[] { StellaOpsScopes.FeedserJobsTrigger });
|
new[] { StellaOpsScopes.ConcelierJobsTrigger });
|
||||||
|
|
||||||
var provider = BuildServiceProvider(new StubBackendClient(new JobTriggerResult(true, "ok", null, null)), options: options, tokenClient: tokenClient);
|
var provider = BuildServiceProvider(new StubBackendClient(new JobTriggerResult(true, "ok", null, null)), options: options, tokenClient: tokenClient);
|
||||||
|
|
||||||
@@ -375,7 +375,7 @@ public sealed class CommandHandlersTests
|
|||||||
"token",
|
"token",
|
||||||
"Bearer",
|
"Bearer",
|
||||||
DateTimeOffset.UtcNow.AddMinutes(5),
|
DateTimeOffset.UtcNow.AddMinutes(5),
|
||||||
new[] { StellaOpsScopes.FeedserJobsTrigger });
|
new[] { StellaOpsScopes.ConcelierJobsTrigger });
|
||||||
|
|
||||||
var provider = BuildServiceProvider(new StubBackendClient(new JobTriggerResult(true, "ok", null, null)), options: options, tokenClient: tokenClient);
|
var provider = BuildServiceProvider(new StubBackendClient(new JobTriggerResult(true, "ok", null, null)), options: options, tokenClient: tokenClient);
|
||||||
|
|
||||||
@@ -573,7 +573,7 @@ public sealed class CommandHandlersTests
|
|||||||
"token-123",
|
"token-123",
|
||||||
"Bearer",
|
"Bearer",
|
||||||
DateTimeOffset.UtcNow.AddMinutes(30),
|
DateTimeOffset.UtcNow.AddMinutes(30),
|
||||||
new[] { StellaOpsScopes.FeedserJobsTrigger });
|
new[] { StellaOpsScopes.ConcelierJobsTrigger });
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ClientCredentialRequests { get; private set; }
|
public int ClientCredentialRequests { get; private set; }
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public sealed class CliBootstrapperTests : IDisposable
|
|||||||
Environment.SetEnvironmentVariable("STELLAOPS_BACKEND_URL", "https://env-backend.example");
|
Environment.SetEnvironmentVariable("STELLAOPS_BACKEND_URL", "https://env-backend.example");
|
||||||
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_URL", "https://authority.env");
|
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_URL", "https://authority.env");
|
||||||
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_CLIENT_ID", "cli-env");
|
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_CLIENT_ID", "cli-env");
|
||||||
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_SCOPE", "feedser.jobs.trigger");
|
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_SCOPE", "concelier.jobs.trigger");
|
||||||
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_ENABLE_RETRIES", "false");
|
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_ENABLE_RETRIES", "false");
|
||||||
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_RETRY_DELAYS", "00:00:02,00:00:05");
|
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_RETRY_DELAYS", "00:00:02,00:00:05");
|
||||||
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_ALLOW_OFFLINE_CACHE_FALLBACK", "false");
|
Environment.SetEnvironmentVariable("STELLAOPS_AUTHORITY_ALLOW_OFFLINE_CACHE_FALLBACK", "false");
|
||||||
@@ -38,7 +38,7 @@ public sealed class CliBootstrapperTests : IDisposable
|
|||||||
Assert.Equal("https://env-backend.example", options.BackendUrl);
|
Assert.Equal("https://env-backend.example", options.BackendUrl);
|
||||||
Assert.Equal("https://authority.env", options.Authority.Url);
|
Assert.Equal("https://authority.env", options.Authority.Url);
|
||||||
Assert.Equal("cli-env", options.Authority.ClientId);
|
Assert.Equal("cli-env", options.Authority.ClientId);
|
||||||
Assert.Equal("feedser.jobs.trigger", options.Authority.Scope);
|
Assert.Equal("concelier.jobs.trigger", options.Authority.Scope);
|
||||||
|
|
||||||
Assert.NotNull(options.Authority.Resilience);
|
Assert.NotNull(options.Authority.Resilience);
|
||||||
Assert.False(options.Authority.Resilience.EnableRetries);
|
Assert.False(options.Authority.Resilience.EnableRetries);
|
||||||
@@ -73,7 +73,7 @@ public sealed class CliBootstrapperTests : IDisposable
|
|||||||
{
|
{
|
||||||
Url = "https://authority.file",
|
Url = "https://authority.file",
|
||||||
ClientId = "cli-file",
|
ClientId = "cli-file",
|
||||||
Scope = "feedser.jobs.trigger"
|
Scope = "concelier.jobs.trigger"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,12 +46,12 @@ public sealed class BackendOperationsClientTests
|
|||||||
|
|
||||||
var httpClient = new HttpClient(handler)
|
var httpClient = new HttpClient(handler)
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("https://feedser.example")
|
BaseAddress = new Uri("https://concelier.example")
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new StellaOpsCliOptions
|
var options = new StellaOpsCliOptions
|
||||||
{
|
{
|
||||||
BackendUrl = "https://feedser.example",
|
BackendUrl = "https://concelier.example",
|
||||||
ScannerCacheDirectory = temp.Path,
|
ScannerCacheDirectory = temp.Path,
|
||||||
ScannerDownloadAttempts = 1
|
ScannerDownloadAttempts = 1
|
||||||
};
|
};
|
||||||
@@ -92,12 +92,12 @@ public sealed class BackendOperationsClientTests
|
|||||||
|
|
||||||
var httpClient = new HttpClient(handler)
|
var httpClient = new HttpClient(handler)
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("https://feedser.example")
|
BaseAddress = new Uri("https://concelier.example")
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new StellaOpsCliOptions
|
var options = new StellaOpsCliOptions
|
||||||
{
|
{
|
||||||
BackendUrl = "https://feedser.example",
|
BackendUrl = "https://concelier.example",
|
||||||
ScannerCacheDirectory = temp.Path,
|
ScannerCacheDirectory = temp.Path,
|
||||||
ScannerDownloadAttempts = 1
|
ScannerDownloadAttempts = 1
|
||||||
};
|
};
|
||||||
@@ -144,12 +144,12 @@ public sealed class BackendOperationsClientTests
|
|||||||
|
|
||||||
var httpClient = new HttpClient(handler)
|
var httpClient = new HttpClient(handler)
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("https://feedser.example")
|
BaseAddress = new Uri("https://concelier.example")
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new StellaOpsCliOptions
|
var options = new StellaOpsCliOptions
|
||||||
{
|
{
|
||||||
BackendUrl = "https://feedser.example",
|
BackendUrl = "https://concelier.example",
|
||||||
ScannerCacheDirectory = temp.Path,
|
ScannerCacheDirectory = temp.Path,
|
||||||
ScannerDownloadAttempts = 3
|
ScannerDownloadAttempts = 3
|
||||||
};
|
};
|
||||||
@@ -196,12 +196,12 @@ public sealed class BackendOperationsClientTests
|
|||||||
|
|
||||||
var httpClient = new HttpClient(handler)
|
var httpClient = new HttpClient(handler)
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("https://feedser.example")
|
BaseAddress = new Uri("https://concelier.example")
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new StellaOpsCliOptions
|
var options = new StellaOpsCliOptions
|
||||||
{
|
{
|
||||||
BackendUrl = "https://feedser.example",
|
BackendUrl = "https://concelier.example",
|
||||||
ScanUploadAttempts = 3
|
ScanUploadAttempts = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -234,12 +234,12 @@ public sealed class BackendOperationsClientTests
|
|||||||
|
|
||||||
var httpClient = new HttpClient(handler)
|
var httpClient = new HttpClient(handler)
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("https://feedser.example")
|
BaseAddress = new Uri("https://concelier.example")
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new StellaOpsCliOptions
|
var options = new StellaOpsCliOptions
|
||||||
{
|
{
|
||||||
BackendUrl = "https://feedser.example",
|
BackendUrl = "https://concelier.example",
|
||||||
ScanUploadAttempts = 2
|
ScanUploadAttempts = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -273,10 +273,10 @@ public sealed class BackendOperationsClientTests
|
|||||||
|
|
||||||
var httpClient = new HttpClient(handler)
|
var httpClient = new HttpClient(handler)
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("https://feedser.example")
|
BaseAddress = new Uri("https://concelier.example")
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new StellaOpsCliOptions { BackendUrl = "https://feedser.example" };
|
var options = new StellaOpsCliOptions { BackendUrl = "https://concelier.example" };
|
||||||
var loggerFactory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Debug));
|
var loggerFactory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Debug));
|
||||||
var client = new BackendOperationsClient(httpClient, options, loggerFactory.CreateLogger<BackendOperationsClient>());
|
var client = new BackendOperationsClient(httpClient, options, loggerFactory.CreateLogger<BackendOperationsClient>());
|
||||||
|
|
||||||
@@ -308,10 +308,10 @@ public sealed class BackendOperationsClientTests
|
|||||||
|
|
||||||
var httpClient = new HttpClient(handler)
|
var httpClient = new HttpClient(handler)
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("https://feedser.example")
|
BaseAddress = new Uri("https://concelier.example")
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new StellaOpsCliOptions { BackendUrl = "https://feedser.example" };
|
var options = new StellaOpsCliOptions { BackendUrl = "https://concelier.example" };
|
||||||
var loggerFactory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Debug));
|
var loggerFactory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Debug));
|
||||||
var client = new BackendOperationsClient(httpClient, options, loggerFactory.CreateLogger<BackendOperationsClient>());
|
var client = new BackendOperationsClient(httpClient, options, loggerFactory.CreateLogger<BackendOperationsClient>());
|
||||||
|
|
||||||
@@ -348,18 +348,18 @@ public sealed class BackendOperationsClientTests
|
|||||||
|
|
||||||
var httpClient = new HttpClient(handler)
|
var httpClient = new HttpClient(handler)
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("https://feedser.example")
|
BaseAddress = new Uri("https://concelier.example")
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new StellaOpsCliOptions
|
var options = new StellaOpsCliOptions
|
||||||
{
|
{
|
||||||
BackendUrl = "https://feedser.example",
|
BackendUrl = "https://concelier.example",
|
||||||
Authority =
|
Authority =
|
||||||
{
|
{
|
||||||
Url = "https://authority.example",
|
Url = "https://authority.example",
|
||||||
ClientId = "cli",
|
ClientId = "cli",
|
||||||
ClientSecret = "secret",
|
ClientSecret = "secret",
|
||||||
Scope = "feedser.jobs.trigger",
|
Scope = "concelier.jobs.trigger",
|
||||||
TokenCacheDirectory = temp.Path
|
TokenCacheDirectory = temp.Path
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -387,7 +387,7 @@ public sealed class BackendOperationsClientTests
|
|||||||
"token-123",
|
"token-123",
|
||||||
"Bearer",
|
"Bearer",
|
||||||
DateTimeOffset.UtcNow.AddMinutes(5),
|
DateTimeOffset.UtcNow.AddMinutes(5),
|
||||||
new[] { StellaOpsScopes.FeedserJobsTrigger });
|
new[] { StellaOpsScopes.ConcelierJobsTrigger });
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask CacheTokenAsync(string key, StellaOpsTokenCacheEntry entry, CancellationToken cancellationToken = default)
|
public ValueTask CacheTokenAsync(string key, StellaOpsTokenCacheEntry entry, CancellationToken cancellationToken = default)
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
# StellaOps.Cli — Agent Brief
|
# StellaOps.Cli — Agent Brief
|
||||||
|
|
||||||
## Mission
|
## Mission
|
||||||
- Deliver an offline-capable command-line interface that drives StellaOps back-end operations: scanner distribution, scan execution, result uploads, and Feedser database lifecycle calls (init/resume/export).
|
- Deliver an offline-capable command-line interface that drives StellaOps back-end operations: scanner distribution, scan execution, result uploads, and Concelier database lifecycle calls (init/resume/export).
|
||||||
- Honour StellaOps principles of determinism, observability, and offline-first behaviour while providing a polished operator experience.
|
- Honour StellaOps principles of determinism, observability, and offline-first behaviour while providing a polished operator experience.
|
||||||
|
|
||||||
## Role Charter
|
## Role Charter
|
||||||
| Role | Mandate | Collaboration |
|
| Role | Mandate | Collaboration |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| **DevEx/CLI** | Own CLI UX, command routing, and configuration model. Ensure commands work with empty/default config and document overrides. | Coordinate with Backend/WebService for API contracts and with Docs for operator workflows. |
|
| **DevEx/CLI** | Own CLI UX, command routing, and configuration model. Ensure commands work with empty/default config and document overrides. | Coordinate with Backend/WebService for API contracts and with Docs for operator workflows. |
|
||||||
| **Ops Integrator** | Maintain integration paths for shell/dotnet/docker tooling. Validate that air-gapped runners can bootstrap required binaries. | Work with Feedser/Agent teams to mirror packaging and signing requirements. |
|
| **Ops Integrator** | Maintain integration paths for shell/dotnet/docker tooling. Validate that air-gapped runners can bootstrap required binaries. | Work with Concelier/Agent teams to mirror packaging and signing requirements. |
|
||||||
| **QA** | Provide command-level fixtures, golden outputs, and regression coverage (unit & smoke). Ensure commands respect cancellation and deterministic logging. | Partner with QA guild for shared harnesses and test data. |
|
| **QA** | Provide command-level fixtures, golden outputs, and regression coverage (unit & smoke). Ensure commands respect cancellation and deterministic logging. | Partner with QA guild for shared harnesses and test data. |
|
||||||
|
|
||||||
## Working Agreements
|
## Working Agreements
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
- Update `TASKS.md` as states change (TODO → DOING → DONE/BLOCKED) and record added tests/fixtures alongside implementation notes.
|
- Update `TASKS.md` as states change (TODO → DOING → DONE/BLOCKED) and record added tests/fixtures alongside implementation notes.
|
||||||
|
|
||||||
## Reference Materials
|
## Reference Materials
|
||||||
- `docs/ARCHITECTURE_FEEDSER.md` for database operations surface area.
|
- `docs/ARCHITECTURE_CONCELIER.md` for database operations surface area.
|
||||||
- Backend OpenAPI/contract docs (once available) for job triggers and scanner endpoints.
|
- Backend OpenAPI/contract docs (once available) for job triggers and scanner endpoints.
|
||||||
- Existing module AGENTS/TASKS files for style and coordination cues.
|
- Existing module AGENTS/TASKS files for style and coordination cues.
|
||||||
- `docs/09_API_CLI_REFERENCE.md` (section 3) for the user-facing synopsis of the CLI verbs and flags.
|
- `docs/09_API_CLI_REFERENCE.md` (section 3) for the user-facing synopsis of the CLI verbs and flags.
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ internal static class CommandFactory
|
|||||||
|
|
||||||
private static Command BuildDatabaseCommand(IServiceProvider services, Option<bool> verboseOption, CancellationToken cancellationToken)
|
private static Command BuildDatabaseCommand(IServiceProvider services, Option<bool> verboseOption, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var db = new Command("db", "Trigger Feedser database operations via backend jobs.");
|
var db = new Command("db", "Trigger Concelier database operations via backend jobs.");
|
||||||
|
|
||||||
var fetch = new Command("fetch", "Trigger connector fetch/parse/map stages.");
|
var fetch = new Command("fetch", "Trigger connector fetch/parse/map stages.");
|
||||||
var sourceOption = new Option<string>("--source")
|
var sourceOption = new Option<string>("--source")
|
||||||
@@ -174,7 +174,7 @@ internal static class CommandFactory
|
|||||||
return CommandHandlers.HandleMergeJobAsync(services, verbose, cancellationToken);
|
return CommandHandlers.HandleMergeJobAsync(services, verbose, cancellationToken);
|
||||||
});
|
});
|
||||||
|
|
||||||
var export = new Command("export", "Run Feedser export jobs.");
|
var export = new Command("export", "Run Concelier export jobs.");
|
||||||
var formatOption = new Option<string>("--format")
|
var formatOption = new Option<string>("--format")
|
||||||
{
|
{
|
||||||
Description = "Export format: json or trivy-db."
|
Description = "Export format: json or trivy-db."
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ internal static class AuthorityTokenUtilities
|
|||||||
|
|
||||||
var scope = options.Authority?.Scope;
|
var scope = options.Authority?.Scope;
|
||||||
return string.IsNullOrWhiteSpace(scope)
|
return string.IsNullOrWhiteSpace(scope)
|
||||||
? StellaOpsScopes.FeedserJobsTrigger
|
? StellaOpsScopes.ConcelierJobsTrigger
|
||||||
: scope.Trim();
|
: scope.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public static class CliBootstrapper
|
|||||||
authority.ClientSecret = string.IsNullOrWhiteSpace(authority.ClientSecret) ? null : authority.ClientSecret.Trim();
|
authority.ClientSecret = string.IsNullOrWhiteSpace(authority.ClientSecret) ? null : authority.ClientSecret.Trim();
|
||||||
authority.Username = authority.Username?.Trim() ?? string.Empty;
|
authority.Username = authority.Username?.Trim() ?? string.Empty;
|
||||||
authority.Password = string.IsNullOrWhiteSpace(authority.Password) ? null : authority.Password.Trim();
|
authority.Password = string.IsNullOrWhiteSpace(authority.Password) ? null : authority.Password.Trim();
|
||||||
authority.Scope = string.IsNullOrWhiteSpace(authority.Scope) ? StellaOpsScopes.FeedserJobsTrigger : authority.Scope.Trim();
|
authority.Scope = string.IsNullOrWhiteSpace(authority.Scope) ? StellaOpsScopes.ConcelierJobsTrigger : authority.Scope.Trim();
|
||||||
|
|
||||||
authority.Resilience ??= new StellaOpsCliAuthorityResilienceOptions();
|
authority.Resilience ??= new StellaOpsCliAuthorityResilienceOptions();
|
||||||
authority.Resilience.RetryDelays ??= new List<TimeSpan>();
|
authority.Resilience.RetryDelays ??= new List<TimeSpan>();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public sealed class StellaOpsCliAuthorityOptions
|
|||||||
|
|
||||||
public string? Password { get; set; }
|
public string? Password { get; set; }
|
||||||
|
|
||||||
public string Scope { get; set; } = StellaOpsScopes.FeedserJobsTrigger;
|
public string Scope { get; set; } = StellaOpsScopes.ConcelierJobsTrigger;
|
||||||
|
|
||||||
public string TokenCacheDirectory { get; set; } = string.Empty;
|
public string TokenCacheDirectory { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ internal static class Program
|
|||||||
clientOptions.ClientSecret = options.Authority.ClientSecret;
|
clientOptions.ClientSecret = options.Authority.ClientSecret;
|
||||||
clientOptions.DefaultScopes.Clear();
|
clientOptions.DefaultScopes.Clear();
|
||||||
clientOptions.DefaultScopes.Add(string.IsNullOrWhiteSpace(options.Authority.Scope)
|
clientOptions.DefaultScopes.Add(string.IsNullOrWhiteSpace(options.Authority.Scope)
|
||||||
? StellaOps.Auth.Abstractions.StellaOpsScopes.FeedserJobsTrigger
|
? StellaOps.Auth.Abstractions.StellaOpsScopes.ConcelierJobsTrigger
|
||||||
: options.Authority.Scope);
|
: options.Authority.Scope);
|
||||||
|
|
||||||
var resilience = options.Authority.Resilience ?? new StellaOpsCliAuthorityResilienceOptions();
|
var resilience = options.Authority.Resilience ?? new StellaOpsCliAuthorityResilienceOptions();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md
|
|||||||
|Introduce command host & routing skeleton|DevEx/CLI|Configuration|**DONE** – System.CommandLine (v2.0.0-beta5) router stitched with `scanner`, `scan`, `db`, and `config` verbs.|
|
|Introduce command host & routing skeleton|DevEx/CLI|Configuration|**DONE** – System.CommandLine (v2.0.0-beta5) router stitched with `scanner`, `scan`, `db`, and `config` verbs.|
|
||||||
|Scanner artifact download/install commands|Ops Integrator|Backend contracts|**DONE** – `scanner download` caches bundles, validates SHA-256 (plus optional RSA signature), installs via `docker load`, persists metadata, and retries with exponential backoff.|
|
|Scanner artifact download/install commands|Ops Integrator|Backend contracts|**DONE** – `scanner download` caches bundles, validates SHA-256 (plus optional RSA signature), installs via `docker load`, persists metadata, and retries with exponential backoff.|
|
||||||
|Scan execution & result upload workflow|Ops Integrator, QA|Scanner cmd|**DONE** – `scan run` drives container scans against directories, emits artefacts in `ResultsDirectory`, auto-uploads on success, and `scan upload` covers manual retries.|
|
|Scan execution & result upload workflow|Ops Integrator, QA|Scanner cmd|**DONE** – `scan run` drives container scans against directories, emits artefacts in `ResultsDirectory`, auto-uploads on success, and `scan upload` covers manual retries.|
|
||||||
|Feedser DB operations passthrough|DevEx/CLI|Backend, Feedser APIs|**DONE** – `db fetch|merge|export` trigger `/jobs/*` endpoints with parameter binding and consistent exit codes.|
|
|Concelier DB operations passthrough|DevEx/CLI|Backend, Concelier APIs|**DONE** – `db fetch|merge|export` trigger `/jobs/*` endpoints with parameter binding and consistent exit codes.|
|
||||||
|CLI observability & tests|QA|Command host|**DONE** – Added console logging defaults & configuration bootstrap tests; future metrics hooks tracked separately.|
|
|CLI observability & tests|QA|Command host|**DONE** – Added console logging defaults & configuration bootstrap tests; future metrics hooks tracked separately.|
|
||||||
|Authority auth commands|DevEx/CLI|Auth libraries|**DONE** – `auth login/logout/status` wrap the shared auth client, manage token cache, and surface status messages.|
|
|Authority auth commands|DevEx/CLI|Auth libraries|**DONE** – `auth login/logout/status` wrap the shared auth client, manage token cache, and surface status messages.|
|
||||||
|Document authority workflow in CLI help & quickstart|Docs/CLI|Authority auth commands|**DONE (2025-10-10)** – CLI help now surfaces Authority config fields and docs/09 + docs/10 describe env vars, auth login/status flow, and cache location.|
|
|Document authority workflow in CLI help & quickstart|Docs/CLI|Authority auth commands|**DONE (2025-10-10)** – CLI help now surfaces Authority config fields and docs/09 + docs/10 describe env vars, auth login/status flow, and cache location.|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using StellaOps.Feedser.Models;
|
using StellaOps.Concelier.Models;
|
||||||
|
|
||||||
namespace StellaOps.Feedser.Core.Tests;
|
namespace StellaOps.Concelier.Core.Tests;
|
||||||
|
|
||||||
public sealed class CanonicalMergerTests
|
public sealed class CanonicalMergerTests
|
||||||
{
|
{
|
||||||
@@ -4,9 +4,9 @@ using System.Linq;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using StellaOps.Feedser.Core.Jobs;
|
using StellaOps.Concelier.Core.Jobs;
|
||||||
|
|
||||||
namespace StellaOps.Feedser.Core.Tests;
|
namespace StellaOps.Concelier.Core.Tests;
|
||||||
|
|
||||||
public sealed class JobCoordinatorTests
|
public sealed class JobCoordinatorTests
|
||||||
{
|
{
|
||||||
@@ -4,10 +4,10 @@ using System.IO;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using StellaOps.Feedser.Core.Jobs;
|
using StellaOps.Concelier.Core.Jobs;
|
||||||
using StellaOps.Plugin.Hosting;
|
using StellaOps.Plugin.Hosting;
|
||||||
|
|
||||||
namespace StellaOps.Feedser.Core.Tests;
|
namespace StellaOps.Concelier.Core.Tests;
|
||||||
|
|
||||||
public sealed class JobPluginRegistrationExtensionsTests
|
public sealed class JobPluginRegistrationExtensionsTests
|
||||||
{
|
{
|
||||||
@@ -53,7 +53,7 @@ public sealed class JobPluginRegistrationExtensionsTests
|
|||||||
Assert.True(schedulerOptions.Definitions.TryGetValue(PluginJob.JobKind, out var definition));
|
Assert.True(schedulerOptions.Definitions.TryGetValue(PluginJob.JobKind, out var definition));
|
||||||
Assert.NotNull(definition);
|
Assert.NotNull(definition);
|
||||||
Assert.Equal(PluginJob.JobKind, definition.Kind);
|
Assert.Equal(PluginJob.JobKind, definition.Kind);
|
||||||
Assert.Equal("StellaOps.Feedser.Core.Tests.PluginJob", definition.JobType.FullName);
|
Assert.Equal("StellaOps.Concelier.Core.Tests.PluginJob", definition.JobType.FullName);
|
||||||
Assert.Equal(TimeSpan.FromSeconds(45), definition.Timeout);
|
Assert.Equal(TimeSpan.FromSeconds(45), definition.Timeout);
|
||||||
Assert.Equal(TimeSpan.FromSeconds(5), definition.LeaseDuration);
|
Assert.Equal(TimeSpan.FromSeconds(5), definition.LeaseDuration);
|
||||||
Assert.Equal("*/10 * * * *", definition.CronExpression);
|
Assert.Equal("*/10 * * * *", definition.CronExpression);
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using StellaOps.Feedser.Core.Jobs;
|
using StellaOps.Concelier.Core.Jobs;
|
||||||
|
|
||||||
namespace StellaOps.Feedser.Core.Tests;
|
namespace StellaOps.Concelier.Core.Tests;
|
||||||
|
|
||||||
public sealed class JobSchedulerBuilderTests
|
public sealed class JobSchedulerBuilderTests
|
||||||
{
|
{
|
||||||
@@ -4,9 +4,9 @@ using System.Threading.Tasks;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using StellaOps.DependencyInjection;
|
using StellaOps.DependencyInjection;
|
||||||
using StellaOps.Feedser.Core.Jobs;
|
using StellaOps.Concelier.Core.Jobs;
|
||||||
|
|
||||||
namespace StellaOps.Feedser.Core.Tests;
|
namespace StellaOps.Concelier.Core.Tests;
|
||||||
|
|
||||||
public sealed class TestPluginRoutine : IDependencyInjectionRoutine
|
public sealed class TestPluginRoutine : IDependencyInjectionRoutine
|
||||||
{
|
{
|
||||||
@@ -5,6 +5,6 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="../StellaOps.Feedser.Core/StellaOps.Feedser.Core.csproj" />
|
<ProjectReference Include="../StellaOps.Concelier.Core/StellaOps.Concelier.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -26,7 +26,7 @@ Out: business logic of connectors/exporters, HTTP handlers (owned by WebService)
|
|||||||
- Logs: kind, trigger, params hash, lease holder, outcome; redact params containing secrets.
|
- Logs: kind, trigger, params hash, lease holder, outcome; redact params containing secrets.
|
||||||
- Honor CancellationToken early and often.
|
- Honor CancellationToken early and often.
|
||||||
## Tests
|
## Tests
|
||||||
- Author and review coverage in `../StellaOps.Feedser.Core.Tests`.
|
- Author and review coverage in `../StellaOps.Concelier.Core.Tests`.
|
||||||
- Shared fixtures (e.g., `MongoIntegrationFixture`, `ConnectorTestHarness`) live in `../StellaOps.Feedser.Testing`.
|
- Shared fixtures (e.g., `MongoIntegrationFixture`, `ConnectorTestHarness`) live in `../StellaOps.Concelier.Testing`.
|
||||||
- Keep fixtures deterministic; match new cases to real-world advisories or regression scenarios.
|
- Keep fixtures deterministic; match new cases to real-world advisories or regression scenarios.
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using StellaOps.Feedser.Models;
|
using StellaOps.Concelier.Models;
|
||||||
|
|
||||||
namespace StellaOps.Feedser.Core;
|
namespace StellaOps.Concelier.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Result emitted by <see cref="CanonicalMerger"/> describing the merged advisory and analytics about key decisions.
|
/// Result emitted by <see cref="CanonicalMerger"/> describing the merged advisory and analytics about key decisions.
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using StellaOps.Feedser.Models;
|
using StellaOps.Concelier.Models;
|
||||||
|
|
||||||
namespace StellaOps.Feedser.Core;
|
namespace StellaOps.Concelier.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resolves conflicts between GHSA, NVD, and OSV advisories into a single canonical advisory following
|
/// Resolves conflicts between GHSA, NVD, and OSV advisories into a single canonical advisory following
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace StellaOps.Feedser.Core.Jobs;
|
namespace StellaOps.Concelier.Core.Jobs;
|
||||||
|
|
||||||
public interface IJob
|
public interface IJob
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace StellaOps.Feedser.Core.Jobs;
|
namespace StellaOps.Concelier.Core.Jobs;
|
||||||
|
|
||||||
public interface IJobCoordinator
|
public interface IJobCoordinator
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace StellaOps.Feedser.Core.Jobs;
|
namespace StellaOps.Concelier.Core.Jobs;
|
||||||
|
|
||||||
public interface IJobStore
|
public interface IJobStore
|
||||||
{
|
{
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user