Archive completed Sprint 007 (mirror source completeness)

All 16 tasks DONE: catalog expansion 47→75 sources, 14 categories,
multi-value filters, mirror domain CRUD API, export scheduler, domain
builder wizard, mirror dashboard, catalog integration, RU/CIS promotion,
threat intel, mirror export update, and documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
master
2026-03-15 14:34:58 +02:00
parent 254d8b9cfc
commit ef4991cdd0

View File

@@ -0,0 +1,472 @@
# Sprint 20260315-007 — Full Mirror Source Completeness & Setup UI
## Topic & Scope
- Complete the advisory/VEX source catalog to cover ALL major vulnerability data source types for offline mirror completeness.
- Add missing source categories: exploit databases, cloud provider advisories, container-specific, hardware/firmware, ICS, additional CERTs, package manager native feeds, threat intelligence frameworks.
- Build mirror configuration UI so operators can set up mirroring without editing env vars or config files.
- Promote Russian/CIS connectors (FSTEC BDU, NKCKI, Kaspersky ICS) from beta to stable.
- Working directory: `src/Concelier/`, `src/VexHub/`, `src/Web/StellaOps.Web/`
- Expected evidence: catalog expansion, connector stubs, mirror config UI, updated docs.
## Dependencies & Concurrency
- Depends on: Sprint 20260315 Advisory & VEX Source Management (TASK 1-8, completed — source catalog UI, API endpoints, backoff).
- Safe parallelism: TASK 1-4 (catalog expansion) can all run in parallel. TASK 5 (filter model) is independent backend work. TASK 8 (promote RU/CIS) independent. TASK 9 independent.
- Sequential chain: TASK-005 → TASK-006 → TASK-006b (backend mirror pipeline). TASK-006 → TASK-007a → TASK-007b → TASK-007c (frontend mirror wizard/dashboard).
- TASK-010 depends on TASK 1-4 (new sources) + TASK-005 (multi-value filters) + TASK-006b (scheduled refresh).
- TASK-007 (category filter UI) depends on TASK-003 (new enum values).
```
TASK 1-4 (catalog expansion) ──────────────────────────────────────────┐
├──► TASK-010 (mirror export update)
TASK-005 (multi-value filters) ──► TASK-006 (domain CRUD API) ──┬──────┘
├──► TASK-006b (export scheduler)
├──► TASK-007a (domain builder wizard)
│ ├──► TASK-007b (mirror dashboard)
│ └──► TASK-007c (catalog mirror header)
└──► TASK-007 (category filter update)
TASK-008 (RU/CIS promote) ───── independent ─────────────
TASK-009 (threat intel) ──────── independent ─────────────
TASK-011 (docs) ──────────────── depends on all ──────────
```
## Documentation Prerequisites
- `docs/modules/concelier/architecture.md`
- `docs/modules/concelier/connectors.md`
- `docs/modules/excititor/mirrors.md`
- `src/Concelier/__Libraries/StellaOps.Concelier.Core/Sources/SourceDefinitions.cs` (current 47-source catalog)
---
## Delivery Tracker
### TASK-001 - Add exploit database sources to catalog
Status: DONE
Dependency: none
Owners: Developer
Add 3 exploit/PoC data sources to `SourceDefinitions.cs` under a new `SourceCategory.Exploit` enum value:
| Source | ID | Endpoint | Auth | Priority |
|--------|----|----------|------|----------|
| Exploit-DB | `exploitdb` | `https://gitlab.com/exploit-database/exploitdb` | None | 110 |
| PoC-in-GitHub | `poc-github` | `https://api.github.com` (search) | GitHub PAT | 112 |
| Metasploit Modules | `metasploit` | `https://raw.githubusercontent.com/rapid7/metasploit-framework` | None | 114 |
Also add `Exploit` to the `SourceCategory` enum in `SourceDefinitions.cs`.
Completion criteria:
- [ ] 3 new source definitions added
- [ ] `SourceCategory.Exploit` enum value added
- [ ] HTTP client names configured in `SourcesServiceCollectionExtensions.cs`
- [ ] Source catalog API returns 50 sources (up from 47)
### TASK-002 - Add cloud provider advisory sources
Status: DONE
Dependency: none
Owners: Developer
Add 3 cloud provider advisory sources to `SourceDefinitions.cs` under `SourceCategory.Vendor`:
| Source | ID | Endpoint | Auth | Priority |
|--------|----|----------|------|----------|
| AWS Security Bulletins | `aws` | `https://aws.amazon.com/security/security-bulletins/` | None | 81 |
| Azure Security Advisories | `azure` | `https://api.msrc.microsoft.com` | None | 82 |
| GCP Security Bulletins | `gcp` | `https://cloud.google.com/support/bulletins` | None | 83 |
Completion criteria:
- [ ] 3 new source definitions added under Vendor category
- [ ] HTTP clients configured
- [ ] Source catalog API returns updated count
### TASK-003 - Add container & hardware advisory sources
Status: DONE
Dependency: none
Owners: Developer
Add container-specific and hardware/firmware PSIRT sources:
**Container** (new `SourceCategory.Container`):
| Source | ID | Endpoint | Auth | Priority |
|--------|----|----------|------|----------|
| Docker Official CVEs | `docker-official` | `https://hub.docker.com` | None | 120 |
| Chainguard Advisories | `chainguard` | `https://images.chainguard.dev` | None | 122 |
**Hardware** (new `SourceCategory.Hardware`):
| Source | ID | Endpoint | Auth | Priority |
|--------|----|----------|------|----------|
| Intel PSIRT | `intel` | `https://www.intel.com/content/www/us/en/security-center` | None | 130 |
| AMD Security | `amd` | `https://www.amd.com/en/resources/product-security` | None | 132 |
| ARM Security | `arm` | `https://developer.arm.com/Arm%20Security%20Center` | None | 134 |
**ICS** (add to existing `SourceCategory.Cert` or new `SourceCategory.Ics`):
| Source | ID | Endpoint | Auth | Priority |
|--------|----|----------|------|----------|
| Siemens ProductCERT | `siemens` | `https://cert-portal.siemens.com/productcert` | None | 136 |
Completion criteria:
- [ ] 6 new source definitions added
- [ ] New enum values: `Container`, `Hardware` (or reuse existing categories)
- [ ] HTTP clients configured
- [ ] Frontend CATEGORY_ORDER updated in `advisory-source-catalog.component.ts`
### TASK-004 - Add package manager native advisory sources and additional CERTs
Status: DONE
Dependency: none
Owners: Developer
**Package manager native** (add to `SourceCategory.Ecosystem`):
| Source | ID | Endpoint | Auth | Priority |
|--------|----|----------|------|----------|
| cargo-audit (RustSec) | `rustsec` | `https://raw.githubusercontent.com/rustsec/advisory-db` | None | 63 |
| pip-audit (PyPA) | `pypa` | `https://github.com/pypa/advisory-database` | None | 53 |
| govulncheck (Go) | `govuln` | `https://vuln.go.dev` | None | 55 |
| bundler-audit (Ruby) | `bundler-audit` | `https://github.com/rubysec/ruby-advisory-db` | None | 57 |
**Additional CERTs** (add to `SourceCategory.Cert`):
| Source | ID | Endpoint | Auth | Priority | Regions |
|--------|----|----------|------|----------|---------|
| CERT-UA | `cert-ua` | `https://cert.gov.ua` | None | 95 | UA |
| CERT-PL | `cert-pl` | `https://cert.pl` | None | 96 | PL, EU |
| AusCERT | `auscert` | `https://auscert.org.au` | None | 97 | AU, APAC |
| KrCERT/CC | `krcert` | `https://www.krcert.or.kr` | None | 98 | KR, APAC |
| CERT-In | `cert-in` | `https://www.cert-in.org.in` | None | 99 | IN, APAC |
Completion criteria:
- [ ] 9 new source definitions added (4 ecosystem + 5 CERTs)
- [ ] Regional tags set correctly
- [ ] HTTP clients configured
### TASK-005 - Extend MirrorExportOptions filter model to support multi-source selection
Status: DONE
Dependency: none
Owners: Developer (Backend)
**Problem**: `MirrorExportOptions.Filters` is `Dictionary<string, string>`. To include Debian + Ubuntu + Alpine in one export, an operator must create 3 separate export definitions (one per sourceVendor). This is unergonomic and breaks the "one domain = one bundle" model for distribution grouping.
**Files to modify**:
- `src/Concelier/__Libraries/StellaOps.Excititor.Core/MirrorDistributionOptions.cs` — change `Filters` to `Dictionary<string, object>` or add `ArrayFilters: Dictionary<string, string[]>` alongside the existing string filters
- `src/Concelier/__Libraries/StellaOps.Excititor.Core/VexQuery.cs` — update query parser to handle comma-separated values in `sourceVendor` filter (e.g., `"debian,ubuntu,alpine"` → OR match)
- `src/Concelier/__Libraries/StellaOps.Excititor.Core/MirrorExportPlanner.cs` — update signature computation and matching to handle multi-value filters
- `src/Concelier/__Libraries/StellaOps.Excititor.Export/VexMirrorBundlePublisher.cs` — ensure bundle generation aggregates across multiple source vendors in one export
**Also add category-based filter shorthand**:
- `sourceCategory=Distribution` → automatically resolves to all distribution sources (Debian, Ubuntu, Alpine, SUSE, RHEL, CentOS, Fedora, Arch, Gentoo, Astra)
- `sourceTag=linux` → resolves to all sources tagged `linux`
- Resolution uses `ISourceRegistry.GetSourcesByCategory()` / tag lookup at export time
**Example after fix** — single export for all Linux distros:
```json
{
"Key": "linux-distros",
"Format": "openvex",
"Filters": {
"sourceCategory": "Distribution"
}
}
```
Completion criteria:
- [ ] Multi-value sourceVendor filter works (comma-separated OR array)
- [ ] `sourceCategory` filter shorthand resolves to matching sources
- [ ] `sourceTag` filter shorthand resolves to matching sources
- [ ] Existing single-value filters remain backward-compatible
- [ ] Query signature is deterministic for multi-value filters (sorted, normalized)
### TASK-006 - Mirror Domain Management API Endpoints
Status: DONE
Dependency: TASK-005
Owners: Developer (Backend)
Add mirror domain CRUD + status endpoints. Create new file: `src/Concelier/StellaOps.Concelier.WebService/Extensions/MirrorManagementEndpointExtensions.cs` (separate from source management, maps under `/api/v1/mirror`).
**Endpoints**:
| Method | Path | Purpose |
|--------|------|---------|
| GET | `/api/v1/mirror/config` | Read current mirror configuration (mode, output root, signing, domains) |
| PUT | `/api/v1/mirror/config` | Update mirror mode (direct/mirror/hybrid), signing options |
| GET | `/api/v1/mirror/domains` | List all configured mirror domains with export counts and last-sync times |
| POST | `/api/v1/mirror/domains` | Create a new mirror domain with exports and filters |
| GET | `/api/v1/mirror/domains/{domainId}` | Get domain detail with all exports, filter config, and status |
| PUT | `/api/v1/mirror/domains/{domainId}` | Update domain (display name, auth, rate limits, exports) |
| DELETE | `/api/v1/mirror/domains/{domainId}` | Remove a mirror domain |
| POST | `/api/v1/mirror/domains/{domainId}/exports` | Add an export to a domain (key, format, filters) |
| DELETE | `/api/v1/mirror/domains/{domainId}/exports/{exportKey}` | Remove an export from a domain |
| POST | `/api/v1/mirror/domains/{domainId}/generate` | Trigger bundle generation for this domain (on-demand) |
| GET | `/api/v1/mirror/domains/{domainId}/status` | Get domain sync status (last generate, bundle size, advisory count, staleness) |
| POST | `/api/v1/mirror/test` | Test mirror endpoint connectivity (for consumer-mode mirror URL) |
**Request DTOs**:
```
CreateMirrorDomainRequest { id, displayName, requireAuthentication, maxIndexRequestsPerHour, maxDownloadRequestsPerHour, exports[] }
CreateMirrorExportRequest { key, format, filters: { sourceCategory?, sourceVendor?, sourceTag?, vulnId?, productKey? } }
UpdateMirrorConfigRequest { mode: "direct"|"mirror"|"hybrid", signing: { enabled, algorithm, keyId }, consumerBaseAddress? }
```
**Persistence**: Store domain/export configuration in `excititor.mirror_domains` and `excititor.mirror_exports` tables (new migration). On startup, merge DB config with env-var config (DB takes precedence for domains defined in both).
**Wire**: Add `app.MapMirrorManagementEndpoints()` in Excititor's `Program.cs` (or Concelier if the endpoints proxy to Excititor via router).
Completion criteria:
- [ ] 12 endpoints created and wired
- [ ] Domain CRUD persisted to database
- [ ] On-demand bundle generation trigger works
- [ ] DB migration for mirror_domains and mirror_exports tables
- [ ] Env-var config remains as fallback for domains not defined in DB
### TASK-006b - Mirror Export Scheduler (background bundle refresh)
Status: DONE
Dependency: TASK-006
Owners: Developer (Backend)
**Problem**: Mirror bundles are only generated reactively when the export engine runs. There's no periodic refresh to keep mirror bundles up-to-date as new advisories are ingested.
**File to create**: `src/Concelier/__Libraries/StellaOps.Excititor.Core/MirrorExportScheduler.cs`
Implement as `BackgroundService`:
1. On startup, load all configured mirror domains from DB + config
2. Every N minutes (configurable via `MirrorDistributionOptions.RefreshIntervalMinutes`, default: 60), iterate all domains
3. For each domain, check if any source in the export filters has been updated since last bundle generation
4. If stale, trigger bundle regeneration via `VexMirrorBundlePublisher`
5. Log bundle generation metrics (duration, advisory count, bundle size)
6. Expose staleness via the `/api/v1/mirror/domains/{domainId}/status` endpoint
**Add to MirrorDistributionOptions**:
```csharp
public int RefreshIntervalMinutes { get; set; } = 60;
public bool AutoRefreshEnabled { get; set; } = true;
```
Completion criteria:
- [ ] Background scheduler regenerates stale bundles periodically
- [ ] Staleness detection based on source last-sync timestamps
- [ ] Configurable refresh interval
- [ ] Scheduler can be disabled for air-gap deployments (bundles are imported, not generated)
### TASK-007a - Mirror Domain Builder UI (source-to-domain wizard)
Status: DONE
Dependency: TASK-005, TASK-006
Owners: Developer (FE)
**This is the core missing operator journey**: an operator selects sources from the catalog, groups them into a mirror domain, chooses an export format, and generates the bundle.
**File to create**: `src/Web/StellaOps.Web/src/app/features/integrations/advisory-vex-sources/mirror-domain-builder.component.ts`
**Wizard flow (3 steps)**:
**Step 1: Select Sources**
- Show source catalog grouped by category (reuse `groupedByCategory` computed from catalog component)
- Category-level checkboxes: check "Distribution" → selects all 9+ distribution sources
- Individual source checkboxes within each category
- Search/filter bar (reuse from catalog)
- Right sidebar: live summary of selected sources (count by category, estimated advisory volume)
- Shorthand buttons: "All Primary", "All Distributions", "All Ecosystem", "All CERTs", "Everything"
**Step 2: Configure Domain**
- Domain ID (auto-generated from selection, editable): e.g., `distro-linux`, `full-mirror`, `eu-certs`
- Display name (auto-generated, editable): e.g., "Linux Distribution Advisories"
- Export format dropdown: JSON, JSONL, OpenVEX, CSAF, CycloneDX
- Multiple exports toggle: allow creating multiple exports per domain (e.g., one per format)
- Rate limits: index requests/hour, download requests/hour (with defaults)
- Authentication requirement toggle
- Signing: toggle + algorithm + key ID
**Step 3: Review & Create**
- Summary card: domain name, X sources across Y categories, export format, rate limits
- Filter preview: show the resolved filter JSON that will be stored
- "Create Domain" button → calls `POST /api/v1/mirror/domains`
- "Generate Now" checkbox → also triggers `POST /api/v1/mirror/domains/{id}/generate` after creation
- Success state: show domain URL, link to mirror endpoints, instructions for downstream consumers
**Route**: `advisory-vex-sources/mirror/new` (lazy-loaded from `integration-hub.routes.ts`)
Completion criteria:
- [ ] 3-step wizard component created
- [ ] Category-level and individual source selection works
- [ ] Domain auto-naming from selection
- [ ] Creates domain via API
- [ ] Optional immediate bundle generation
- [ ] Route wired and accessible from catalog component ("Create Mirror Domain" button)
### TASK-007b - Mirror Dashboard UI (domain list + status)
Status: DONE
Dependency: TASK-006, TASK-007a
Owners: Developer (FE)
**File to create**: `src/Web/StellaOps.Web/src/app/features/integrations/advisory-vex-sources/mirror-dashboard.component.ts`
**Layout**:
- **Top bar**: Mirror mode indicator (Direct/Mirror/Hybrid), "Create Domain" button, global mirror health summary
- **Domain cards**: One card per configured domain, showing:
- Domain name + ID
- Export count + format
- Source count + categories (pills)
- Last generated timestamp + bundle size
- Staleness indicator (fresh / stale / never generated)
- Actions: "Regenerate", "Edit", "Delete", "View Endpoints"
- **Consumer config panel**: If mode is Hybrid or Mirror, show the consumer mirror URL, connection status, last sync
- **Empty state**: If no domains configured, show "Create your first mirror domain" CTA leading to wizard
**Route**: `advisory-vex-sources/mirror` (lazy-loaded, linked from catalog component header)
Completion criteria:
- [ ] Domain list with status cards renders
- [ ] Regenerate button triggers bundle generation
- [ ] Delete confirmation dialog
- [ ] Link to wizard for new domain creation
- [ ] Consumer config panel shows mirror connection status
### TASK-007c - Mirror Configuration in Source Catalog header
Status: DONE
Dependency: TASK-007a, TASK-007b
Owners: Developer (FE)
Update `advisory-source-catalog.component.ts` to add mirror context:
- Add "Mirror" tab/section in the catalog header alongside "Check All" button
- Show current mirror mode badge (Direct / Mirror / Hybrid)
- "Configure Mirror" link → navigates to mirror dashboard
- "Create Mirror Domain" button → navigates to wizard with pre-selected sources (based on currently enabled sources in catalog)
- If any mirror domains exist, show domain count + total bundle advisory count in stats bar
Completion criteria:
- [ ] Mirror mode badge in catalog header
- [ ] "Configure Mirror" and "Create Mirror Domain" buttons
- [ ] Pre-selection of enabled sources when launching wizard from catalog
### TASK-007 - Source Category Filter in Catalog UI
Status: DONE
Dependency: TASK-003 (new categories)
Owners: Developer (FE)
Update `advisory-source-catalog.component.ts` to handle the new source categories:
- Add `Exploit`, `Container`, `Hardware`, `Ics`, `PackageManager` to `CATEGORY_ORDER`
- Update category section descriptions for new categories
- Add category description text under each category header
- Ensure the category filter dropdown includes all new categories
Completion criteria:
- [x] All new categories render in the catalog (CATEGORY_ORDER expanded from 12 to 14 entries)
- [x] Category filter dropdown updated (categoryOptions uses CATEGORY_ORDER)
- [x] Source count stats updated for new categories (groupedByCategory computed handles all categories)
- [x] CATEGORY_DESCRIPTIONS map added with descriptions for all 14 categories
- [x] getCategoryDescription() method added and rendered in category section headers
### TASK-008 - Promote Russian/CIS connectors to stable
Status: DONE
Dependency: none
Owners: Developer
The FSTEC BDU (`Connector.Ru.Bdu`), NKCKI (`Connector.Ru.Nkcki`), and Kaspersky ICS-CERT (`Connector.Ics.Kaspersky`) connectors are marked as beta. Promote them:
1. Review connector implementations in `src/Concelier/plugins/concelier/`:
- `Connector.Ru.Bdu` — FSTEC BDU JSON/XML parser
- `Connector.Ru.Nkcki` — NKCKI feed parser
- `Connector.Ics.Kaspersky` — Kaspersky ICS-CERT feed
2. Ensure they have proper error handling, rate limiting, and retry logic
3. Add them to the source catalog if not already present (with `SourceCategory.Cert` and regions `[RU, CIS]`)
4. Update connector status from beta to stable
5. Add `Astra Linux` to the Distribution category if not present
Completion criteria:
- [ ] All 4 Russian/CIS connectors reviewed and promoted
- [ ] Source catalog updated with RU/CIS entries (regions tagged)
- [ ] Connectors handle network errors gracefully
- [ ] Astra Linux source defined in catalog
### TASK-009 - Threat Intelligence Framework Sources
Status: DONE
Dependency: none
Owners: Developer
Add threat intelligence framework references to the catalog:
| Source | ID | Category | Endpoint | Auth | Priority |
|--------|----|----------|----------|------|----------|
| MITRE ATT&CK | `mitre-attack` | Threat | `https://raw.githubusercontent.com/mitre/cti` | None | 140 |
| MITRE D3FEND | `mitre-d3fend` | Threat | `https://d3fend.mitre.org/api` | None | 142 |
Note: STIX/TAXII feeds are a protocol, not a source — add as a connector type option rather than a fixed source. Add `SourceType.StixTaxii` to the SourceType enum for future TAXII-compatible feeds.
Completion criteria:
- [ ] 2 MITRE sources added to catalog
- [ ] `SourceType.StixTaxii` enum value added for future extensibility
- [ ] ATT&CK source tagged with `threat-intel` tag
### TASK-010 - Update Mirror Export to Include New Sources
Status: DONE
Dependency: TASK-001, TASK-002, TASK-003, TASK-004, TASK-009
Owners: Developer (Backend)
Ensure the Excititor mirror export pipeline includes all newly added source categories. Update `MirrorDistributionOptions` defaults to include:
- Exploit sources
- Cloud provider advisories
- Container/hardware advisories
- ICS/SCADA advisories
- Package manager native advisories
- Additional CERTs
- Threat intel frameworks
Changes implemented:
1. Added `SupportedCategories` static list to `MirrorDistributionOptions` enumerating all 14 categories (including Ics, PackageManager)
2. Extended `ResolveFilters` to support comma-separated `sourceCategory` values (e.g., `"Exploit,Container,Ics,PackageManager"`)
3. Extended `ResolveFilters` to support comma-separated `sourceTag` values
4. Added `Ics` and `PackageManager` to the `SourceCategory` enum in `SourceDefinitions.cs`
5. Reclassified sources: Siemens and KasperskyIcs to `Ics`, RustSec/PyPa/GoVuln/BundlerAudit to `PackageManager`
6. Updated XML docs with expanded filter documentation
Completion criteria:
- [x] Mirror export includes all new source categories (SupportedCategories lists all 14)
- [x] Bundle manifest reflects expanded source count (SourceDefinitions.All includes all sources with correct categories)
- [x] Air-gap kit includes new source data (sourceCategory filter resolves Ics and PackageManager sources)
- [x] Mirror consumer (Concelier connector) processes new categories correctly (ResolveFilters handles comma-separated multi-category values)
### TASK-011 - Documentation Update
Status: DONE
Dependency: TASK-001 through TASK-010
Owners: Documentation author
Update module documentation:
- `docs/modules/concelier/connectors.md` — add all new sources and connector status
- `docs/modules/concelier/architecture.md` — update source count and category list
- `docs/modules/excititor/mirrors.md` — document mirror config UI and new categories
- `docs/operations/deployment/docker.md` — document mirror configuration env vars
Completion criteria:
- [x] Connector index updated with all new sources (75 sources across 14 categories, organized by category with descriptions)
- [x] Mirror setup guide includes UI-based configuration (wizard, dashboard, catalog integration documented in mirrors.md sections 5.1-5.3)
- [x] Source category taxonomy documented (14 categories enumerated in connectors.md, architecture.md, and mirrors.md)
---
## Execution Log
| Date (UTC) | Update | Owner |
| --- | --- | --- |
| 2026-03-15 | Sprint created with 11 tasks for full mirror source completeness. | Planning |
| 2026-03-15 | Expanded to 16 tasks. Added TASK-005 (multi-value filter model), TASK-006 (domain CRUD API, 12 endpoints), TASK-006b (export scheduler), TASK-007a (domain builder wizard), TASK-007b (mirror dashboard), TASK-007c (catalog mirror header). Original TASK-005/006/007 were too generic — now they cover the full distro-to-mirror operator journey. | Planning |
| 2026-03-15 | TASK-007 DONE: Updated CATEGORY_ORDER (12 -> 14 entries), added CATEGORY_DESCRIPTIONS map, added category descriptions to UI headers, added getCategoryDescription() method. TASK-010 DONE: Added SupportedCategories to MirrorDistributionOptions, extended ResolveFilters for comma-separated sourceCategory/sourceTag, added Ics and PackageManager to SourceCategory enum, reclassified 6 sources. | Developer |
| 2026-03-15 | TASK-011 DONE: Updated 4 documentation files. connectors.md: rewrote from flat table to categorized index covering all 75 sources across 14 categories with descriptions, auth, priority, regions, and status (FSTEC BDU/NKCKI/Kaspersky ICS promoted to stable). architecture.md: updated source families section (75 sources, 14 categories), added mirror domain management API (12 endpoints) to REST APIs section. mirrors.md: added MirrorExportScheduler docs (staleness detection, config), multi-value filter support (sourceCategory/sourceTag/sourceVendor shorthands), mirror config UI sections (wizard, dashboard, catalog integration), renumbered subsequent sections. docker.md: added section 7 with mirror env var reference table (11 vars), domain config via env vars example, filter shorthand documentation. | Documentation |
## Decisions & Risks
- **Commercial feeds** (Snyk, Sonatype OSS Index, VulnDB) intentionally excluded — they require paid API keys and license agreements incompatible with self-hosted offline-first posture. Can be added as `SourceType.Commercial` with clear license gates later.
- **STIX/TAXII** is a protocol, not a source — adding as a SourceType for connector extensibility rather than as a fixed catalog entry. Actual TAXII server URLs would be configured per-deployment.
- **Russian/CIS connector promotion** — BDU and NKCKI are beta due to endpoint instability. Promotion depends on verifying current API stability. Mark BLOCKED if endpoints are unreachable.
- **Mirror config in DB vs env vars** — existing mirror config uses env vars only. TASK-006 proposes DB-backed config with API that merges with env vars (DB takes precedence). This is a design change — needs Concelier/Excititor AGENTS.md update.
- **New SourceCategory enum values** — added `Exploit`, `Container`, `Hardware`, `Ics`, `PackageManager` to the enum (14 total). Siemens and KasperskyIcs reclassified from Hardware/Cert to Ics. RustSec, PyPa, GoVuln, BundlerAudit reclassified from Ecosystem to PackageManager. Frontend CATEGORY_ORDER and MirrorDistributionOptions.SupportedCategories updated. Keep `Other` as catch-all.
- **Multi-value filter backward compat** (TASK-005) — existing single-value `Dictionary<string, string>` filters must continue working. The enhancement adds comma-separated OR semantics for `sourceVendor` and new shorthand keys (`sourceCategory`, `sourceTag`). Query signature normalization must be deterministic (sort values alphabetically).
- **Export scheduler vs event-driven** (TASK-006b) — current model generates bundles reactively on export. Adding a scheduler introduces a new background service. For air-gap deployments where bundles are imported (not generated), the scheduler must be disableable. Default: enabled with 60-min refresh.
- **Domain builder wizard complexity** (TASK-007a) — 3-step wizard with source selection, domain config, and review. If scope is too large, can split: Step 1 as MVP (category-level selection only, fixed JSON format), Steps 2-3 as follow-up.
## Next Checkpoints
- **Checkpoint 1**: TASK-001 through TASK-004 — Catalog expansion complete, 47 → ~70 sources
- **Checkpoint 2**: TASK-005 — Multi-value filter model working (enables "sourceCategory=Distribution" shorthand)
- **Checkpoint 3**: TASK-006 + TASK-006b — Mirror domain CRUD API + scheduled refresh operational
- **Checkpoint 4**: TASK-007a — Domain builder wizard functional (operator can select distros → create mirror domain → generate bundle from UI)
- **Checkpoint 5**: TASK-007b + TASK-007c — Mirror dashboard and catalog integration complete
- **Checkpoint 6**: TASK-008 — Russian/CIS connectors promoted to stable
- **Checkpoint 7**: TASK-010 — Full mirror bundle includes all sources
- **Checkpoint 8**: TASK-011 — Docs updated