From d56155231814633e04f856d22646fea24ef97011 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Wed, 15 Jul 2026 01:41:34 +0200 Subject: Add NodeAction: an append-only log of who did what to a node node_id/page_id/user_id are lookup and ordering only -- all three nullify on delete, so an entry outlives its actor and its subject. Everything that must survive those deletions lives in a mandatory metadata jsonb written once at creation: the actor's username, the node's human-readable name (pinned to the default locale), and action-specific extras such as publish's title from/to. NodeAction.record! is the single constructor, so every entry gets the same baseline metadata without each call site re-implementing it. occurred_at is one field for live and backfilled entries alike; inferred_from distinguishes them -- nil means witnessed at the moment it happened, populated names how a backfilled entry was estimated. Instrumented so far: publish (crediting the actual publisher, threaded through from the controller -- previously nobody had the act of publishing recorded anywhere), revert's discard_autosave and destroy_draft branches, and translation destroy. publish_draft! now runs in a transaction so the promotion and its log entry land together. The remaining verbs follow once this mechanism has proven itself. --- db/migrate/20260714233414_create_node_actions.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 db/migrate/20260714233414_create_node_actions.rb (limited to 'db') diff --git a/db/migrate/20260714233414_create_node_actions.rb b/db/migrate/20260714233414_create_node_actions.rb new file mode 100644 index 0000000..6c18285 --- /dev/null +++ b/db/migrate/20260714233414_create_node_actions.rb @@ -0,0 +1,19 @@ +class CreateNodeActions < ActiveRecord::Migration[8.1] + def change + create_table :node_actions do |t| + t.references :node, foreign_key: { on_delete: :nullify } + t.references :page, foreign_key: { on_delete: :nullify } + t.references :user, foreign_key: { on_delete: :nullify } + t.string :action, null: false + t.string :locale + t.string :inferred_from + t.jsonb :metadata, null: false + t.datetime :occurred_at, null: false + + t.timestamps + end + + add_index :node_actions, [:node_id, :occurred_at] + add_index :node_actions, :action + end +end -- cgit v1.3