Files
git.stella-ops.org/CLAUDE.md
2026-01-05 16:02:11 +02:00

28 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

StellaOps is a self-hostable, sovereign container-security platform released under AGPL-3.0-or-later. It provides reproducible vulnerability scanning with VEX-first decisioning, SBOM generation (SPDX 3.0.1 and CycloneDX 1.7), in-toto/DSSE attestations, and optional Sigstore Rekor transparency. The platform is designed for offline/air-gapped operation with regional crypto support (eIDAS/FIPS/GOST/SM).

Build Commands

# Build the entire solution
dotnet build src/StellaOps.sln

# Build a specific module (example: Concelier web service)
dotnet build src/Concelier/StellaOps.Concelier.WebService/StellaOps.Concelier.WebService.csproj

# Run the Concelier web service
dotnet run --project src/Concelier/StellaOps.Concelier.WebService

# Build CLI for current platform
dotnet publish src/Cli/StellaOps.Cli/StellaOps.Cli.csproj --configuration Release

# Build CLI for specific runtime (linux-x64, linux-arm64, osx-x64, osx-arm64, win-x64)
dotnet publish src/Cli/StellaOps.Cli/StellaOps.Cli.csproj --configuration Release --runtime linux-x64

Test Commands

# Run all tests
dotnet test src/StellaOps.sln

# Run tests for a specific project
dotnet test src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/StellaOps.Scanner.WebService.Tests.csproj

# Run a single test by filter
dotnet test --filter "FullyQualifiedName~TestMethodName"

# Run tests with verbosity
dotnet test src/StellaOps.sln --verbosity normal

Note: Integration tests use Testcontainers for PostgreSQL. Ensure Docker is running before executing tests.

Linting and Validation

# Lint OpenAPI specs
npm run api:lint

# Validate attestation schemas
npm run docs:attestor:validate

# Validate Helm chart
helm lint devops/helm/stellaops

# Validate Docker Compose profiles
./devops/scripts/validate-compose.sh

# Run local CI tests
./devops/scripts/test-local.sh

Architecture

Technology Stack

  • Runtime: .NET 10 (net10.0) with latest C# preview features
  • Frontend: Angular v17 (in src/Web/StellaOps.Web)
  • Database: PostgreSQL (≥16) with per-module schema isolation; see docs/db/ for specification
  • Testing: xUnit with Testcontainers (PostgreSQL), Moq, Microsoft.AspNetCore.Mvc.Testing
  • Observability: Structured logging, OpenTelemetry traces
  • NuGet: Uses standard NuGet feeds configured in nuget.config (dotnet-public, nuget-mirror, nuget.org)

Module Structure

The codebase follows a monorepo pattern with modules under src/:

