You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat: agent permission requests and approvals in the management UI #67
🤖 AI agent: owner request on #59 (2026-10-31): surface permission notifications and approvals from agents in the management UI. The design is in docs/security-model.md, section Approvals and permission notifications.
Sources:
Claude permission prompts (--permission-prompt-tool mcp__agentdev__approve)
Storage: an Approval custom resource. API endpoints: list, an SSE stream, and decision (allow once, allow for this job, or deny), restricted to agentdev-admins and audit-logged.
UI: a badge with the number of pending requests, an Approvals page, and "waiting for approval" as an agent state. Optionally, a comment on the forge issue.
🤖 AI agent: agreed. The approver is now the user the agent works for, the same person who would answer the prompt in an interactive Claude Code session. Revised design (it lands in docs/security-model.md in a docs PR once #59 merges, to keep your approval on #59 valid):
Principal: for an issue job, the user who assigned the issue to the agent. For a feedback job, the author of the review being addressed (if they own or requested the PR), otherwise the user who assigned the issue. The forge login is linked to the authentik user.
No more than the user's own rights: the principal can approve only what they could do themselves. For example, a push under .github/workflows/ needs workflow write access in that repo, checked against the forge.
Set by the API: the principal comes from the job's forge data, never from the agent's request, so a compromised agent can't pick a friendlier approver.
Fallback: if the principal has no linked account or doesn't answer in time, the request goes to the agent's owners, then it's denied.
Admins:agentdev-admins see every request and can deny any (emergency stop), but approve only as the principal or an owner.
UI: the badge counts requests waiting for me; admins get an "all requests" view.
Audit: each entry records who decided and on whose behalf.
New dependency: linking forge accounts to authentik users.
Why linking forge accounts to authentik users? An agent runs within a project. Approval request surfaces into the project. Whoever has write access to this project can approve
🤖 AI agent: agreed, that's simpler. Approval now belongs to the project:
Requests show up in the project the agent runs in. Anyone with write access to that repository can approve or deny them. There's no principal, no extra role, and no account-linking step.
Forge as an approval surface: the agent comments on its issue or PR with "waiting for approval". A reply of /approve, /approve-job or /deny from a user with write access decides it. The sidecar checks the commenter's permission through the forge API. Here the forge identity is just the commenter, so nothing needs linking.
In the UI, the API has to know which forge user is clicking in order to check their write access. The plan is to make the forge an authentik login source (sign in with GitHub or Gitea). That's ordinary authentik setup, not a separate link per user. If you'd rather have the UI show requests and leave decisions to the forge, that drops this dependency entirely.
Admins can still deny anything as an emergency stop. Nobody can approve beyond their own rights in the repo. Whatever no one decides before the timeout is denied.
The doc update goes into the post-#59 docs PR. Question: should UI decisions be in scope, with forge login through authentik, or should the forge be the only place to decide for now?
🤖 AI agent: decision needed (asked earlier only in chat, sorry).
Question: should approvals be decided in the UI in the first version, or only on the forge?
Proposed default: both, in two steps.
First version: the forge (/approve <id> comments). It needs no new sign-in and works today with your forge accounts. The UI shows the requests and their history, read-only.
Next: decisions in the UI too, once the forge is set up as an authentik login source, so the API knows which forge user clicked and can check their write access.
🤖 AI agent: noted. #67 covers approvals decided on the forge, with read-only Pending and History views in the UI. Deciding in the UI is now #80. I've removed needs-decision.
🤖 Decision recorded: deciding approvals in the UI is part of #67 and on the path to 1.0.0. This replaces the earlier forge-first-only scope. #107 delivers the forge decisions and the read-only Approvals page. A follow-up PR adds Approve / Approve for job / Deny buttons in the UI, with the same rules as forge comments: live write-access check, never the requester, audited, first decision wins and void records are ignored. #80 is folded into #67.
Activity
docs: link security model phases to issues #64-#67
valentinalexeev commentedon Oct 31, 2026
Why restricted to agentdev-admins? Should be to the user - same level as if the agent was running interactively with the owner.
valentinalexeev-bot commentedon Oct 31, 2026
🤖 AI agent: agreed. The approver is now the user the agent works for, the same person who would answer the prompt in an interactive Claude Code session. Revised design (it lands in docs/security-model.md in a docs PR once #59 merges, to keep your approval on #59 valid):
.github/workflows/needs workflow write access in that repo, checked against the forge.agentdev-adminssee every request and can deny any (emergency stop), but approve only as the principal or an owner.New dependency: linking forge accounts to authentik users.
valentinalexeev commentedon Oct 31, 2026
Why linking forge accounts to authentik users? An agent runs within a project. Approval request surfaces into the project. Whoever has write access to this project can approve
valentinalexeev-bot commentedon Oct 31, 2026
🤖 AI agent: agreed, that's simpler. Approval now belongs to the project:
/approve,/approve-jobor/denyfrom a user with write access decides it. The sidecar checks the commenter's permission through the forge API. Here the forge identity is just the commenter, so nothing needs linking.The doc update goes into the post-#59 docs PR. Question: should UI decisions be in scope, with forge login through authentik, or should the forge be the only place to decide for now?
docs(security): decision rules for approvals from the independent review
docs(security): approvals history and request context in the UI
docs(security): approvals history review fixes
valentinalexeev-bot commentedon Oct 31, 2026
🤖 AI agent: decision needed (asked earlier only in chat, sorry).
Question: should approvals be decided in the UI in the first version, or only on the forge?
Proposed default: both, in two steps.
/approve <id>comments). It needs no new sign-in and works today with your forge accounts. The UI shows the requests and their history, read-only.Reply "default ok" or pick one option.
valentinalexeev commentedon Oct 31, 2026
Default ok, UI approvals as a separate task
valentinalexeev-bot commentedon Oct 31, 2026
🤖 AI agent: noted. #67 covers approvals decided on the forge, with read-only Pending and History views in the UI. Deciding in the UI is now #80. I've removed
needs-decision.34 remaining items
fix(approvals): per-fingerprint in-flight dedup, void retry, kind-onl…
Merge origin/main into feature/67-approvals (keep approvals #67 and u…
valentinalexeev commentedon Nov 1, 2026
UI decisioning is in scope here. On the path to 1.0.0.
valentinalexeev-bot commentedon Nov 1, 2026
🤖 Decision recorded: deciding approvals in the UI is part of #67 and on the path to 1.0.0. This replaces the earlier forge-first-only scope. #107 delivers the forge decisions and the read-only Approvals page. A follow-up PR adds Approve / Approve for job / Deny buttons in the UI, with the same rules as forge comments: live write-access check, never the requester, audited, first decision wins and void records are ignored. #80 is folded into #67.
Merge origin/main into feature/67-approvals (#67)
feat: deterministic executors with a trusted plan and an approval-gat…
Merge origin/main into feature/67-approvals (#67)
Merge origin/main (#116 executors, #67 approvals) into feature/65-egress
docs(changelog): approvals on GKE unlock (#67)
feat(ansible): approvals on by default on GKE (#67)
feat: agent approval requests decided on the forge (#107)
fix(api): repeated CAS conflict answers 409; renumber risks to R90, R…
feat: decide approvals in the web UI (#67) (#138)