External Event Reported (v1)

Event reported by a non-Plumery service to be recorded in the shared audit trail

Event published by a non-Plumery service to record an action in the shared audit trail, alongside entries generated from actions taken inside Plumery

How to Publish Audit Events from External Services

Overview

By default, Plumery’s audit trail captures all user interactions (HTTP requests) coming into Plumery services

Audit trail also supports events coming from non-Plumery services. To enable this, the bespoke service needs to send an ExternalEventReported event for every request

This is useful when:

  • The action is performed entirely outside Plumery (e.g. by a partner or bespoke service)
  • You need the action to be queryable and exportable through the same audit-trail-api used for Plumery-native audit entries
  • You want the event clearly attributed to its originating service, distinct from Plumery’s own access-log entries

How It Works

You publish a CloudEvents-compatible Avro record to the dedicated topic audit.event.external. Once received, the audit-trail service will:

  1. Validate the event against the ExternalEventReported schema
  2. Persist it, tagged with origin: EXTERNAL and the publishing eventSource
  3. Make it queryable and exportable via the existing audit-trail-api search/export endpoints, filterable by source

Events that fail schema validation are routed to the audit.dlq dead-letter topic instead of being recorded

Event Payload Structure

{
  "id": "a1cc063a-76b0-4a88-a60f-2f640a859b0e",
  "eventSource": "partner-payments-service",
  "type": "com.partner.payments.PaymentInitiated",
  "time": 1779119676000,
  "action": "PaymentInitiated",
  "description": "Payment initiated by partner",
  "userId": "partner-service-user-42",
  "partyId": null,
  "staffId": null,
  "staffRoles": null,
  "userLocation": null,
  "userAgent": null,
  "sessionId": null,
  "apiRequest": null,
  "responseStatusCode": 200,
  "responseStatus": "OK",
  "metadata": "{\"correlationId\":\"c1a2b3\"}",
  "payload": "{\"amount\":100,\"currency\":\"USD\"}"
}

Field Reference

  • id - Unique event identifier, assigned by the publisher
  • eventSource - Identifies who/what the event is about: the publishing service name, or a business resource identifier such as payment:6878951b-256b-4baa-9e81-ad4c577adc4e
  • type - Event type, e.g. com.partner.payments.PaymentInitiated
  • time - When the action occurred, as milliseconds since the Unix epoch, e.g. 1779119676000
  • action - What happened, e.g. PaymentInitiated
  • description (optional) - Human-readable description of the action
  • userId / partyId / staffId (optional) - Identifiers of the acting end-user, party or staff member, if known to the publisher
  • staffRoles (optional) - Roles of the acting staff member, if applicable
  • userLocation / userAgent / sessionId (optional) - Context of the acting client, if known
  • apiRequest (optional) - Details of the API request that triggered the action (requestId, uri, httpMethod, requestBody), if applicable
  • responseStatusCode / responseStatus (optional) - HTTP response outcome of the action, if applicable
  • metadata (optional) - Free-form JSON-encoded context
  • payload (optional) - Free-form JSON-encoded payload

Note: masking of sensitive data (e.g. PII, card numbers) is the publisher’s responsibility — the audit-trail service stores metadata and payload as provided

Architecture

Schema

Message Schema
{
"type": "record",
"name": "ExternalEventReported",
"namespace": "com.plumery.audittrail.events",
"doc": "A generic event reported by a non-Plumery service to be recorded in the shared audit trail",
"fields": [
{
"name": "id",
"type": "string",
"doc": "Unique event identifier"
},
{
"name": "eventSource",
"type": "string",
"doc": "Origin/context the event is about, e.g. publishing service name or a business resource identifier such as payment:6878951b-256b-4baa-9e81-ad4c577adc4e"
},
{
"name": "type",
"type": "string",
"doc": "Event type, e.g. com.partner.payments.PaymentInitiated"
},
{
"name": "time",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
},
"doc": "When the action occurred"
},
{
"name": "action",
"type": "string",
"doc": "What happened, e.g. PaymentInitiated"
},
{
"name": "description",
"type": [
"null",
"string"
],
"default": null,
"doc": "Human-readable description of the action"
},
{
"name": "userId",
"type": [
"null",
"string"
],
"default": null,
"doc": "Identifier of the acting end-user, if known to the publisher"
},
{
"name": "partyId",
"type": [
"null",
"string"
],
"default": null,
"doc": "Identifier of the acting party, if known to the publisher"
},
{
"name": "staffId",
"type": [
"null",
"string"
],
"default": null,
"doc": "Identifier of the acting staff member, if known to the publisher"
},
{
"name": "staffRoles",
"type": [
"null",
{
"type": "array",
"items": "string"
}
],
"default": null,
"doc": "Roles of the acting staff member, if applicable"
},
{
"name": "userLocation",
"type": [
"null",
"string"
],
"default": null,
"doc": "Location the action was performed from, if known"
},
{
"name": "userAgent",
"type": [
"null",
"string"
],
"default": null,
"doc": "User agent of the acting client, if known"
},
{
"name": "sessionId",
"type": [
"null",
"string"
],
"default": null,
"doc": "Session identifier, if known"
},
{
"name": "apiRequest",
"type": [
"null",
{
"type": "record",
"name": "ApiRequest",
"fields": [
{
"name": "requestId",
"type": [
"null",
"string"
],
"default": null
},
{
"name": "uri",
"type": "string"
},
{
"name": "httpMethod",
"type": "string"
},
{
"name": "requestBody",
"type": [
"null",
"string"
],
"default": null
}
]
}
],
"default": null,
"doc": "Details of the API request that triggered the action, if applicable"
},
{
"name": "responseStatusCode",
"type": [
"null",
"int"
],
"default": null,
"doc": "HTTP response status code of the action outcome, if applicable"
},
{
"name": "responseStatus",
"type": [
"null",
"string"
],
"default": null,
"doc": "Response status description of the action outcome, if applicable"
},
{
"name": "metadata",
"type": [
"null",
"string"
],
"default": null,
"doc": "Free-form JSON-encoded context"
},
{
"name": "payload",
"type": [
"null",
"string"
],
"default": null,
"doc": "Free-form JSON-encoded payload"
}
]
}