---
title: Configuration settings
summary: Configuration keys consumed by this library, retrieval methods, and runtime dependencies.
status: draft
owner: SAIF Framework Platform Team
last_reviewed: 2026-10-02
library: SAIF.NetCore.OIDC
reference_type: package
---

# Configuration settings

This library reads no `IConfiguration`/`appsettings.json` keys directly. Every OIDC-related setting is read live from the Environment API section `NetCore_OIDC` through `IEnvironmentClient`, via the typed facade `OidcSettings`: 20 static keys in total — 16 string-type, 3 integer-type (`ClockSkewSeconds`, `CookieExpireMinutes`, `RoleTransformCacheOffset`), and 1 secure key (`BOLAppCredentials`) — plus a separate dynamic indexer-based read (`OidcSettings.this[key]`, with no in-repository caller) that is not part of the 20-key static catalog. The library defines no options classes bound from `appsettings.json`; its two `IConfigureNamedOptions<T>` implementations source every value from `IOidcSettings`, not from `IConfiguration`.

## Configuration retrieval methods

| Method | Class / interface | Namespace | Usage pattern | Call sites |
| --- | --- | --- | --- | --- |
| `IEnvironmentClient.GetSettingValue(string key, string section)` | `IEnvironmentClient` (impl. `BaseEnvironmentClient`/`SecureEnvironmentClient`) | `SAIF.NetCore.Services.Contracts` | Live read on every property access, section fixed to `NetCore_OIDC`. The composed lookup key is `"netcore_oidc.<key>"`, lower-cased. A missing key returns `""`. | `OidcSettings` string properties and the `this[key]` indexer |
| `IEnvironmentClient.GetSettingValue<int>(string key, string section)` | same | same | Typed read. A missing key throws `EnvironmentClientException`. | `OidcSettings.RoleTransformCacheOffset`, `CookieExpireMinutes`, `ClockSkewSeconds` |
| `IEnvironmentClient.GetSecureSetting(string key, string section, string systemHashValue)` | same; real decryption only in `SecureEnvironmentClient` | same | Decrypted read. The hash comes from `ISystemHashService.ComputeHash(SystemType.Other, Assembly.GetExecutingAssembly().GetName().Name)` — the executing assembly is this library, so every consuming app shares one hash identity. On `BaseEnvironmentClient` this always throws. | `OidcSettings.AppCredentials` |
| `IEnvironmentClient.IsDeveloperMachine()` | same | same | Read once in the singleton constructor; relaxes the missing-certificate failure. | `DataProtectionCertService..ctor` |
| `OidcSettings` indexer `this[string key]` | `IOidcSettings` | `SAIF.NetCore.Services.Contracts` | Passes any caller-supplied key through to the string retrieval method in section `NetCore_OIDC`. No caller in this repository uses it. | — |

**Read timing.**

| Consumer | Lifetime | When the setting is read | Effect of an Environment API change |
| --- | --- | --- | --- |
| `ConfigureCookieAuthenticationOptions`, `ConfigureOpenIdConnectOptions` | options configurators | When the named options for `"Cookies"`/`"OpenIdConnect"` are first built, then cached by the options system | Requires an app restart* |
| `ClaimTransformationCacheService` (singleton) | singleton | `RoleTransformCacheOffset`, read once in the constructor | Requires an app restart |
| `DataProtectionCertService` (singleton) | singleton | `IsDeveloperMachine()` in the constructor; `DPCertName` on each `GetCertificate()` call | Developer flag: restart. Certificate name: live |
| `LoginRedirectService`, `RefreshJwtMiddleware`, `JwtRefreshService`, `RoleClaimTransformer` | transient/scoped | Per call | Live, governed by the EnvironmentClient refresh cycle* |

## Environment API settings catalog

All keys belong to section **`NetCore_OIDC`**, so the composed key is `NetCore_OIDC:<key>`. EnvironmentClient lower-cases the composed key, so matching is case-insensitive but **not** spelling-tolerant.

