Files
git.stella-ops.org/docs/product-advisories/29-Nov-2025 - StellaOps – Mid-Level .NET Onboarding (Quick Start).md
StellaOps Bot 25254e3831 news advisories
2025-11-30 21:00:38 +02:00

19 KiB
Raw Blame History

Heres a compact, nofluff onboarding brief to get a midlevel .NET dev productive on StellaOps in a couple of days.


StellaOps MidLevel .NET Onboarding (Quick Start)

0) What youre building (context in one minute)

StellaOps is a sovereign, airgapfriendly SBOM→VEX platform written in .NET 10. Core ideas: deterministic scans, cryptographic attestations (DSSE/intoto; optional PQC), trust lattices for VEX decisions, and a replayable audit trail.


1) Repos to open first (read in this order)

  1. src/StellaOps.Scanner.WebService/ — scanning surfaces, rules plumbing, lattice calls.
  2. src/StellaOps.Vexer/ (a.k.a. Excititor) — VEX verdict engine & trustmerge logic.
  3. src/StellaOps.Sbomer/ — SBOM ingest/normalize (CycloneDX/SPDX).
  4. src/StellaOps.Authority/ — keys, attestations, license tokens, Rekor integration.
  5. src/StellaOps.Scheduler/ — batch & replay orchestration.
  6. src/StellaOps.Shared/CanonicalModel/ — canonical entities & graph IDs (read carefully).