Module Path Purpose
Core Platform
Authority src/Authority/ Authentication, authorization, OAuth/OIDC, DPoP
Gateway src/Gateway/ API gateway with routing and transport abstraction
Router src/Router/ Transport-agnostic messaging (TCP/TLS/UDP/RabbitMQ/Valkey)
Data Ingestion
Concelier src/Concelier/ Vulnerability advisory ingestion and merge engine
Excititor src/Excititor/ VEX document ingestion and export
VexLens src/VexLens/ VEX consensus computation across issuers
VexHub src/VexHub/ VEX distribution and exchange hub
IssuerDirectory src/IssuerDirectory/ Issuer trust registry (CSAF publishers)
Feedser src/Feedser/ Evidence collection library for backport detection
Mirror src/Mirror/ Vulnerability feed mirror and distribution
Scanning & Analysis
Scanner src/Scanner/ Container scanning with SBOM generation (11 language analyzers)
BinaryIndex src/BinaryIndex/ Binary identity extraction and fingerprinting
AdvisoryAI src/AdvisoryAI/ AI-assisted advisory analysis
ReachGraph src/ReachGraph/ Reachability graph service
Symbols src/Symbols/ Symbol resolution and debug information
Artifacts & Evidence
Attestor src/Attestor/ in-toto/DSSE attestation generation
Signer src/Signer/ Cryptographic signing operations
SbomService src/SbomService/ SBOM storage, versioning, and lineage ledger
EvidenceLocker src/EvidenceLocker/ Sealed evidence storage and export
ExportCenter src/ExportCenter/ Batch export and report generation
Provenance src/Provenance/ SLSA/DSSE attestation tooling
Policy & Risk
Policy src/Policy/ Policy engine with K4 lattice logic
RiskEngine src/RiskEngine/ Risk scoring runtime with pluggable providers
VulnExplorer src/VulnExplorer/ Vulnerability exploration and triage UI backend
Unknowns src/Unknowns/ Unknown component and symbol tracking
Operations
Scheduler src/Scheduler/ Job scheduling and queue management
Orchestrator src/Orchestrator/ Workflow orchestration and task coordination
TaskRunner src/TaskRunner/ Task pack execution engine
Notify src/Notify/ Notification toolkit (Email, Slack, Teams, Webhooks)
Notifier src/Notifier/ Notifications Studio host
PacksRegistry src/PacksRegistry/ Task packs registry and distribution
TimelineIndexer src/TimelineIndexer/ Timeline event indexing
Replay src/Replay/ Deterministic replay engine
Integration
CLI src/Cli/ Command-line interface (Native AOT)
Zastava src/Zastava/ Container registry webhook observer
Web src/Web/ Angular 17 frontend SPA
API src/Api/ OpenAPI contracts and governance
Infrastructure
Cryptography src/Cryptography/ Crypto plugins (FIPS, eIDAS, GOST, SM, PQ)
Telemetry src/Telemetry/ OpenTelemetry traces, metrics, logging
Graph src/Graph/ Call graph and reachability data structures
Signals src/Signals/ Runtime signal collection and correlation
AirGap src/AirGap/ Air-gapped deployment support
AOC src/Aoc/ Append-Only Contract enforcement (Roslyn analyzers)

Note: See docs/modules/<module>/architecture.md for detailed module dossiers.

Code Organization Patterns

  • Libraries: src/<Module>/__Libraries/StellaOps.<Module>.*
  • Tests: src/<Module>/__Tests/StellaOps.<Module>.*.Tests/
  • Plugins: Follow naming StellaOps.<Module>.Connector.* or StellaOps.<Module>.Plugin.*
  • Shared test infrastructure: StellaOps.Concelier.Testing and StellaOps.Infrastructure.Postgres.Testing provide PostgreSQL fixtures

Naming Conventions

  • All modules are .NET 10 projects, except the UI (Angular)
  • Module projects: StellaOps.<ModuleName>
  • Libraries/plugins common to multiple modules: StellaOps.<LibraryOrPlugin>
  • Each project lives in its own folder

Key Glossary

  • OVAL — Vendor/distro security definition format; authoritative for OS packages
  • NEVRA / EVR — RPM and Debian version semantics for OS packages
  • PURL / SemVer — Coordinates and version semantics for OSS ecosystems
  • KEV — Known Exploited Vulnerabilities (flag only)

Coding Rules

Core Principles

  1. Determinism: Outputs must be reproducible - stable ordering, UTC ISO-8601 timestamps, immutable NDJSON where applicable
  2. Offline-first: Remote host allowlist, strict schema validation, avoid hard-coded external dependencies unless explicitly allowed
  3. Plugin architecture: Concelier connectors, Authority plugins, Scanner analyzers are all plugin-based
  4. VEX-first decisioning: Exploitability modeled in OpenVEX with lattice logic for stable outcomes

Implementation Guidelines

  • Follow .NET 10 and Angular v17 best practices
  • Apply SOLID principles (SRP, OCP, LSP, ISP, DIP) when designing services, libraries, and tests
  • Keep in mind the nuget versions are controlled centrally by src/Directory* files, not via csproj
  • Maximise reuse and composability
  • Never regress determinism, ordering, or precedence
  • Every change must be accompanied by or covered by tests
  • Gated LLM usage (only where explicitly configured)

