This commit is contained in:
StellaOps Bot
2025-12-09 00:20:52 +02:00
parent 3d01bf9edc
commit bc0762e97d
261 changed files with 14033 additions and 4427 deletions

View File

@@ -1,7 +1,22 @@
# ICSCISA / KISA Feed Provenance Notes (2025-11-19)
# ICSCISA / KISA Feed Provenance Notes (2025-12-08)
- Expected signing: not provided by sources; set `signature=null` and `skip_reason="unsigned"`.
- Hashing: sha256 of raw advisory payload before normalization.
- Expected signing: not provided by sources; record `signature` as `{ status: "missing", reason: "unsigned_source" }`.
- Hashing: sha256 of raw advisory payload before normalization (stored as `payload_sha256` per advisory) and sha256 of run artefacts (`hashes.sha256`).
- 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.
## Run 2025-12-08 (run_id=icscisa-kisa-20251208T0205Z)
- Artefacts: `out/feeds/icscisa-kisa/20251208/advisories.ndjson`, `delta.json`, `fetch.log`, `hashes.sha256`.
- Hashes:
- `0844c46c42461b8eeaf643c01d4cb74ef20d4eec8c984ad5e20c49d65dc57deb advisories.ndjson`
- `1273beb246754382d2e013fdc98b11b06965fb97fe9a63735b51cc949746418f delta.json`
- `8fedaa9fb2b146a1ef500b0d2e4c1592ddbc770a8f15b7d03723f8034fc12a75 fetch.log`
- Delta summary: added ICS CISA advisories `ICSA-25-123-01`, `ICSMA-25-045-01`; added KISA advisories `KISA-2025-5859`, `KISA-2025-5860`; no updates or removals; backlog window 60 days; retries 0 for both sources.
- Signature posture: both sources unsigned; all records marked `signature.missing` with reason `unsigned_source`.
- Next actions: maintain weekly cadence; staleness review on 2025-12-21 with refreshed hash manifest and retry histogram.
## CI automation
- Scheduled workflow `.gitea/workflows/icscisa-kisa-refresh.yml` runs Mondays 02:00 UTC (manual dispatch enabled) and executes `scripts/feeds/run_icscisa_kisa_refresh.py` with live fetch + offline fallback.
- Configure feed endpoints via `ICSCISA_FEED_URL` / `KISA_FEED_URL`; set `LIVE_FETCH=false` or `OFFLINE_SNAPSHOT=true` to force offline-only mode when running in sealed CI. Host override for on-prem mirrors is available via `FEED_GATEWAY_HOST` / `FEED_GATEWAY_SCHEME` (default `concelier-webservice` on the Docker network).
- Fetch log traces: `fetch.log` captures gateway (`FEED_GATEWAY_*`), effective ICS/KISA URLs, live/offline flags, and statuses so operators can verify when defaults are used vs explicit endpoints.

View File

