Class: Portage::Ucp::Policy

Inherits:
Object
  • Object
show all
Defined in:
lib/portage/ucp/policy.rb

Overview

Local policy config for PolicyGuard (docs/plans/agentic-payments.md Phase 2). File format is deliberately private/internal — portage-ucp is a published gem, so PolicyGuard.check!'s keyword API is the stable surface, not this schema, which can change across releases.

Absent file, or an absent field within it, means "no restriction" for that check — a fresh install doesn't block dispatch just because no policy was ever configured. That's a deliberate default-permissive choice: PolicyGuard.check! and Phase 3's Confirmer are two independent layers, and confirmation defaults to on (Phase 1), so an unconfigured policy isn't the only thing standing between an agent and a charge.

A corrupt file is not the same as an absent one — that's data damage, not "nothing configured" — so JSON parse errors raise rather than silently falling back to permissive defaults.

Constant Summary collapse

PATH =
File.join(Dir.home, ".portage", "policy.json").freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path: PATH, data: {}) ⇒ Policy

Returns a new instance of Policy.



28
29
30
31
# File 'lib/portage/ucp/policy.rb', line 28

def initialize(path: PATH, data: {})
  @path = path
  @data = data
end

Class Method Details

.load(path: PATH) ⇒ Object



24
25
26
# File 'lib/portage/ucp/policy.rb', line 24

def self.load(path: PATH)
  new(path: path, data: read(path))
end

Instance Method Details

#merchant_allowlist ⇒ Object



36
# File 'lib/portage/ucp/policy.rb', line 36

def merchant_allowlist = Array(@data["merchant_allowlist"])

#per_transaction_cap ⇒ Object



33
# File 'lib/portage/ucp/policy.rb', line 33

def per_transaction_cap = @data["per_transaction_cap"]

#rolling_cap ⇒ Object



34
# File 'lib/portage/ucp/policy.rb', line 34

def rolling_cap = @data["rolling_cap"]

#set(key, value) ⇒ Object



48
49
50
51
52
# File 'lib/portage/ucp/policy.rb', line 48

def set(key, value)
  @data[key.to_s] = value
  write
  value
end

#set_token_scope(token_ref, scope) ⇒ Object

Parameters:

  • token_ref (String) —

    from Support::TokenRef.for — bound at enrollment time (portage-cli's PaymentMethods#enroll), not per-call.



41
42
43
44
45
46
# File 'lib/portage/ucp/policy.rb', line 41

def set_token_scope(token_ref, scope)
  @data["token_scopes"] ||= {}
  @data["token_scopes"][token_ref] = scope
  write
  scope
end

#to_h ⇒ Object



54
# File 'lib/portage/ucp/policy.rb', line 54

def to_h = @data.dup

#token_scope(token_ref) ⇒ Object



37
# File 'lib/portage/ucp/policy.rb', line 37

def token_scope(token_ref) = (@data["token_scopes"] || {})[token_ref]

#velocity ⇒ Object



35
# File 'lib/portage/ucp/policy.rb', line 35

def velocity = @data["velocity"]