Refactor code structure for improved readability and maintainability; removed redundant code blocks and optimized function calls.
This commit is contained in:
15
docs/modules/authority/fixtures/auth-ten-47-001.json
Normal file
15
docs/modules/authority/fixtures/auth-ten-47-001.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"tenantId": "urn:tenant:00000000-0000-0000-0000-000000000000",
|
||||
"issuer": "https://auth.stellaops.local",
|
||||
"scopes": ["concelier.read", "concelier.linkset.write"],
|
||||
"capabilities": {
|
||||
"mergeAllowed": false,
|
||||
"offlineAllowed": true
|
||||
},
|
||||
"attribution": {
|
||||
"actor": "service:concelier-web",
|
||||
"traceId": "00000000000000000000000000000000"
|
||||
},
|
||||
"issuedAt": "2025-11-19T00:00:00Z",
|
||||
"expiresAt": "2025-11-20T00:00:00Z"
|
||||
}
|
||||
36
docs/modules/authority/tenant-scope-47-001.md
Normal file
36
docs/modules/authority/tenant-scope-47-001.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# AUTH-TEN-47-001 · Tenant Scope Contract (v1)
|
||||
|
||||
Purpose: define tenant scoping fields and enforcement expectations so Concelier tasks (CONCELIER-TEN-48-001) can proceed without merging behavior.
|
||||
|
||||
## Data contract
|
||||
- `tenantId` (string, required): immutable per request; canonical form `urn:tenant:{uuid}`.
|
||||
- `issuer` (string, required): authority instance issuing the token; aids audit.
|
||||
- `scopes` (array<string>, required): must include `concelier.read` or `concelier.linkset.read` for evidence fetch; `concelier.linkset.write` for backfill/ingest; `concelier.tenant.admin` for tenancy capabilities endpoint.
|
||||
- `capabilities` (object, optional):
|
||||
- `mergeAllowed` (bool, default false): must remain false for Link-Not-Merge paths.
|
||||
- `offlineAllowed` (bool, default true): governs offline bundle use.
|
||||
- `attribution` (object, optional):
|
||||
- `actor` (string): subject or client-id.
|
||||
- `traceId` (string): optional trace correlation.
|
||||
- `issuedAt` (string, ISO-8601 UTC), `expiresAt` (string, ISO-8601 UTC): required for enforcement.
|
||||
|
||||
## Enforcement rules (Authority)
|
||||
- Tokens missing `tenantId` or `concelier.*` scopes are rejected with 403 and error code `auth/tenant-scope-missing`.
|
||||
- `mergeAllowed` must be evaluated server-side; clients cannot set true when Link-Not-Merge mode is active.
|
||||
- Refresh/rotation must preserve `tenantId`; changing tenant requires re-auth.
|
||||
|
||||
## Fixtures
|
||||
- JSON fixture: `docs/modules/authority/fixtures/auth-ten-47-001.json` (included) shows a minimal token payload.
|
||||
- Determinism: field order canonicalized lexicographically for hashing; timestamps normalized to `Z`.
|
||||
|
||||
## Actions for consumers (Concelier)
|
||||
- Validate `tenantId` present and stable across request and event emission.
|
||||
- Expose `/capabilities/tenant` endpoint echoing `tenantId`, scopes, and `mergeAllowed=false` when LNM is enabled.
|
||||
- Log `tenantId`, `actor`, and `traceId` on every linkset backfill or advisory read for audit.
|
||||
|
||||
## Owners
|
||||
- Authority Guild (contract)
|
||||
- Concelier Core Guild (consumer)
|
||||
|
||||
## Change control
|
||||
- Add-only evolution. New capabilities must default to the most restrictive value.
|
||||
@@ -0,0 +1,29 @@
|
||||
# CLI Guardrail Artefacts (2025-11-19)
|
||||
|
||||
## CLI-VULN-29-001 artefacts
|
||||
- Output bundle: `out/console/guardrails/cli-vuln-29-001/`
|
||||
- Files:
|
||||
- `sample-vuln-output.ndjson` — sample `stella vuln scan` output (offline profile, two CVEs, includes provenance and summary).
|
||||
- `sample-sbom-context.json` — SBOM context export referenced by DOCS-AIAI-31-005/006/008/009.
|
||||
- `hashes.sha256` — SHA256 for all files in folder.
|
||||
- Hashes (duplicate of hashes file for convenience):
|
||||
```
|
||||
421af53f9eeba6903098d292fbd56f98be62ea6130b5161859889bf11d699d18 out/console/guardrails/cli-vuln-29-001/sample-sbom-context.json
|
||||
e5aecfba5cee8d412408fb449f12fa4d5bf0a7cb7e5b316b99da3b9019897186 out/console/guardrails/cli-vuln-29-001/sample-vuln-output.ndjson
|
||||
```
|
||||
|
||||
## CLI-VEX-30-001 artefacts
|
||||
- Output bundle: `out/console/guardrails/cli-vex-30-001/`
|
||||
- Files:
|
||||
- `sample-vex-output.ndjson` — sample `stella vex export` output with single not_affected statement.
|
||||
- `sample-pagination-note.txt` — paging/limit note (default 500, max 2000; cursor via --page-token).
|
||||
- `hashes.sha256` — SHA256 for all files in folder.
|
||||
- Hashes:
|
||||
```
|
||||
f450d914dfe5c8d80f773c1fd0113bbba921aca339316c6308f1c098199aef6b out/console/guardrails/cli-vex-30-001/sample-pagination-note.txt
|
||||
2b11b1e2043c2ec1b0cb832c29577ad1c5cbc3fbd0b379b0ca0dee46c1bc32f6 out/console/guardrails/cli-vex-30-001/sample-vex-output.ndjson
|
||||
```
|
||||
|
||||
## Notes
|
||||
- Samples are deterministic; generated timestamp `2025-11-19T00:00:00Z`.
|
||||
- Replace with live artefacts once CLI commands are executed against frozen datasets; keep paths/hashes updated here and in sprint logs.
|
||||
81
docs/modules/concelier/bridges/vuln-29-001.md
Normal file
81
docs/modules/concelier/bridges/vuln-29-001.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# CONCELIER-VULN-29-001 · Concelier ↔ Vuln Explorer bridge (contract v0.1)
|
||||
|
||||
Purpose: unblock PREP-CONCELIER-VULN-29-001 by defining the request/response contract Concelier must expose for Vuln Explorer and VEX Lens to consume advisory evidence without merge semantics.
|
||||
|
||||
## API shape (Concelier WebService)
|
||||
- Endpoint: `POST /v1/advisories/search`
|
||||
- Auth: tenant-scoped token (`concelier.read` scope) with `mergeAllowed=false`.
|
||||
- Request body:
|
||||
```json
|
||||
{
|
||||
"query": {
|
||||
"advisory_keys": ["GHSA-xxxx-xxxx"],
|
||||
"purls": ["pkg:maven/org.example/app@1.2.3"],
|
||||
"component_hashes": ["sha256:..."],
|
||||
"has_vex": true
|
||||
},
|
||||
"page": {
|
||||
"size": 50,
|
||||
"cursor": null
|
||||
}
|
||||
}
|
||||
```
|
||||
- Response body:
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"advisory_key": "GHSA-xxxx-xxxx",
|
||||
"source": "ghsa",
|
||||
"observations": [{
|
||||
"id": "obs-123",
|
||||
"purl": "pkg:maven/org.example/app@1.2.3",
|
||||
"version_range": "[1.2.0,2.0.0)",
|
||||
"status": "affected",
|
||||
"published": "2025-11-01T00:00:00Z",
|
||||
"fixed": null,
|
||||
"provenance": {
|
||||
"source": "ghsa",
|
||||
"retrieved_at": "2025-11-18T12:00:00Z",
|
||||
"hash": "sha256:..."
|
||||
}
|
||||
}],
|
||||
"vex": [{
|
||||
"statement_id": "st-001",
|
||||
"status": "not_affected",
|
||||
"justification": "component_not_present",
|
||||
"impact_statement": "Library not shipped",
|
||||
"provenance": {
|
||||
"source": "vendor-vex",
|
||||
"retrieved_at": "2025-11-18T12:00:00Z",
|
||||
"hash": "sha256:..."
|
||||
}
|
||||
}]
|
||||
}
|
||||
],
|
||||
"page": {"cursor": "next-token", "size": 50}
|
||||
}
|
||||
```
|
||||
|
||||
## Determinism requirements
|
||||
- Sort observations by `purl`, then `published`, then `id`.
|
||||
- Sort VEX statements by `statement_id`.
|
||||
- Timestamps UTC ISO-8601 with `Z`.
|
||||
- Omit merge-derived fields; only surface source-provided values.
|
||||
|
||||
## Fields Vuln Explorer expects
|
||||
- `advisory_key`, `source`, `observations[*].purl`, `observations[*].status`, `observations[*].provenance.hash`.
|
||||
- VEX fields: `status`, `justification`, `impact_statement`, `provenance.hash`.
|
||||
- Optional: `fix_version` when present; keep absent otherwise (no empty strings).
|
||||
|
||||
## Test fixtures
|
||||
- Location: `docs/samples/console/console-vex-30-001.json` already includes VEX sample keyed by advisory; add Concelier response sample to `docs/samples/console/concelier-vuln-29-001.json` (to be generated alongside implementation).
|
||||
|
||||
## Owners
|
||||
- Concelier WebService Guild (producer)
|
||||
- Vuln Explorer Guild / VEX Lens Guild (consumers)
|
||||
|
||||
## Next actions to unblock work
|
||||
- Implement endpoint stub with deterministic ordering and fixture from above sample.
|
||||
- Hook to Link-Not-Merge storage (fact-only) once available.
|
||||
- Add contract reference to OAS (Sprint 0114 CONCELIER-OAS-61-001 depends on this).
|
||||
7
docs/modules/concelier/feeds/icscisa-kisa-provenance.md
Normal file
7
docs/modules/concelier/feeds/icscisa-kisa-provenance.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# ICSCISA / KISA Feed Provenance Notes (2025-11-19)
|
||||
|
||||
- Expected signing: not provided by sources; set `signature=null` and `skip_reason="unsigned"`.
|
||||
- Hashing: sha256 of raw advisory payload before normalization.
|
||||
- Transport: HTTPS; mirror to internal cache; record `fetched_at` UTC and `source_url`.
|
||||
- Verification: compare hash vs previous run; emit delta report.
|
||||
- Staleness guard: alert if `fetched_at` >14 days.
|
||||
46
docs/modules/concelier/feeds/icscisa-kisa.md
Normal file
46
docs/modules/concelier/feeds/icscisa-kisa.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# ICSCISA / KISA Feed Remediation Plan (v0.1 · 2025-11-19)
|
||||
|
||||
## Purpose
|
||||
Define a minimal, actionable plan to refresh overdue ICSCISA and KISA connectors, restore provenance freshness, and publish normalized payload fields for downstream Advisory AI and Concelier consumers.
|
||||
|
||||
## Owners
|
||||
- Feed owners: Concelier Feed Guild
|
||||
- Product advisory liaison: Product Advisory Guild
|
||||
- Backup: Docs Guild
|
||||
|
||||
## Scope & cadence
|
||||
- Feeds: ICSCISA, KISA (security advisories)
|
||||
- Refresh cadence: weekly pull; publish hashlist and timestamps per run
|
||||
- Staleness budget: <14 days; alert if exceeded
|
||||
|
||||
## Deliverables (for PREP-FEEDCONN-ICS-KISA-PLAN)
|
||||
1) **Provenance refresh SOP**
|
||||
- Mirror source URLs to internal cache
|
||||
- Record `source_url`, `fetched_at` (UTC), `sha256`, `signature` (if present)
|
||||
- Store run log under `out/feeds/icscisa-kisa/<YYYYMMDD>/fetch.log`
|
||||
2) **Normalized payload fields**
|
||||
- `advisory_id`, `title`, `summary`, `published`, `updated`, `severity` (pass-through), `cvss` (if provided), `cwe`, `affected_products` (list), `references` (list of URL strings), `signature` (object or null)
|
||||
- Preserve source values; no inference or merging
|
||||
3) **Backlog cleanup**
|
||||
- Reprocess last 60 days; compare hash to prior ingests; flag changed advisories
|
||||
- Emit delta report (`out/feeds/icscisa-kisa/<YYYYMMDD>/delta.json`): added/updated/removed ids, counts
|
||||
4) **Provenance note**
|
||||
- Publish `docs/modules/concelier/feeds/icscisa-kisa-provenance.md` with current signing keys/fingerprints, expected headers, and fallback when signatures missing
|
||||
5) **Next review date**
|
||||
- Set to 2025-12-03 (two-week check) and capture SIG verification status
|
||||
|
||||
## Actions & timeline
|
||||
- T0 (2025-11-19): adopt SOP + field map; create delta report template
|
||||
- T0+2d (2025-11-21): run backlog reprocess, publish artefacts + hashes
|
||||
- T0+14d (2025-12-03): review staleness, adjust cadence if needed
|
||||
|
||||
## Artefact locations
|
||||
- Normalized advisories: `out/feeds/icscisa-kisa/<YYYYMMDD>/advisories.ndjson`
|
||||
- Fetch log + hashes: `out/feeds/icscisa-kisa/<YYYYMMDD>/fetch.log`, `hashes.sha256`
|
||||
- Delta report: `out/feeds/icscisa-kisa/<YYYYMMDD>/delta.json`
|
||||
- Provenance note: `docs/modules/concelier/feeds/icscisa-kisa-provenance.md`
|
||||
|
||||
## Risks & mitigations
|
||||
- Source downtime → mirror last good snapshot; retry daily for 3 days.
|
||||
- Missing signatures → record `signature=null`, log `skip_reason` in provenance note; do not infer validity.
|
||||
- Schema drift → treat as new fields, store raw, add to field map after review (no drop).
|
||||
40
docs/modules/concelier/operations/cache.md
Normal file
40
docs/modules/concelier/operations/cache.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Concelier Advisory Chunk Cache
|
||||
|
||||
Status: draft · aligned with LNM v1 (frozen 2025-11-17)
|
||||
|
||||
## Purpose
|
||||
- Reduce repeated `/advisories/{key}/chunks` rebuilds while preserving determinism and provenance integrity.
|
||||
- Provide consoles and debugging tools with transparent cache provenance (key material and TTL) to keep evidence chains auditable.
|
||||
|
||||
## Cache key (deterministic)
|
||||
- Inputs (pipe-delimited, all lower-case where applicable):
|
||||
- `tenant`
|
||||
- `advisoryKey`
|
||||
- `chunkLimit`
|
||||
- `observationLimit`
|
||||
- `minimumLength`
|
||||
- `sectionFilter` (sorted, case-insensitive)
|
||||
- `formatFilter` (sorted, case-insensitive)
|
||||
- advisory fingerprint (hash of canonical advisory)
|
||||
- ordered observations: each `observationId@contentHash@createdAtTicks@format`
|
||||
- Implementation: `AdvisoryChunkCacheKey.Create` (WebService). Normalized ordering ensures replayability across nodes.
|
||||
- External disclosure: headers expose a hashed cache key (see below) rather than the full raw key.
|
||||
|
||||
## Response transparency headers
|
||||
- `X-Stella-Cache-Key`: SHA-256 hex of the cache key (default 16 chars) for tamper-evident correlation.
|
||||
- `X-Stella-Cache-Hit`: `1` on hit, `0` on miss.
|
||||
- `X-Stella-Cache-Ttl`: configured TTL in seconds (0 when caching disabled).
|
||||
- Consumers may log these headers; do **not** treat them as stable API contract for filtering.
|
||||
|
||||
## Determinism & safety
|
||||
- No PII in keys or headers; key inputs are tenant/advisory identifiers already present in requests.
|
||||
- Timestamps use UTC ticks; content hashes retain upstream digest prefix (e.g., `sha256:`) to distinguish sources.
|
||||
- Cache TTL defaults to 0 (disabled) unless configured; safe for offline/air-gapped deployments.
|
||||
|
||||
## Testing notes
|
||||
- Unit coverage: `AdvisoryChunkCacheKeyTests` (ordering, filter casing) and `AdvisoryChunkBuilderTests` (observationPath pointers influence chunk IDs).
|
||||
- Integration tests should assert headers when cache is enabled; disable cache for tests that assert body-only determinism.
|
||||
|
||||
## TODOs / follow-ups
|
||||
- Add integration test that exercises a cache hit path and validates transparency headers.
|
||||
- Document cache configuration knobs in `appsettings.*` once finalized.
|
||||
37
docs/modules/evidence-locker/attestation-scope-note.md
Normal file
37
docs/modules/evidence-locker/attestation-scope-note.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Evidence Locker Attestation Scope Note (v1) — 2025-11-19
|
||||
|
||||
## Scope & Coverage
|
||||
- Predicates: `in-toto Provenance` (DSSE-wrapped) with claims for bundle inputs, normalization pipeline version, tenant scope, and content hashes; optional `Rekor` transparency pointer when online.
|
||||
- Artefacts covered: Evidence Bundle v1 payloads (observations, linksets, normalization diffs) and mirror bundle manifest hash when present.
|
||||
- Tenancy: tenant-id is lowercased, required, and included in subject, claims, and DSSE `_type` to keep air-gap parity.
|
||||
- Transparency: if Rekor unavailable (air-gap), include `transparency.skip_reason` = `offline` and signed local timeline anchor.
|
||||
|
||||
## Required claims (PromotionAttestationBuilder input)
|
||||
- `subject.digest` (sha256 of bundle tar) and `subject.name` (bundle_id).
|
||||
- `bundle.created` (UTC RFC3339) and `bundle.version` (semantic).
|
||||
- `pipeline.version` (build ID or git SHA) and `pipeline.inputs` (hashes of observation/linkset payloads).
|
||||
- `tenant` (lowercase) and `scope` (advisory | vex | policy | mixed).
|
||||
- `evidence_bundle` (path/doi) and `transparency` (rekor UUID or skip reason).
|
||||
- `aoc.guardrails` (boolean) and `aoc.details` (list of enforced checks).
|
||||
|
||||
## Example builder payload
|
||||
```json
|
||||
{
|
||||
"subject": {"name": "evidence-bundle-m0", "digest": "sha256:REPLACE"},
|
||||
"bundle": {"id": "evidence-bundle-m0", "version": "1.0.0", "created": "2025-11-19T00:00:00Z"},
|
||||
"pipeline": {"version": "git:abcd1234", "inputs": ["sha256:payload-hash-1", "sha256:payload-hash-2"]},
|
||||
"tenant": "demo",
|
||||
"scope": "vex",
|
||||
"evidence_bundle": "out/evidence/bundles/evidence-bundle-m0.tar.gz",
|
||||
"transparency": {"rekor_uuid": null, "skip_reason": "offline"},
|
||||
"aoc": {"guardrails": true, "details": ["schema:frozen:1.0", "limits:chunk:max=2000"]}
|
||||
}
|
||||
```
|
||||
|
||||
## Placement
|
||||
- File: `docs/modules/evidence-locker/attestation-scope-note.md` (this document).
|
||||
- Reference in Evidence Bundle changelog and sprint `Execution Log` when updated.
|
||||
|
||||
## Next steps
|
||||
- Swap placeholder digest values with real bundle hash after MIRROR-CRT-56-001 emits artefact.
|
||||
- Attach this note to Concelier/Excititor attestation tasks (CONCELIER-ATTEST-73-001/002, EXCITITOR-ATTEST-73-001/002).
|
||||
57
docs/modules/evidence-locker/evidence-bundle-v1.md
Normal file
57
docs/modules/evidence-locker/evidence-bundle-v1.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Evidence Bundle v1 Contract (2025-11-19)
|
||||
|
||||
## Scope
|
||||
Frozen contract for Evidence Bundle v1 covering AdvisoryAI/Concelier/Excititor evidence exports used by air-gap and attestation flows.
|
||||
|
||||
## Artefact layout
|
||||
- Tarball name: `evidence-bundle-<id>.tar.gz`
|
||||
- Manifest (required): `manifest.json`
|
||||
- Payloads (required): `observations.ndjson`, `linksets.ndjson`
|
||||
- Optional: `timeline.ndjson` (time anchors), `transparency.json` (Rekor UUID or skip_reason)
|
||||
- Hash list: `hashes.sha256` (sha256 of each file)
|
||||
|
||||
### manifest.json fields
|
||||
```json
|
||||
{
|
||||
"bundle_id": "evidence-bundle-m0",
|
||||
"version": "1.0.0",
|
||||
"created": "2025-11-19T00:00:00Z",
|
||||
"tenant": "demo",
|
||||
"scope": "vex",
|
||||
"inputs": ["sha256:payload-obs", "sha256:payload-linksets"],
|
||||
"aoc": {"guardrails": true, "details": ["schema:frozen:1.0", "limits:chunk:max=2000"]}
|
||||
}
|
||||
```
|
||||
|
||||
### observations.ndjson (sample record)
|
||||
```json
|
||||
{"observationId":"obs-ossl-001","advisoryId":"CVE-2024-1234","component":"pkg:deb/openssl@1.1.1w","source":"nvd","fetchedAt":"2025-11-18T12:00:00Z"}
|
||||
```
|
||||
|
||||
### linksets.ndjson (sample record)
|
||||
```json
|
||||
{"linksetId":"lnm-ossl-001","advisoryId":"CVE-2024-1234","components":["pkg:deb/openssl@1.1.1w"],"normalized":true,"createdAt":"2025-11-18T12:05:00Z"}
|
||||
```
|
||||
|
||||
### transparency.json (optional)
|
||||
```json
|
||||
{"rekor_uuid": null, "skip_reason": "offline"}
|
||||
```
|
||||
|
||||
## Determinism rules
|
||||
- All timestamps must be UTC RFC3339.
|
||||
- Ordering: sort NDJSON by `advisoryId`, then `component`, ascending.
|
||||
- Hashes: compute sha256 on raw file bytes; record in `hashes.sha256` and in manifest `inputs`.
|
||||
- Tenant must be lowercase; include in manifest and any attestation subject claims.
|
||||
|
||||
## Example bundle (sample)
|
||||
- Path: `docs/samples/evidence-bundle/evidence-bundle-m0.tar.gz`
|
||||
- SHA256: `$(cat docs/samples/evidence-bundle/evidence-bundle-m0.tar.gz.sha256 | awk '{print $1}')`
|
||||
- Contains sample manifest/observations/linksets/transparency per above.
|
||||
|
||||
## Attestation linkage
|
||||
- See `attestation-scope-note.md` for required claims.
|
||||
- Subject digest should reference the tarball sha256; include `bundle_id` and `tenant`.
|
||||
|
||||
## Change log
|
||||
- 2025-11-19: v1 frozen (initial publication). Add real sample tarball + hashes once produced.
|
||||
@@ -85,5 +85,8 @@ This note defines the deterministic, aggregation-only contract that Excititor ex
|
||||
- When mirror bundles are configured, `provenance.canonicalUri` points to the local bundle path; otherwise it is omitted.
|
||||
- All payloads are side-effect free; no remote fetches occur while streaming.
|
||||
|
||||
## Samples
|
||||
- NDJSON sample: `docs/samples/excititor/chunks-sample.ndjson` (hashes in `.sha256`) aligned to the schema above.
|
||||
|
||||
## Versioning
|
||||
- Contract version: `v1` (this document). Changes must be additive; breaking changes require `v2` path and updated doc.
|
||||
|
||||
104
docs/modules/excititor/vex_linksets_api.md
Normal file
104
docs/modules/excititor/vex_linksets_api.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# Excititor VEX linkset APIs (observations + linksets)
|
||||
|
||||
> Draft examples for Sprint 119 (EXCITITOR-LNM-21-203). Aligns with WebService endpoints implemented in `src/Excititor/StellaOps.Excititor.WebService/Program.cs`.
|
||||
|
||||
## /v1/vex/observations
|
||||
|
||||
### List
|
||||
```
|
||||
GET /v1/vex/observations?vulnerabilityId=CVE-2024-0001&productKey=pkg:maven/org.demo/app@1.2.3&providerId=ubuntu-csaf&status=affected&limit=2
|
||||
Headers:
|
||||
Authorization: Bearer <token>
|
||||
X-Tenant: default
|
||||
Response 200 (application/json):
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"tenant": "default",
|
||||
"observationId": "vex:obs:sha256:...",
|
||||
"providerId": "ubuntu-csaf",
|
||||
"document": {
|
||||
"digest": "sha256:...",
|
||||
"uri": "https://example.com/csaf/1.json",
|
||||
"signature": null
|
||||
},
|
||||
"scope": {
|
||||
"vulnerabilityId": "CVE-2024-0001",
|
||||
"productKey": "pkg:maven/org.demo/app@1.2.3"
|
||||
},
|
||||
"statements": [
|
||||
{
|
||||
"vulnerabilityId": "CVE-2024-0001",
|
||||
"productKey": "pkg:maven/org.demo/app@1.2.3",
|
||||
"status": "affected",
|
||||
"justification": {
|
||||
"type": "component_not_present",
|
||||
"reason": "Not shipped in base profile"
|
||||
},
|
||||
"signals": { "severity": { "score": 7.5 } },
|
||||
"provenance": {
|
||||
"providerId": "ubuntu-csaf",
|
||||
"sourceId": "USN-9999-1",
|
||||
"fieldMasks": ["statements"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"linkset": {
|
||||
"aliases": ["USN-9999-1"],
|
||||
"purls": ["pkg:maven/org.demo/app"],
|
||||
"cpes": [],
|
||||
"references": [{"type": "advisory", "url": "https://..."}],
|
||||
"disagreements": []
|
||||
},
|
||||
"createdAt": "2025-11-18T12:34:56Z"
|
||||
}
|
||||
],
|
||||
"nextCursor": "eyJ2dWxuZXJhYmlsaXR5SWQiOiJDVkUtMjAyNC0wMDAxIiwiY3JlYXRlZEF0IjoiMjAyNS0xMS0xOFQxMjozNDo1NloifQ=="
|
||||
}
|
||||
```
|
||||
|
||||
### Get by key
|
||||
```
|
||||
GET /v1/vex/observations/CVE-2024-0001/pkg:maven/org.demo/app@1.2.3
|
||||
Headers: Authorization + X-Tenant
|
||||
Response 200: same projection shape as list items (single object).
|
||||
```
|
||||
|
||||
## /v1/vex/linksets
|
||||
```
|
||||
GET /v1/vex/linksets?vulnerabilityId=CVE-2024-0001&productKey=pkg:maven/org.demo/app@1.2.3&status=affected&limit=2
|
||||
Headers: Authorization + X-Tenant
|
||||
Response 200:
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"linksetId": "CVE-2024-0001:pkg:maven/org.demo/app@1.2.3",
|
||||
"tenant": "default",
|
||||
"vulnerabilityId": "CVE-2024-0001",
|
||||
"productKey": "pkg:maven/org.demo/app@1.2.3",
|
||||
"providers": ["ubuntu-csaf", "suse-csaf"],
|
||||
"statuses": ["affected", "fixed"],
|
||||
"aliases": ["USN-9999-1"],
|
||||
"purls": ["pkg:maven/org.demo/app"],
|
||||
"cpes": [],
|
||||
"references": [{"type": "advisory", "url": "https://..."}],
|
||||
"disagreements": [{"providerId": "suse-csaf", "status": "fixed", "justification": null, "confidence": null}],
|
||||
"observations": [
|
||||
{"observationId": "vex:obs:...", "providerId": "ubuntu-csaf", "status": "affected", "severity": 7.5},
|
||||
{"observationId": "vex:obs:...", "providerId": "suse-csaf", "status": "fixed", "severity": null}
|
||||
],
|
||||
"createdAt": "2025-11-18T12:34:56Z"
|
||||
}
|
||||
],
|
||||
"nextCursor": null
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
- Pagination: `limit` (default 200, max 500) + `cursor` (opaque base64 of `vulnerabilityId` + `createdAt`).
|
||||
- Filters: `vulnerabilityId`, `productKey`, `providerId`, `status`; multiple query values allowed.
|
||||
- Headers: `Excititor-Results-Count`, `Excititor-Results-Cursor` (observations) and `Excititor-Results-Total` / `Excititor-Results-Truncated` (chunks) already implemented.
|
||||
- Determinism: responses sorted by `vulnerabilityId`, then `productKey`; arrays sorted lexicographically.
|
||||
|
||||
## SDK generation
|
||||
- Use this file plus `vex_observations.md` as the source of truth for SDK examples in EXCITITOR-LNM-21-203.
|
||||
30
docs/modules/mirror/milestone-0-thin-bundle.md
Normal file
30
docs/modules/mirror/milestone-0-thin-bundle.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Mirror Thin Bundle · Milestone 0 (sample)
|
||||
|
||||
## Scope
|
||||
- Provide a deterministic placeholder thin bundle so downstream air-gap/console/attestation tracks can wire references while MIRROR-CRT-56-001 code lands.
|
||||
- Sample bundle published at `out/mirror/thin/mirror-thin-m0-sample.tar.gz` (created 2025-11-19 UTC) with fixed metadata only; no advisories/policies/images included.
|
||||
|
||||
## Owners
|
||||
- Primary: Alex Kim
|
||||
- Backup: Priya Desai
|
||||
|
||||
## Artefacts
|
||||
- Bundle: `out/mirror/thin/mirror-thin-m0-sample.tar.gz`
|
||||
- SHA256: `bd1013885a27f651e28331c7a240d417d265bd411d09b51b47bd7c2196659674`
|
||||
- Manifest inside bundle: `sample-m0/manifest.json`
|
||||
- Notes: `sample-m0/README.txt`
|
||||
|
||||
## Layout (within tar.gz)
|
||||
```
|
||||
sample-m0/
|
||||
manifest.json # version, bundle_id, created, notes
|
||||
README.txt # purpose, determinism and replacement guidance
|
||||
```
|
||||
|
||||
## Refresh cadence
|
||||
- Replace this sample with real thin bundle once MIRROR-CRT-56-001 assembler emits manifests (target: 2025-11-20).
|
||||
- Maintain same path prefix `out/mirror/thin/` and update hash in this file and sprint log when refreshed.
|
||||
|
||||
## Usage
|
||||
- Downstream tasks may reference this path/hash to unblock contract wiring and CI harnesses.
|
||||
- Do not ship to customers; for internal wiring/tests only.
|
||||
34
docs/modules/mirror/thin-bundle-assembler.md
Normal file
34
docs/modules/mirror/thin-bundle-assembler.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# MIRROR-CRT-56-001 · Thin bundle assembler handoff (v0.1)
|
||||
|
||||
Purpose: unblock MIRROR-CRT-56-001 by defining expected assembler outputs so the real thin bundle can replace the milestone-0 sample.
|
||||
|
||||
## Expected outputs
|
||||
- Artifact: `out/mirror/thin/mirror-thin-v1.tar.gz`
|
||||
- Manifest: `out/mirror/thin/mirror-thin-v1.manifest.json` containing:
|
||||
- `version`: "1.0.0"
|
||||
- `created`: UTC ISO-8601
|
||||
- `layers`: array of `{ digest, size, path }`
|
||||
- `indexes`: array of `{ name, digest }` for evidence/linkset indexes
|
||||
- `hashes`: `{ tarball_sha256, manifest_sha256 }`
|
||||
- Checksums: `.sha256` files for tarball and manifest stored alongside artifacts.
|
||||
|
||||
## Assembly steps (reference for assembler owners)
|
||||
1) Produce layer tar parts deterministically (sorted entries, zeroed mtimes/uid/gid, pax headers disabled).
|
||||
2) Compose `mirror-thin-v1.tar.gz` using stable order: `manifest.json`, `layers/*`, `indexes/*`.
|
||||
3) Generate manifest JSON and compute SHA256 for both tarball and manifest; write `.sha256` files.
|
||||
4) Sign manifest (DSSE optional) and place signature next to manifest if available.
|
||||
|
||||
## Determinism requirements
|
||||
- POSIX tar with numeric owner 0:0, mtime 0, sorted paths.
|
||||
- Gzip with `--no-name` and fixed timestamp 0.
|
||||
- No duplicate files; symlinks forbidden.
|
||||
|
||||
## Evidence
|
||||
- When produced, place artefacts under `out/mirror/thin/` and add hashes to this doc.
|
||||
|
||||
## Owners
|
||||
- Mirror Creator Guild (assembler)
|
||||
- AirGap Guild (consumer)
|
||||
|
||||
## Status
|
||||
- Handoff doc published 2025-11-19; awaiting assembler output to replace milestone-0 sample.
|
||||
Reference in New Issue
Block a user