@@ -32,8 +32,8 @@ Define a minimal, actionable plan to refresh overdue ICSCISA and KISA connectors
- Set to 2025-12-21 (two-week check from v0.2) and capture SIG verification status + open deltas.
## Actions & timeline (v0.2 refresh)
- T0 (2025-12-08): adopt SOP + field map; create delta report template; preflight cache paths.
- T0+2d (2025-12-10): run backlog reprocess, publish artefacts + hashes for both feeds; capture unsigned counts and retry reasons.
- T0 (2025-12-08): adopt SOP + field map; create delta report template; preflight cache paths. **Done** via run `icscisa-kisa-20251208T0205Z` (see run summary below).
- T0+2d (2025-12-10): run backlog reprocess, publish artefacts + hashes for both feeds; capture unsigned counts and retry reasons. **Done** in the 2025-12-08 execution (backlog window 60 days).
- T0+14d (2025-12-21): review staleness, adjust cadence if needed; reset review date and owners.
## Artefact locations
@@ -46,3 +46,18 @@ Define a minimal, actionable plan to refresh overdue ICSCISA and KISA connectors
- 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).
## Run summary (2025-12-08 · run_id=icscisa-kisa-20251208T0205Z)
- Backlog window: 60 days; cadence: weekly; start/end: 2025-12-08T02:05:00Z / 2025-12-08T02:09:30Z.
- Outputs: `out/feeds/icscisa-kisa/20251208/advisories.ndjson`, `delta.json`, `fetch.log`, `hashes.sha256`.
- Delta: ICS CISA added `ICSA-25-123-01`, `ICSMA-25-045-01`; KISA added `KISA-2025-5859`, `KISA-2025-5860`; no updates or removals.
- Hash manifest: `hashes.sha256` records advisories/delta/log digests (see provenance note).
- Signatures: none provided by sources; recorded as missing with reason `unsigned_source` (tracked in provenance note).
- Next review: 2025-12-21 (staleness guard <14 days remains satisfied after this run).
## CI automation
- Workflow: `.gitea/workflows/icscisa-kisa-refresh.yml` (cron: Mondays 02:00 UTC; also manual dispatch) running `scripts/feeds/run_icscisa_kisa_refresh.py`.
- Outputs: uploads `icscisa-kisa-<YYYYMMDD>` artifact with `advisories.ndjson`, `delta.json`, `fetch.log`, `hashes.sha256`.
- Live vs offline: defaults to live RSS fetch with offline-safe fallback; set `LIVE_FETCH=false` or `OFFLINE_SNAPSHOT=true` in dispatch inputs/environment to force offline samples. Optional feed URLs/secrets: `ICSCISA_FEED_URL`, `KISA_FEED_URL`.
- On-prem feed host: feeds are configurable via `FEED_GATEWAY_HOST`/`FEED_GATEWAY_SCHEME`. Default resolves to `http://concelier-webservice` (Docker network DNS) so on-prem deployments hit the local mirror/web service instead of the public internet.
- Fetch log traces defaults: `fetch.log` records the resolved gateway (`FEED_GATEWAY_*`) and the effective URLs used for ICS CISA and KISA. If env vars are absent, the log shows the Docker-network default so operators can confirm on-prem wiring without inspecting workflow inputs.

View File