Test Layout

  • Module tests: src/<Module>/__Tests/StellaOps.<Module>.<Component>.Tests/
  • Global tests: src/__Tests/{Category}/ (Integration, Acceptance, Load, Security, Chaos, E2E, etc.)
  • Shared testing libraries: src/__Tests/__Libraries/StellaOps.*.Testing/
  • Benchmarks & golden corpus: src/__Tests/__Benchmarks/
  • Ground truth datasets: src/__Tests/__Datasets/
  • Tests use xUnit, Testcontainers for PostgreSQL integration tests
  • See src/__Tests/AGENTS.md for detailed test infrastructure guidance

Code Quality & Determinism Rules

These rules were distilled from a comprehensive audit of 324+ projects. They address the most common recurring issues and must be followed by all implementers.

8.1) Compiler & Warning Discipline

Rule Guidance
Enable TreatWarningsAsErrors All projects must set <TreatWarningsAsErrors>true</TreatWarningsAsErrors> in the .csproj or via Directory.Build.props. Relaxed warnings mask regressions and code quality drift.
<!-- In .csproj or Directory.Build.props -->
<PropertyGroup>
  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

8.2) Deterministic Time & ID Generation

Rule Guidance
Inject TimeProvider / ID generators Never use DateTime.UtcNow, DateTimeOffset.UtcNow, Guid.NewGuid(), or Random.Shared directly in production code. Inject TimeProvider (or ITimeProvider) and IGuidGenerator abstractions.
// BAD - nondeterministic, hard to test
public class BadService
{
    public Record CreateRecord() => new Record
    {
        Id = Guid.NewGuid(),
        CreatedAt = DateTimeOffset.UtcNow
    };
}

// GOOD - injectable, testable, deterministic
public class GoodService(TimeProvider timeProvider, IGuidGenerator guidGenerator)
{
    public Record CreateRecord() => new Record
    {
        Id = guidGenerator.NewGuid(),
        CreatedAt = timeProvider.GetUtcNow()
    };
}

8.2.1) Resolver Version Tracking

Rule Guidance
Include resolver/engine version in snapshots For strict reproducibility verification, include the resolver or engine version digest in KnowledgeSnapshot and similar input manifests. This ensures that identical inputs processed by different engine versions can be detected and flagged.
// BAD - snapshot missing engine version
public sealed record KnowledgeSnapshot
{
    public required ImmutableArray<SbomRef> Sboms { get; init; }
    public required ImmutableArray<VexDocRef> VexDocuments { get; init; }
    // Missing: engine version that produced the verdict
}

// GOOD - includes engine version for reproducibility verification
public sealed record KnowledgeSnapshot
{
    public required ImmutableArray<SbomRef> Sboms { get; init; }
    public required ImmutableArray<VexDocRef> VexDocuments { get; init; }
    public required EngineVersionRef EngineVersion { get; init; }
}

public sealed record EngineVersionRef(
    string EngineName,      // e.g., "VexConsensusEngine"
    string Version,         // e.g., "2.1.0"
    string SourceDigest);   // SHA-256 of engine source or build artifact

8.3) ASCII-Only Output

Rule Guidance
No mojibake or non-ASCII glyphs Use ASCII-only characters in comments, output strings, and log messages. No ƒ?, , , , , or box-drawing characters. When Unicode is truly required, use explicit escapes (\uXXXX) and document the rationale.
// BAD - non-ASCII glyphs
Console.WriteLine("✓ Success → proceeding");
// or mojibake comments like: // ƒ+ validation passed

// GOOD - ASCII only
Console.WriteLine("[OK] Success - proceeding");
// Comment: validation passed

8.4) Test Project Requirements

Rule Guidance
Every library needs tests All production libraries/services must have a corresponding *.Tests project covering: (a) happy paths, (b) error/edge cases, (c) determinism, and (d) serialization round-trips.
src/
  Scanner/
    __Libraries/
      StellaOps.Scanner.Core/
    __Tests/
      StellaOps.Scanner.Core.Tests/   <-- Required

8.5) Culture-Invariant Parsing

