Module: Vangrail::ReferenceMonitorAuthority

Included in:
ReferenceMonitor
Defined in:
lib/vangrail/reference_monitor_authority.rb

Overview

Opaque confirmation and transaction capabilities owned by a monitor.

Instance Method Summary collapse

Instance Method Details

#claim(authorization) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
# File 'lib/vangrail/reference_monitor_authority.rb', line 6

def claim(authorization)
  return false unless authorization.is_a?(Authorization)

  @mutex.synchronize do
    call_id = authorization.call.id
    return false unless @authorized[call_id].equal?(authorization)
    return false if @claimed[call_id] || @finished.key?(call_id)

    @claimed[call_id] = true
  end
end

#confirm(call, actor:) ⇒ Object

Raises:

  • (ArgumentError)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/vangrail/reference_monitor_authority.rb', line 18

def confirm(call, actor:)
  raise ArgumentError, 'call must be a Call' unless call.is_a?(Call)
  raise PrivilegeError, 'confirmation requires a privileged actor' unless actor.is_a?(Cell) && actor.privileged?

  @mutex.synchronize do
    raise PrivilegeError, 'call belongs to another conversation' if call.conversation_id != plan.id

    grants = plan.grants_for(call.tool)
    raise PrivilegeError, "call #{call.tool} has no confirmation grant" unless grants.any?(&:confirmation_required?)
    raise PrivilegeError, 'authorized calls cannot be reconfirmed' if @authorized.key?(call.id)

    Confirmation.new(call, actor).tap do |token|
      @confirmations[call.id] = token
      audit.record(:confirmation, call_id: call.id, confirmation_id: token.id, actor: actor)
    end
  end
end

#finish_transaction(prepared, committed:) ⇒ Object



54
55
56
57
58
59
60
61
62
63
# File 'lib/vangrail/reference_monitor_authority.rb', line 54

def finish_transaction(prepared, committed:)
  @mutex.synchronize do
    return false unless @transactions[prepared.call_id].equal?(prepared)

    type = committed ? :transaction_committed : :transaction_rolled_back
    audit.record(type, call_id: prepared.call_id, transaction_id: prepared.id,
                       tool: prepared.tool)
    true
  end
end

#prepare_transaction(call, prepared) ⇒ Object

Raises:

  • (ArgumentError)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/vangrail/reference_monitor_authority.rb', line 36

def prepare_transaction(call, prepared)
  raise ArgumentError, 'call must be a Call' unless call.is_a?(Call)
  unless prepared.is_a?(PreparedTransaction) && prepared.tool == call.tool &&
         prepared.call_id == call.id && prepared.fingerprint == call.fingerprint
    raise PrivilegeError, 'transaction does not match the call'
  end

  @mutex.synchronize do
    raise PrivilegeError, 'call belongs to another conversation' if call.conversation_id != plan.id
    raise PrivilegeError, 'authorized calls cannot be prepared' if @authorized.key?(call.id)

    @transactions[call.id] = prepared
    audit.record(:transaction_prepared, call_id: call.id, transaction_id: prepared.id,
                                        tool: call.tool)
    prepared
  end
end