Signals

The reachability and runtime-evidence plane for Stella Ops — call graphs, reachability facts, and runtime observations that make vulnerability verdicts reachability-aware.

Status: Implemented Source: src/Signals/ Owner: Policy Guild

Purpose

Signals is the reachability and runtime-evidence plane. It ingests and serves call graphs, reachability facts, runtime facts (observed symbol execution), unknown symbols, execution evidence, and verification beacons over an HTTP API under /signals (plus SCM/CI webhooks under /webhooks and a compatibility /api/v1/signals surface), owns the signals PostgreSQL schema, and publishes signals.fact.updated.v1 (reachability) and runtime.updated events. The host also owns the tenant-scoped /api/v1/score evaluation, history, weights, replay, verification, and explanation surface backed by signals.score_history; its established OAuth claims are the canonical score.read and score.evaluate scopes.

Components

Host:

Libraries / referenced projects:

Evidence Normalizers (EWS scoring code, EvidenceWeightedScore/Normalizers/):

HTTP API

All /signals/* handlers authorize per-request via Program.TryAuthorize (Authority bearer token or X-Scopes header dev fallback) and run the sealed-mode gate (SignalsSealedModeMonitor). Scopes are defined in Routing/SignalsPolicies.cs and the canonical catalog StellaOpsScopes (signals:read / signals:write / signals:admin). See ./architecture.md and ./api-reference.md for the full route reference. Highlights:

MethodRouteScopeNotes
GET/signals/ping, /signals/statussignals:readLiveness / version + sealed-mode status.
POST/signals/callgraphssignals:writeIngest a call graph; 202 + callgraphId. Audited.
GET/signals/callgraphs/{id} , /{id}/manifestsignals:readFetch document / stream manifest blob.
POST/signals/runtime-facts , /runtime-facts/ndjsonsignals:writeIngest runtime facts (JSON or gzip-aware NDJSON). Audited.
POST/signals/runtime-facts/syntheticsignals:writeLocal-harness only (not mapped in production). Audited.
GET/signals/facts/{subjectKey}signals:readFetch the reachability fact for a subject.
POST/signals/reachability/unionsignals:writeIngest a union graph (application/zip, X-Analysis-Id). Audited.
GET/signals/reachability/union/{analysisId}/meta , /files/{fileName}signals:readStream union artifacts.
POST/signals/reachability/recomputesignals:adminRecompute a reachability fact. Audited.
POST/GET/signals/unknowns (+ /{subjectKey}, /{id}/explain)signals:write / signals:readIngest / query / explain unknown symbols. Ingest audited.
POST/signals/execution-evidencesignals:writeBuild execution evidence; 202 / rate_limited / 422. Audited.
POST/GET/signals/beacons , /beacons/rate/{artifactId}/{environmentId}signals:write / signals:readVerification beacon ingest / rate query. Ingest audited.
GET/api/v1/signals/hot-symbols (+ /top, /stats, /correlated)— (controller)Hot-symbol index queries by image digest (HotSymbolsController).
POST/GET/DELETE/PATCH/api/v1/agents (+ /{agentId} , /register , /heartbeat , /commands , /posture , /{agentId}/facts)— (controller)Runtime-agent registration, heartbeat, commands, posture, facts ingest.
POST/api/v1/runtime/observationsAnonymous (network-edge trust)Deployment-observation agent dual-write into signals.runtime_facts tagged with release_id; 503 when no durable PostgreSQL is configured.
POST/webhooks/{github,gitlab,gitea}Anonymous + HMAC/token signatureSCM/CI webhook ingest (scan/SBOM trigger evaluation); 202 on success.
GET/api/v1/signals , /api/v1/signals/statssignals:read or orch:readCompatibility list/stats surface — see Current Status (serves static demo records, not live data).
GET/api/v1/score/{id}, /history, /weights*, /explain/{digest}, /{id}/replayscore.readTenant-scoped unified-score reads.
POST/api/v1/score/evaluatescore.read + score.evaluateCompute and persist a unified score. Audited.
POST/api/v1/score/verifyscore.readRe-execute and compare a replay envelope. Audited.
GET/healthz , /readyz , /openapi/v1.json , /api/v1/buildinfoAnonymousHealth, readiness (sealed-mode aware), OpenAPI discovery, image provenance.

Configuration

See etc/signals.yaml.sample for configuration options (section Signals:).

Key settings (all under the Signals: root, bound to SignalsOptions):

Dependencies

Signals has no build-time project references to Policy, Concelier, Scanner, or Excititor. Evidence reaches Signals over its HTTP ingest API, not via direct module calls.

Persistence (schema: signals)

Embedded SQL migrations live in StellaOps.Signals.Persistence/Migrations/ and apply on startup. 001_v1_signals_baseline.sql is the collapsed v1 baseline; 002_v1_score_history.sql adds the unified-score history store. The earlier 001–005 source migrations are archived pre-v1 history. Tables include:

Migration policy is forward-only (ADR-004). Without a configured PostgreSQL connection the host falls back to in-memory repositories only in the explicit local-harness mode.

Current Status

Implemented: callgraph / reachability / runtime-facts / unknowns ingest and serve over HTTP, hot-symbol and runtime-agent controllers, SCM/CI webhook ingest, durable signals PostgreSQL schema (auto-migrated), artifact storage (filesystem / RustFS CAS), reachability-fact events (signals.fact.updated.v1) and runtime-update events (runtime.updated), and the six-dimension EWS / Unified Score scoring code with deterministic scoring and evidence decomposition, plus the live /api/v1/score surface and durable score history.

Caveats grounded in source: