API reference — Entry point

Nuvora.Nexus.Sentinel

Sentinel entry point: AddSentinel() dependency-injection wiring, options, and startup guards. Sentinel is a batteries-included, embeddable identity provider, authentication, and authorization platform for .NET.

dotnet add package Nuvora.Nexus.Sentinel

Nuvora.Nexus.Sentinel

SentinelOptions

public sealed class SentinelOptions

Top-level Sentinel configuration. Feature areas add their own options classes (SentinelTokenOptions, SentinelAbuseOptions, …) as they land; this class holds only what the core wiring itself consumes.

Properties

Guid DefaultRealmId { get; set; }

The default realm’s id — signing-key rings are per-realm, so single-realm hosts set this once. Guid.Empty is accepted (a valid single-realm deployment id); multi-realm routing replaces this in the reference server.

bool AllowDevelopmentDefaults { get; set; }

The environment gate for fail-fast checks: when false (production posture), missing signing-key configuration and similar unsafe defaults throw at startup instead of degrading. Hosts bind this to their environment; it defaults to strict.

string DefaultRealmKey { get; set; }

The realm this host serves by default when a request carries no explicit realm signal. Multi-realm hosts (the reference server) route per-request instead.

Nuvora.Nexus.Sentinel.DependencyInjection

BreakGlassLoginObserverGate

public sealed class BreakGlassLoginObserverGate : ILoginGate

ILoginGate decorator that watches for successful logins by break-glass-flagged users and fires BreakGlassService.HandleLoginAsync. The gate seam is the one place every password-login success flows through without modifying LoginService (same composition rule as the abuse gate). Observation is best-effort by gate contract: a failure here must never fail the login itself.

Constructors

BreakGlassLoginObserverGate(ILoginGate inner, IServiceScopeFactory scopeFactory)

ILoginGate decorator that watches for successful logins by break-glass-flagged users and fires BreakGlassService.HandleLoginAsync. The gate seam is the one place every password-login success flows through without modifying LoginService (same composition rule as the abuse gate). Observation is best-effort by gate contract: a failure here must never fail the login itself.

Methods

ValueTask RecordFailureAsync(string? ip, string identifier, Guid realmId, CancellationToken cancellationToken = default(CancellationToken))
ValueTask RecordSuccessAsync(string identifier, Guid realmId, CancellationToken cancellationToken = default(CancellationToken))

Realm-scoped like every counter key: one tenant’s traffic must not touch another’s thresholds.

ValueTask<bool> AllowAttemptAsync(string? ip, string identifier, Guid realmId, CancellationToken cancellationToken = default(CancellationToken))

SentinelAdminServiceCollectionExtensions

public static class SentinelAdminServiceCollectionExtensions

Registration for the delegated-administration surface. Separate from SentinelServiceCollectionExtensions.AddSentinel because the admin surface is an opt-in mount, not something every resource server hosting Sentinel authentication needs.

Methods

static IServiceCollection AddSentinelAdmin(this IServiceCollection services)

Registers SentinelAdminService, AuthorizationInspector and an in-memory IAdminStore default. Idempotent TryAdd registrations: register a persistent store first (e.g. AddSentinelEfCoreAdminStore()) and it wins over the in-memory default. Call alongside AddSentinel() — the service resolves the audit ledger, clock, cache bus, and snapshot source registered there.

SentinelBreakGlassServiceCollectionExtensions

public static class SentinelBreakGlassServiceCollectionExtensions

Registration for break-glass. Two decorations do the break-glass work structurally:

  • BreakGlassCappingDataSource wraps the registered ISubjectDataSource so a flagged account’s grants are capped at snapshot-build time — every evaluation path sees only the capped set, no login hook to forget.
  • A login-gate observer wraps ILoginGate so a successful break-glass login triggers the break-glass alarms (event + operator mail + rotation-required signal) without touching LoginService.

Call AFTER the subject data source is registered (store adapter or host registration) and after AddSentinel(), so both decorations wrap the real registrations.

Methods

static IServiceCollection AddSentinelBreakGlass(this IServiceCollection services, Action<BreakGlassPolicy>? configure = null)

SentinelHost

public static class SentinelHost

Startup-time initialization for hosts that don’t use the AspNetCore hosted service.

Methods

static Task InitializeAsync(IServiceProvider services, CancellationToken cancellationToken = default(CancellationToken))

SentinelImpersonationServiceCollectionExtensions

