Excititor connector hygiene fixes — 2026-05

Sprint: SPRINT_20260501_025_Excititor_connector_specific_fixes

This release closes audit pass 2 finding E5: four independent low-risk fixes across four CSAF connectors. All four ship together to keep tracking simple. None of these fixes change the signature verification surface introduced by sprints 020 and 021.

Operator impact

MSRC — configurable base URL & scope (EXCITITOR-FIX-MSRC-01)

Action required for air-gap operators only.

MsrcConnectorOptions.BaseUri and MsrcConnectorOptions.Scope are now bindable configuration keys. Existing deployments that hit the public https://api.msrc.microsoft.com/sug/v2.0/ endpoint do not need any configuration change — the defaults are preserved. Air-gap deployments can now redirect every MSRC request at a local mirror:

excititor:
  connectors:
    msrc:
      baseUri: "https://msrc-mirror.local/sug/v2.0/"
      scope:   "api://msrc-mirror.local/.default"

The validator now rejects empty/non-HTTPS values; an empty Scope no longer silently falls back to the public default. See the sample at etc/excititor.worker.yaml.sample and the updated docs/modules/excititor/architecture.md for the full operator guide.

Oracle — digest comparison normalised (EXCITITOR-FIX-ORACLE-02)

No operator action.

Oracle’s catalog publishes bare-hex SHA-256 digests; the connector itself stamps the canonical sha256:<lower-hex> shape. The previous OrdinalIgnoreCase comparison treated the two shapes as unequal and silently dropped the document. The new helper StellaOps.Excititor.Core.Hashing.DigestNormalization normalises both sides to the canonical shape before an Ordinal compare; bare and prefixed digests now correctly compare equal. The helper is reused by the Rancher and Ubuntu connectors via the same Excititor.Core export.

Rancher Hub — time-based digest history trim (EXCITITOR-FIX-RANCHER-03)

No operator action; tunable.

The Rancher connector previously kept the last 200 document digests as a fixed-size dedupe set. After 200 new documents, an old digest could re-enter the set and cause re-processing. The trim is now time-based with a default 30-day retention window:

excititor:
  connectors:
    rancher:
      digestHistoryRetention: "30.00:00:00"  # 30 days, configurable

Each digest entry carries an inline observed-at unix timestamp in the vex.connector_states.document_digests array. Legacy entries (no suffix) are accepted on read and stamped at load-time; the next save re-encodes them with the new shape. No schema migration is required — the retention metadata lives in the existing TEXT[] column rather than a new observed_at column. See Decisions & Risks in the sprint file for the rationale.

Ubuntu — hashed ETag resume tokens (EXCITITOR-FIX-UBUNTU-04)

Action required: provide an HMAC secret.

Ubuntu CSAF resume tokens previously embedded the raw advisory URI in the vex.connector_states.document_digests column and worker logs. Anyone with read access could reconstruct the tracked-advisory list. Tokens are now etag:<hash>|<etag> where <hash> is HMAC-SHA256 of the URI keyed by a per-tenant secret:

excititor:
  connectors:
    ubuntu:
      etagSecret: "${UBUNTU_CONNECTOR_ETAG_SECRET}"  # required, >= 32 bytes

UbuntuConnectorOptions.Validate rejects an empty/missing secret so misconfiguration fails loud at validation rather than silently falling back to the plaintext shape. All HMAC operations route through StellaOps.Cryptography.IHmacAlgorithm; regional crypto plugins (FIPS, GOST, SM, eIDAS) substitute the implementation automatically.

Migration: legacy plaintext tokens are accepted on the first read after upgrade and replaced with the hashed shape on the next save. No backfill job is required.

Test coverage added

ProjectTests added
StellaOps.Excititor.Core.UnitTestsDigestNormalizationTests (12 cases incl. Oracle audit regression)
StellaOps.Excititor.Connectors.Oracle.CSAF.TestsFetchAsync_BareHexCatalogDigest_NowMatchesPrefixedComputedDigest
StellaOps.Excititor.Connectors.SUSE.RancherVEXHub.TestsRancherHubDigestRetentionTests (5 cases incl. 1000-doc / 60-day simulation)
StellaOps.Excititor.Connectors.Ubuntu.CSAF.TestsUbuntuEtagHashTests (5 cases incl. legacy-migration + URI-leak guard)
StellaOps.Excititor.Connectors.MSRC.CSAF.TestsMsrcConfigurableBaseUriTests (5 cases incl. mirror-routing assertion)

Files of interest