@@ -124,6 +124,62 @@ Excititor workers now hydrate signature metadata with issuer trust data retrieve
`GET /v1/vex/statements/{advisory_key}` produces sorted JSON responses containing raw statement metadata (`issuer`, `content_hash`, `signature`), normalised tuples, and provenance pointers. Advisory AI consumes this endpoint to build retrieval contexts with explicit citations.
### 1.5 Postgres raw store (replaces Mongo/GridFS)
> Mongo/BSON/GridFS are being removed. This is the canonical design for the Postgres-backed raw store that powers `/vex/raw` and ingestion.
Schema: `vex`
- **`vex_raw_documents`** (append-only)
- `digest TEXT PRIMARY KEY``sha256:{hex}` of canonical UTF-8 JSON bytes.
- `tenant TEXT NOT NULL`
- `provider_id TEXT NOT NULL`
- `format TEXT NOT NULL CHECK (format IN ('openvex','csaf','cyclonedx','custom'))`
- `source_uri TEXT NOT NULL`, `etag TEXT NULL`
- `retrieved_at TIMESTAMPTZ NOT NULL`, `recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW()`
- `supersedes_digest TEXT NULL REFERENCES vex_raw_documents(digest)`
- `content_json JSONB NOT NULL` — canonicalised payload (truncated when blobbed)
- `content_size_bytes INT NOT NULL`
- `metadata_json JSONB NOT NULL` — statement_id, issuer, spec_version, content_type, connector version, hashes, quarantine flags
- `provenance_json JSONB NOT NULL` — DSSE/chain/rekor/trust info
- `inline_payload BOOLEAN NOT NULL DEFAULT TRUE`
- UNIQUE (`tenant`, `provider_id`, `source_uri`, `etag`)
- Indexes: `(tenant, retrieved_at DESC)`, `(tenant, provider_id, retrieved_at DESC)`, `(tenant, supersedes_digest)`, GIN on `metadata_json`, GIN on `provenance_json`.
- **`vex_raw_blobs`** (large payloads)
- `digest TEXT PRIMARY KEY REFERENCES vex_raw_documents(digest) ON DELETE CASCADE`
- `payload BYTEA NOT NULL` (canonical JSON bytes; no compression to preserve determinism)
- `payload_hash TEXT NOT NULL` (hash of stored bytes)
- **`vex_raw_attachments`** (optional future)
- `digest TEXT REFERENCES vex_raw_documents(digest) ON DELETE CASCADE`
- `name TEXT NOT NULL`, `media_type TEXT NOT NULL`
- `payload BYTEA NOT NULL`, `payload_hash TEXT NOT NULL`
- PRIMARY KEY (`digest`, `name`)
- **Observations/linksets** — use the append-only Postgres linkset schema already defined for `IAppendOnlyLinksetStore` (tables `vex_linksets`, `vex_linkset_observations`, `vex_linkset_disagreements`, `vex_linkset_mutations`) with indexes on `(tenant, vulnerability_id, product_key)` and `updated_at`.
**Canonicalisation & hashing**
1. Parse upstream JSON; sort keys; normalize newlines; encode UTF-8 without BOM. Preserve array order.
2. Compute `digest = "sha256:{hex}"` over canonical bytes.
3. If `size <= inline_threshold_bytes` (default 256 KiB) set `inline_payload=true` and store in `content_json`; otherwise store bytes in `vex_raw_blobs` and set `inline_payload=false`.
4. Persist `content_size_bytes` (pre-canonical length) and `payload_hash` for integrity.
**API mapping (replaces Mongo/BSON)**
List/query `/vex/raw` via `SELECT ... FROM vex.vex_raw_documents WHERE tenant=@t ORDER BY retrieved_at DESC, digest LIMIT @n OFFSET @offset`; cursor uses `(retrieved_at, digest)`. `GET /vex/raw/{digest}` loads the row and optional blob; `GET /vex/raw/{digest}/provenance` projects `provenance_json` + `metadata_json`. Filters (`providerId`, `format`, `since`, `until`, `supersedes`, `hasAttachments`) map to indexed predicates; JSON subfields use `metadata_json ->> 'field'`.
**Write semantics**
- `IVexRawStore` Postgres implementation enforces append-only inserts; duplicate `digest` => no-op; duplicate (`tenant`, `provider_id`, `source_uri`, `etag`) with new digest inserts a new row and sets `supersedes_digest`.
- `IVexRawWriteGuard` runs before insert; tenant is mandatory on every query and write.
**Rollout**
1. Add migration under `src/Excititor/__Libraries/StellaOps.Excititor.Storage.Postgres/Migrations` creating the tables/indexes above.
2. Implement `PostgresVexRawStore` and switch WebService/Worker DI to `AddExcititorPostgresStorage`; remove `VexMongoStorageOptions`, `IMongoDatabase`, and GridFS paths.
3. Update `/vex/raw` endpoints/tests to the Postgres store; delete Mongo fixtures once parity is green. Mark Mongo storage paths as deprecated and remove them in the next release.
---
## 2) Inputs, outputs & canonical domain

View File

@@ -56,6 +56,7 @@
- **Correlation:** Each API request includes `requestId` + `traceId` logged with events. Projector logs capture `replayId` and `rebuildReason`.
- **Timeline events:** `ledger.event.appended` and `ledger.projection.updated` are emitted as structured logs carrying `tenant`, `chainId`, `sequence`, `eventId`, `policyVersion`, `traceId`, and placeholder `evidence_ref` fields for downstream timeline consumers.
- **Secrets:** Ensure `event_body` is never logged; log only metadata/hashes.
- **Incident mode:** When incident mode is active, emit `ledger.incident.mode`, `ledger.incident.lag_trace`, `ledger.incident.conflict_snapshot`, and `ledger.incident.replay_trace` logs (with activation id, retention extension days, lag seconds, conflict reason). Snapshot TTLs inherit an incident retention extension and are annotated with `incident.*` metadata.
## 4. Alerts

View File