| Key (`NetCore_OIDC:`) | Secure | Type / format | Seed default | Missing → | Required | Consuming class (member) |
| --- | --- | --- | --- | --- | --- | --- |
| `BOLAppCredentials` | **Yes** | `clientId\|clientSecret` | secure (vault reference; not reproduced) | On the standard `SecureEnvironmentClient`, a null/default cached or fetched value throws `EnvironmentClientException` ("No crypto data found for requested secure setting") before `OidcAppCredentials` is ever constructed; the non-secure `BaseEnvironmentClient` throws `EnvironmentClientException` for a different reason ("Operation not allowed"). Independently of those client-layer errors, `OidcAppCredentials`'s own constructor (in `SAIF.NetCore.ServiceContracts`) rejects a `null` raw value with `ArgumentNullException`, and a non-`null` value without exactly one `\|` with `ArgumentException`. `SecureEnvironmentClient` validates only for `null`/default, not pipe-field shape, so a non-null malformed secret (for example an empty string, or a string missing/with extra `\|` characters) reaches this parser through the **standard** client and throws `ArgumentException` there; only the `ArgumentNullException` branch requires a custom `IEnvironmentClient` implementation that returns `null` | **Required** (OIDC challenge) | `OidcSettings.AppCredentials` → `ConfigureOpenIdConnectOptions.Configure` (`ClientId`/`ClientSecret`) |
| `CallbackPath` | No | URL path | `/authorization-code/callback` | `""` → `new PathString("")`; the OIDC handler rejects an empty callback path during options validation* | Required | `ConfigureOpenIdConnectOptions.Configure` |
| `ClockSkewSeconds` | No | int seconds | `5` | `EnvironmentClientException` | **Required** | `ConfigureOpenIdConnectOptions.Configure` → `TokenValidationParameters.ClockSkew` |
| `CookieAccessDeniedPath` | No | URL path | `/unknown` | `""` → empty `AccessDeniedPath` | Recommended | `ConfigureCookieAuthenticationOptions.Configure` |
| `CookieExpireMinutes` | No | int minutes | `60` | `EnvironmentClientException` | **Required** | `ConfigureCookieAuthenticationOptions.Configure` → `ExpireTimeSpan` |
| `CookieLoginPath` | No | URL path (login app) | `/OnlineLoginV2` | `""`: login redirect goes to `https://{host}{CookieSigninUri}`, and the loop guard matches every path, so `origin` is never appended* | Required | `ConfigureCookieAuthenticationOptions.Configure`; `LoginRedirectService.Redirect` |
| `CookieName` | No | cookie name; must be shared across SSO apps | `SAIF.Asp.AuthenticationCookie` | `""`: an empty cookie name breaks shared-cookie SSO* | Required | `ConfigureCookieAuthenticationOptions.Configure` |
| `CookieSigninUri` | No | URL path | `/account/signin` | `""` → redirect to the login app root | Required | `LoginRedirectService.Redirect` |
| `DefaultOidcScope` | No | CSV of scopes (no trim) | `profile,openid,email,offline_access` | `""` → `[""]`, adding one empty scope* | Required | `OidcSettings.DefaultScopes` → `ConfigureOpenIdConnectOptions.Configure` |
| `DPApplicationName` | No | data-protection app discriminator; must be identical across apps sharing the cookie | `SAIFBusinessOnline` | `""`: both the cookie and OIDC (`-oidc`) key rings use a blank or near-blank discriminator* | Required | `ConfigureCookieAuthenticationOptions.Configure`; `ConfigureOpenIdConnectOptions.Configure` (as `{value}-oidc`) |
| `DPCertName` | No | exact X.509 Subject in LocalMachine\My | `CN=BOL_OIDC_DP` | `""`: no certificate matches → `MissingDataProtectionCertificateException` (non-developer machines); developer machines get `null` and an unencrypted key ring | **Required** (servers) | `DataProtectionCertService.GetCertificate` → `ConfigureCookieAuthenticationOptions` |
| `DPKeyDirectory` | No | file-system path | `C:\OIDC\DP` | `""` → `new DirectoryInfo("")` → `ArgumentException` at options build* | **Required** | `ConfigureCookieAuthenticationOptions.Configure`; `ConfigureOpenIdConnectOptions.Configure` |
| `OktaAuthorizationServerUrl` | No | URL path segment | `/oauth2/default` | `""` → authority = Okta org root | Required | `ConfigureOpenIdConnectOptions.Configure` (authority); `JwtRefreshService.Refresh` |
| `OktaBaseUrl` | No | absolute HTTPS URL of the Okta tenant | present only in `EnvironmentSettings.json`/`.enttest7.json`; **absent from `.global.json`** | `""` → relative authority → OIDC metadata retrieval fails* | **Required** | `ConfigureOpenIdConnectOptions.Configure`; `JwtRefreshService.Refresh` |
| `RefreshTokenQueryString` | No | query-string prefix ending in `refresh_token=` | `?grant_type=refresh_token&redirect_uri=&scope=offline_access openid&refresh_token=` (unencoded space) | `""` → token POST without a grant → Okta 400 → `JwtRefreshException`* | Required when `IJwtRefreshService` is used | `JwtRefreshService.Refresh` |
| `RefreshTokenRedirectUrl` | No | URL path of the JwtRefresh app | `/JwtRefresh/token/refresh` | `""` → 301 to a relative URL made of the query only* | Required when `UseJwtRefreshMiddleware` | `RefreshJwtMiddleware.InvokeAsync` |
| `RefreshTokenUrl` | No | URL path | `/v1/token` | `""` → POST to the authorization-server root* | Required when `IJwtRefreshService` is used | `OidcSettings.RefresnTokenUrl` (property-name typo) → `JwtRefreshService.Refresh` |
| **`RoleClaimIdentitifier`** (code key, typo) | No | substring matched against lower-cased claim types | seed key is `RoleClaimIdentifier` (correct spelling) / `_roles_` — **the code key has no seed entry** | `""` (likely in every seeded environment): `"anything".Contains("")` is true, so every non-array claim becomes a `ClaimTypes.Role` | Required (security-relevant) | `OidcSettings.RoleClaimIdentifier` → `RoleClaimTransformer.TransformAsync` → `RoleClaimService.AddRoleClaims` |
| `RoleTransformCacheOffset` | No | int seconds | `30` | `EnvironmentClientException`, while resolving the singleton `IClaimTransformCacheService`, failing the scoped `RoleClaimService` resolution | Required | `ClaimTransformationCacheService..ctor` |
| `SignedOutCallbackPath` | No | URL path | `/signout/callback` | `""` → `PathString("")` | Required | `ConfigureOpenIdConnectOptions.Configure` |
| *(dynamic)* `NetCore_OIDC:<caller key>` | No | any | — | `""` | — | `OidcSettings.this[key]` — no in-repo caller |

