Signals
Verified against commit
942a18727con 2026-09-26 (UTC). Re-verify:git grep -n "Map\(Get\|Post\|Group\)(\|AddHostedService" -- src/Signals/StellaOps.Signalsandls src/Signals/__Libraries/StellaOps.Signals.Persistence/Migrations.Service rows (host project, image, database and role, compose file, bundle presence, Doctor registration) are generated in
docs/architecture/service-inventory.md; where this page and the inventory differ, the inventory is authoritative.
Purpose
Signals is the reachability and runtime-evidence service. It ingests and serves call graphs, reachability facts, runtime facts, unknown symbols, execution evidence and verification beacons, receives SCM and CI webhooks, owns the unified-score API and its history, and publishes reachability-fact change events.
Deployables
| Deployable | Source | Compose | Release bundle |
|---|---|---|---|
signals | src/Signals/StellaOps.Signals/ (Program.cs) | devops/compose/docker-compose.signals.yml | Yes: service signals, image stellaops/signals, alias signals.stella-ops.local |
Libraries composed by the host: StellaOps.Signals.Persistence and StellaOps.Signals.EvidenceWeightedScore (under src/Signals/__Libraries/). StellaOps.Signals.Ebpf exists in the solution but no production host composes it (see architecture.md). StellaOps.Signals.Scheduler and StellaOps.Signals.RuntimeAgent are withdrawn (below).
Database
- Own database
stellaops_signals, schemasignals(src/Signals/__Libraries/StellaOps.Signals.Persistence/SignalsSchemaTopology.cs). - Connection:
STELLAOPS_POSTGRES_SIGNALS_CONNECTION(keyPostgres:Signals:ConnectionString). No shared-connection fallback; the bundle fails closed when the variable is unset. - Migrations:
src/Signals/__Libraries/StellaOps.Signals.Persistence/Migrations/(001to005), applied on startup byAddSignalsPersistence(AddStartupMigrations).
API surface
| Family | Routes | Source |
|---|---|---|
| Evidence ingest and read | /signals/callgraphs*, /signals/runtime-facts*, /signals/facts/{subjectKey}, /signals/reachability/*, /signals/unknowns*, /signals/execution-evidence, /signals/beacons*, /signals/ping, /signals/status | StellaOps.Signals/Program.cs |
| Runtime observations | POST /api/v1/runtime/observations | Program.cs |
| SCM and CI webhooks | POST /webhooks/github, /webhooks/gitlab, /webhooks/gitea | Scm/ScmWebhookEndpoints.cs |
| Unified score | /api/v1/score/* | Score/Endpoints/ScoreEndpoints.cs |
| Compatibility list | GET /api/v1/signals, /api/v1/signals/stats (static records, not stored data) | CompatibilityApiV1Endpoints.cs |
| Operations | /healthz, /readyz, /openapi/v1.json, build info, /doctor/signals/checks | Program.cs |
Withdrawn 2026-09-27 (SPRINT_20260927_003 PCD-44). The never-served MVC controllers
HotSymbolsController(/api/v1/signals/hot-symbols*),RuntimeAgentControllerandRuntimeFactsController(/api/v1/agents*), the unknowns rescan worker andStellaOps.Signals.Schedulerare withdrawn tosrc/__Obsoleted/Signals/. Their routes answer404. The unknowns rescan schedule the worker was meant to act on was retired on 2026-09-29 (below).
Withdrawn 2026-09-29 (SPRINT_20260928_001 PCD-159). The
StellaOps.Signals.RuntimeAgentlibrary and its tests, referenced by no deploying host, are frozen atsrc/__Obsoleted/Signals/. Its EventPipe agent never collected events. Runtime facts arrive overPOST /signals/runtime-facts.
Route and scope detail: architecture.md and the generated api-reference.md.
Configuration
Root section Signals (Options/SignalsOptions.cs): Authority, Storage, AirGap, Scoring, Cache, Events, OpenApi, Retention, Scm; separate sections Signals:UnknownsScoring, Signals:UnknownsDecay, Signals:ExecutionEvidence, Signals:Beacon. Environment variables use the SIGNALS_ prefix. Optional YAML files ../etc/signals.yaml and signals.yaml are read relative to the content root; the sample is devops/etc/signals.yaml.sample.
Installation posture replication: Catalog:Replication:EnvironmentState (Enabled, FeedBaseAddress, AuthTenant, AuthMode) enables the drain of Platform’s environment-state catalog into Signals’ own database (Hosting/SignalsPostureReplication.cs). The release bundle on this commit does not set it; see the posture note in architecture.md.
Doctor checks
doctor.signals.database.own-database-cutover, doctor.signals.schema.table-census, doctor.signals.persistence.local-harness-escape-hatch, doctor.signals.retention.overdue-rows (StellaOps.Signals/Doctor/), plus the standard service checks. Registered only when the Signals connection resolves.
The endpoint requires ops.health and nothing else. The Doctor policy never includes resource-server default scopes, so no signals:* scope is combined into it. Signals accepts the estate audience stellaops in addition to api://signals, including when a deployment lists only api://signals. Platform’s Doctor aggregation pull authenticates as stellaops-platform-doctor, whose tokens carry audience stellaops and scope ops.health, so the pull reaches the checks. Before SPRINT_20260926_002 PCD-4 the same pull was refused with 401 (audience) and, once past that, 403 (default scopes).
Retired predecessors
- The unknowns rescan schedule (
nextScheduledRescan,rescanAttempts,lastRescanResult, the three rescan-cadence scoring options and their columns): retired by006_v1_signals_retire_unknowns_rescan_schedule.sql(SPRINT_20260928_001 PCD-158, owner ruling of 2026-09-29). Nothing acted on it. signals.graph_metricsand its viewhigh_centrality_nodes: retired by005_v1_signals_retire_graph_metrics.sql(RFC-12, owner ruling Q-40). The unknowns centrality factor is reported as unavailable.- Eight baseline tables with no production writer: retired by
003_v1_signals_retire_unused_tables.sql(RFC-12). - The pre-window connection keys (
ConnectionStrings:Signals,Signals:Postgres:ConnectionStringand their environment forms): no longer read (SPRINT_20260722_020 W3-06).
Subordinate documents
| Document | Status |
|---|---|
| architecture.md | current |
| api-reference.md, openapi/v1.json | current generated reference |
| unified-score.md | design record, not re-verified 2026-09-26 |
| contracts/signals-provenance-contract.md | design record, not re-verified 2026-09-26 |
| contracts/ebpf-micro-witness-determinism-profile.md | design record, not re-verified 2026-09-26; the eBPF library has no production host composition |
| guides/ | design records, not re-verified 2026-09-26; some name a runtime collector (“Zastava Observer”) that is not a module in src/ |
| decay/, heuristics/, unknowns/, SHA256SUMS, dev-smoke/ | design records and their signed 2025-12 artifacts; the workflow that signed them is archived (.gitea/workflows-archived/signals-dsse-sign.yml) |
| events/ | shared event-envelope schemas and samples for several producers (Scanner, Scheduler, Attestor, AdvisoryAI), housed here; not re-verified 2026-09-26 |
| samples/reachability/ | benchmark inputs cited by src/Tools/StellaOps.Bench/Signals/README.md. Verify with sha256sum -c *.ndjson.sha256 in that directory. No generator is committed (the bench only reads them); the samples are byte-identical since efaf3cb789 (2025-12-12), and each .sha256 records the committed LF blob. Until 2026-09-27 the sidecars held the CRLF rendering’s digest, taken from a Windows working copy. |
retention-classification-verification-20260923.json | RFC-12 verification record |
