forest_admin_agent 1.38.3 → 1.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/AUDIT_TRAIL.md +347 -0
  3. data/lib/forest_admin_agent/audit_trail/action_capture.rb +99 -0
  4. data/lib/forest_admin_agent/audit_trail/audit_record.rb +16 -0
  5. data/lib/forest_admin_agent/audit_trail/capture.rb +229 -0
  6. data/lib/forest_admin_agent/audit_trail/diff.rb +156 -0
  7. data/lib/forest_admin_agent/audit_trail/record_state.rb +43 -0
  8. data/lib/forest_admin_agent/audit_trail/recording.rb +57 -0
  9. data/lib/forest_admin_agent/audit_trail/snapshots.rb +85 -0
  10. data/lib/forest_admin_agent/audit_trail/sql/audit_connection_base.rb +53 -0
  11. data/lib/forest_admin_agent/audit_trail/sql/audit_log.rb +16 -0
  12. data/lib/forest_admin_agent/audit_trail/sql/field_filter.rb +58 -0
  13. data/lib/forest_admin_agent/audit_trail/sql/migrations.rb +53 -0
  14. data/lib/forest_admin_agent/audit_trail/sql/migrator.rb +117 -0
  15. data/lib/forest_admin_agent/audit_trail/sql/text_search.rb +78 -0
  16. data/lib/forest_admin_agent/audit_trail/store.rb +253 -0
  17. data/lib/forest_admin_agent/audit_trail.rb +68 -0
  18. data/lib/forest_admin_agent/builder/agent_factory.rb +20 -0
  19. data/lib/forest_admin_agent/http/correlation_id.rb +37 -0
  20. data/lib/forest_admin_agent/http/correlation_id_middleware.rb +29 -0
  21. data/lib/forest_admin_agent/http/router.rb +6 -0
  22. data/lib/forest_admin_agent/routes/abstract_related_route.rb +3 -1
  23. data/lib/forest_admin_agent/routes/action/actions.rb +76 -1
  24. data/lib/forest_admin_agent/routes/capabilities/collections.rb +11 -1
  25. data/lib/forest_admin_agent/routes/resources/audit_trail.rb +237 -0
  26. data/lib/forest_admin_agent/routes/resources/audit_trail_correlation.rb +101 -0
  27. data/lib/forest_admin_agent/routes/resources/audit_trail_route.rb +115 -0
  28. data/lib/forest_admin_agent/routes/resources/related/update_related.rb +1 -1
  29. data/lib/forest_admin_agent/routes/resources/update.rb +10 -0
  30. data/lib/forest_admin_agent/utils/caller_parser.rb +4 -0
  31. data/lib/forest_admin_agent/utils/schema/schema_emitter.rb +1 -1
  32. data/lib/forest_admin_agent/version.rb +1 -1
  33. data/lib/forest_admin_agent.rb +4 -0
  34. metadata +23 -2
@@ -23,6 +23,7 @@ module ForestAdminAgent
23
23
  filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
24
24
  condition_tree: ConditionTree::ConditionTreeFactory.intersect([condition_tree, scope])
25
25
  )
26
+ drop_relationships!(args)
26
27
  data = format_attributes(args, context.collection)
27
28
  context.collection.update(context.caller, filter, data)
28
29
  records = context.collection.list(context.caller, filter, ProjectionFactory.all(context.collection))
@@ -37,6 +38,15 @@ module ForestAdminAgent
37
38
  )
38
39
  }
39
40
  end
41
+
42
+ private
43
+
44
+ # The frontend writes relations through PUT /:collection/:id/relationships/:name, which fires
45
+ # before this route. Honouring the relationships block here would turn the untouched relations
46
+ # it always resends as `data: null` into foreign keys set to nil. Parity with agent-nodejs.
47
+ def drop_relationships!(args)
48
+ args[:params][:data].delete(:relationships)
49
+ end
40
50
  end
41
51
  end
42
52
  end
@@ -18,6 +18,10 @@ module ForestAdminAgent
18
18
  @token_data = decode_token
19
19
  @token_data[:timezone] = extract_timezone
20
20
  @token_data[:request] = { ip: @args[:headers]['action_dispatch.remote_ip'].to_s }
21
+ # One id per request, generated by the agent, shared by every operation it triggers (used to
22
+ # correlate the audit trail) and echoed back to the client in the response header.
23
+ # See ForestAdminAgent::Http::CorrelationId.
24
+ @token_data[:request_id] = Http::CorrelationId.current
21
25
  project, environment = extract_forest_context
22
26
  @token_data[:project] = project
23
27
  @token_data[:environment] = environment
