# Connector Setup Guide — Concelier + Excititor

Operator reference for bringing up the Concelier (advisory source) and Excititor (VEX provider) connectors. This guide describes the federated source catalog (Concelier advisory sources + Excititor VEX providers, surfaced through one /api/v1/advisory-sources/catalog endpoint), which connectors are backend-wired on ingest today, and the credential-acquisition steps for the few providers that require operator-minted secrets.

RETIRED OPERATOR PATH (2026-08-25). Do not use this guide to bring up a service or obtain credentials. The Concelier/Excititor plane is stopped and backs nothing running; remaining source retires under SPRINT_20260722_003 VULN-B1. Live ingestion is owned by src/Vulnerabilities, whose Tier-0 CVE path uses credential-free CVE List v5. There is no live CVE Services credential path. The snapshot and procedures below are historical migration evidence; use the Vulnerability Operations Runbook.

Reconciliation note (verify against source): the runtime snapshot below (source list, doc counts, health timestamps) was captured against a 2026-04-22 dev stack and is not kept current. The connector landscape has grown substantially since then — see “Backend-wired reality” for the source-of-truth pointers. Treat all counts/timestamps in this file as illustrative, not authoritative; re-run sources status / the DB queries below to get live state.

Backend-wired reality (source of truth)

The authoritative connector catalog lives in src/Concelier/__Libraries/StellaOps.Concelier.Core/Sources/SourceDefinitions.cs (SourceDefinitions.All). Each connector library under src/Concelier/__Libraries/StellaOps.Concelier.Connector.* ships an IDependencyInjectionRoutine and a plugin DLL (StellaOps.Concelier.Plugin.*.dll) that the WebService loads on startup; a source becomes runnable when its connector registers a fetch job (source:{id}:fetch) in the scheduler. The current per-connector auth/credential matrix — the single source of truth for “what needs a secret” — is docs/modules/concelier/connectors/credentials-matrix.md.

