class RubyLLM::Browser::Rails::ActiveRecordApprovalStore
Durable {RubyLLM::Browser::ApprovalStore} backed by ActiveRecord.
{#consume_once} performs every check and uses a conditional database update: existence, active, actor/run, URL, page revision, operation/session and exact action digest — before it marks the row consumed. Two workers cannot both consume the same grant, and a replayed or cross-actor approval is refused.
Public Class Methods
new(record_class: ApprovalRecord)
click to toggle source
Calls superclass method
# File lib/ruby_llm/browser/rails/active_record_approval_store.rb, line 13 def initialize(record_class: ApprovalRecord) super() @record_class = record_class end
Public Instance Methods
consume_once(id, actor_id:, run_id:, url:, action_digest:, now:, page_revision: nil, operation_id: nil, session_id: nil)
click to toggle source
# File lib/ruby_llm/browser/rails/active_record_approval_store.rb, line 38 def consume_once(id, actor_id:, run_id:, url:, action_digest:, now:, page_revision: nil, operation_id: nil, session_id: nil) record = @record_class.find_by(id: id) raise ApprovalRequired, "no approval was issued" unless record approval = record.to_approval raise ApprovalStale, "approval #{id} was already consumed" if approval.consumed? raise ApprovalStale, "approval #{id} was revoked" if approval.revoked? raise ApprovalStale, "approval #{id} has expired" if approval.expired?(now) unless approval.binding_matches?( actor_id: actor_id, run_id: run_id, url: url, action_digest: action_digest, page_revision: page_revision, operation_id: operation_id, session_id: session_id ) raise ApprovalStale, "approval #{id} does not authorize this actor, URL, page or action" end consumed = approval.consume!(now: now) changed = @record_class.where(id: id, consumed_at: nil, revoked: false) .where("expires_at > ?", now) .update_all(consumed_at: now, updated_at: now) raise ApprovalStale, "approval is no longer active" unless changed == 1 consumed end
fetch(id)
click to toggle source
# File lib/ruby_llm/browser/rails/active_record_approval_store.rb, line 34 def fetch(id) @record_class.find_by(id: id)&.to_approval end
issue(approval)
click to toggle source
# File lib/ruby_llm/browser/rails/active_record_approval_store.rb, line 18 def issue(approval) @record_class.create!( id: approval.id, actor_id: approval.actor_id, run_id: approval.run_id, url: approval.url, action_digest: approval.action_digest, action: @record_class.dump_action(approval.action), page_revision: approval.page_revision, operation_id: approval.operation_id, session_id: approval.session_id, issued_at: approval.issued_at, expires_at: approval.expires_at, consumed_at: approval.consumed_at, revoked: approval.revoked?, created_at: approval.issued_at, updated_at: approval.issued_at ) approval rescue ActiveRecord::RecordNotUnique raise InvalidInput, "approval #{approval.id} already exists" end
revoke(id)
click to toggle source
# File lib/ruby_llm/browser/rails/active_record_approval_store.rb, line 63 def revoke(id) changed = @record_class.where(id: id).update_all(revoked: true, updated_at: Time.now.utc) raise ApprovalRequired, "no approval was issued" if changed.zero? fetch(id) end