Surface the requesting party on the decision overview
The single-memo review page already fetched and labeled approval-engine's binding.principal "Requesting party" -- the party the approval was issued on behalf of, distinct from memo.binding.principal (the reviewer being bound). The overview/list page fetched the same live approval record for status but never surfaced this field. OverviewRow gains requesting_party, populated only when the fetched binding's digest matches the memo's pinned digest (same trust condition status already uses); ui.py renders it as "Requested by: ...". No new approval-engine call or flex-auth scope needed -- the record was already being read. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 169987@bnt-lap001 Assistant-Session: 322ef1ef-9048-4021-8570-b6d6f6347999
This commit is contained in:
parent
656301b659
commit
13ca3a5372
3 changed files with 27 additions and 2 deletions
|
|
@ -47,6 +47,7 @@ class OverviewRow:
|
|||
engine_status: str | None = None
|
||||
reason: str | None = None
|
||||
approved_at: str | None = None
|
||||
requesting_party: str | None = None
|
||||
history: tuple = () # ({"verb", "memo_version", "at", "state"}, ...), the person's own
|
||||
|
||||
|
||||
|
|
@ -160,11 +161,12 @@ class ReviewController:
|
|||
if exc.code == "session_expired":
|
||||
raise
|
||||
return OverviewRow(memo.id, "unavailable", reason=exc.code)
|
||||
status, reason = None, None
|
||||
status, reason, requesting_party = None, None, None
|
||||
try:
|
||||
current = self.approval_factory(session).get_approval(memo.approval_id)
|
||||
if current["binding"]["digest"] == memo.approval_binding_digest:
|
||||
status = current["status"]
|
||||
requesting_party = current["binding"].get("principal")
|
||||
else:
|
||||
reason = "binding_changed"
|
||||
except (ApprovalEngineError, ValueError):
|
||||
|
|
@ -192,7 +194,7 @@ class ReviewController:
|
|||
else:
|
||||
group = "closed"
|
||||
return OverviewRow(memo.id, group, memo.question, memo.version, status, reason,
|
||||
intent.get("approved_at") if intent else None,
|
||||
intent.get("approved_at") if intent else None, requesting_party,
|
||||
tuple({"verb": d.verb.value, "memo_version": d.memo_version, "at": d.at,
|
||||
"state": s["state"] if s else None} for d, s in history))
|
||||
|
||||
|
|
|
|||
|
|
@ -148,6 +148,8 @@ def _overview_row(row):
|
|||
return (f'<div class="record"><strong>{text(row.memo_id)}</strong>'
|
||||
f'<p class="muted">{text(reason)}</p></div>')
|
||||
facts = [f'Memo {text(row.memo_id)} · version {row.version}']
|
||||
if row.requesting_party:
|
||||
facts.append(f'Requested by: {text(row.requesting_party)}')
|
||||
if row.engine_status:
|
||||
facts.append(f'Approval status: {text(row.engine_status)}')
|
||||
elif row.reason:
|
||||
|
|
|
|||
|
|
@ -346,9 +346,29 @@ def test_overview_degrades_one_row_when_engine_is_unreachable(review):
|
|||
[row]=controller.overview(session)
|
||||
assert (row.group,row.engine_status,row.reason)==('open',None,'engine_unavailable')
|
||||
assert row.question==memo.question
|
||||
assert row.requesting_party is None
|
||||
transport.request=original
|
||||
|
||||
|
||||
def test_overview_shows_the_requesting_party(review):
|
||||
"""approval-engine's binding.principal is the party the approval was
|
||||
issued on behalf of -- a different role from memo.binding.principal, the
|
||||
reviewer (docs/memo.py's `_binding_document` docstring). The overview
|
||||
surfaces the former alongside status so a reviewer can tell who asked."""
|
||||
controller,session,app,memo,engine,transport=review
|
||||
[row]=controller.overview(session)
|
||||
assert row.requesting_party=='factory-fixture'
|
||||
|
||||
|
||||
def test_overview_does_not_surface_a_requesting_party_when_binding_changed(review):
|
||||
controller,session,app,memo,engine,transport=review
|
||||
stale=replace(memo,version=memo.version+1,approval_binding_digest='sha256:'+'0'*64)
|
||||
controller.store.save_memo(stale)
|
||||
[row]=controller.overview(session)
|
||||
assert row.reason=='binding_changed'
|
||||
assert row.requesting_party is None
|
||||
|
||||
|
||||
def test_overview_surfaces_unconfirmed_submission(review):
|
||||
controller,session,app,memo,engine,transport=review;p=opened(review).presentation
|
||||
controller.acknowledge(session,p.id,['h-1'])
|
||||
|
|
@ -379,6 +399,7 @@ def test_home_lists_open_then_accepted_memos_and_keeps_the_manual_form(review):
|
|||
assert r['status']==200 and 'Open for you (1)' in r['body'] and 'Accepted (' not in r['body']
|
||||
assert '<a href="/review?memo_id=memo-1"><strong>Approve the synthetic factory delivery?</strong></a>' in r['body']
|
||||
assert 'Approval status: requested' in r['body'] and 'Open a decision review' in r['body']
|
||||
assert 'Requested by: factory-fixture' in r['body']
|
||||
assert 'private-brief-sentinel' not in r['body'] and 'private-packet-sentinel' not in r['body']
|
||||
assert len(controller.store.evidence())==0
|
||||
p=opened(review).presentation;controller.acknowledge(session,p.id,['h-1'])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue