Skip to content

Audit Service ​

audit-service owns compliance-grade append-only audit and security event history for native Go services. It is a downstream event sink, not a domain decision maker.

Audit-service now has an internal admin operations audit compatibility preview. A non-default gateway route rehearsal maps GET /api/admin/operations/audit to that preview. A local browser proof exists, but the default public route remains on the existing admin-service compatibility path until legacy backfill, response parity, and rollback evidence explicitly promote audit-service.

Boundary ​

Owns:

  • Append-only audit events with actor, account, action, entity, source service, source event id, outcome, severity, category, request/correlation IDs, metadata schema version, retention policy, legal hold, content hash, and metadata fields.
  • Append-only security events with principal, event type, risk level, success, reason, account, source service, source event id, request/correlation IDs, metadata schema version, retention policy, legal hold, content hash, and metadata fields.
  • IAM security-event projections sent by the optional IAM sink with sourceService=iam-service, replay-safe sourceEventId, redacted metadata, metadataSchemaVersion=1, and retentionPolicy=security.
  • Admin operations audit projections sent by the optional admin-service sink with sourceService=admin-service, replay-safe sourceEventId=<admin audit log id>, category=ADMIN, severity=INFO, metadataSchemaVersion=1, and retentionPolicy=admin-operations.
  • Wallet ledger projections sent by the optional wallet-service sink with sourceService=wallet-service, replay-safe sourceEventId=<ledger entry id>, category=DOMAIN, severity=INFO, metadataSchemaVersion=1, and retentionPolicy=wallet-ledger.
  • Billing event projections sent by the optional billing-service sink with sourceService=billing-service, replay-safe sourceEventId=<billing event id>, category=DOMAIN, severity=INFO, metadataSchemaVersion=1, and retentionPolicy=billing-events.
  • Payment event projections sent by the optional payment-service sink with sourceService=payment-service, replay-safe sourceEventId=<payment event id>, category=DOMAIN, severity=INFO, metadataSchemaVersion=1, and retentionPolicy=payment-events.
  • Notification event projections sent by the optional notification-service sink with sourceService=notification-service, replay-safe sourceEventId=<notification event id>, category=DOMAIN, severity=INFO, metadataSchemaVersion=1, and retentionPolicy=notification-events.
  • Profile event projections sent by the optional profile-service sink with sourceService=profile-service, replay-safe sourceEventId=<profile event id>, category=DATA, severity=INFO, metadataSchemaVersion=1, and retentionPolicy=profile-events.
  • Query filters for compliance review and retention scans.

Does not own:

  • Feature maintenance, moderation, admin dashboards, support workflows, or source domain writes. Those stay in owner services or admin-service.
  • IAM credentials, sessions, roles, or permission checks.
  • Wallet/payment/billing ledger decisions.
  • Public route compatibility until a gateway cutover task explicitly adds it.

Native Routes ​

MethodPathPurpose
POST/v1/audit-eventsAppend an audit event idempotently by id or (sourceService, sourceEventId).
GET/v1/audit-eventsQuery audit events by org, actor, account, source, category, severity, action, entity, outcome, date, retention, and legal hold.
POST/v1/audit-events/legacy-admin-logProject one read-only legacy AuditLog row into audit-service with sourceService=admin-service, sourceEventId=<legacy AuditLog id>, and createdAt -> occurredAt.
POST/v1/audit-events/legacy-admin-log/batchProject already-read legacy AuditLog rows and return processed/created/replayed/failed counts plus per-row failures.
GET/v1/admin/operations/audit-compatInternal compatibility preview for the legacy admin operations audit list. Requires X-Internal-Service: api-gateway, the shared internal token, and X-User-Id/X-User-Role: ADMIN; preserves action, entity, limit, skip, newest-first {items,total,skip,limit}, legacy/source id, Vietnamese metadata labels, and createdAt mapped from occurredAt.
POST/v1/security-eventsAppend a security/auth event idempotently by id or (sourceService, sourceEventId).
GET/v1/security-eventsQuery security events by principal, account, source, type, risk, success, date, retention, and legal hold.

