Module: ForestAdminAgent::AuditTrail

Defined in:
lib/forest_admin_agent/audit_trail.rb,
lib/forest_admin_agent/audit_trail/diff.rb,
lib/forest_admin_agent/audit_trail/store.rb,
lib/forest_admin_agent/audit_trail/capture.rb,
lib/forest_admin_agent/audit_trail/recording.rb,
lib/forest_admin_agent/audit_trail/snapshots.rb,
lib/forest_admin_agent/audit_trail/audit_record.rb,
lib/forest_admin_agent/audit_trail/record_state.rb,
lib/forest_admin_agent/audit_trail/sql/migrator.rb,
lib/forest_admin_agent/audit_trail/sql/audit_log.rb,
lib/forest_admin_agent/audit_trail/action_capture.rb,
lib/forest_admin_agent/audit_trail/sql/migrations.rb,
lib/forest_admin_agent/audit_trail/sql/text_search.rb,
lib/forest_admin_agent/audit_trail/sql/field_filter.rb,
lib/forest_admin_agent/audit_trail/sql/audit_connection_base.rb

Overview

The audit trail is inert unless config.audit_trail[:database] was set: the agent factory builds the store during setup — connecting and migrating there rather than on first write — and everything (capture layers and routes) resolves it from here.

Defined Under Namespace

Modules: Diff, RecordState, Recording, Sql Classes: ActionCapture, AuditRecord, Capture, Snapshots, Store

Constant Summary collapse

MAX_RECORDS_PER_OPERATION =

One operation must not materialise an unbounded number of records: a "delete all" would otherwise read every matched row and, with the pending/confirm protocol, write each of them twice. Truncation is logged, never silent.

Matches the Node agent's MAX_SNAPSHOT_RECORDS: the same feature behind the same config key, so a bulk operation must not be audited on one agent and truncated on the other. Change it in both or neither.

1000

Class Method Summary collapse

Class Method Details

.critical?Boolean

critical: true makes the pending insert a precondition of the write: if the audit trail cannot record that an operation is about to happen, the operation is refused. Nothing was written, so there is nothing to repair and no compensating write ever happens. Default false keeps today's behaviour, where a broken audit database costs rows rather than writes.

Returns:

  • (Boolean)


47
48
49
# File 'lib/forest_admin_agent/audit_trail.rb', line 47

def self.critical?
  options[:critical] == true
end

.gateObject

Runs the pending insert under the configured policy: refusing the operation when critical, logging and carrying on otherwise.



57
58
59
60
61
62
63
64
65
66
# File 'lib/forest_admin_agent/audit_trail.rb', line 57

def self.gate
  return yield if critical?

  begin
    yield
  rescue StandardError => e
    log_failure(e)
    nil
  end
end

.log_failure(error) ⇒ Object



51
52
53
# File 'lib/forest_admin_agent/audit_trail.rb', line 51

def self.log_failure(error)
  Facades::Container.logger.log('Error', "[ForestAdmin] Audit trail unavailable, skipping: #{error.message}")
end

.log_truncation(kept, total) ⇒ Object



23
24
25
26
27
28
29
30
31
# File 'lib/forest_admin_agent/audit_trail.rb', line 23

def self.log_truncation(kept, total)
  skipped = total ? total - kept : 'further'

  Facades::Container.logger.log(
    'Warn',
    "[ForestAdmin] Audit trail: #{kept} records audited, #{skipped} skipped " \
    "(cap #{MAX_RECORDS_PER_OPERATION} per operation)"
  )
end

.optionsObject



33
34
35
36
37
# File 'lib/forest_admin_agent/audit_trail.rb', line 33

def self.options
  config = Facades::Container.config_from_cache

  (config && config[:audit_trail]) || {}
end

.refuse_over_cap!Object

Auditing a subset while the write touches every match is the one thing critical exists to prevent, so over the cap the operation is refused instead — before anything is written, in both the write and the action path, which is why the message lives here rather than in either of them.

Raises:

  • (ForestAdminDatasourceToolkit::Exceptions::ForestException)


17
18
19
20
21
# File 'lib/forest_admin_agent/audit_trail.rb', line 17

def self.refuse_over_cap!
  raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
        'The audit trail is configured as critical and cannot record an operation touching more than ' \
        "#{MAX_RECORDS_PER_OPERATION} records at once. Narrow the selection."
end

.storeObject



39
40
41
# File 'lib/forest_admin_agent/audit_trail.rb', line 39

def self.store
  options[:store]
end