Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5fa285d
Add files via upload
hilmarf Sep 19, 2025
040d5ba
REUSE status
hilmarf Apr 28, 2026
6803d8a
Ensure GHA work properly on fork or are disabled!
hilmarf Apr 28, 2026
a65b712
reuse download --all
hilmarf May 19, 2026
b5d4212
Add REUSE compliance: LICENSES/, .reuse/dep5, and fix invalid SPDX ex…
hilmarf May 19, 2026
3ea5d22
using APEIRORA_BOT
hilmarf Jun 4, 2026
6653e70
revert to upstream
hilmarf Jun 9, 2026
20f6b7b
add .dockerignore
hilmarf Jun 10, 2026
e15cc02
group = "eu.apeirora.opentelemetry"
hilmarf Jun 10, 2026
eb31429
Remap the Maven group to the Java package root:
hilmarf Jun 10, 2026
5951b7f
Add initial audit logging pipeline:
hilmarf Apr 28, 2026
780ffa2
Ensure GHA work properly on fork or are disabled!
hilmarf Apr 28, 2026
237bad1
refactor: migrated the separate package `api\audit` into `api\all`
hilmarf Apr 28, 2026
70fecae
refactored fields to attributes
hilmarf Apr 29, 2026
32ca0e7
integrityValue + algorithm + certificate
hilmarf Apr 29, 2026
8ab5b68
Add audit signal tests, fix exporter imports, update apidiffs and bui…
hilmarf Jun 5, 2026
cef7c30
sync with main
hilmarf Jun 8, 2026
74a272c
gradle jApiCmp
hilmarf Jun 9, 2026
287fe61
fix spotlessJavaCheck issues
hilmarf Jun 9, 2026
3a7faad
audit.* semantic conventions
hilmarf Jun 10, 2026
01aed0a
AuditRecordData extends LogRecordData
hilmarf Jun 10, 2026
9c7de86
simplify audit API
hilmarf Jun 10, 2026
b4d2414
Convert remaining declarative config factory tests to parameterized t…
jack-berg Jun 10, 2026
64c06d8
Exclude certain github actions from running on forks (#8466)
jaydeluca Jun 10, 2026
0b850e6
using APEIRORA_BOT
hilmarf Jun 4, 2026
0d282b0
revert to upstream
hilmarf Jun 9, 2026
3d3b253
build: add GitHub Packages repository to publish conventions
hilmarf Jun 10, 2026
f678551
build: restrict GitHub Packages publishing to SNAPSHOT versions only
hilmarf Jun 10, 2026
1c7a84e
ci: add snapshot publish workflow for GitHub Packages
hilmarf Jun 10, 2026
60c9398
docs: add GitHub Packages SNAPSHOT consumer guide
hilmarf Jun 10, 2026
85e5317
docs: clarify Maven CI settings.xml token wiring for GitHub Packages
hilmarf Jun 10, 2026
eb447d1
docs: update CLAUDE.md with language rules and publishing architecture
hilmarf Jun 10, 2026
2ca22d7
build: gate signing on GPG_PRIVATE_KEY instead of CI env var
hilmarf Jun 10, 2026
7884cee
ci: use targeted publish task to avoid Sonatype credential errors
hilmarf Jun 10, 2026
61bf20a
fix: resolve AutoValue constructor mismatch in SdkAuditRecordData
hilmarf Jun 10, 2026
eb2fd5b
apidiffs
hilmarf Jun 10, 2026
f03d26d
Merge branch 'main' into auditing
hilmarf Jun 10, 2026
ce6f533
remove duplicate condition
hilmarf Jun 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ class NoSharedInternalCodeTest {
"opentelemetry-exporter-common",
"opentelemetry-exporter-logging",
"opentelemetry-exporter-logging-otlp",
"opentelemetry-exporter-otlp-audit",
"opentelemetry-exporter-prometheus",
"opentelemetry-extension-trace-propagators",
"opentelemetry-opencensus-shim",
"opentelemetry-sdk-common",
"opentelemetry-sdk-audit",
"opentelemetry-sdk-logs",
"opentelemetry-sdk-metrics",
"opentelemetry-sdk-profiles",
Expand Down
23 changes: 23 additions & 0 deletions api/all/src/main/java/io/opentelemetry/api/audit/ActorType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.audit;

/**
* Classifies the kind of entity that performed an auditable action.
*
* @see AuditRecordBuilder#setActorType(ActorType)
*/
public enum ActorType {

/** A human user, identified by a user account. */
USER,

/** An automated service, daemon, or service account. */
SERVICE,

/** The operating system or a privileged system component. */
SYSTEM
}
63 changes: 63 additions & 0 deletions api/all/src/main/java/io/opentelemetry/api/audit/Audit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.audit;

/**
* Semantic convention attribute names for OpenTelemetry audit records.
*
* <p>These constants correspond to the {@code audit.*} attributes defined by the audit record data
* model.
*/
public final class Audit {

/** Unique stable identifier for an audit record. */
public static final String RECORD_ID = "audit.record.id";

/** Identity of the actor that performed the action. */
public static final String ACTOR_ID = "audit.actor.id";

/** Type of the actor that performed the action. */
public static final String ACTOR_TYPE = "audit.actor.type";

/** Verb describing what the actor did. */
public static final String ACTION = "audit.action";

/** Result of the auditable action. */
public static final String OUTCOME = "audit.outcome";

/** Identifier of the target resource acted upon. */
public static final String TARGET_ID = "audit.target.id";

/** Type of the target resource acted upon. */
public static final String TARGET_TYPE = "audit.target.type";

/** Identifier of the source of the auditable action. */
public static final String SOURCE_ID = "audit.source.id";

/** Type of the source of the auditable action. */
public static final String SOURCE_TYPE = "audit.source.type";

/** Base64-encoded cryptographic integrity proof for the record. */
public static final String INTEGRITY_VALUE = "audit.integrity.value";

/** Monotonic sequence number used for hash-chain continuity. */
public static final String SEQUENCE_NUMBER = "audit.sequence.number";

/** Hash of the previous record in the same audit stream. */
public static final String PREV_HASH = "audit.prev.hash";

/** Schema version of the audit payload. */
public static final String SCHEMA_VERSION = "audit.schema.version";

/** Resource attribute naming the integrity algorithm used for emitted audit records. */
public static final String INTEGRITY_ALGORITHM = "audit.integrity.algorithm";

/** Resource attribute referencing the certificate or key used for integrity proofs. */
public static final String INTEGRITY_CERTIFICATE = "audit.integrity.certificate";

private Audit() {}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.audit;

/**
* Hard-error thrown by {@link AuditRecordBuilder#emit()} when the audit sink cannot be reached and
* all retries are exhausted. This is an unchecked exception so that audit-logging call sites remain
* clean, but callers SHOULD catch it and escalate the failure through their incident-management
* process.
*/
public final class AuditDeliveryException extends RuntimeException {

private static final long serialVersionUID = 1L;

public AuditDeliveryException(String message) {
super(message);
}

public AuditDeliveryException(String message, Throwable cause) {
super(message, cause);
}
}
25 changes: 25 additions & 0 deletions api/all/src/main/java/io/opentelemetry/api/audit/AuditLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.audit;

import javax.annotation.concurrent.ThreadSafe;

/**
* The entry point for emitting audit records.
*
* <p>Obtain an {@link AuditRecordBuilder} via {@link #auditRecordBuilder()}, populate all required
* fields, and call {@link AuditRecordBuilder#emit()} to deliver the record to the audit sink.
*
* <p>Unlike {@link io.opentelemetry.api.logs.Logger}, this interface does <em>not</em> expose an
* {@code isEnabled} check: audit records are ALWAYS emitted. Dropping audit records is prohibited
* by the audit logging specification.
*/
@ThreadSafe
public interface AuditLogger {

/** Returns an {@link AuditRecordBuilder} for constructing and emitting an audit record. */
AuditRecordBuilder auditRecordBuilder();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.audit;

/**
* Builder for creating named {@link AuditLogger} instances.
*
* <p>The {@code name} (set on the owning {@link AuditProvider}) is stored as a diagnostic label on
* the logger. Unlike {@link io.opentelemetry.api.logs.LoggerBuilder}, the name is NOT mapped to an
* OTLP {@code InstrumentationScope}.
*/
public interface AuditLoggerBuilder {

/**
* Sets the schema URL to be recorded on emitted {@link AuditRecordBuilder}s for semantic
* convention versioning.
*/
AuditLoggerBuilder setSchemaUrl(String schemaUrl);

/** Sets the version of the component or library that is emitting audit records. */
AuditLoggerBuilder setInstrumentationVersion(String instrumentationVersion);

/** Returns the configured {@link AuditLogger}. */
AuditLogger build();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.audit;

import javax.annotation.concurrent.ThreadSafe;

/**
* The entry point of the Audit Logging API. Provides named {@link AuditLogger} instances.
*
* <p>The provider is expected to be accessed from a central place. Use {@link
* GlobalAuditProvider#get()} to obtain the globally registered instance, or create an {@link
* AuditProvider} directly via the SDK.
*
* <p>When no SDK is installed, {@link #noop()} returns an {@link AuditProvider} whose loggers emit
* no-op receipts without error.
*/
@ThreadSafe
public interface AuditProvider {

/**
* Gets or creates a named {@link AuditLogger} instance.
*
* @param name A string identifying the component or subsystem emitting audit records (for example
* {@code "com.example.auth"}). MUST NOT be empty.
*/
default AuditLogger get(String name) {
return auditLoggerBuilder(name).build();
}

/**
* Creates an {@link AuditLoggerBuilder} for a named {@link AuditLogger}.
*
* @param name A string identifying the component or subsystem emitting audit records. MUST NOT be
* empty.
*/
AuditLoggerBuilder auditLoggerBuilder(String name);

/**
* Returns a no-op {@link AuditProvider} whose loggers return no-op {@link AuditReceipt}s
* immediately without error.
*/
static AuditProvider noop() {
return DefaultAuditProvider.getInstance();
}
}
87 changes: 87 additions & 0 deletions api/all/src/main/java/io/opentelemetry/api/audit/AuditReceipt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.audit;

import javax.annotation.concurrent.Immutable;

/**
* Proof-of-delivery returned by {@link AuditLogger} once the audit sink has persisted the record.
*
* <p>The {@code recordId} echoes the caller's {@link AuditRecordBuilder#setRecordId(String)}.
* {@code integrityHash} is the SHA-256 of the record as written by the sink. {@code
* sinkTimestampEpochNanos} is the nanosecond UNIX epoch at which the sink persisted the record.
*/
@Immutable
public final class AuditReceipt {

private final String recordId;
private final String integrityHash;
private final long sinkTimestampEpochNanos;

private AuditReceipt(String recordId, String integrityHash, long sinkTimestampEpochNanos) {
this.recordId = recordId;
this.integrityHash = integrityHash;
this.sinkTimestampEpochNanos = sinkTimestampEpochNanos;
}

/** Creates an {@link AuditReceipt} with the given fields. */
public static AuditReceipt create(
String recordId, String integrityHash, long sinkTimestampEpochNanos) {
return new AuditReceipt(recordId, integrityHash, sinkTimestampEpochNanos);
}

/** Returns the {@code RecordId} echoed from the corresponding {@link AuditRecordBuilder}. */
public String recordId() {
return recordId;
}

/**
* Returns the SHA-256 hex digest of the canonical serialization of the {@code AuditRecord} as
* persisted by the audit sink.
*/
public String integrityHash() {
return integrityHash;
}

/** Returns the nanosecond UNIX epoch at which the audit sink persisted the record. */
public long sinkTimestampEpochNanos() {
return sinkTimestampEpochNanos;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof AuditReceipt)) {
return false;
}
AuditReceipt other = (AuditReceipt) obj;
return recordId.equals(other.recordId)
&& integrityHash.equals(other.integrityHash)
&& sinkTimestampEpochNanos == other.sinkTimestampEpochNanos;
}

@Override
public int hashCode() {
int result = recordId.hashCode();
result = 31 * result + integrityHash.hashCode();
result = 31 * result + Long.hashCode(sinkTimestampEpochNanos);
return result;
}

@Override
public String toString() {
return "AuditReceipt{"
+ "recordId="
+ recordId
+ ", integrityHash="
+ integrityHash
+ ", sinkTimestampEpochNanos="
+ sinkTimestampEpochNanos
+ "}";
}
}
Loading
Loading