Legacy Evidence ​

Legacy AuditLog has stable organizationId, actorId, action, entity, entityId, metadata, and createdAt fields. The current public GET /api/admin/operations/audit list shape supports action, entity, limit, and skip, returns newest-first {items,total,skip,limit}, and is still covered by the admin-service route rehearsal until a separate compatibility task moves it.

Native legacy projection:

Compliance scans:

  • retentionBefore=<date-time> returns rows with non-empty retentionUntil at or before the timestamp.

  • legalHoldBefore=<date-time> returns rows with non-empty legalHoldUntil at or before the timestamp. It is available on both audit and security event list routes for retention/legal-hold review jobs.

  • POST /v1/audit-events/legacy-admin-log is an internal projection/backfill route for a single already-read legacy AuditLog row.

  • POST /v1/audit-events/legacy-admin-log/batch accepts up to 500 already-read legacy rows and reports processed, created, replayed, failed, projected items, and per-row failures.

  • It maps id -> sourceEventId, organizationId, actorId, action, entity, entityId, metadata, and createdAt -> occurredAt.

  • It writes sourceService=admin-service, category=ADMIN, severity=INFO, and metadataSchemaVersion=1.

  • Replaying the same legacy id returns the original projected audit event and does not mutate it. Batch replay counts these rows as replayed.

  • GET /v1/admin/operations/audit-compat reads ADMIN audit events through audit-service and returns the legacy admin operations page shape with action/entity filters, limit/skip, newest-first rows, and createdAt mapped from occurredAt. For projected legacy rows, id is the original legacy/source id. The read requires api-gateway internal authentication plus a forwarded ADMIN principal; direct, forged, missing, or non-ADMIN headers are rejected.

  • It does not read from or mutate the legacy database. Backfill jobs must read legacy rows externally and post them to the single-row or batch projection route.

Gateway rehearsal:

  • deploy/gateway/routes.audit-admin-compat-native-example.json maps GET /api/admin/operations/audit to audit-service /v1/admin/operations/audit-compat for Compose.
  • deploy/gateway/routes.audit-admin-compat-native-localhost-example.json maps the same public route to http://localhost:8101 for local go run.
  • make test-audit-admin-compat-routes verifies the non-default route examples, gateway behavior, ADMIN role guard, exact-method capture, query forwarding, and legacy fallback for writes/nested admin operations routes.
  • make test-admin-audit-owner-browser starts a fresh audit Postgres cluster, temporary audit-service/Gateway/Admin Vite processes, then proves the Admin Operations audit tab renders the owner response through the exact candidate route. It removes the temporary cluster and processes on exit.
  • The default deploy/gateway/routes.json remains legacy until browser/runtime proof, backfill proof, response parity, and rollback evidence are recorded.

Legacy reader command:

bash
LEGACY_DATABASE_URL='postgres://legacy-readonly:...' \
AUDIT_SERVICE_URL='http://localhost:8080' \
GOTOOLCHAIN=go1.25.11 go run ./services/audit-service/cmd/legacy-admin-audit-backfill \
  -batch-size 200

The command reads "AuditLog" in read-only transactions, posts batches to /v1/audit-events/legacy-admin-log/batch, and prints the aggregate report. Use -dry-run to count legacy rows without posting.

Verification ​

bash
GOTOOLCHAIN=go1.25.11 go test ./services/audit-service/... -count=1

Optional Postgres repository integration:

bash
AUDIT_SERVICE_POSTGRES_TEST_DATABASE_URL='postgres://hoctapaz:hoctapaz@localhost:5433/hoctapaz_platform?sslmode=disable' \
  GOTOOLCHAIN=go1.25.11 go test ./services/audit-service/internal/repository \
  -run TestPostgresAuditAndSecurityIntegration -count=1 -v

Go-platform documentation is generated from repository Markdown.