@@ -0,0 +1,41 @@
# Dart Analyzer Scope · SCANNER-ENG-0012 (2025-12-08)
## Goals
- Define Dart analyzer for pubspec/pub cache parity with other language analyzers.
- Keep offline-first (no `pub get`), deterministic inventories/graphs, and policy-ready signals.
## Inputs
- `pubspec.yaml` + `pubspec.lock` (dependencies, sources, sdk constraints).
- `.dart_tool/package_config.json` (resolved packages, language version, root URIs).
- AOT artifacts: `*.aot`, `*.snapshot`, `build/` outputs (record presence only).
- Optional Flutter plugins: `ios/`/`android/` platform manifests (metadata only).
## Pipeline (deterministic, offline)
1) **Normalize pubspec/pubspec.lock**:
- Parse lock entries; map sources: `hosted`, `sdk:flutter`, `git`, `path`.
- Emit PURLs (`pkg:pub/<name>@<version>`) with `source` metadata (`hosted.url`, `git.sha`, `path`).
- Enforce sorted components by name.
2) **Package config**:
- Read `.dart_tool/package_config.json`; map package `rootUri`/`packageUri` to build module graph roots.
- Capture `languageVersion` and `generated` timestamp (drop or normalize to `0001-01-01Z` for determinism).
3) **Graph builder**:
- Build dependency edges from `pubspec.lock` -> `package_config` packages; include `sdk:flutter` nodes when present.
- Record `sourceType` (hosted/git/path/sdk) for provenance.
4) **Signals**:
- `dart.sdk` requirement from `environment.sdk`; `flutter` channel/version when present.
- AOT snapshot presence flags (`aot=true`, `snapshot=true`); no binary parsing.
5) **Outputs**:
- Inventory: list of PURLs + source metadata + checksum if provided in lock (hosted `sha256`).
- Graph: edges `(package -> dependency)` sorted.
- Signals: `dart.sdkConstraint`, `flutter.sdk`, `flutter.plugins` (names only), `buildArtifacts` flags.
## Tests & fixtures
- Fixtures under `src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Dart.Tests/Fixtures/`:
- Hosted-only lockfile, git dependency, path dependency, Flutter project with plugins.
- Determinism tests: stable ordering, normalized timestamps, no network.
- Signal tests: sdk constraint extraction, AOT/snapshot flagging.
## Deliverables
- Design captured here; wire into implementation plan + sprint log.
- Analyzer to live under `StellaOps.Scanner.Analyzers.Lang.Dart` with tests mirroring fixtures.
- Offline posture: never invoke `dart pub`; rely solely on provided lock/config; error clearly when missing lock.

View File

@@ -0,0 +1,44 @@
# Deno Analyzer Scope · SCANNER-ENG-0011 (2025-12-08)
## Goals
- Deliver offline-safe Deno analyzer (lockfile/import graph/runtime signals) that matches Ruby/PHP parity bar.
- Provide deterministic SBOM/inventory outputs and capability signals consumable by Policy/Surface.
## Inputs
- `deno.json` / `deno.jsonc` (tasks, import map refs, npm bridging).
- `deno.lock` v2/v3 (modules, npm section, integrity hashes).
- Optional `import_map.json`; vendor/cache roots (`$DENO_DIR`, `vendor/`).
- CLI flags via Surface.Env: `deno.disable_npm`, `deno.vendor`, `deno.lock_path`, `deno.import_map`.
## Pipeline (deterministic, offline)
1) **Normalize config**: parse `deno.json`/jsonc; resolve `importMap` path; default to repo root import map if present. Sort keys.
2) **Lock resolver**: read `deno.lock`; emit components:
- `npm:` entries → PURL (`pkg:npm/<name>@<version>`) + integrity from `integrity`.
- `specifiers` → source→target map for transitive graph.
- `modules` (remote URLs) → canonical URL + content hash when present; mark `fetchSource: cache`.
3) **Import map & vendor**:
- Apply `imports`/`scopes` to rewrite edges before graph emission.
- If `vendor/` exists, prefer vendored paths; emit `provenance: vendor`.
4) **Graph builder**:
- Build module graph from `specifiers` + import map rewrites; emit edges `(from -> to, kind: import|dynamic|npm)`.
- Recognise `npm:` specifiers; map to npm package node.
- Stable ordering: sort by `from, to`.
5) **Runtime/capability signals**:
- Detect permissions from `tasks` (`--allow-*` flags) and `deno.json` `unstable`/`no-check`.
- Capture `nodeModulesDir` toggle to flag npm bridge.
6) **Outputs**:
- Inventory: npm components + remote module list (`digest`, `source`, `origin`).
- Graph: edges with provenance (`lockfile`, `import_map`, `vendor`).
- Signals: `deno.permissions[]`, `deno.node_compat`, `deno.unstable`.
## Tests & fixtures
- Add fixtures under `src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Fixtures/`:
- lockfile v2 + import map,
- lockfile v3 with npm section,
- vendorized project (`vendor/` present).
- Determinism assertions: sorted edges, stable hash of inventory, no network calls (enforce via stubbed fetcher).
## Deliverables
- Analyzer implementation + tests in `StellaOps.Scanner.Analyzers.Lang.Deno`.
- Doc cross-link to `docs/modules/scanner/implementation_plan.md` and sprint log.
- Offline posture: default `LIVE_FETCH=false` equivalent; rely solely on lock/import map/vendor.