Catalog ≠runnable. A source can be present in SourceDefinitions.All but not runnable on a given host if no connector plugin registers its fetch job. Unlike the older “no-op enable” behaviour, the server-side REST enable/sync path now returns 501 Not Implemented (problem type https://stellaops.org/problems/not-implemented, code NOT_IMPLEMENTED) for a cataloged-but-unrunnable source rather than silently accepting it — see IsSourceRunnable in ConfiguredAdvisorySourceService.cs and the enable/sync handlers in SourceManagementEndpointExtensions.cs.

A large set of connectors that this guide previously listed as “aspirational / NOT backend-wired” now ship real connector libraries with DI routines and config contributors, including: npm, pypi, go, rubygems, maven, crates, packagist, hex, nuget, rustsec, pypa, govuln, bundler-audit, intel, amd, siemens, kaspersky-ics, cccs, jpcert (JVN), krcert (KISA), cert-fr, cert-in, cert-de (CERT-Bund), cert-cc, aws, gcp, azure, arch, gentoo, apple, fstec-bdu, nkcki. Several of those are alias-only or stubs (see the caveats below), but they are no longer unmapped catalog entries. mitre-attack / mitre-d3fend were removed entirely (PM Path 2 decision, Sprint 20260513_008).

Caveats from the live credentials matrix (verify there before relying on a row):

Concelier runtime snapshot (illustrative — 2026-04-22 dev stack, stale)

SourceBackend wired?Health checkDocs in DBLast updated
redhatYEShealthy6512026-04-22 17:16
osvYEShealthy (498ms)592026-04-22 17:40
debianYEShealthy412026-04-22 17:07
suseYEShealthy262026-04-22 17:00
alpineYEShealthy82026-04-22 17:06
ubuntuYEShealthy22026-04-22 17:41
auscertYEShealthy0never
vmwareYEShealthy0never
stella-mirrorYESunhealthy (404)0never

The stella-mirror failure on the dev stack is expected — that source is a downstream relay that pulls a pre-aggregated bundle from a parent Stella Ops deployment’s evidence-locker/mirror exports endpoint (typically an air-gap relay). It is disabled by default; set STELLA_MIRROR_BASE_URL to the parent’s mirror root and flip enabled=true on the vuln.sources row to activate. (Note: Stella Ops is itself the mirror publisher — this connector is for consumers of that feed, not the publisher side.)

Excititor — VEX providers (federated into the same catalog)

Excititor VEX providers surface through the unified catalog under the excititor:{provider} source-id namespace, with backend = "excititor" on each entry (Sprint 20260503-012, B-VEXUNI-002). Mutating an excititor:* source via the Concelier /api/v1/advisory-sources/... endpoints returns a 308 Permanent Redirect to the canonical Excititor management surface (/excititor/providers/{id}/...); Excititor’s VexProviderRuntimeSettingsCache / VexProviderConfigurationService remain the single source of truth for trust weight, signing material, and PGP fingerprints. The Concelier facade never duplicates that state.

The provider list and base URIs are owned by Excititor, not by this guide — enumerate them from the catalog (backend=excititor) or the vex.providers table rather than trusting a frozen snapshot. The previously listed excititor:redhat, excititor:ubuntu, excititor:cisco, and excititor:oracle entries are illustrative.

Provider management is available to operators with vex.admin, integration:write, or integration:operate. The unified source catalog and the dedicated VEX provider catalog must use the same scope gate as the Excititor API so integration operators can enable, configure, and run VEX providers without a separate vex.admin grant.

2026-06-02 local verification on https://stella-ops.local enabled and ran all 7 Excititor providers: Cisco, MSRC, OCI OpenVEX, Oracle, Red Hat, SUSE Rancher, and Ubuntu. All provider counters ended in succeeded. Cisco exceeded the frontdoor request timeout but completed in Excititor with 2 stored documents and 9 claims; use provider counters/history rather than the gateway timeout alone when diagnosing long-running provider runs.

Note about Cisco: the VEX side uses Cisco’s public CSAF feed (unauthenticated). The Concelier advisory side of Cisco (Connector.Vndr.Cisco) is now backend-wired and DOES require PSIRT openVuln OAuth client credentials (client_credentials) — see the credential section below.

Catalog and runnable connectors

The catalog and enable operation have separate contracts:

Historical tracking sprints (SPRINT_20260422_004, SPRINT_20260422_007) are archived; do not rely on their status here — verify the current catalog against SourceDefinitions.All and the credentials matrix.

Credential requirements

Authoritative source of truth: docs/modules/concelier/connectors/credentials-matrix.md (per-connector auth mechanism, config keys, rate limits, geo flags), grounded in each connector’s *Options.cs + *DependencyInjectionRoutine.cs. Read it before acting on anything below.

Other current-state inventories:

Connectors that actually require an operator-minted secret are few. Per the credentials matrix:

Many connectors register an editable config schema (a configuration contributor). Enumerate UI/CLI-configurable sources via the catalog (supportsConfiguration: true) rather than a hard-coded list.

The sections below keep the acquisition steps for the connectors that genuinely require a minted secret.

GitHub Security Advisories (GHSA)

What Stella Ops needs: nothing mandatory. The GHSA connector reads GitHub’s public global-advisory REST API anonymously by default and falls back to OSV. A token is optional and only raises rate limits / supports enterprise routing (the connector sends it as Authorization: Bearer <token>; there is no fixed scope requirement). Configure it via concelier:sources:ghsa:ApiToken.

Steps (only if you want higher rate limits):

  1. https://github.com/settings/tokens → generate a token (classic or fine-grained).
  2. Name: stella-ops-concelier-ghsa. A read-only public-advisory scope is sufficient; no read:packages/public_repo write scopes are required for global advisory reads.
  3. If your GitHub org enforces SAML SSO: Configure SSO next to the token → authorize per org.
  4. Store the value under concelier:sources:ghsa:ApiToken (or the Platform credential store, see below).

Cisco PSIRT openVuln (Concelier advisory cisco connector; VEX uses public CSAF)

What Stella Ops needs: a Cisco PSIRT OAuth 2.0 client (grant_type=client_credentials). Plaintext schema stored as "{clientId}:{clientSecret}"; token endpoint defaults to https://id.cisco.com/oauth2/default/v1/token.

Steps:

  1. https://apiconsole.cisco.com/Register a New App.
  2. Tick Client Credentials grant. Enable the openVuln API entitlement.
  3. Copy client_id + client_secret from the app detail page.
  4. Store via concelier:sources:cisco:ClientId / :ClientSecret (optionally :TokenEndpoint, :BaseUri) or the Platform credential store.

Cisco ref: https://developer.cisco.com/docs/psirt/authentication/.

Microsoft MSRC (Concelier advisory + Excititor VEX)

What Stella Ops needs: Concelier’s MSRC advisory connector still uses a Microsoft Entra confidential client app with the consent and scope required by your MSRC onboarding flow. Excititor’s excititor:msrc VEX provider runs in public mode by default; configure Entra fields there only when selecting authMode=ClientCredentials or when pointing at a mirror that requires bearer tokens.

Steps:

  1. https://entra.microsoft.com/App registrationsNew registration.
  2. Name: stella-ops-concelier-msrc. Single-tenant. Redirect URI blank.
  3. From Overview: copy Directory (tenant) ID + Application (client) ID.
  4. Certificates & secretsNew client secret → 24-month expiry → copy the Value column immediately.
  5. Grant the application permissions and consent required by your MSRC onboarding process before storing the values in Stella Ops. For Excititor VEX, skip these steps when staying on authMode=Public.

Config keys (Concelier microsoft connector): concelier:sources:microsoft:TenantId, :ClientId, :ClientSecret, :Scope (default api://api.msrc.microsoft.com/.default). The runtime overlay stores the resolved secret as "{aadTenantId}:{clientId}:{clientSecret}". The connector skips-with-WARN when no credential is resolvable (Sprint 037).

Microsoft refs: https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app, https://learn.microsoft.com/en-us/entra/identity-platform/how-to-add-credentials, MSRC SUG: https://api.msrc.microsoft.com/sug/v2.0/swagger.

Where credentials are stored (precedence)

Credentialed connectors resolve secrets in this order (RFC-0001 §8.2, wired under SPRINT_20260512_021):

  1. Platform credential store via IRemoteCredentialResolver — the preferred path. Managed through the Console connector-credentials surface and governed by the connector:credentials:read / connector:credentials:write scopes (StellaOpsScopes.ConnectorCredentialsRead / ...Write).
  2. Env var / source config — e.g. concelier:sources:cisco:ClientId. With the CONCELIER_ env prefix and :__, that key is the env var CONCELIER_concelier__sources__cisco__ClientId; equivalently concelier.sources.cisco.clientId in etc/concelier.yaml.
  3. Connector natural fallback — anonymous/public access or skip-with-WARN, per the credentials matrix step-3 column.

Credential dry-run (verify a stored secret without ingesting)

POST /api/v1/connectors/{connectorId}/dry-run-credential (body { "credentialId": "<guid>" }) exercises a connector’s auth path with a single upstream vendor call — no advisory persistence and no source-state mutation (only the standard Platform runtime-read audit row). It is governed by the concelier:credentials:dry-run scope (StellaOpsScopes.ConcelierCredentialsDryRun, policy Concelier.Credentials.DryRun). The {connectorId} path segment matches the connector’s namespaced IConnectorDryRun.ConnectorId (e.g. concelier:ghsa, concelier:cisco). Connectors that do not register an IConnectorDryRun handler return 501 Not Implemented (type https://stellaops.org/problems/not-implemented) — use the Platform metadata-only Verify endpoint instead. As of the source verified for this revision, the connectors that implement dry-run are GHSA (concelier:ghsa), Cisco (concelier:cisco), CVE (concelier:cve), MSRC (concelier:msrc), and Red Hat (concelier:redhat), plus the Excititor Red Hat CSAF provider (excititor:redhat-csaf); every other connector returns 501. Verify the live set against the registered IConnectorDryRun implementations (ConnectorDryRunRegistry.SupportedConnectorIds) rather than this list. The endpoint declines (409 Conflict) when the credential state is not active.

Day-to-day operator commands

# Using the CLI (src/Cli/StellaOps.Cli/bin/Debug/net10.0/StellaOps.Cli.dll):
dotnet StellaOps.Cli.dll sources list --json           # catalog view (local registry)
dotnet StellaOps.Cli.dll sources status                # configuration status summary
dotnet StellaOps.Cli.dll sources check <id>            # connectivity probe
dotnet StellaOps.Cli.dll sources enable <id> [<id>...] # enable (local registry; not the server runnability gate)
dotnet StellaOps.Cli.dll sources disable <id>
dotnet StellaOps.Cli.dll db fetch --source <id> --stage fetch  # trigger ingest (stage: fetch|parse|map)
dotnet StellaOps.Cli.dll db merge                      # run canonical merge reconciliation
dotnet StellaOps.Cli.dll db export --format json       # run export job (json only; trivy-db retired 2026-08-09)
dotnet StellaOps.Cli.dll db connectors configure <id> --set Key=Value  # persist connector config via REST

Command-surface notes (verify against CommandFactory.cs / DbCommandGroup.cs):

Environment:

Verify persisted state directly:

SELECT key, source_type, enabled FROM vuln.sources ORDER BY key;
SELECT s.key, COUNT(d.*) AS docs, MAX(d.updated_at) AS last_update
FROM vuln.sources s LEFT JOIN concelier.source_documents d ON d.source_id = s.id
GROUP BY s.key ORDER BY docs DESC;
SELECT id, kind, enabled, array_to_string(base_uris,' | ') FROM vex.providers ORDER BY id;

What the UI workflow looks like

  1. Open the advisory sources catalog (served from the federated GET /api/v1/advisory-sources/catalog; each row carries a backend discriminator of concelier or excititor).
  2. Each source row shows enabled, readiness (ready / blocked / disabled / unsupported), and — when supportsConfiguration is true — the stored configuration schema.
  3. Use View more details on a row to inspect the Stored Connector Configuration and compact sync summary. Use View error history to open the source history dialog; it is backed by GET /api/v1/advisory-sources/{id}/sync-history and shows readiness, fetch job, ready-for-sync state, persisted last error/success/error count, and recent coordinator runs without expanding the row.
  4. readiness=blocked means the source is persisted as enabled but is missing required fields (credentials, URIs). The source is excluded from automatic and manual sync with a blocked-outcome response carrying the error code SOURCE_CONFIG_REQUIRED (see ConfiguredAdvisorySourceService.cs); an unsupported readiness instead means no runnable fetch job is registered on this host.
  5. Paste credentials in the source’s detail editor (PUT /api/v1/advisory-sources/{id}/configuration). The server persists them; subsequent reads surface only a masked “secret retained” badge (isSecretRetained) — secrets are never echoed back.
  6. Updating an unrelated field doesn’t require re-entering the secret; when a sensitive field is submitted empty, the server leaves the existing secret in place. Per-field validation failures return 422 with the offending fieldKey.

Local fixture-mode source sync

When running the local fixture lane, apply devops/compose/docker-compose.integration-fixtures.yml together with devops/compose/docker-compose.fixture-mode.yml; the stellaops-advisory-fixture nginx container must be present on the Compose network before Concelier sync jobs run. If the fixture container is missing, fixture hostnames can resolve incorrectly inside the stack and many sources surface as upstream 404/DNS failures.

Fixture-mode deliberately uses a smaller deterministic corpus than live upstreams:

Authorization (scopes & policies)

Verified against src/Concelier/StellaOps.Concelier.WebService/Program.cs and the canonical scope catalog (src/Authority/.../StellaOpsScopes.cs):

Follow-up for this stack