StellaOps Authority Audit Events
Audience: SOC/SecOps, Authority Core, compliance and evidence engineers. Scope: The Authority audit-event contract, its data classifications and event catalogue, PostgreSQL persistence, and the EvidenceLocker EU regulatory audit catalogue.
Related: Authority threat model · Authority scopes · EU regulatory audit-event contract (
../contracts/eu-regulatory-audit-events-v1.md).
StellaOps Authority emits structured audit records for every credential flow and bootstrap operation. The goal is to provide deterministic, privacy-aware telemetry that can be persisted offline and replayed for incident response without leaking credentials.
Contract
Audit events share the StellaOps.Cryptography.Audit.AuthEventRecord contract (defined in src/__Libraries/StellaOps.Cryptography/Audit/AuthEventRecord.cs). Key fields:
EventType— canonical identifier such asauthority.password.grant,authority.client_credentials.grant, orauthority.bootstrap.user.OccurredAt— UTC timestamp captured at emission time (defaults toDateTimeOffset.UtcNow; deterministic callers set it explicitly).CorrelationId— stable identifier propagated across logs, traces, and persistence (nullable).Outcome—AuthEventOutcomeenum:Unknown(default),Success,Failure,LockedOut,RequiresFreshAuth,RequiresMfa,RateLimited, orError. When persisted, the outcome is normalised to a lowercase snake-case string (success,failure,locked_out,rate_limited,error); any other value — includingUnknown,RequiresFreshAuth, andRequiresMfa— is persisted asunknown.Reason— optional failure or policy message.Subject—AuthEventSubjectcarrying subject identifier, username, display name, optional realm metadata, and anAttributeslist of additional classified properties (e.g.subject.email). All core subject fields are tagged as PII.Client—AuthEventClientwith client identifier (PII for confidential clients), friendly name, and originating provider/plugin.Tenant—ClassifiedStringtenant identifier associated with the authenticated principal or client (defaults toClassifiedString.Empty).Project—ClassifiedStringproject identifier (optional; defaults toClassifiedString.Empty).Scopes— granted or requested OAuth scopes (IReadOnlyList<string>; deduplicated and sorted ordinally before persistence).Network—AuthEventNetworkwith remote address, forwarded headers, and user agent string (all treated as PII).Properties— additionalAuthEventPropertyentries for context-specific details (lockout durations, policy decisions, retries,request.tampered/request.unexpected_parameter,client.confidential,bootstrap.invite_token, tenant compliance-profile attributes, etc.).
Records are written through the IAuthEventSink interface; the Authority host’s implementation is AuthorityAuditSink (src/Authority/StellaOps.Authority/StellaOps.Authority/Audit/AuthorityAuditSink.cs).
Data Classifications
Every string value uses ClassifiedString to assign a data classification:
None— public or operational metadata (event type, outcome).Personal— personally identifiable information (PII) such as subject identifiers, usernames, remote IP addresses, and user agents.Sensitive— secrets or derived credentials (client secrets, retry tokens). Avoid storing raw credentials; emit only hashed or summarised data when the classification isSensitive.
Downstream log sinks and persistence layers can inspect classifications to redact or separate PII before export.
Event Naming
Event names follow authority.<surface>.<action> dotted notation. The set below is the catalog of EventType values actually emitted to AuthEventRecord as of this writing (grouped by surface); it is not necessarily exhaustive across future releases. Note: OpenTelemetry activity/span names such as authority.token.validate_access, authority.token.handle_password_grant, authority.token.persist, and authority.token.revoke are tracing names, not audit EventType values, and are not persisted as audit records.
Token grants and tampering (OpenIddict handlers):
authority.password.grant— password grant handled by OpenIddict.authority.client_credentials.grant— client credential grant handling. (The legacy formauthority.client.credentialsstill appears in older fixtures.)authority.token.tamper— suspicious/tokenrequest detected (unexpected parameters or manipulated payload); carriesrequest.tampered/request.unexpected_parameterproperties.authority.token.replay.suspected— replay heuristics detected a token being used from a new device fingerprint.
DPoP sender-constraint validation (DpopHandlers):
authority.dpop.proof.valid— DPoP proof validated successfully.authority.dpop.proof.challenge— DPoP nonce challenge issued.authority.dpop.proof.bypass— DPoP enforcement temporarily bypassed (configured).authority.dpop.proof.disabled— client requires DPoP but server-side DPoP is disabled.authority.dpop.proof.error— DPoP validation aborted due to an error.
Bootstrap and invites:
authority.bootstrap.userandauthority.bootstrap.client— bootstrap API operations.authority.bootstrap.invite.created— operator created a bootstrap invite.authority.bootstrap.invite.consumed— invite consumed during user/client provisioning.authority.bootstrap.invite.released— invite released back to the pool.authority.bootstrap.invite.expired— invite expired without being used.authority.bootstrap.invite.rejected— invite was rejected (invalid, mismatched provider/target, or already consumed).
Delegation, AI, and deprecation:
authority.delegation.revoked— a delegated service-account grant was revoked.authority.advisory_ai.remote_inference— Advisory AI remote inference request audited.authority.api.legacy_endpoint— a deprecated legacy auth endpoint was invoked (LegacyAuthDeprecationMiddleware).authority.tenant_compliance_profile.read— tenant compliance profile read.
Resource authorization (StellaOpsScopeAuthorizationHandler):
authority.resource.authorize— scope authorization decision for a protected resource.authority.audit.authorize.emitted— companion audit-emission marker.
Standard plugin (StandardCredentialAuditLogger):
authority.plugin.standard.password_verification— password verification result from the standard identity plugin.
Console read endpoints (ConsoleEndpointExtensions):
authority.console.tenants.read,authority.console.profile.read,authority.console.token.introspect,authority.console.dashboard,authority.console.filters,authority.console.branding.readauthority.console.vuln.findings,authority.console.vuln.finding,authority.console.vuln.ticketauthority.console.vex.statements,authority.console.vex.events
Console Admin endpoints (ConsoleAdminEndpointExtensions, ConsoleBrandingEndpointExtensions):
- Tenants:
authority.admin.tenants.list/.create/.update/.suspend/.resume(plus failure variants such asauthority.admin.tenants.create.propagation_failedandauthority.admin.tenants.create.client_grant_failed). - Operator config:
authority.admin.operator_config.read/.update/.approver.assign/.approver.revoke/.pack.enable/.pack.disable/.pack.mode_change/.retention.change. - Users:
authority.admin.users.list/.create/.password.set/.update/.disable/.enable. - Roles:
authority.admin.roles.list/.create/.update/.preview. - Clients:
authority.admin.clients.list/.create/.update/.rotate. - Tokens:
authority.admin.tokens.list/.revoke. - Audit and branding:
authority.admin.audit.list,authority.admin.branding.read/.update/.preview.
Future additions should preserve the authority.<surface>.<action> pattern to keep filtering deterministic.
Note: break-glass session events use a separate
BreakGlassAuditEventcontract (BreakGlassSessionManager), notAuthEventRecord, and are out of scope for the fields described above.
Persistence
The Authority host (AuthorityAuditSink) converts audit records into AuthorityLoginAttemptDocument rows for PostgreSQL persistence (schema authority). The mapped document:
- Preserves
EventType,CorrelationId,SubjectId,Username,ClientId,Plugin(the client provider),Outcome(normalised lowercase snake-case),Reason,Tenant, andOccurredAt. - Stores the remote address in
RemoteAddress(falling back to the forwarded-for address), classified as PII. - Includes a summary
Successfulboolean (trueonly whenOutcome == Success) to accelerate lockout policy checks. - Persists deduplicated, ordinally sorted
Scopes. - Flattens subject, client, network, and contextual
PropertiesintoAuthorityLoginAttemptPropertyDocumentchild rows, each carrying its ownClassification(none/personal/sensitive). Subject attributes are namespaced assubject.attr.<name>; network values asnetwork.remote/network.forwarded_for/network.user_agent.
Tenant compliance-profile enrichment
When a tenant compliance-profile provider is registered and the record carries a known tenant, AuthorityAuditSink enriches the record with tenant.compliance_profile.* properties before persistence (schema version, presence flag, canonical SHA-256 hash, LEI, jurisdiction, responsibility locus, regulated regimes, and NIS2/CRA flags). Enrichment is skipped when the record already carries compliance-profile properties or the tenant is not found.
Timeline dual-write
In addition to the PostgreSQL row, AuthorityAuditSink performs a best-effort dual-write to the Timeline unified audit sink via IAuditEventEmitter (AuditEventPayload, Module = "authority", Action = EventType). This write is fire-and-forget: any failure is logged and never affects the local write or the calling endpoint. Severity is derived from the outcome (Failure/LockedOut → warning, Error → error, otherwise info).
When exporting to external SIEMs, honour the ClassifiedString.Classification tag (None / Personal / Sensitive) to avoid shipping PII into restricted environments.
EvidenceLocker EU Regulatory Audit Events
EvidenceLocker owns the EU regulatory audit event catalog used by CRA, NIS2, DORA, RoI, TLPT, and standards-mapping artifacts. The authoritative contract is docs/contracts/eu-regulatory-audit-events-v1.md.
Catalog names (from RegulatoryAuditEventNames in src/EvidenceLocker/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.Core/Regulatory/RegulatoryAuditEvent.cs):
evidence.eu.artifact.generatedevidence.eu.artifact.exportedevidence.eu.control.lifecycle_recordedevidence.eu.control.snapshot_publishedevidence.eu.artifact.approvedevidence.eu.artifact.rejectedevidence.eu.retention.override_recordedevidence.eu.schema_pin.changedevidence.eu.artifact.signedevidence.eu.artifact.verifiedevidence.eu.artifact.handed_offevidence.eu.submit.attemptedevidence.eu.public_metadata.published
Each event carries tenant id, actorKind (stella-manufacturer or customer-operator), regime, artifact type, artifact hash, schema/taxonomy pin ids, signer key/fingerprint where applicable, approver id where applicable, and prior/new value hashes for overrides. Classified properties are redacted before persistence: personal values become SHA-256 hashes and sensitive values become [redacted].