**Declared but never read (orphaned constants).** The removed `SigningKeys*` services left these behind; no code reads them and the seed files do not list them: `JwtSigningKeysUrl`, `JwtSigninKeysExpireMinutes`.

Host-level toggles that affect this library come from `SAIF.NetCore.ServiceExtensions`/`AppStartup`, not this library: `HostLocation` (must be `External`), `ChallengeType` (`OpenIdConnect`), `UseJwtRefreshMiddleware`.

## Developer overrides

| Override | Applied when | Effect on this library |
| --- | --- | --- |
| `IEnvironmentClient.IsDeveloperMachine()` | Evaluated once when the `DataProtectionCertService` singleton is constructed | A missing `DPCertName` certificate returns `null` instead of throwing; the cookie key ring in `DPKeyDirectory` is then written without certificate encryption |
| Developer settings override file (`AppSettings:EnvApiDeveloperSettingsOverride`, conventionally `developersettings.json`) | Developer machine and the file exists; re-read on each non-secure lookup | Can override any non-secure `NetCore_OIDC.*` value by entries with `section: "NetCore_OIDC"`, matched case-insensitively. It cannot override `BOLAppCredentials`, because secure reads bypass the override. It can be used locally to supply the typo key `RoleClaimIdentitifier`* |

The library ships no developer settings file of its own.