Rule Guidance
Use InvariantCulture Always use CultureInfo.InvariantCulture for parsing and formatting dates, numbers, percentages, and any string that will be persisted, hashed, or compared. Current culture causes locale-dependent, nondeterministic behavior.
// BAD - culture-sensitive
var value = double.Parse(input);
var formatted = percentage.ToString("P2");

// GOOD - invariant culture
var value = double.Parse(input, CultureInfo.InvariantCulture);
var formatted = percentage.ToString("P2", CultureInfo.InvariantCulture);

8.6) DSSE PAE Consistency

Rule Guidance
Single DSSE PAE implementation Use one spec-compliant DSSE PAE helper (StellaOps.Attestation.DsseHelper or equivalent) across the codebase. DSSE v1 requires ASCII decimal lengths and space separators. Never reimplement PAE encoding.
// BAD - custom PAE implementation
var pae = $"DSSEv1 {payloadType.Length} {payloadType} {payload.Length} ";

// GOOD - use shared helper
var pae = DsseHelper.ComputePreAuthenticationEncoding(payloadType, payload);

8.7) RFC 8785 JSON Canonicalization

Rule Guidance
Use shared RFC 8785 canonicalizer For digest/signature inputs, use a shared RFC 8785-compliant JSON canonicalizer with: sorted keys, minimal escaping per spec, no exponent notation for numbers, no trailing/leading zeros. Do not use UnsafeRelaxedJsonEscaping or CamelCase naming for canonical outputs.
// BAD - non-canonical JSON
var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});

// GOOD - use shared canonicalizer
var canonicalJson = CanonicalJsonSerializer.Serialize(obj);
var digest = ComputeDigest(canonicalJson);

8.8) CancellationToken Propagation

Rule Guidance
Propagate CancellationToken Always propagate CancellationToken through async call chains. Never use CancellationToken.None in production code except at entry points where no token is available.
// BAD - ignores cancellation
public async Task ProcessAsync(CancellationToken ct)
{
    await _repository.SaveAsync(data, CancellationToken.None);  // Wrong!
    await Task.Delay(1000);  // Missing ct
}

// GOOD - propagates cancellation
public async Task ProcessAsync(CancellationToken ct)
{
    await _repository.SaveAsync(data, ct);
    await Task.Delay(1000, ct);
}

8.9) HttpClient via Factory

Rule Guidance
Use IHttpClientFactory Never new HttpClient() directly. Use IHttpClientFactory with configured timeouts and retry policies via Polly or Microsoft.Extensions.Http.Resilience. Direct HttpClient creation risks socket exhaustion.
// BAD - direct instantiation
public class BadService
{
    public async Task FetchAsync()
    {
        using var client = new HttpClient();  // Socket exhaustion risk
        await client.GetAsync(url);
    }
}

// GOOD - factory with resilience
public class GoodService(IHttpClientFactory httpClientFactory)
{
    public async Task FetchAsync()
    {
        var client = httpClientFactory.CreateClient("MyApi");
        await client.GetAsync(url);
    }
}

// Registration with timeout/retry
services.AddHttpClient("MyApi")
    .ConfigureHttpClient(c => c.Timeout = TimeSpan.FromSeconds(30))
    .AddStandardResilienceHandler();

8.10) Path/Root Resolution

Rule Guidance
Explicit CLI options for paths Do not derive repository root from AppContext.BaseDirectory with parent directory walks. Use explicit CLI options (--repo-root) or environment variables. Provide sensible defaults with clear error messages.
// BAD - fragile parent walks
var repoRoot = Path.GetFullPath(Path.Combine(
    AppContext.BaseDirectory, "..", "..", "..", ".."));

// GOOD - explicit option with fallback
[Option("--repo-root", Description = "Repository root path")]
public string? RepoRoot { get; set; }

public string GetRepoRoot() =>
    RepoRoot ?? Environment.GetEnvironmentVariable("STELLAOPS_REPO_ROOT")
    ?? throw new InvalidOperationException("Repository root not specified. Use --repo-root or set STELLAOPS_REPO_ROOT.");

8.11) Test Categorization

