Module: Portage::Ucp::Ap2::MandateGuard
- Defined in:
- lib/portage/ucp/ap2/mandate_guard.rb
Overview
Mandate validation (design-log §33/Phase B): required fields present,
not expired, and — when the caller supplies a trust anchor —
cryptographic proof via Ap2::MandateSignature. trusted_keys has no
default because this gem has no key infrastructure of its own to
default it to (§9's convention: keys are always consumer-provided,
never generated or assumed here); a caller that omits it gets
shape-only validation, same posture this guard always had, not a
silent downgrade. A real PSP adapter is expected to pass the issuing
agent's trust anchor (its own store, or a resolver against the
agent's own manifest) once it has one. A caller that wants that
omission to be an error instead — fail closed rather than silently
downgrade to shape-only — sets require_signature: true.
Constant Summary collapse
- REQUIRED_FIELDS =
%i[amount currency merchant expires_at signature].freeze
Class Method Summary collapse
Class Method Details
.validate!(mandate, trusted_keys: nil, require_signature: false) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/portage/ucp/ap2/mandate_guard.rb', line 26 def self.validate!(mandate, trusted_keys: nil, require_signature: false) missing = REQUIRED_FIELDS.reject { |field| mandate.public_send(field) } unless missing.empty? raise Portage::Ucp::InvalidMandateError, "payment mandate is missing required field(s): #{missing.join(', ')}" end if Time.now >= Time.parse(mandate.expires_at) raise Portage::Ucp::InvalidMandateError, "payment mandate expired at #{mandate.expires_at}" end if trusted_keys Ap2::MandateSignature.verify!(mandate, trusted_keys: trusted_keys) elsif require_signature raise Portage::Ucp::InvalidMandateError, "payment mandate signature verification is required but no trusted_keys are configured" end end |