## Environment variables

The library reads no environment variables directly. These are read by packages and the host that activate or support OIDC, and are listed for completeness.

| Variable | Read by | Scope | Accepted values | Default when unset | Effect on this library |
| --- | --- | --- | --- | --- | --- |
| `ASPNETCORE_HOST_LOCATION` | `AppStartup.HostLocation` (ServiceExtensions) | Process, then Machine (Windows-only) | `EXTERNAL`/`INTERNAL` (case-insensitive) | `NotDefined` | Only `EXTERNAL` registers and wires OIDC; `RegisterOidcServices` and the `LowerCaseUrl`/`JwtClaim`/`RefreshJwt` middleware run only then |
| `ASPNETCORE_REDIRECT_SSL` | `AppStartup.EnforceSslRedirect` | Machine only | `true`/`false` | `true` | HTTPS redirection runs after the OIDC middleware, so it is relevant to the cookie `SecurePolicy` risk |
| `EnvironmentApiUrl` | `BaseEnvironmentClient` field initializer | Process | absolute URL | none → `MissingEnvironmentUrlVariableException` | No OIDC setting can be resolved without it |
| `COREAPIENABLED` (usually `ASPNETCORE_COREAPIENABLED`) | `SecureEnvironmentClient` ctor | via `IConfiguration` | `1` | unset → secure client throws unless on a developer machine | `AppStartup` registers the secure client, and `BOLAppCredentials` needs it |

## Database connection configuration

Not applicable. This library has no database access, no `IDBConnectionClient` usage, and no connection strings. Persistence is limited to the file system (data-protection key ring at `DPKeyDirectory`) and the Windows certificate store (`DPCertName`, LocalMachine\My, read-only).

## Secure settings

| Setting key | Retrieval | Hash method | Application type | Application name (hash input) | Credential provided |
| --- | --- | --- | --- | --- | --- |
| `NetCore_OIDC:BOLAppCredentials` | `IEnvironmentClient.GetSecureSetting(key, section, systemHashValue)` | `ISystemHashService.ComputeHash(SystemType, string)` | `SystemType.Other` | `Assembly.GetExecutingAssembly().GetName().Name` = `SAIF.NetCore.OIDC` (the library assembly, not the host app) | Okta OIDC client credentials, `clientId\|clientSecret`, parsed by `OidcAppCredentials` |