public static class SentinelImpersonationServiceCollectionExtensions

Registration for the impersonation surface. Opt-in like the admin surface: call alongside AddSentinel(); an EF host registers AddSentinelEfCoreStores first so the persistent IImpersonationStore wins over the in-memory default.

Methods

static IServiceCollection AddSentinelImpersonation(this IServiceCollection services, Action<SentinelImpersonationOptions>? configure = null)

SentinelLocalizationServiceCollectionExtensions

public static class SentinelLocalizationServiceCollectionExtensions

Registration for the i18n surface: the localizer port (embedded six-locale catalog by default) and the LocalizedMailerDecorator around whatever ISentinelMailer is registered. Opt-in like the other mounts — hosts that render their own templates simply never call this and keep receiving raw Kind + Data mails.

Methods

static IServiceCollection AddSentinelLocalization(this IServiceCollection services, Action<SentinelLocalizationOptions>? configure = null)

Adds ISentinelLocalizer (default: ResourceSentinelLocalizer, the embedded EN/DE/FR/ES/IT/RO catalog — a host localizer registered earlier wins) and wraps the current ISentinelMailer registration in LocalizedMailerDecorator, preserving its lifetime. Call AFTER registering your real mailer (and typically after AddSentinel()) so the decorator wraps it; with no mailer registered yet it decorates the NoopMailer default and any later TryAdd of a mailer is a no-op. Idempotent: a second call changes nothing.

SentinelPrivacyServiceCollectionExtensions

public static class SentinelPrivacyServiceCollectionExtensions

Registration for the privacy/GDPR surface: crypto-shredding, export/erasure, and the retention sweep. Opt-in like the admin surface. An EF host registers AddSentinelEfCoreStores first so the persistent key store and the EF IPersonalDataSource/IRetentionStore win; with the Core in-memory audit store, IRetentionStore resolves to that same instance.

Methods

static IServiceCollection AddSentinelPrivacy(this IServiceCollection services, Action<SentinelRetentionOptions>? configure = null)

SentinelServiceCollectionExtensions

public static class SentinelServiceCollectionExtensions

Methods

static IServiceCollection AddSentinel(this IServiceCollection services, Action<SentinelOptions>? configure = null)

Registers Sentinel’s core services and safe in-process defaults for every port. Idempotent and additive like Relay’s AddRelay: every registration uses TryAdd, so calling it twice is harmless and a host (or a store adapter package registered earlier) always wins over the defaults. What is NOT defaulted: the identity stores (IUserStore, IMfaStore, ISessionStore, ISubjectDataSource). Silently running an IdP on an in-memory user database is a footgun, not a default — register a store adapter (e.g. AddSentinelEfCoreStores) or your own implementations; the in-memory ones in Core are exported for tests and samples to opt into explicitly. After building the provider, call SentinelHost.InitializeAsync once at startup — it fail-fast-checks the signing keys and runs definition sync. The AspNetCore package does this via a hosted service.

SentinelWebhookServiceCollectionExtensions

public static class SentinelWebhookServiceCollectionExtensions

Registration for the outbound-webhook surface. Separate from SentinelServiceCollectionExtensions.AddSentinel because webhooks are an opt-in mount — hosts that only consume the in-process sink need none of this.

Methods

static IServiceCollection AddSentinelWebhooks(this IServiceCollection services, Action<WebhookDispatcherOptions>? configure = null)

Registers the webhook store (in-memory default — a persistent store registered earlier, e.g. AddSentinelEfCoreStores(), wins), WebhookAdminService, WebhookDispatcher, and the event-sink composition: the ISentinelEventSink registration becomes a CompositeEventSink of [whatever sink was already registered, webhook enqueue] — the host’s own sink keeps receiving every event, and the webhook outbox gets its copy. (A pre-existing NoopEventSinkAddSentinel()’s default — is dropped rather than pointlessly wrapped, so call order relative to AddSentinel() does not matter.) The sink registration stays SINGLETON (Core services like RefreshTokenService capture it at construction); the enqueue sink reaches the possibly DbContext-bound IWebhookStore by opening its own scope per emitted event. This wires enqueue only. Actually DELIVERING needs an HTTP transport (Func<WebhookRequest, CancellationToken, Task<int>>) and a poll loop — the AspNetCore package provides both via AddSentinelWebhookDispatcher(); non-web hosts register their own transport and call WebhookDispatcher.RunOnceAsync on their own schedule.