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.
Offline/determinism essentials (read first):
- Install from the curated offline kit (no network); pin SDK + tool versions in
inputs.lock. - Use DSSE-signed configs and keep signing keys in offline
~/.stellaops/keyswith short-lived tokens. - Run
dotnet format/dotnet testwith--blame-crash --blame-hangusing fixed seeds (Random(1337)) to avoid flakiness. - Capture DB/queue matrix upfront: MongoDB (pinned version), optional Postgres slices, and local cache paths; set
TZ=UTCfor all runs.
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:
src/StellaOps.Scanner.WebService/
Scanning endpoints, rule plumbing, and calls into the trust lattice.src/StellaOps.Vexer/(a.k.a. Excititor)
VEX verdict engine and trust-merge logic.src/StellaOps.Sbomer/
SBOM ingest / normalize (CycloneDX, SPDX).src/StellaOps.Authority/
Key management, DSSE/in-toto attestations, license tokens, Rekor integration.src/StellaOps.Scheduler/
Batch processing, replay orchestration.src/StellaOps.Shared/CanonicalModel/
Canonical entities & graph IDs. Read this carefully – it underpins determinism.
Starter issues to grab on day 1 (all offline-friendly):
- Add DSSE verification to a small CLI path (
stella verify --local-only). - Extend
inputs.lockexamples with a pinned scanner/DB matrix. - Write a deterministic unit test for canonical ID ordering.
- Improve
docs/cross-links (Developer Quickstart ↔ platform architecture) and ensuredocs:trailer appears in commits.
UI note: Console remains in flux; focus on backend determinism first, then follow UI sprints 0209/0215 for micro-interactions and proof-linked VEX updates.
3. Environment & DB matrix
- MongoDB: 6.0.12 (pin in
inputs.lock). - Optional Postgres slices: see sprint 340x series; keep read-only in dev until instructed.
- Offline feeds:
offline-cache-2025-11-30(scanner, advisories, VEX). - Timezone:
TZ=UTCfor all tests and tooling.
4. Secrets & signing
- Store short-lived signing keys in
~/.stellaops/keys(gitignored); never commit secrets. - Use DSSE for pack manifests and fixtures; include signer IDs.
- For Rekor: use mirrored bundle (no live log writes); verify receipts offline.
5. Contribution checklist
See docs/onboarding/contribution-checklist.md for the minimal gates (docs trailer, seeds, inputs.lock, DSSE, secrets).
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:
# 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
cp env/example.local.env .env
Key settings:
STELLAOPS_DB=MongoorPostgres.AUTHORITY_*– key material and config (see comments inexample.local.env).- Optional:
AUTHORITY_PQC=onto enable post-quantum 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
GraphRevisionIDand DSSE payload hashes.
If they differ, inspect:
- JSON canonicalization.
- Locale / culture.
- Line endings.
4.2 In-toto Chain: Source → Build → Image Attestation
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
dotnet test tests/Lattice/Lattice_VendorPlusRuntime.csproj
What it checks:
- Merge verdict is stable regardless of input set order.
- Resulting
TrustReceiptis 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
CanonicalJsonhelper whenever a payload is hashed, signed, or used for IDs. - Rules: UTF-8, sorted keys, no insignificant whitespace,
\nline endings.
5.2 DSSE Envelopes
payloadTypemust always beapplication/vnd.stellaops.trust+json.- Sign over the canonicalized bytes.
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.Nowor 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
receiptsigned by Authority, covering verdict, proof hashes, and context.
6. Daily Workflow
- Pick a focused issue (see starter tasks below).
- Write tests first, especially determinism scenarios.
- Implement changes with canonicalization boundaries explicit and signing centralized.
- Run
dotnet test --filter Category=Determinism. - Commit with the appropriate prefix (
feat(scanner):,feat(vexer):,feat(authority):) and mention the affectedGraphRevisionIDif 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.hashis 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 reportsstatus = not_affectedand the proof recordsconfigPath+observed=false. - Proof hash is deterministic and included in the DSSE receipt.
- Lattice merge flips the verdict to
not_affectedwhen the runtime/config proof weight crosses the threshold, even if the vendor saysaffected.
7.3 Authority Offline Rekor Mirror Submitter
Area: StellaOps.Authority/Rekor/RekorMirrorClient.cs
Definition of done:
RekorMode.OfflineMirrorIfAirgappedrecords canonical entries (JSON + hash path) locally.rekor syncreplays 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.Persistencerepository 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
- Non-canonical JSON (unsorted keys, extra whitespace, mixed
\r\n). - Local time creeping into proofs (
DateTime.Now). - Unstable GUIDs in tests or canonical entities.
- Unordered collections (
Dictionary<>iterations, LINQ withoutOrderBy) while hashing or serializing. - Platform drift (Windows vs Linux newline/culture differences) – always use invariant culture and
\nin canonical data.
10. Useful Commands
10.1 Determinism Pack
# Run determinism-tagged fixtures
dotnet test --filter Category=Determinism
Update golden snapshots deliberately:
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 (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:
- Read the CanonicalModel types.
- Run the determinism tests.
- Ship one of the starter tasks with deterministic, test-covered changes.
Keep everything canonical, hashable, and replayable and you’ll fit right in.