Rule Guidance
Correct test categories Tag tests correctly: [Trait("Category", "Unit")] for pure unit tests, [Trait("Category", "Integration")] for tests requiring databases, containers, or network. Don't mix DB/network tests into unit suites.
// BAD - integration test marked as unit
public class UserRepositoryTests  // Uses Testcontainers/Postgres
{
    [Fact]  // Missing category, runs with unit tests
    public async Task Save_PersistsUser() { ... }
}

// GOOD - correctly categorized
[Trait("Category", "Integration")]
public class UserRepositoryTests
{
    [Fact]
    public async Task Save_PersistsUser() { ... }
}

[Trait("Category", "Unit")]
public class UserValidatorTests
{
    [Fact]
    public void Validate_EmptyEmail_ReturnsFalse() { ... }
}

8.12) No Silent Stubs

Rule Guidance
Unimplemented code must throw Placeholder code must throw NotImplementedException or return an explicit error/unsupported status. Never return success (null, empty results, or success codes) from unimplemented paths.
// BAD - silent stub masks missing implementation
public async Task<Result> ProcessAsync()
{
    // TODO: implement later
    return Result.Success();  // Ships broken feature!
}

// GOOD - explicit failure
public async Task<Result> ProcessAsync()
{
    throw new NotImplementedException("ProcessAsync not yet implemented. See SPRINT_XYZ.");
}

8.13) Immutable Collection Returns

Rule Guidance
Return immutable collections Public APIs must return IReadOnlyList<T>, ImmutableArray<T>, or defensive copies. Never expose mutable backing stores that callers can mutate.
// BAD - exposes mutable backing store
public class BadRegistry
{
    private readonly List<string> _scopes = new();
    public List<string> Scopes => _scopes;  // Callers can mutate!
}

// GOOD - immutable return
public class GoodRegistry
{
    private readonly List<string> _scopes = new();
    public IReadOnlyList<string> Scopes => _scopes.AsReadOnly();
    // or: public ImmutableArray<string> Scopes => _scopes.ToImmutableArray();
}

8.14) Options Validation at Startup

Rule Guidance
ValidateOnStart for options Use ValidateDataAnnotations() and ValidateOnStart() for options. Implement IValidateOptions<T> for complex validation. All required config must be validated at startup, not at first use.
// BAD - no validation until runtime failure
services.Configure<MyOptions>(config.GetSection("My"));

// GOOD - validated at startup
services.AddOptions<MyOptions>()
    .Bind(config.GetSection("My"))
    .ValidateDataAnnotations()
    .ValidateOnStart();

// With complex validation
public class MyOptionsValidator : IValidateOptions<MyOptions>
{
    public ValidateOptionsResult Validate(string? name, MyOptions options)
    {
        if (options.Timeout <= TimeSpan.Zero)
            return ValidateOptionsResult.Fail("Timeout must be positive");
        return ValidateOptionsResult.Success;
    }
}

8.15) No Backup Files in Source

Rule Guidance
Exclude backup/temp artifacts Add backup patterns (*.Backup.tmp, *.bak, *.orig) to .gitignore. Regularly audit for and remove stray artifacts. Consolidate duplicate tools/harnesses.
# .gitignore additions
*.Backup.tmp
*.bak
*.orig
*~

8.16) Test Production Code, Not Reimplementations

Rule Guidance
Helpers call production code Test helpers must call production code, not reimplement algorithms (Merkle trees, DSSE PAE, parsers, canonicalizers). Only mock I/O and network boundaries. Reimplementations cause test/production drift.
// BAD - test reimplements production logic
[Fact]
public void Merkle_ComputesCorrectRoot()
{
    // Custom Merkle implementation in test
    var root = TestMerkleHelper.ComputeRoot(leaves);  // Drift risk!
    Assert.Equal(expected, root);
}

// GOOD - test exercises production code
[Fact]
public void Merkle_ComputesCorrectRoot()
{
    // Uses production MerkleTreeBuilder
    var root = MerkleTreeBuilder.ComputeRoot(leaves);
    Assert.Equal(expected, root);
}

