7.7 KiB
Concelier Fixture Maintenance
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.
GHSA ↔ OSV parity fixtures
- Location:
src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests/Fixtures/osv-ghsa.*.json - Purpose: Exercised by
OsvGhsaParityRegressionTeststo ensure OSV + GHSA outputs stay aligned on aliases, ranges, references, and credits. - Regeneration: Either run the test harness with online regeneration (
UPDATE_PARITY_FIXTURES=1 dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests/StellaOps.Concelier.Connector.Osv.Tests.csproj) or execute the fixture updater (dotnet run --project src/Tools/FixtureUpdater/FixtureUpdater.csproj). Both paths normalise timestamps and canonical ordering. - SemVer provenance: The regenerated fixtures should show
normalizedVersions[].notesin theosv:{ecosystem}:{advisoryId}:{identifier}shape emitted bySemVerRangeRuleBuilder. Confirm the constraints and notes line up with GHSA/NVD composites before committing. - Verification: Inspect the diff, then re-run
dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests/StellaOps.Concelier.Connector.Osv.Tests.csprojto confirm parity.
GHSA credit parity fixtures
- Location:
src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa.Tests/Fixtures/credit-parity.{ghsa,osv,nvd}.json - Purpose: Exercised by
GhsaCreditParityRegressionTeststo guarantee GHSA/NVD/OSV acknowledgements remain in lockstep. - Regeneration:
dotnet run --project src/Tools/FixtureUpdater/FixtureUpdater.csprojrewrites all three canonical snapshots. - Verification:
dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa.Tests/StellaOps.Concelier.Connector.Ghsa.Tests.csproj.
Always commit fixture changes together with the code that motivated them and reference the regression test that guards the behaviour.
Apple security update fixtures
- Location:
src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Apple.Tests/Apple/Fixtures/*.htmland.expected.json. - Purpose: Exercised by
AppleLiveRegressionTeststo 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.shorscripts/update-apple-fixtures.ps1). They exportUPDATE_APPLE_FIXTURES=1, propagate the flag throughWSLENV, 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/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Apple.Tests/StellaOps.Concelier.Connector.Vndr.Apple.Tests.csprojwithout the env var to confirm determinism.
Tip for other connector owners: mirror the sentinel +
WSLENVpattern (touch .update-<connector>-fixtures, append the env var viaWSLENV) when you add fixture refresh scripts so contributors running under WSL inherit the regeneration flag automatically.
KISA advisory fixtures
- Location:
src/Concelier/__Tests/StellaOps.Concelier.Connector.Kisa.Tests/Fixtures/kisa-{feed,detail}.(xml|json) - Purpose: Used by
KisaConnectorTeststo verify Hangul-aware fetch → parse → map flows and to assert telemetry counters stay wired. - Regeneration:
UPDATE_KISA_FIXTURES=1 dotnet test src/Concelier/__Tests/StellaOps.Concelier.Connector.Kisa.Tests/StellaOps.Concelier.Connector.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.
- Localisation note: RSS
categoryvalues (e.g.취약점정보) remain in Hangul—do not translate them in fixtures; they feed directly into metrics/log tags.
Fixture Tiers & Retention Rules
Added in Sprint: SPRINT_20251229_004_LIB_fixture_harvester (FH-010)
Tier Classification
Test fixtures in StellaOps are classified into tiers based on their source, purpose, and maintenance requirements:
| Tier | Name | Purpose | Retention |
|---|---|---|---|
| T0 | Synthetic | Minimal, deterministic fixtures for unit testing | Permanent |
| T1 | Specification Examples | Reference fixtures from CycloneDX, SPDX, OpenVEX specs | Per spec version |
| T2 | Real-World Samples | Production-representative fixtures from real ecosystems | 6 months + current |
| T3 | Regression | Fixtures capturing specific bugs or production incidents | Permanent |
Tier Details
T0 - Synthetic Fixtures
- Source: Generated/hand-crafted
- Size: Minimal (< 100 KB)
- External Dependencies: None
- Refresh Policy: Manual only
- Use Cases: Unit tests, schema validation, edge cases, air-gap testing
T1 - Specification Examples
- Source: CycloneDX, SPDX, OpenVEX official specs
- Size: Small to medium (< 1 MB)
- External Dependencies: Spec repositories
- Refresh Policy: Quarterly (with spec updates)
- Use Cases: Format compliance, parser validation, interoperability
T2 - Real-World Samples
- Source: Public registries, OSS projects
- Size: Medium (< 10 MB)
- External Dependencies: Public APIs
- Refresh Policy: Monthly or on-demand
- Use Cases: Integration testing, performance benchmarks
T3 - Regression Fixtures
- Source: Bug reports, production incidents
- Size: Varies
- External Dependencies: None (self-contained)
- Refresh Policy: Never (historical record)
- Use Cases: Regression prevention, bug reproduction
Storage Guidelines
| Tier | Git Storage | LFS Required | Archive |
|---|---|---|---|
| T0 | Direct | No | No |
| T1 | Direct | Optional | Spec releases |
| T2 | Via LFS | Yes (> 1MB) | Monthly snapshots |
| T3 | Direct | If > 1MB | Incident reports |
Fixture Harvester Tool
The FixtureHarvester CLI tool manages fixture acquisition and validation:
# Harvest a new fixture
dotnet run --project src/__Tests/Tools/FixtureHarvester harvest --type sbom --id my-fixture --source https://example.com/sbom.json
# Validate all fixtures
dotnet run --project src/__Tests/Tools/FixtureHarvester validate
# Regenerate expected outputs (requires confirmation)
dotnet run --project src/__Tests/Tools/FixtureHarvester regen --fixture my-fixture --confirm
Fixture Directory Structure
src/__Tests/fixtures/
├── fixtures.manifest.yml # Root manifest
├── sbom/
│ └── <fixture-id>/
│ ├── meta.json # Provenance and metadata
│ ├── raw/ # Original files
│ ├── normalized/ # Processed files
│ └── expected/ # Expected outputs
├── feeds/
│ └── <fixture-id>/...
└── vex/
└── <fixture-id>/...
meta.json Schema
{
"id": "fixture-id",
"source": "local-build | url | api | manual",
"sourceUrl": "https://...",
"retrievedAt": "2025-12-29T00:00:00Z",
"license": "CC0-1.0",
"sha256": "sha256:...",
"refreshPolicy": "manual | monthly | quarterly",
"tier": "T0 | T1 | T2 | T3",
"notes": "Additional context"
}
See also: FixtureHarvester README