Tip: keep docs/modules/platform/* open for protocol notes (DSSE envelopes, lattice terms).


2) Local dev up in ~1015 min

  • Prereqs: .NET 10 SDK (preview), Docker, Node (for Angular UI if needed), WSL2 optional.
  • From repo root:
# infra
docker compose -f compose/offline-kit.yml up -d  # Mongo/Postgres/Rabbit/MinIO per profile

# backend
dotnet restore
dotnet build -c Debug

# run a focused slice (scanner + authority)
dotnet run --project src/StellaOps.Authority/StellaOps.Authority.csproj
dotnet run --project src/StellaOps.Scanner.WebService/StellaOps.Scanner.WebService.csproj
  • Environment: copy env/example.local.env.env, then set STELLAOPS_DB provider (Mongo or Postgres) and AUTHORITY_* keys.

3) Deterministic testcases to run locally (prove your env is correct)

These are “golden” replays: same inputs → same graph & hashes.

  1. HelloSBOM → VEX NotAffected (Reachabilityfalse)
dotnet test tests/Determinism/Det_SbomToVex_NotAffected.csproj

Checks: identical GraphRevisionID and DSSE payload hash across two consecutive runs.

  1. Intoto chain: source→build→image attestation
dotnet test tests/Attestations/Att_InToto_Chain.csproj

Checks: DSSE envelope canonicalization stable; signature over CBORcanonical JSON matches stored hash.

  1. Lattice merge: vendor VEX + runtime signal
dotnet test tests/Lattice/Lattice_VendorPlusRuntime.csproj

Checks: merge verdict is stable with the same input set order; produces identical TrustReceipt.

If any golden snapshot differs, your clock/locale/lineendings or JSON canonicalizer is misconfigured.


4) Coding conventions (cryptographic attestations & determinism)

  • JSON: serialize with our CanonicalJson (UTF8, sorted keys, no insignificant whitespace, \n line endings).
  • DSSE: always embed payloadType = application/vnd.stellaops.trust+json.
  • Hashing: BLAKE3 for internal content addressing, SHA256 where interop requires.
  • Keys: use Authority.KeyRing provider (Ed25519 by default; PQC Dilithium optional flag AUTHORITY_PQC=on).
  • Timestamps: use Instant (UTC) with truncation to milliseconds; never DateTime.Now.
  • IDs: graph nodes use HashStableId derived from canonical bytes; never database autoinc for public IDs.
  • VEX: verdicts must include proofs[] (e.g., reachability, configguards, runtime path) and a receipt signed by Authority.
  • Repro: any function that affects verdicts must be pure or behind a deterministic adapter.

Snippet (sign a DSSE envelope deterministically):

var payload = CanonicalJson.Serialize(trustDoc);
var env = DsseEnvelope.Create("application/vnd.stellaops.trust+json", payload);
var signed = await keyRing.SignAsync(env.CanonicalizeBytes());
await rekor.SubmitAsync(signed, RekorMode.OfflineMirrorIfAirgapped);

5) Minimal daily loop

  • Pick one starter issue (below).
  • Write unit tests first; ensure golden snapshots match.
  • Run dotnet test --filter Category=Determinism.
  • Commit with feat(scanner|vexer|authority): … and include the GraphRevisionID delta in the body.

6) Three starter issues (teach the canonical data model)

A) Normalize CycloneDX components → Canonical Packages

Goal: map CycloneDX components to CanonicalPackage with stable IDs. Where: StellaOps.Sbomer + tests in tests/Determinism/Det_SbomMapping. Done when:

  • Two equivalent SBOMs (field order shuffled) map to identical package set & IDs.
  • Snapshot CanonicalPackageSet.hash is stable.
  • Edge cases: missing purl, duplicate components, case differences.

B) Implement “NotAffected by Configuration” proof

Goal: add proof generator that marks a CVE as notaffected if a config gate is off. Where: StellaOps.Vexer/Proofs/ConfigSwitchProof.cs. Done when:

  • Given FeatureX=false, CVE1234 becomes not_affected with proof payload including configPath, observed=false.
  • Deterministic proof hash and DSSE receipt exist.
  • Lattice merge keeps vendor “affected” but flips to not_affected when runtime/config proof weight > threshold.

C) Authority offline Rekor mirror submitter

Goal: if airgapped, write DSSE entries to local mirror; sync later. Where: StellaOps.Authority/Rekor/RekorMirrorClient.cs. Done when:

  • RekorMode.OfflineMirrorIfAirgapped stores canonical entry (JSON+hash path).
  • rekor sync job replays in order, preserving entry IDs.
  • Golden test ensures same input sequence → same mirror tree hash.

7) Database notes (Mongo ↔ Postgres switchability)

  • Use repository interfaces in StellaOps.Shared.Persistence.
  • Canonical/public IDs are hashderived; DB keys are implementationlocal.
  • Never rely on DB sort order for any hash or verdict; always recanonicalize before hashing.

8) Debug checklist (most common slips)

  • Noncanonical JSON (unsorted keys, trailing spaces).
  • Local time sneaking into proofs.
  • Unstable GUIDs in tests.
  • Nondeterministic enumeration over Dictionary<>.
  • Different newline conventions on Windows—enforce \n in canonical paths.

9) Useful commands

# run determinism pack
dotnet test --filter Category=Determinism

# update golden snapshots (intentional change only)
dotnet test --filter Category=Determinism -- TestRunParameters.Parameter(name=\"UpdateSnapshots\", value=\"true\")

# quick API smoke
curl -s http://localhost:5080/health
curl -s -X POST http://localhost:5081/scan -d @samples/nginx.sbom.json

# verify DSSE signature locally
dotnet run --project tools/StellaOps.Tools.Verify -- file trust.receipt.json

10) Askonce glossary

  • SBOM: software bill of materials (CycloneDX/SPDX).
  • VEX: vulnerability exploitability exchange (verdicts: affected / notaffected / underinvestigation).
  • DSSE: signed payload wrapper; we canonicalize before signing.
  • Lattice: rule system to merge proofs/verdicts from different sources deterministically.
  • GraphRevisionID: hash of the canonical trust graph; your “build number” for audits.

Want me to turn this into docs/onboarding/dev-quickstart.md plus three readytorun GitHub issues and the test scaffolds?

# StellaOps Developer Quickstart

> **Audience:** Midlevel .NET developers  
> **Goal:** Get you productive on StellaOps in 12 days, with special focus on determinism, cryptographic attestations, and the canonical data model.

---

## 1. What Youre Building (Context)

StellaOps is a sovereign, airgapfriendly platform that turns **SBOMs → VEX** with a fully **replayable, deterministic trust graph**.

Core concepts:

- **Deterministic scans:** Same inputs → same graph, hashes, and verdicts.
- **Cryptographic attestations:** DSSE/intoto envelopes, optional PQC.
- **Trust lattice:** Merges vendor VEX, runtime signals, configs, etc. into a single deterministic verdict.
- **Audit trail:** Every decision is reproducible from stored inputs and proofs.

If you think “contentaddressed trust pipeline for SBOMs + VEX,” youre in the right mental model.

---

## 2. Repository & Docs Map

Start by opening these projects **in order**:

1. `src/StellaOps.Scanner.WebService/`  
   Scanning endpoints, rule plumbing, and calls into the trust lattice.

2. `src/StellaOps.Vexer/` (a.k.a. *Excititor*)  
   VEX verdict engine and trustmerge logic.

3. `src/StellaOps.Sbomer/`  
   SBOM ingest / normalize (CycloneDX, SPDX).

4. `src/StellaOps.Authority/`  
   Key management, DSSE/intoto attestations, license tokens, Rekor integration.

5. `src/StellaOps.Scheduler/`  
   Batch processing, replay orchestration.

6. `src/StellaOps.Shared/CanonicalModel/`  
   Canonical entities & graph IDs. **Read this carefully**  it underpins determinism.

Helpful docs:

- `docs/modules/platform/*`  protocols (DSSE envelopes, lattice terms, trust receipts).
- `docs/architecture/*`  highlevel diagrams and flows (if present).

---

## 3. Local Dev Setup

### 3.1 Prerequisites

- **.NET 10 SDK** (preview as specified in repo)
- **Docker** (for DB, queues, object storage)
- **Node.js** (for Angular UI, if youre touching the frontend)
- **WSL2** (optional, but makes life easier on Windows)

### 3.2 Bring Up Infra

From the repo root:

```bash
# Bring up core infra for offline / airgap friendly dev
docker compose -f compose/offline-kit.yml up -d

This usually includes:

  • MongoDB or Postgres (configurable)
  • RabbitMQ (or equivalent queue)
  • MinIO / object storage (depending on profile)

3.3 Configure Environment

Copy the example env and tweak:

cp env/example.local.env .env

Key settings:

  • STELLAOPS_DB=Mongo or Postgres
  • AUTHORITY_* key material and config (see comments in example.local.env)
  • Optional: AUTHORITY_PQC=on to enable postquantum keys (Dilithium).

3.4 Build & Run Backend

# Restore & build everything
dotnet restore
dotnet build -c Debug

# Run a focused slice for development
dotnet run --project src/StellaOps.Authority/StellaOps.Authority.csproj
dotnet run --project src/StellaOps.Scanner.WebService/StellaOps.Scanner.WebService.csproj

Health checks (adjust ports if needed):

curl -s http://localhost:5080/health          # Authority
curl -s http://localhost:5081/health          # Scanner

4. Deterministic Sanity Tests

These tests prove your local environment is configured correctly for determinism. If any of these fail due to snapshot mismatch, fix your environment before writing new features.

4.1 SBOM → VEX “Not Affected” (Reachability False)

dotnet test tests/Determinism/Det_SbomToVex_NotAffected.csproj

What it checks:

  • Two consecutive runs with the same SBOM produce:

    • Identical GraphRevisionID
    • Identical DSSE payload hashes

If they differ, inspect:

  • JSON canonicalization
  • Locale / culture
  • Line endings

4.2 Intoto Chain: Source → Build → Image Attestation

dotnet test tests/Attestations/Att_InToto_Chain.csproj

What it checks:

  • DSSE envelope canonicalization is stable.
  • Signature over CBORcanonical JSON matches the stored hash.
  • Full intoto chain can be replayed deterministically.

4.3 Lattice Merge: Vendor VEX + Runtime Signal

dotnet test tests/Lattice/Lattice_VendorPlusRuntime.csproj

What it checks:

  • Merge verdict is stable regardless of input set order.
  • Resulting TrustReceipt is byteforbyte identical between runs.

If any “golden” snapshots differ, you likely have:

  • Noncanonical JSON
  • Unstable enumeration (e.g., iterating Dictionary<> directly)
  • Locale or newline drift

5. Coding Conventions (Determinism & Crypto)

These are nonnegotiable when working on code that affects trust graphs, proofs, or attestations.

5.1 JSON & Canonicalization

  • Use our CanonicalJson helper for anything that will be:

    • Hashed
    • Signed
    • Used as a canonical ID input
  • Rules:

    • UTF8
    • Sorted keys
    • No insignificant whitespace
    • \n line endings (enforced for canonical paths)

5.2 DSSE Envelopes

  • payloadType must always be:

    • application/vnd.stellaops.trust+json
  • Envelopes are signed over the canonicalized bytes of the payload.

Example:

var payload = CanonicalJson.Serialize(trustDoc);
var env = DsseEnvelope.Create("application/vnd.stellaops.trust+json", payload);
var signed = await keyRing.SignAsync(env.CanonicalizeBytes());
await rekor.SubmitAsync(signed, RekorMode.OfflineMirrorIfAirgapped);

5.3 Hashing

  • Internal content addressing: BLAKE3
  • External / interop where required: SHA256

Never mix algorithms for the same ID type.

5.4 Keys & Algorithms

  • Default signatures: Ed25519 via Authority.KeyRing
  • Optional PQC: Dilithium when AUTHORITY_PQC=on
  • Never manage keys directly always use the keyring abstraction.

5.5 Time & Clocks

  • Use Instant (UTC) / DateTimeOffset in UTC.
  • Truncate to milliseconds for anything that ends up in canonical data.
  • Never use DateTime.Now or local time in trustcritical code.

5.6 IDs & Graph Nodes

  • Public / canonical IDs are derived from hashes of canonical bytes.
  • DB primary keys are implementation details; do not leak them externally.
  • Do not depend on DB autoincrement or sort order for anything that affects hashing.

5.7 VEX Verdicts

Every VEX verdict must:

  • Be backed by proofs[] (e.g., reachability analysis, config guards, runtime path).

  • Emit a receipt signed by Authority, wrapping:

    • Verdict
    • Proof hashes
    • Context (component, vulnerability, scope, etc.)

6. Daily Workflow

A minimal loop that keeps you aligned with the platforms guarantees:

  1. Pick a focused issue (see starter tasks below).

  2. Write tests first, especially determinism tests where applicable.

  3. Implement the change, keeping:

    • Canonicalization boundaries explicit
    • Hashing and signing centralized
  4. Run:

    dotnet test --filter Category=Determinism
    
  5. Commit using:

    • feat(scanner): ...
    • feat(vexer): ...
    • feat(authority): ...
    • etc.

    Include the affected GraphRevisionID in the commit body when relevant to trustgraph changes.


7. Suggested Starter Tasks

These are good first issues that teach the canonical model and determinism expectations.

7.1 Normalize CycloneDX Components → Canonical Packages

Goal: Map CycloneDX components to our CanonicalPackage model with stable IDs.

  • Area: StellaOps.Sbomer
  • Tests: tests/Determinism/Det_SbomMapping

Definition of done:

  • Two equivalent SBOMs (only field order differs) produce:

    • Identical package sets
    • Identical canonical package IDs
  • CanonicalPackageSet.hash is stable.

  • Edge cases handled:

    • Missing purl
    • Duplicate components
    • Case differences in names or versions

7.2 Implement “NotAffected by Configuration” Proof

Goal: Add proof generator that marks a CVE as not_affected when a config gate disables the vulnerable path.

  • Area: StellaOps.Vexer/Proofs/ConfigSwitchProof.cs

Definition of done:

  • Given FeatureX=false, CVE1234 yields verdict:

    • status = not_affected

    • proofs[] includes a ConfigSwitchProof with:

      • configPath
      • observed=false
  • Proof is hashed deterministically and included in the DSSE receipt.

  • Lattice merge behavior:

    • Vendor verdict: affected
    • Runtime/config proof weight > threshold → merged verdict becomes not_affected deterministically.

7.3 Authority Offline Rekor Mirror Submitter

Goal: Support airgapped mode: DSSE entries are written to a local Rekor mirror and synced later.

  • Area: StellaOps.Authority/Rekor/RekorMirrorClient.cs

Definition of done:

  • RekorMode.OfflineMirrorIfAirgapped:

    • Stores canonical entries (JSON + hashbased path) on disk / object store.
  • A rekor sync background job (or CLI) replays entries in order to the real Rekor instance.

  • Determinism test:

    • Same input DSSE sequence → same mirror tree hash and Rekor entry order.

8. Database Notes (Mongo ↔ Postgres)

StellaOps is designed to be DBagnostic.

  • Use repository interfaces from StellaOps.Shared.Persistence.

  • Keep canonical/public IDs hashderived; DB keys are internal.

  • Do not depend on DB sort order for anything that:

    • Affects hashes
    • Affects verdicts
    • Ends up in canonical data

If you need ordering, sort after canonicalization using deterministic criteria.


9. Common Pitfalls & Debug Checklist

When a determinism test fails, look for these first:

  1. Noncanonical JSON

    • Unsorted keys
    • Extra whitespace
    • Mixed \r\n vs \n line endings
  2. Local Time Leaks

    • Any DateTime.Now or local time in proofs or receipts.
  3. Random / Unstable IDs

    • New GUIDs in tests or canonical entities.
    • Autoincrement IDs leaking into hashes.
  4. Unordered Collections

    • Iterating over Dictionary<> or HashSet<> without ordering.
    • Using LINQ without explicit OrderBy when hashing or serializing.
  5. Platform Differences

    • Windows vs Linux newline differences.
    • Locale differences (, vs . for decimals, etc.) always use invariant culture for canonical data.

10. Useful Commands

10.1 Determinism Pack

# Run only determinismtagged tests
dotnet test --filter Category=Determinism

Update golden snapshots when you intend to change canonical behavior:

dotnet test --filter Category=Determinism -- \
  TestRunParameters.Parameter(name="UpdateSnapshots", value="true")

10.2 Quick API Smoke

curl -s http://localhost:5080/health

curl -s -X POST \
  http://localhost:5081/scan \
  -H "Content-Type: application/json" \
  -d @samples/nginx.sbom.json

10.3 Verify DSSE Signature Locally

dotnet run --project tools/StellaOps.Tools.Verify -- file trust.receipt.json

11. Glossary (AskOnce)

  • SBOM Software Bill of Materials (CycloneDX/SPDX).

  • VEX Vulnerability Exploitability eXchange:

    • Verdicts like affected, not_affected, under_investigation.
  • DSSE Dead Simple Signing Envelope:

    • Wrapper around payload + signature; we sign canonical bytes.
  • Intoto Supplychain attestation framework; we use it for source→build→artifact chains.

  • Lattice Rule system that merges multiple verdicts/proofs into a single deterministic verdict.

  • GraphRevisionID Hash of the canonical trust graph at a point in time; acts like a build number for audits.


Welcome aboard. Your best “map” into the system is:

  1. Read CanonicalModel types.
  2. Run the determinism tests.
  3. Pick one of the starter tasks and ship a small, welltested change.

If you keep everything canonical, hashable, and replayable, youll fit right in.