8.17) Bounded Caches with Eviction

Rule Guidance
No unbounded Dictionary caches Do not use ConcurrentDictionary or Dictionary for caching without eviction policies. Use bounded caches with TTL/LRU eviction (MemoryCache with size limits, or external cache like Valkey). Document expected cardinality and eviction behavior.
// BAD - unbounded growth
private readonly ConcurrentDictionary<string, CacheEntry> _cache = new();

public void Add(string key, CacheEntry entry)
{
    _cache[key] = entry;  // Never evicts, memory grows forever
}

// GOOD - bounded with eviction
private readonly MemoryCache _cache = new(new MemoryCacheOptions
{
    SizeLimit = 10_000
});

public void Add(string key, CacheEntry entry)
{
    _cache.Set(key, entry, new MemoryCacheEntryOptions
    {
        Size = 1,
        SlidingExpiration = TimeSpan.FromMinutes(30)
    });
}

8.18) DateTimeOffset for PostgreSQL timestamptz

Rule Guidance
Use GetFieldValue<DateTimeOffset> PostgreSQL timestamptz columns must be read via reader.GetFieldValue<DateTimeOffset>(), not reader.GetDateTime(). GetDateTime() loses offset information and causes UTC/local confusion. Store and retrieve all timestamps as UTC DateTimeOffset.
// BAD - loses offset information
var createdAt = reader.GetDateTime(reader.GetOrdinal("created_at"));

// GOOD - preserves offset
var createdAt = reader.GetFieldValue<DateTimeOffset>(reader.GetOrdinal("created_at"));

Documentation Updates

