Unknowns Registry
Verified against commit
942a18727c(2026-09-26). Re-verify with:grep -rnE 'Map(Get|Post|Put|Delete|Group|Methods)\(' src/Unknowns/StellaOps.Unknowns.WebService; grep -n 'unknowns-web:' -A60 devops/release/bundle/docker-compose.yml; ls src/Unknowns/__Libraries/StellaOps.Unknowns.Persistence/MigrationsThe estate-wide service, database, compose and bundle wiring is generated in the service inventory; this dossier describes the module and defers to that inventory for the service list.
Status: Implemented (the Grey Queue API is a forward design and answers 501 Not Implemented — see Implementation Status) Source: src/Unknowns/ Deployable: compose service unknowns-web (container ${STELLAOPS_ESTATE_PREFIX:-stellaops}-unknowns-web, image stellaops/unknowns-web, network alias unknowns.stella-ops.local, port 8080; router service name unknowns). It ships in the release bundle (devops/release/bundle/docker-compose.yml) and the local stack (devops/compose/docker-compose.stella-services.yml). Owner: Signals Guild, Policy Guild
Purpose
The Unknowns Registry tracks ambiguities discovered during vulnerability scanning that cannot be definitively resolved — packages without known provenance, binaries without build-IDs/debug symbols, dependencies not covered by any advisory feed, unbounded version ranges, unsupported formats, and gaps in transitive dependency chains. It models “what we don’t know” as first-class, queryable risk signals using bitemporal semantics, then prioritizes them with a composite triage score and surfaces provenance hints to help operators resolve each unknown.
It is a standalone HTTP microservice (not a Policy Engine sub-library): the Unknowns WebService exposes the registry over the Stella Router, persists to its own PostgreSQL database stellaops_unknowns, and auto-migrates on startup.
Quick Links
Components
Service:
StellaOps.Unknowns.WebService— Minimal-API HTTP service (Program.cs) exposing the Unknowns and Grey Queue endpoints, OpenAPI/Swagger, health/readiness probes, the doctor-check/v1 surface (Doctor/UnknownsDoctorChecks.cs), Stella Router integration, scope-based authorization, tenant middleware, audit emission, and localization.
Libraries:
StellaOps.Unknowns.Core— Domain models (Unknown,GreyQueueEntry), enums, repository interfaces (IUnknownRepository,IGreyQueueRepository), provenance-hint builders, the native-binary classifier, the unknown ranker, and the grey-queue state machine.StellaOps.Unknowns.Persistence— PostgreSQL/EF Core persistence:UnknownsDataSource,UnknownsDbContext,PostgresUnknownRepository,UnknownsConnectionResolver(fail-closed connection resolution),UnknownsSchemaTopology(database, schema, and migration names), and the embedded SQL migrations applied throughAddStartupMigrations.StellaOps.Unknowns.Services— Background/operational services:GreyQueueWatchdogService,UnknownsSlaMonitorService,UnknownsLifecycleService,UnknownsMetricsService,SlaCalculator,UnknownsSlaHealthCheck. Note: these are referenced only byStellaOps.Unknowns.Core.Testsand are not referenced or hosted by the WebService (see Implementation Status).
Key Features
- First-class Unknown state: Explicit modeling of uncertainty (
UnknownKindclassification) rather than hiding gaps as false negatives. - Bitemporal tracking: Valid-time (
valid_from/valid_to) and system-time (sys_from/sys_to) columns, with point-in-timeas_ofqueries and history retrieval. - Triage scoring & bands: A composite score (popularity, exploit potential, uncertainty, graph centrality, staleness) assigns each unknown a
TriageBandofHot/Warm/Cold, driving a HOT processing queue. - Provenance hints: Structured hypotheses with confidence levels and suggested actions, with a combined-confidence rollup and a high-confidence query.
- Native binary classification: Dedicated kinds for missing/unknown build-IDs, unresolved native libraries, heuristic (
dlopen) dependencies, and unsupported binary formats. - Grey Queue (evidence pipeline): A signed/replayable evidence-bundle queue (SBOM slice, advisory snippet, VEX evidence, diff traces, reachability evidence) with deterministic fingerprints, trigger conditions (feed/tool/CVE/PURL), a multi-state workflow, and SLA banding.
- Multi-tenant isolation: Row-Level Security on the
unknowns.unknowntable keyed by theapp.tenant_idsession variable.
API Surface
All endpoints are exposed via the Stella Router under the unknowns service. Both route groups call .RequireTenant(): the tenant is resolved only from the envelope-bound stellaops:tenant claim, a missing tenant is rejected with 400 tenant_missing, and the X-Tenant-Id request header is never a tenancy source. Named authorization policies gate access: Unknowns.Read (scope unknowns:read), Unknowns.Write (scope unknowns:write), and Unknowns.DoctorHealth (scope ops.health, doctor surface only).
Unknowns (/api/unknowns, requires unknowns:read)
GET /api/unknowns— List with pagination; supportsskip,take,asOf(bitemporal),kind,severity, andsubjectRef(open unknowns recorded against exactly that purl or bom-ref; the read the Policy unknowns gate makes) query filters.GET /api/unknowns/{id}— Get a single unknown (with hints).GET /api/unknowns/{id}/hints— Provenance hints only, plus best hypothesis / combined confidence / primary suggested action.GET /api/unknowns/{id}/history— Bitemporal history for the unknown.GET /api/unknowns/triage/{band}— Unknowns in a given triage band (Hot/Warm/Cold).GET /api/unknowns/hot-queue— HOT unknowns for immediate processing.GET /api/unknowns/high-confidence— Unknowns whose hints exceedminConfidence(default 0.7).GET /api/unknowns/summary— Counts by kind, severity, and triage band plus total open.
Grey Queue (/api/grey-queue)
Not operational in a deployed host. No IGreyQueueRepository is registered, so MapGreyQueueEndpoints maps one anonymous catch-all that answers every /api/grey-queue/* request with 501 Not Implemented (title: grey_queue_not_implemented). The routes below are the forward contract; they map automatically once a repository is registered (the WebService test host does so).
Read endpoints require unknowns:read; mutating endpoints require unknowns:write and emit audit events (AuditModules.Unknowns).
GET /api/grey-queue— List (filter bystatus/reason).GET /api/grey-queue/{id}— Get entry by ID.GET /api/grey-queue/by-unknown/{unknownId}— Get entry by unknown ID.GET /api/grey-queue/ready— Entries ready for processing.GET /api/grey-queue/triggers/feed/{feedId}|/triggers/tool/{toolId}|/triggers/cve/{cveId}— Entries matching a trigger.GET /api/grey-queue/summary— Summary statistics (counts per status, averages, oldest-pending hours).GET /api/grey-queue/{id}/transitions— Valid next states for an entry.POST /api/grey-queue— Enqueue a new entry (audit actionenqueue).POST /api/grey-queue/{id}/process— Mark processing (start_processing).POST /api/grey-queue/{id}/result— Record a processing result (record_result).POST /api/grey-queue/{id}/resolve— Resolve (resolve).POST /api/grey-queue/{id}/dismiss— Dismiss (dismiss).POST /api/grey-queue/{id}/assign— Assign for review (assign; requires an assignee).POST /api/grey-queue/{id}/escalate— Escalate to the security team (escalate).POST /api/grey-queue/{id}/reject— Reject (reject).POST /api/grey-queue/{id}/reopen— Reopen a closed entry (reopen).POST /api/grey-queue/expire— Expire old entries (expire).
Health
GET /healthz— Liveness (anonymous; ignores DB).GET /readyz— Readiness (anonymous; exercises the DB probe via theready-taggeddatabasecheck).GET /health— Combined health (all registered checks).
Doctor
GET /doctor/unknowns/checks— doctor-check/v1 results (policyUnknowns.DoctorHealth, scopeops.health). Checks:doctor.unknowns.database.own-database-cutover,doctor.unknowns.database.schema-census(catalog-only; never counts tenant rows),doctor.unknowns.database.tenant-isolation, plus the standard service checks fromAddServiceDoctorChecks("unknowns"). Registration with the Platform doctor registry is opt-in (Doctor:Registration:Enabled).
Domain Model & Enums
Unknown(StellaOps.Unknowns.Core/Models/Unknown.cs) — bitemporal record with subject (SubjectHash, SubjectType, SubjectRef), Kind, optional Severity, source references (SourceScanId/SourceGraphId/SourceSbomDigest), bitemporal columns, resolution tracking, the full scoring breakdown, rescan scheduling, evidence hashes (EvidenceSetHash/GraphSliceHash), audit fields, and provenance hints.
Enums (Unknown.cs):
UnknownSubjectType:Package,Ecosystem,Version,SbomEdge,File,Runtime,Binary.UnknownKind:MissingSbom,AmbiguousPackage,MissingFeed,UnresolvedEdge,NoVersionInfo,UnknownEcosystem,PartialMatch,VersionRangeUnbounded,UnsupportedFormat,TransitiveGap, and the native-binary kindsMissingBuildId,UnknownBuildId,UnresolvedNativeLibrary,HeuristicDependency,UnsupportedBinaryFormat.UnknownSeverity:Critical,High,Medium,Low,Info.ResolutionType:FeedUpdated,SbomProvided,ManualMapping,Superseded,FalsePositive,WontFix.TriageBand:Hot(score ≥ 0.70),Warm(0.40–0.69),Cold(< 0.40).
GreyQueueEntry(StellaOps.Unknowns.Core/Models/GreyQueueEntry.cs) — references an Unknown, carries the DSSE-style evidence bundle (with per-artifact SHA-256 hashes), trigger conditions, processing metadata (attempts / MaxAttempts = 10), and a status workflow.
Enums (GreyQueueEntry.cs):
GreyQueueStatus:Pending,Processing,Retrying,UnderReview,Escalated,Resolved,Rejected,Failed,Expired,Dismissed. Transitions are enforced byGreyQueueStateMachine.GreyQueueReason:InsufficientVex,ConflictingVex,MissingReachability,AmbiguousIdentity,FeedNotAvailable,ToolUnsupported,BinaryAnalysisInconclusive,BackportUncertain,MultipleInterpretations,AwaitingUpstreamAdvisory.GreyQueueResolution:FeedUpdate,ToolUpdate,VexReceived,ManualResolution,Superseded,NotApplicable,Expired.
Configuration
- Database connection, resolved by
UnknownsConnectionResolverin this precedence order: the environment variableSTELLAOPS_POSTGRES_UNKNOWNS_CONNECTION; the configuration keyPostgres:Unknowns:ConnectionString. No other key is read; the former aliasPostgres:ConnectionStringis ignored. A canonical source that is present but blank is refused instead of falling back. With no source the host fails closed at startup; there is no generic shared-connection fallback. Compose and the release bundle setSTELLAOPS_POSTGRES_UNKNOWNS_CONNECTIONas a required variable. - The rest of
PostgresOptions(timeouts, pool sizes, schema override) binds from thePostgressection; the schema defaults tounknowns. - Authentication (
Authority:ResourceServer:*), CORS, localization, audit emission (AuditEmission:*), and the Stella Router (Routersection, service nameunknowns) are configured inProgram.cs. - Doctor registration:
Doctor:Registration:Enabled(default off). When enabled,Authority,ClientId, andClientSecretin that section are required and must not be blank.
The
StellaOps.Unknowns.Serviceslibrary defines options records (GreyQueueWatchdogOptions,UnknownsSlaOptions) for the SLA/watchdog/lifecycle background services. These are not bound or hosted by the WebService (see Implementation Status), so their keys are not part of the deployed service surface.
Authorization Scopes
Defined in the canonical catalog StellaOps.Auth.Abstractions/StellaOpsScopes.cs:
unknowns:read(StellaOpsScopes.UnknownsRead) — query/view unknowns and grey-queue entries.unknowns:write(StellaOpsScopes.UnknownsWrite) — mutate unknowns and grey-queue entries.unknowns:admin(StellaOpsScopes.UnknownsAdmin) — defined in the catalog; not referenced by any Unknowns endpoint policy.ops.health(StellaOpsScopes.OpsHealth) — gates the doctor-check/v1 surface.
Storage
- Database: own PostgreSQL database
stellaops_unknownswith its own role on the shared server (ADR-039); schemaunknownsplus theunknowns_apphelper schema, which holds only the RLS tenant-context functionrequire_current_tenant(). - Auto-migration: Embedded SQL migrations under
StellaOps.Unknowns.Persistence/Migrations/are applied on startup viaAddStartupMigrations(moduleUnknowns.Persistence). The archivedMigrations/_archived/**set is explicitly excluded from embedding. - Migrations: two live files.
002_unknowns_retention_classes.sqlis comment-only (theretention-class: source-of-truthheader onunknowns.unknown).001_v1_unknowns_baseline.sqlis the collapsed pre-1.0 chain (bitemporal table, types, indexes, views, scoring/temporal functions, RLS; provenance-hint columns + GIN indexes + validation function; idempotent scoring-column repair). The pre-collapse filenames (001_initial_schema.sql,002_provenance_hints.sql,003_unknowns_scoring_drift_repair.sql) survive only underMigrations/_archived/pre_1.0/mig061/and are not embedded. - Table:
unknowns.unknown— the single bitemporal table, with Row-Level Security policyunknown_tenant_isolation(enabled and forced). Rows are never deleted; corrections and supersessions close the open row. - Views:
unknowns.current(valid + known now),unknowns.resolved,unknowns.triage_summary(counts/score stats by band & kind). - Functions:
unknowns.as_of(...),unknowns.count_by_kind(...),unknowns.count_by_severity(...),unknowns.assign_band(...),unknowns.calc_popularity_score(...),unknowns.calc_staleness_score(...),unknowns.calc_composite_score(...),unknowns.update_updated_at()(trigger),unknowns.validate_provenance_hints(...). - PostgreSQL enum types:
unknowns.subject_type,unknowns.unknown_kind,unknowns.unknown_severity,unknowns.resolution_type,unknowns.triage_band.
There is no
grey_queuetable in the current migrations, and no concreteIGreyQueueRepositoryimplementation is registered. The Grey Queue domain model, endpoints, and background services exist, but their persistence is not yet wired (see Implementation Status).
Integration Points
Stella Router / Authority: Registered as the unknowns router microservice; authentication via the Stella resource-server integration with scope-based policies and tenant middleware.
Policy: Policy Engine and Policy Gateway call GET /api/unknowns over HTTP from UnknownsGateChecker (src/Policy/__Libraries/StellaOps.Policy/Gates/UnknownsGateChecker.cs), configured by Policy:UnknownsGate:UnknownsApiUrl. No project outside src/Unknowns/ holds a ProjectReference to an Unknowns project.
Audit: Grey Queue mutations emit audit events under AuditModules.Unknowns (enqueue, start_processing, record_result, resolve, dismiss, expire, assign, escalate, reject, reopen).
Notifications: Escalations publish an EscalationNotification through an optional INotificationPublisher; no production implementation is registered today (test stubs only).
Dependencies
- PostgreSQL (registry storage, bitemporal audit, RLS tenant isolation).
- StellaOps Authority / Router (authentication, scope policies, service mesh).
- StellaOps Audit Emission (grey-queue action auditing).
- StellaOps Localization (endpoint descriptions).
Related Documentation
- Architecture, API reference, and Grey Queue state machine.
- Module agent guide:
src/Unknowns/AGENTS.md. - PostgreSQL operational patterns runbook.
- ADR-004: forward-only migrations.
Implementation Status
Implemented and wired into the WebService:
- Bitemporal
unknowns.unknownregistry with EF Core/PostgreSQL persistence and startup auto-migration. - Unknowns read API (list/get/hints/history/triage-band/hot-queue/high-confidence/summary).
- Triage scoring, bands, and provenance hints (model, SQL functions, and read endpoints).
- Scope-based authorization, claim-based tenant resolution with RLS isolation, health/readiness probes, the doctor-check/v1 surface, Stella Router integration.
Partially implemented (present in source but NOT wired into the deployed WebService):
- Grey Queue persistence: The
/api/grey-queueendpoints andIGreyQueueRepositoryinterface exist, but no concrete repository is registered in the WebService and nogrey_queuetable exists in the migrations. The deployed host therefore answers every/api/grey-queue/*request with501 Not Implemented. - Background workers / SLA monitoring / metrics:
StellaOps.Unknowns.Services(watchdog, SLA monitor, lifecycle, metrics emittingunknowns_queue_depth,unknowns_sla_compliance_rate,unknowns_processing_time_seconds,unknowns_resolution_time_hours,unknowns_state_transitions_total) is referenced only byStellaOps.Unknowns.Core.Tests, not by the WebService. No background workers run in the deployed service.
Key differentiator: Unlike scanners that hide uncertainty, Stella Ops makes “what we don’t know” an explicit, queryable, bitemporal signal with deterministic scoring and provenance hints — important for air-gapped deployments and zero-day scenarios where external validation is unavailable.