View File

@@ -0,0 +1,42 @@
# Native Reachability Graph Plan (Scanner · Signals Alignment)
## Goals
- Extract native reachability graphs from ELF binaries across layers (stripped and unstripped), emitting:
- Build IDs (`.note.gnu.build-id`) and code IDs per file.
- Symbol digests (purl+symbol) and edges (callgraph) with deterministic ordering.
- Synthetic roots for `_init`, `.init_array`, `.preinit_array`, entry points.
- DSSE graph bundle per layer for Signals ingestion.
- Offline-friendly, deterministic outputs (stable ordering, UTF-8, UTC).
## Inputs
- Layered filesystem with ELF binaries and shared objects.
- Layer metadata: digests from `scanner.rootfs.layers` and `scanner.layer.archives` (when provided).
- Optional runtime proc snapshot for reconciliation (if available via Signals pipeline).
## Approach
- **Discovery**: Walk layer directories; identify ELF binaries (`e_ident`, machine, class). Record per-layer path.
- **Identifiers**: Capture build-id (hash of `.note.gnu.build-id`), fallback to SHA-256 of `.text` when absent; store code-id (PE/ELF-friendly string).
- **Symbols**: Parse `.symtab`/`.dynsym`; compute stable symbol digests (e.g., SHA-256 over symbol bytes + name); include size/address for ordering.
- **Edges**: Build callgraph from relocation/import tables and (when available) `.eh_frame`/`.plt` linkage; emit Unknown edges when target unresolved.
- **Synthetic Roots**: Insert edges from synthetic root nodes (per binary) to `_start`, `_init`, `.init_array` entries.
- **Layer Bundles**: Emit DSSE bundle per layer with edges, symbols, identifiers, and provenance (layer digest, path, sha256).
- **Determinism**: Sort by layer digest, path, symbol name; normalize paths to POSIX separators; timestamps fixed to generation time in UTC ISO-8601.
## Deliverables
- Library: `StellaOps.Scanner.Analyzers.Native` (new) with ELF reader and graph builder.
- Tests: fixtures under `src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests` using stripped/unstripped ELF samples (no network).
- DSSE bundle schema: shared constants/types reused by Signals ingestion.
- Sprint doc links: referenced from `SPRINT_0146_0001_0001_scanner_analyzer_gap_close.md`.
## Task Backlog (initial)
1) Skeleton project `StellaOps.Scanner.Analyzers.Native` + plugin registration for scanner worker.
2) ELF reader: header detection, build-id extraction, code-id calculation, section loader with deterministic sorting.
3) Symbol digests: compute `sha256(name + addr + size + binding)`; emit per-symbol evidence and purl+symbol IDs.
4) Callgraph builder: edges from PLT/relocs/imports; Unknown targets captured; synthetic roots for init arrays.
5) Layer attribution: carry layer digest/source through evidence; emit DSSE bundle per layer with signatures stubbed for now.
6) Tests/fixtures: stripped+unstripped ELF, shared objects, missing build-id, init array edges; golden JSON/NDJSON bundles.
7) Signals alignment: finalize DSSE graph schema and bundle naming; hook into reachability ingestion contract.
## Open Questions
- Final DSSE payload shape (Signals team) — currently assumed `graph.bundle` with edges, symbols, metadata.
- Whether to include debugline info for coverage (could add optional module later).***

View File