Notes: the hash input is the OIDC assembly name, so every consuming application presents the same system hash for this secret — crypto-API authorization cannot distinguish one consuming app from another. The secure client is required (`BaseEnvironmentClient.RetrieveSecureSetting` always throws `EnvironmentClientException`); `AppStartup` registers `SecureEnvironmentClient`. On the standard `SecureEnvironmentClient`, `RetrieveSecureSetting<T>` itself throws `EnvironmentClientException` if the cached/fetched value is `null` or the type default, before the value is ever returned to `OidcSettings.AppCredentials` — so the credential-parsing constructor `OidcAppCredentials` (declared in `SAIF.NetCore.ServiceContracts`, not in this library's `OidcSettings.cs`) never observes a `null` raw value through that path. `OidcAppCredentials` separately and independently rejects a `null` raw value with `ArgumentNullException` and a non-`null` but malformed (wrong pipe-field-count) raw value with `ArgumentException`. Because `SecureEnvironmentClient` validates only for `null`/default and performs no pipe-field validation, a non-null malformed secret reaches this parser through the **standard** client and triggers the `ArgumentException` branch there; only the `ArgumentNullException` branch requires a custom `IEnvironmentClient` implementation that returns `null` where the standard client would have thrown first. The seed marks `BolAppCredentials` as `SecureFlag: true`; its value is a reference and is not reproduced here.

## Transitive configuration (from dependencies)

| Key / input | Required by | Why this library needs it |
| --- | --- | --- |
| `EnvironmentApiUrl` (env var) | `SAIF.NetCore.EnvironmentClient` | All 20 Environment API reads |
| `COREAPIENABLED=1` (server) | `SecureEnvironmentClient` | `BOLAppCredentials` secure read |
| `AppSettings:ApplicationHost`, `AppSettings:EnvApiDeveloperOverrideAllowed`, `AppSettings:EnvApiDeveloperSettingsOverride` | `HostResolver`/`BaseEnvironmentClient` | Track resolution; developer flag; override file |
| `EnvironmentClient:GetHostsByTrack:RetryCount`/`:RetrySleepMs` (optional) | `BaseEnvironmentClient` | Startup resilience of the client this library depends on |
| `ISystemHashService` registration (assembly-based) | `SAIF.NetCore.SystemHash` | Hash for `BOLAppCredentials` |
| `ISaifLogService` and its configuration | `SAIF.NetCore.Logging` | Error/warning logging in options, middleware, and the certificate service |
| `IHttpJsonClient` | `SAIF.NetCore.HttpClients` | `JwtRefreshService` POST to Okta |
| Host toggles `AppStartup.AuthenticationChallengeType` (default `Cookie`) and `AppStartup.UseJwtRefreshMiddleware` (default `true`) | `SAIF.NetCore.ServiceExtensions` | Code properties, not configuration keys. `LowerCaseUrlMiddleware` and `RefreshJwtMiddleware` are always registered as concrete scoped types by `RegisterOidcServices`, regardless of either toggle; `AuthenticationChallengeType` instead decides only whether `LowerCaseUrlMiddleware` is added to the pipeline by `AppStartup.Configure`, and `UseJwtRefreshMiddleware` decides both whether `IJwtRefreshService` is registered in DI and whether `RefreshJwtMiddleware` is added to the pipeline — see [Service registration](service-registration.md) |

This library has no ProjectReferences and only one internal package reference, `SAIF.NetCore.ServiceContracts`, which is contracts-only with no configuration reads of its own.

## Environment variance assessment

The seed files (`EnvironmentSettings.json`, `.global.json`, `.enttest7.json`) are solution items, not compiled, and imply a pattern of global defaults plus a per-track `OktaBaseUrl`. Only one track, `enttest7`, is represented in this repository.

| Setting key | Varies by environment | Classification basis |
| --- | --- | --- |
| `BOLAppCredentials` | Yes | Credential; Okta app per tenant* |
| `OktaBaseUrl` | Yes | Tenant host URL; the only key with a per-track seed file |
| `OktaAuthorizationServerUrl` | No (typically) | Static path `/oauth2/default`, same in all seeds |
| `RefreshTokenUrl`, `RefreshTokenQueryString` | No | Okta protocol constants* |
| `RefreshTokenRedirectUrl`, `CookieLoginPath`, `CookieSigninUri`, `CookieAccessDeniedPath`, `CallbackPath`, `SignedOutCallbackPath` | No | Relative app paths, identical across hosts* |
| `CookieName`, `DPApplicationName` | No — must be identical across all SSO apps in an environment | Shared-cookie SSO depends on equality* |
| `DPKeyDirectory` | Possibly (per server farm) | File-system path; must be shared or synchronized per farm* |
| `DPCertName` | Possibly | Certificate subject may differ per environment PKI* |
| `CookieExpireMinutes`, `ClockSkewSeconds`, `RoleTransformCacheOffset` | No | Numeric thresholds* |
| `DefaultOidcScope` | No | Static scope list* |
| `RoleClaimIdentitifier` (code) / `RoleClaimIdentifier` (seed) | No | Static claim pattern `_roles_`; see CR-01 for the key mismatch |
| `ASPNETCORE_HOST_LOCATION` (transitive) | Yes (per server role) | Decides whether OIDC is active at all |

## Configuration dependencies (risks)

| ID | Risk | Severity |
| --- | --- | --- |
| CR-01 | `RoleClaimIdentitifier`/`RoleClaimIdentifier` key mismatch: the code requests `netcore_oidc.roleclaimidentitifier`; the seed defines `RoleClaimIdentifier`. Lower-casing does not reconcile a spelling difference, so the read returns `""`, and `RoleClaimService` matches every non-array claim type. Impact is limited today only because the transformer is registered as a concrete type, not as `IClaimsTransformation` (see [Security and authorization](security-authorization.md)). | **High** (conditional) |
| CR-02 | `OktaBaseUrl` absent from the global seed; any track without its own override has an empty authority, so OIDC metadata retrieval and `JwtRefreshService` both fail. | Medium |
| CR-03 | Silent empty-string defaults on 16 string keys; misconfiguration surfaces later as broken redirects, empty scopes, or an invalid authority rather than a clear startup error. | Medium |
| CR-04 | Int keys throw at singleton/options construction: a missing `RoleTransformCacheOffset` breaks DI resolution of the claim-transform chain; a missing `CookieExpireMinutes` or `ClockSkewSeconds` breaks the auth options build, failing every authenticated request. | Medium |
| CR-05 | No cookie `SecurePolicy`; HTTPS redirect is controlled by `ASPNETCORE_REDIRECT_SSL` and runs after the OIDC middleware. | Medium |
| CR-06 | Single secure-hash identity (`SystemType.Other` + `"SAIF.NetCore.OIDC"`) for every consuming app's client secret. | Design / Medium |
| CR-07 | Settings captured for the process lifetime in singletons and options; Environment API changes need an app restart. | Low |
| CR-08 | The developer-machine flag disables certificate encryption of the cookie key ring; a misdetected developer flag on a server would silently weaken data protection. | Medium |
| CR-09 | `DPKeyDirectory` must be shared across farm nodes and readable by the app pool, or cookies fail to decrypt on other nodes. | Medium |
| CR-10 | `RefreshTokenQueryString` contains an unencoded space and is concatenated with an unencoded refresh token. | Low |
| CR-11 | Orphaned keys `JwtSigningKeysUrl` and `JwtSigninKeysExpireMinutes` are declared but never read. | Low (tech debt) |
| CR-12 | This library is activated by an environment variable (`ASPNETCORE_HOST_LOCATION=EXTERNAL`); a missing or incorrect value silently leaves the site without OIDC. | Medium |

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Security and authorization](security-authorization.md)
- [Service registration](service-registration.md)
- [API reference](api/index.md)

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Sources
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/OidcSettings.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Constants.cs`
- `src/SAIF.NetCore.OIDC/src/SAIF.NetCore.OIDC/Services/DataProtectionCertService.cs`
- `src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/OidcAppCredentials.cs` (consumer dependency; owns the `clientId|clientSecret` parsing and the `ArgumentNullException`/`ArgumentException` credential-parser failure modes documented on this page)
- `src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/BaseEnvironmentClient.cs` (consumer dependency; `GetSettingValue`/`GetSettingValue<int>` lookup, lower-casing, and missing-key behavior documented on this page)
- `src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SecureEnvironmentClient.cs` (consumer dependency; `GetSecureSetting`/`RetrieveSecureSetting` decryption and null/default failure behavior for `BOLAppCredentials`)
- `src/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/SAIF.NetCore.EnvironmentClient/HostResolver.cs` (consumer dependency; developer-override and track-resolution behavior)
- `src/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/SAIF.NetCore.ServiceContracts/IOidcSettings.cs` (consumer dependency; defines the `RefresnTokenUrl` property-name typo referenced on this page)
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` (consumer composition; `ASPNETCORE_HOST_LOCATION`/`ASPNETCORE_REDIRECT_SSL`/`AuthenticationChallengeType`/`UseJwtRefreshMiddleware` host toggles documented on this page)
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IServiceCollectionExtensions.cs` (consumer composition; `RegisterOidcServices` registration conditions documented on this page)
- `src/SAIF.NetCore.OIDC/src/EnvironmentSettings.json` (seed defaults declaring source)
- `src/SAIF.NetCore.OIDC/src/EnvironmentSettings.global.json` (seed defaults declaring source; absence of `OktaBaseUrl` documented on this page)
- `src/SAIF.NetCore.OIDC/src/EnvironmentSettings.enttest7.json` (track-specific seed override declaring source)

