{% extends "mirrorwall/base.html" %} {% from "mirrorwall/components.html" import badge, empty_state, json_viewer, table %} {% from "_macros.html" import short, trajectory_link %} {% block title %}Approvals — PromptCadence{% endblock %} {% block content %}
Every request waiting for a person, oldest first. A grant mints the envelope the work then runs under, and a denial halts the trajectory with your reason on the record — so both answers are recorded, not just the one that let work continue.
{% if not may_approve %}This session holds the read scope and not
approve, so the buttons are not shown. Granting is deliberately a separate scope from
submitting, so the identity that starts work cannot approve its own egress.
{{ one.reason }}
Waiting {{ one.age_seconds | round(0) | int }} s · requested {{ one.created_at }} · expires {{ one.expires_at }} · steps {{ one.step_ids | join(", ") if one.step_ids else "—" }}
{% if one.detail %}{{ json_viewer(one.detail, label="What a grant would widen") }}{% endif %} {% if may_approve %}{{ report.row_count }} request{{ '' if report.row_count == 1 else 's' }} pending
{% else %} {{ empty_state("Nothing is waiting for a person.", "Trajectories", "/trajectories") }} {% endif %}