@@ -0,0 +1,40 @@
# Runtime Alignment (Scanner ↔ Zastava) · SCANNER-ENG-0014 (2025-12-08)
## Objective
Align Kubernetes/VM target coverage between Scanner and Zastava so runtime signals, job orchestration, and evidence exports stay consistent across clusters and on-prem installs.
## Scope
- Scanner: Worker runtime capture (EntryTrace), Surface.Env/FS detectors, analyzer job manifests, and policy predicates that rely on runtime/container metadata.
- Zastava: runtime observation feeds (system call/ebpf), workload labeling, and admission hooks.
## Alignment Plan
1) **Workload identity contract**
- Standardize labels/annotations for scan jobs and Zastava monitors:
- `stellaops.workload/id`, `tenant`, `project`, `component`, `channel`.
- Container image digest required; tag optional.
- Shared manifest snippet lives in `deploy/helm/stellaops` overlays; reuse in job templates.
2) **Runtime evidence channels**
- Scanner EntryTrace publishes `runtime.events` with fields: `workloadId`, `namespace`, `node`, `edgeType` (syscall/net/fs), `timestamp` (UTC, ISO-8601), `code_id` (when available).
- Zastava observers mirror the same schema on `zastava.runtime.events`; controller stitches by `workloadId` and `imageDigest`.
- Determinism: sort edge batches by `(workloadId, timestamp, edgeType)`.
3) **Kubernetes defaults**
- Namespace allowlist `scanner-runtime`/`zastava-runtime`; service accounts share RBAC for `pods/exec`, `pods/log`, `nodes/proxy` (read-only).
- Feature flags: `scanner.runtime.capture.enabled` (default false), `zastava.attach.enabled` (default false) to keep sealed-mode/offline safe.
4) **VM/bare-metal**
- Use node agent mode: Scanner jobs emit host metadata `hostId`, `osRelease`; Zastava tailers tag events with same ids.
- Shared log shipper config uses file socket paths under `/var/log/stellaops/runtime/*.ndjson`.
5) **Evidence export**
- Export Center receives combined runtime bundle with two streams: `scanner.entrytrace.ndjson`, `zastava.runtime.ndjson`; manifest includes hash of each and workload identity table.
- Offline kit: bundle path `offline/runtime/<runId>/`; deterministic manifests/hashes.
6) **SLOs & alerts**
- Target: runtime event lag < 30s P95; drop rate < 0.5%.
- Alerts wired via Prometheus: `stella_runtime_events_lag_seconds`, `stella_runtime_events_dropped_total`.
## Deliverables
- Update job/observer templates (Helm/Compose) to include shared labels and feature flags.
- Documented schema alignment (this note) referenced from sprint log.
- Tests: determinism checks on merged runtime bundle; label presence asserted in integration harness.
## Next Steps
- Wire labels/flags into `deploy/helm/stellaops` templates and Scanner Worker job manifests.
- Add integration test to ensure EntryTrace and Zastava events with same workload id are coalesced without reordering.

View File

@@ -0,0 +1,42 @@
# SwiftPM Coverage Plan · SCANNER-ENG-0013 (2025-12-08)
## Goals
- Plan Swift Package Manager coverage for Scanner: inventory, dependency graph, xcframework/binary target awareness, runtime hints.
- Keep processing offline and deterministic; no `swift package` execution.
## Inputs
- `Package.swift` (manifest) and `Package.resolved` (v2/v3 lockfile).
- `.build/checkouts/**` (optional for checksum verification only).
- Binary targets: `binaryTarget` entries, xcframeworks under `.xcframework/`.
- Platform hints: `platforms`, `cLanguageStandard`, `cxxLanguageStandard`.
## Pipeline (deterministic, offline)
1) **Resolve lockfile**:
- Parse `Package.resolved`; emit packages with identity, version, repo URL, checksum.
- PURL: `pkg:swift/<identity>@<version>`; include `vcs` metadata (git URL, revision).
- Sort packages by identity.
2) **Manifest signals**:
- Parse `Package.swift` (static parse via tree-sitter Swift or manifest JSON dump if available) to extract:
- products/targets (name, type library/test/executable).
- binary targets (path/url, checksum).
- platform minimum versions.
3) **Graph builder**:
- Edges from targets → dependencies; packages → transitive dependencies from lockfile pins.
- Mark binary targets with `provenance: binary-target` and attach checksum if supplied.
4) **Runtime hints**:
- Collect `unsafeFlags`, linker settings, `swiftSettings`/`cSettings`/`cxxSettings` indicators (e.g., `-enable-library-evolution`).
- Emit `xcframework` presence for Apple platform binaries.
5) **Outputs**:
- Inventory: Swift packages (PURL + checksum/vcs), binary targets (type=binary, checksum/path).
- Graph: package dependency edges; target-to-target edges (optional).
- Signals: platform minimums, binary target flags, unsafe flags presence.
## Tests & fixtures
- Fixtures under `src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests/Fixtures/SwiftPM/`:
- Simple library/executable, binary target with checksum, mixed platform constraints.
- Determinism: stable ordering, normalized checksums, no filesystem time dependency.
## Deliverables
- Implementation to land under `StellaOps.Scanner.Analyzers.Native` (SwiftPM module).
- Documentation cross-link to sprint log and `docs/modules/scanner/implementation_plan.md`.
- Offline posture: never invoke `swift build`; rely solely on `Package.resolved`/manifest; error clearly when lockfile missing.