@@ -6,7 +6,7 @@ module ForestAdminAgent
6
6
  module Schema
7
7
  class SchemaEmitter
8
8
  LIANA_NAME = "agent-ruby"
9
- LIANA_VERSION = "1.38.3"
9
+ LIANA_VERSION = "1.39.1"
10
10
 
11
11
  def self.generate(datasource)
12
12
  datasource.collections
@@ -1,3 +1,3 @@
1
1
  module ForestAdminAgent
2
- VERSION = "1.38.3"
2
+ VERSION = "1.39.1"
3
3
  end
@@ -4,7 +4,11 @@ require 'zeitwerk'
4
4
 
5
5
  loader = Zeitwerk::Loader.for_gem
6
6
  loader.inflector.inflect('oauth2' => 'OAuth2')
7
+ loader.inflector.inflect('sql' => 'Sql')
7
8
  loader.inflector.inflect('sse_cache_invalidation' => 'SSECacheInvalidation')
9
+ # ActiveRecord is only needed by agents configuring an audit-trail database, and Rails eager loads
10
+ # every gem loader (Zeitwerk::Loader.eager_load_all), so these files must stay strictly autoloaded.
11
+ loader.do_not_eager_load("#{__dir__}/forest_admin_agent/audit_trail/sql")
8
12
  loader.setup
9
13
 
10
14
  module ForestAdminAgent
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_admin_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.38.3
4
+ version: 1.39.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2026-08-14 00:00:00.000000000 Z
12
+ date: 2026-08-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -330,10 +330,26 @@ extensions: []
330
330
  extra_rdoc_files: []
331
331
  files:
332
332
  - ".rspec"
333
+ - AUDIT_TRAIL.md
333
334
  - Rakefile
334
335
  - forest_admin
335
336
  - forest_admin_agent.gemspec
336
337
  - lib/forest_admin_agent.rb
338
+ - lib/forest_admin_agent/audit_trail.rb
339
+ - lib/forest_admin_agent/audit_trail/action_capture.rb
340
+ - lib/forest_admin_agent/audit_trail/audit_record.rb
341
+ - lib/forest_admin_agent/audit_trail/capture.rb
342
+ - lib/forest_admin_agent/audit_trail/diff.rb
343
+ - lib/forest_admin_agent/audit_trail/record_state.rb
344
+ - lib/forest_admin_agent/audit_trail/recording.rb
345
+ - lib/forest_admin_agent/audit_trail/snapshots.rb
346
+ - lib/forest_admin_agent/audit_trail/sql/audit_connection_base.rb
347
+ - lib/forest_admin_agent/audit_trail/sql/audit_log.rb
348
+ - lib/forest_admin_agent/audit_trail/sql/field_filter.rb
349
+ - lib/forest_admin_agent/audit_trail/sql/migrations.rb
350
+ - lib/forest_admin_agent/audit_trail/sql/migrator.rb
351
+ - lib/forest_admin_agent/audit_trail/sql/text_search.rb
352
+ - lib/forest_admin_agent/audit_trail/store.rb
337
353
  - lib/forest_admin_agent/auth/auth_manager.rb
338
354
  - lib/forest_admin_agent/auth/oauth2/forest_provider.rb
339
355
  - lib/forest_admin_agent/auth/oauth2/forest_resource_owner.rb
@@ -344,6 +360,8 @@ files:
344
360
  - lib/forest_admin_agent/facades/whitelist.rb
345
361
  - lib/forest_admin_agent/http/Exceptions/business_error.rb
346
362
  - lib/forest_admin_agent/http/Exceptions/http_exception.rb
363
+ - lib/forest_admin_agent/http/correlation_id.rb
364
+ - lib/forest_admin_agent/http/correlation_id_middleware.rb
347
365
  - lib/forest_admin_agent/http/error_translator.rb
348
366
  - lib/forest_admin_agent/http/forest_admin_api_requester.rb
349
367
  - lib/forest_admin_agent/http/router.rb
@@ -357,6 +375,9 @@ files:
357
375
  - lib/forest_admin_agent/routes/charts/charts.rb
358
376
  - lib/forest_admin_agent/routes/query_handler.rb
359
377
  - lib/forest_admin_agent/routes/request_context.rb
378
+ - lib/forest_admin_agent/routes/resources/audit_trail.rb
379
+ - lib/forest_admin_agent/routes/resources/audit_trail_correlation.rb
380
+ - lib/forest_admin_agent/routes/resources/audit_trail_route.rb
360
381
  - lib/forest_admin_agent/routes/resources/count.rb
361
382
  - lib/forest_admin_agent/routes/resources/csv.rb
362
383
  - lib/forest_admin_agent/routes/resources/delete.rb