327 lines
10 KiB
Markdown
327 lines
10 KiB
Markdown
# StellaOps Developer Quickstart
|
||
|
||
> **Audience:** Mid-level .NET developers
|
||
> **Goal:** Get you productive on StellaOps in 1–2 days, with special focus on determinism, cryptographic attestations, and the canonical data model.
|
||
|
||
---
|
||
|
||
This quickstart mirrors the 29-Nov-2025 Developer Onboarding advisory (`docs/product-advisories/29-Nov-2025 - StellaOps – Mid-Level .NET Onboarding (Quick Start).md`) and keeps the determinism-first guidance in sync with that release note.
|
||
|
||
## 1. What You’re Building (Context)
|
||
|
||
StellaOps is a sovereign, air-gap-friendly 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/in-toto 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 “content-addressed trust pipeline for SBOMs + VEX,” you’re 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 trust-merge logic.
|
||
3. `src/StellaOps.Sbomer/`
|
||
SBOM ingest / normalize (CycloneDX, SPDX).
|
||
4. `src/StellaOps.Authority/`
|
||
Key management, DSSE/in-toto 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/*` – high-level diagrams and flows.
|
||
|
||
---
|
||
|
||
## 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 you’re touching the frontend).
|
||
- **WSL2** (optional but convenient on Windows).
|
||
|
||
### 3.2 Bring Up Infra
|
||
|
||
From the repo root:
|
||
|
||
```bash
|
||
# Bring up core infra for offline / air-gap 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
|
||
|
||
```bash
|
||
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 post-quantum keys (Dilithium).
|
||
|
||
### 3.4 Build & Run Backend
|
||
|
||
```bash
|
||
# 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):
|
||
|
||
```bash
|
||
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)
|
||
|
||
```bash
|
||
dotnet test tests/Determinism/Det_SbomToVex_NotAffected.csproj
|
||
```
|
||
|
||
**What it checks:**
|
||
|
||
- Two consecutive runs with the same SBOM produce identical `GraphRevisionID` and DSSE payload hashes.
|
||
|
||
If they differ, inspect:
|
||
|
||
- JSON canonicalization.
|
||
- Locale / culture.
|
||
- Line endings.
|
||
|
||
### 4.2 In-toto Chain: Source → Build → Image Attestation
|
||
|
||
```bash
|
||
dotnet test tests/Attestations/Att_InToto_Chain.csproj
|
||
```
|
||
|
||
**What it checks:**
|
||
|
||
- DSSE envelope canonicalization is stable.
|
||
- Signature over CBOR-canonical JSON matches the stored hash.
|
||
- Full in-toto chain can be replayed deterministically.
|
||
|
||
### 4.3 Lattice Merge: Vendor VEX + Runtime Signal
|
||
|
||
```bash
|
||
dotnet test tests/Lattice/Lattice_VendorPlusRuntime.csproj
|
||
```
|
||
|
||
**What it checks:**
|
||
|
||
- Merge verdict is stable regardless of input set order.
|
||
- Resulting `TrustReceipt` is byte-for-byte identical between runs.
|
||
|
||
If any “golden” snapshots differ, you likely have:
|
||
|
||
- Non-canonical JSON.
|
||
- Unstable enumeration (e.g., iterating `Dictionary<>` directly).
|
||
- Locale or newline drift.
|
||
|
||
---
|
||
|
||
## 5. Coding Conventions (Determinism & Crypto)
|
||
|
||
These are **non-negotiable** in code that affects trust graphs, proofs, or attestations.
|
||
|
||
### 5.1 JSON & Canonicalization
|
||
|
||
- Use the **`CanonicalJson`** helper whenever a payload is hashed, signed, or used for IDs.
|
||
- Rules: UTF-8, sorted keys, no insignificant whitespace, `\n` line endings.
|
||
|
||
### 5.2 DSSE Envelopes
|
||
|
||
- `payloadType` must always be `application/vnd.stellaops.trust+json`.
|
||
- Sign over the canonicalized bytes.
|
||
|
||
```csharp
|
||
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
|
||
|
||
- **BLAKE3** for internal content addressing.
|
||
- **SHA-256** where interop demands it.
|
||
- Never mix algorithms within the same ID type.
|
||
|
||
### 5.4 Keys & Algorithms
|
||
|
||
- Default signatures: **Ed25519** via `Authority.KeyRing`.
|
||
- Optional PQC: **Dilithium** when `AUTHORITY_PQC=on`.
|
||
- Always go through the keyring abstraction; never manage raw keys manually.
|
||
|
||
### 5.5 Time & Clocks
|
||
|
||
- Use `Instant`/`DateTimeOffset` (UTC), truncated to milliseconds.
|
||
- Never use `DateTime.Now` or local clocks in canonical data.
|
||
|
||
### 5.6 IDs & Graph Nodes
|
||
|
||
- Canonical/public IDs derive from hashes of canonical bytes.
|
||
- DB primary keys are implementation details.
|
||
- Do not depend on DB auto-increment or implicit sort order when hashing.
|
||
|
||
### 5.7 VEX Verdicts
|
||
|
||
Every VEX verdict must:
|
||
|
||
- Carry `proofs[]` (reachability, config guards, runtime paths).
|
||
- Emit a `receipt` signed by Authority, covering verdict, proof hashes, and context.
|
||
|
||
---
|
||
|
||
## 6. Daily Workflow
|
||
|
||
1. Pick a focused issue (see starter tasks below).
|
||
2. Write tests first, especially determinism scenarios.
|
||
3. Implement changes with canonicalization boundaries explicit and signing centralized.
|
||
4. Run `dotnet test --filter Category=Determinism`.
|
||
5. Commit with the appropriate prefix (`feat(scanner):`, `feat(vexer):`, `feat(authority):`) and mention the affected `GraphRevisionID` if your change alters the trust graph.
|
||
|
||
---
|
||
|
||
## 7. Suggested Starter Tasks
|
||
|
||
These introduce the canonical data model and determinism mindset.
|
||
|
||
### 7.1 Normalize CycloneDX Components → Canonical Packages
|
||
|
||
**Area:** `StellaOps.Sbomer`
|
||
|
||
**Tests:** `tests/Determinism/Det_SbomMapping`
|
||
|
||
**Definition of done:**
|
||
|
||
- Equivalent SBOMs (even if fields shuffle) yield identical package sets and canonical IDs.
|
||
- `CanonicalPackageSet.hash` is stable.
|
||
- Edge cases covered: missing `purl`, duplicate components, case variation.
|
||
|
||
### 7.2 Implement “Not-Affected by Configuration” Proof
|
||
|
||
**Area:** `StellaOps.Vexer/Proofs/ConfigSwitchProof.cs`
|
||
|
||
**Definition of done:**
|
||
|
||
- With `FeatureX=false`, CVE-1234 reports `status = not_affected` and the proof records `configPath` + `observed=false`.
|
||
- Proof hash is deterministic and included in the DSSE receipt.
|
||
- Lattice merge flips the verdict to `not_affected` when the runtime/config proof weight crosses the threshold, even if the vendor says `affected`.
|
||
|
||
### 7.3 Authority Offline Rekor Mirror Submitter
|
||
|
||
**Area:** `StellaOps.Authority/Rekor/RekorMirrorClient.cs`
|
||
|
||
**Definition of done:**
|
||
|
||
- `RekorMode.OfflineMirrorIfAirgapped` records canonical entries (JSON + hash path) locally.
|
||
- `rekor sync` replays entries in order, preserving entry IDs.
|
||
- Golden test ensures the same input sequence → same mirror tree hash.
|
||
|
||
---
|
||
|
||
## 8. Database Notes (Mongo ↔ Postgres)
|
||
|
||
- Use `StellaOps.Shared.Persistence` repository interfaces.
|
||
- Canonical/public IDs are hash-derived; DB keys are internal details.
|
||
- Never rely on DB sort order for anything that affects hashes or verdicts; re-canonicalize before hashing and apply deterministic ordering afterwards.
|
||
|
||
---
|
||
|
||
## 9. Common Pitfalls
|
||
|
||
1. Non-canonical JSON (unsorted keys, extra whitespace, mixed `\r\n`).
|
||
2. Local time creeping into proofs (`DateTime.Now`).
|
||
3. Unstable GUIDs in tests or canonical entities.
|
||
4. Unordered collections (`Dictionary<>` iterations, LINQ without `OrderBy`) while hashing or serializing.
|
||
5. Platform drift (Windows vs Linux newline/culture differences) – always use invariant culture and `\n` in canonical data.
|
||
|
||
---
|
||
|
||
## 10. Useful Commands
|
||
|
||
### 10.1 Determinism Pack
|
||
|
||
```bash
|
||
# Run determinism-tagged fixtures
|
||
dotnet test --filter Category=Determinism
|
||
```
|
||
|
||
Update golden snapshots deliberately:
|
||
|
||
```bash
|
||
dotnet test --filter Category=Determinism -- \
|
||
TestRunParameters.Parameter(name="UpdateSnapshots", value="true")
|
||
```
|
||
|
||
### 10.2 Quick API Smoke
|
||
|
||
```bash
|
||
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
|
||
|
||
```bash
|
||
dotnet run --project tools/StellaOps.Tools.Verify -- file trust.receipt.json
|
||
```
|
||
|
||
---
|
||
|
||
## 11. Glossary (Ask-Once)
|
||
|
||
- **SBOM** – Software Bill of Materials (CycloneDX/SPDX).
|
||
- **VEX** – Vulnerability Exploitability eXchange: verdicts include `affected`, `not_affected`, `under_investigation`.
|
||
- **DSSE** – Dead Simple Signing Envelope; we sign canonical bytes.
|
||
- **In-toto** – Supply-chain attestation framework for source → build → artifact chains.
|
||
- **Lattice** – Rule system merging multiple verdicts/proofs into deterministic outcomes.
|
||
- **GraphRevisionID** – Hash of the canonical trust graph; acts like a build number for audits.
|
||
|
||
Welcome aboard. Your best “map” is:
|
||
|
||
1. Read the CanonicalModel types.
|
||
2. Run the determinism tests.
|
||
3. Ship one of the starter tasks with deterministic, test-covered changes.
|
||
|
||
Keep everything **canonical, hashable, and replayable** and you’ll fit right in.
|