View File

@@ -0,0 +1,10 @@
{
// Enable IL/dependency edge emission and entrypoint export.
"emitDependencyEdges": true,
"includeEntrypoints": true,
// Optional runtime evidence merge (NDJSON lines with package/target/reason/confidence/source).
// When provided, runtime edges are appended with prefix "edge.runtime".
"runtimeEvidencePath": "runtime-evidence.ndjson",
"runtimeEvidenceConfidence": "medium"
}

View File

@@ -0,0 +1,2 @@
{"package":"stellaops.toolkit","target":"native-lib","reason":"runtime-load","confidence":"medium","source":"trace"}
{"package":"microsoft.extensions.logging","target":"microsoft.extensions.dependencyinjection","reason":"runtime-resolve","confidence":"medium","source":"probe"}

View File

@@ -11,21 +11,24 @@ Artifacts prepared 2025-12-05 (UTC) for DSSE signing and Evidence Locker ingest:
## CI Automated Signing
The `.gitea/workflows/signals-dsse-sign.yml` workflow automates DSSE signing.
- `.gitea/workflows/signals-dsse-sign.yml` ƒ?" DSSE signing of decay/unknowns/heuristics on push or manual dispatch.
- `.gitea/workflows/signals-reachability.yml` ƒ?" reachability smoke (SIGNALS-24-004/005), DSSE signing, and optional Evidence Locker upload.
- `.gitea/workflows/signals-evidence-locker.yml` ƒ?" production re-sign + deterministic tar upload; defaults to `evidence-locker/signals/2025-12-05`.
### Prerequisites (CI Secrets)
| Secret | Description |
### Prerequisites (CI Secrets or Repo Vars)
| Secret/Var | Description |
|--------|-------------|
| `COSIGN_PRIVATE_KEY_B64` | Base64-encoded cosign private key (required for production) |
| `COSIGN_PASSWORD` | Password for encrypted key (if applicable) |
| `CI_EVIDENCE_LOCKER_TOKEN` | Token for Evidence Locker push (optional) |
| `CI_EVIDENCE_LOCKER_TOKEN` | Token for Evidence Locker push |
| `EVIDENCE_LOCKER_URL` | Base URL for locker PUT (e.g., `https://locker.example.com`) |
### Trigger
- **Automatic**: Push to `main` affecting `docs/modules/signals/**` or `tools/cosign/sign-signals.sh`
- **Manual**: Workflow dispatch with `allow_dev_key=1` for testing
- **Automatic**: Push to `main` affecting `docs/modules/signals/**`, `tools/cosign/sign-signals.sh`, or Signals sources (reachability workflow).
- **Manual**: Workflow dispatch with `allow_dev_key=1` for testing; `out_dir` input defaults to `evidence-locker/signals/2025-12-05`.
### Output
Signed artifacts uploaded as workflow artifact `signals-dsse-signed-{run}` and optionally pushed to Evidence Locker.
Signed artifacts uploaded as workflow artifacts and, when secrets/vars are present, pushed to Evidence Locker. Evidence tar SHA256 is emitted in job logs.
## Development Signing (Local Testing)