When scope, contracts, or workflows change, update the relevant docs under:

  • docs/modules/** - Module architecture dossiers
  • docs/api/ - API documentation
  • docs/risk/ - Risk documentation
  • docs/airgap/ - Air-gap operation docs

Role-Based Behavior

When working in this repository, behavior changes based on the role specified:

As Implementer (Default for coding tasks)

  • Work only inside the module's directory defined by the sprint's "Working directory"
  • Cross-module edits require explicit notes in commit/PR descriptions
  • Do not ask clarification questions - if ambiguity exists:
    • Mark the task as BLOCKED in the sprint Delivery Tracker
    • Add a note in Decisions & Risks describing the issue
    • Skip to the next unblocked task
  • Maintain status tracking: TODO → DOING → DONE/BLOCKED in sprint files
  • Read the module's AGENTS.md before coding in that module

As Project Manager

Create implementation sprint files under docs/implplan/ using the mandatory sprint filename format:

SPRINT_<IMPLID>_<BATCHID>_<MODULEID>_<topic_in_few_words>.md

  • <IMPLID>: implementation epoch (e.g., 20251219). Determine by scanning existing docs/implplan/SPRINT_*.md and using the highest epoch; if none exist, use today's epoch.
  • <BATCHID>: 001, 002, etc. — grouping when more than one sprint is needed for a feature.
  • <MODULEID>: FE (Frontend), BE (Backend), AG (Agent), LB (library), BE (Backend), AG (Agent), LB (library), 'SCANNER' (scanner), 'AUTH' (Authority), 'CONCEL' (Concelier), 'CONCEL-ASTRA' - (Concelier Astra source connecto) and etc.
  • <topic_in_few_words>: short topic description.
  • If any existing sprint file name or internal format deviates from the standard, rename/normalize it and record the change in its Execution Log.
  • Normalize sprint files to standard template while preserving content
  • Ensure module AGENTS.md files exist and are up to date
  • When sprint is fully completed move it to docs-archived/implplan/

As Product Manager

  • Review advisories in docs/product-advisories/
  • Check for overlaps with docs-archived/product-advisories/
  • Validate against module docs and existing implementations
  • Hand over to project manager role for sprint/task definition

Task Workflow

Status Discipline

Always update task status in docs/implplan/SPRINT_*.md:

  • TODO - Not started
  • DOING - In progress
  • DONE - Completed
  • BLOCKED - Waiting on decision/clarification

Prerequisites

Before coding, confirm required docs are read:

  • docs/README.md
  • docs/ARCHITECTURE_REFERENCE.md
  • docs/modules/platform/architecture-overview.md
  • Relevant module dossier (e.g., docs/modules/<module>/architecture.md)
  • Module-specific AGENTS.md file

Git Rules

  • Never use git reset unless explicitly told to do so
  • Never skip hooks (--no-verify, --no-gpg-sign) unless explicitly requested

Configuration

  • Sample configs: etc/concelier.yaml.sample, etc/authority.yaml.sample
  • Plugin manifests: etc/authority.plugins/*.yaml
  • NuGet sources: Package cache in .nuget/packages/, public sources configured in nuget.config

Documentation

  • Architecture overview: docs/ARCHITECTURE_OVERVIEW.md
  • Architecture reference: docs/ARCHITECTURE_REFERENCE.md
  • Module dossiers: docs/modules/<module>/architecture.md
  • Database specification: docs/db/SPECIFICATION.md
  • PostgreSQL operations: docs/operations/postgresql-guide.md
  • API/CLI reference: docs/API_CLI_REFERENCE.md
  • Offline operation: docs/OFFLINE_KIT.md
  • Quickstart: docs/CONCELIER_CLI_QUICKSTART.md
  • Sprint planning: docs/implplan/SPRINT_*.md

CI/CD

Folder Structure

The CI/CD infrastructure uses a two-tier organization:

Folder Purpose
.gitea/workflows/ Gitea Actions workflow YAML files (87+)
.gitea/scripts/ CI/CD scripts called by workflows
devops/ Deployment, tooling, and operational configs

CI/CD Scripts (.gitea/scripts/)

.gitea/scripts/
├── build/      # Build orchestration (build-cli.sh, build-multiarch.sh)
├── test/       # Test execution (test-lane.sh, determinism-run.sh)
├── validate/   # Validation (validate-sbom.sh, validate-helm.sh)
├── sign/       # Signing (sign-signals.sh, publish-attestation.sh)
├── release/    # Release automation (build_release.py, verify_release.py)
├── metrics/    # Performance metrics (compute-reachability-metrics.sh)
├── evidence/   # Evidence bundles (upload-all-evidence.sh)
└── util/       # Utilities (cleanup-runner-space.sh)

DevOps Folder (devops/)

devops/
├── compose/        # Docker Compose profiles (dev, stage, prod, airgap)
├── helm/           # Helm charts (stellaops)
├── docker/         # Dockerfiles (platform, crypto-profile, ci)
├── telemetry/      # OpenTelemetry, Prometheus, Grafana configs
├── services/       # Service-specific configs (authority, crypto, signals)
├── offline/        # Air-gap and offline deployment
├── observability/  # Alerts, SLOs, incident management
├── database/       # PostgreSQL and MongoDB configs
├── ansible/        # Ansible playbooks
├── gitlab/         # GitLab CI templates
├── releases/       # Release manifests
├── tools/          # Development tools (callgraph, corpus, feeds)
└── scripts/        # DevOps scripts (test-local.sh, validate-compose.sh)

Key Workflows

Workflow Purpose
build-test-deploy.yml Main build, test, and deployment pipeline
test-matrix.yml Unified test execution with TRX reporting
module-publish.yml Per-module NuGet and container publishing
release-suite.yml Full suite release (Ubuntu-style versioning)
cli-build.yml CLI multi-platform builds
scanner-determinism.yml Scanner output reproducibility tests
policy-lint.yml Policy validation

Versioning

  • Suite releases: Ubuntu-style YYYY.MM with codenames (e.g., "2026.04 Nova")
  • Module releases: Semantic versioning MAJOR.MINOR.PATCH
  • See docs/releases/VERSIONING.md for full documentation

Environment Variables

  • STELLAOPS_BACKEND_URL - Backend API URL for CLI
  • STELLAOPS_TEST_POSTGRES_CONNECTION - PostgreSQL connection string for integration tests
  • StellaOpsEnableCryptoPro - Enable GOST crypto support (set to true in build)