Module: Hecks::Adapters::GovernanceAuthorization
- Defined in:
- lib/hecks/adapters/driven/governance_authorization.rb
Overview
THE authorization PORT, FULFILLED BY GOVERNANCE — same registry,
same boot, so "ask Governance" is a dispatch against records
already sitting in the store this adapter is handed, not a bridge
to a second runtime. Runtime::Dispatcher.new(registry) is cheap
to build fresh per call (Registry#capability_graph's own
neighbor, #repository, does the same kind of on-demand build) —
nothing here holds one across calls, so there is no boot-order
dependency on WHEN Governance's bluebook loads relative to this
adapter, only that it has by the time holds_role? is called.
AN ACTIVE ASSIGNMENT, not merely a historical one : RoleAssignment
answers with every assignment an actor has ever held
(AssignmentsForActor's own description — "currently or
historically") and leaves ends_at for the caller to read, the
same deferral Governance::RoleTransition.Allowed makes for the
same reason. This is that caller.
Class Method Summary collapse
-
.authorized_as?(registry, from_role:, to_role:) ⇒ Boolean
THE OTHER HALF — may role X act as role Y.
- .holds_role?(registry, actor_id:, role:) ⇒ Boolean
-
.live_role_for(registry, actor_id:) ⇒ Object
THE ROLE ITSELF, not just a yes/no about one — the same
AssignmentsForActorqueryholds_role?runs, just returning the live (non-revoked) row'srole_nameinstead of comparing it against a caller-supplied guess.
Class Method Details
.authorized_as?(registry, from_role:, to_role:) ⇒ Boolean
THE OTHER HALF — may role X act as role Y. RoleTransition.Allowed
is identified by the exact pair, so at most one row ever comes
back ; still read as .any? rather than trusting that structurally,
the same defensiveness holds_role? already has to have anyway
since AssignmentsForActor can return several.
36 37 38 39 40 41 42 43 |
# File 'lib/hecks/adapters/driven/governance_authorization.rb', line 36 def (registry, from_role:, to_role:) rows = Runtime::Dispatcher.new(registry).query( "Governance::RoleTransition.Allowed", from_role: { value: from_role.to_s }, to_role: { value: to_role.to_s } ) rows.any? { |row| row[:ends_at].nil? } end |
.holds_role?(registry, actor_id:, role:) ⇒ Boolean
22 23 24 25 26 27 28 29 |
# File 'lib/hecks/adapters/driven/governance_authorization.rb', line 22 def holds_role?(registry, actor_id:, role:) rows = Runtime::Dispatcher.new(registry).query( "Governance::RoleAssignment.AssignmentsForActor", actor_id: { value: actor_id.to_s } ) rows.any? { |row| row[:role_name][:value] == role.to_s && row[:ends_at].nil? } end |
.live_role_for(registry, actor_id:) ⇒ Object
THE ROLE ITSELF, not just a yes/no about one — the same
AssignmentsForActor query holds_role? runs, just returning
the live (non-revoked) row's role_name instead of comparing it
against a caller-supplied guess. nil for no live assignment at
all — the caller's own fallback (an aggregate's own role field,
a default) is domain-specific and does not belong here.
51 52 53 54 55 56 57 58 59 |
# File 'lib/hecks/adapters/driven/governance_authorization.rb', line 51 def live_role_for(registry, actor_id:) rows = Runtime::Dispatcher.new(registry).query( "Governance::RoleAssignment.AssignmentsForActor", actor_id: { value: actor_id.to_s } ) live = rows.find { |row| row[:ends_at].nil? } live && live[:role_name][:value] end |