fix(prd-140): unblock + harden platform-tool authz gate (org-chart writes)#399
Conversation
…atform writes The merged PRD-140 helper required a keyword-only `workspace_id` (no default) and exposed no `escalation_target`, but the sole caller (`platform_executor`) invokes it without `workspace_id` and reads `decision.escalation_target`. Every gated `platform_*` write/destructive action (org-chart edits via `platform_update_agent`, agent updates, task/ playbook/tool mutations) therefore raised TypeError and failed closed — surfacing to Auto as a "missing workspace authorization/context" error. Rewrite the helper to the contract its caller and the 20 hierarchy tests expect: - signature `(db, *, actor_agent_id, target_type, target_id=None, change_type="update")` - `PermissionDecision` regains `escalation_target` (set to "auto" on escalatable denials) while keeping every field bypass_audit consumes - model: None actor -> allow (trusted platform flow); is_system_agent -> allow (Auto bypass); otherwise scope to the actor's reports_to_id subtree, resolving task/playbook owners via SAVEPOINT-guarded lookups so a missing column escalates instead of crashing the caller's transaction 20/20 hierarchy tests pass; CI hierarchy gate and bypass_audit unchanged.
…orm tools The prior commit restored the gate's signature but left a weak contract. Re-harden to deny-by-default and make every check workspace-bound: - Actor gate fails closed: anonymous (no actor id), unknown, cross-workspace, and inactive actors are denied. Absence of identity is no longer treated as trusted ambient authority — trusted flows must pass an explicit seeded actor. - System bypass is narrowed: requires is_system_agent=True AND a name on SYSTEM_BYPASS_ALLOWLIST (Auto, Auto CTO, onboarding agents, service actors). A stray is_system_agent flag alone is no longer a master key. - Every scope check is workspace-bound; cross-tenant targets/owners denied (IDOR closed) before any hierarchy reasoning. - escalation_target="auto" is set only on authority limits (out-of-subtree, unresolved owner, skill, broken hierarchy) so legitimate-but-unauthorized actors route to Auto. Security failures get no escalation hint. - platform_executor passes workspace_id + source into the gate. - exec_platform now server-mints actor identity from the trusted runtime agent_id only: strip any LLM-supplied _agent_id/_agent_name before reapply, closing an impersonation path that bypassed the gate entirely. Auto retains org-chart authority via the allowlist bypass. 24 gate tests + CI hierarchy gate green.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR hardens the hierarchy permission system into a deny-by-default, workspace-scoped authorization chokepoint. ChangesWorkspace-Scoped Hierarchy Authorization with Deny-by-Default Gate
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
The PRD-140 hierarchy permission gate (
can_actor_modify) — the single chokepoint for mutatingplatform_*tool actions — was crashing every gated platform write (e.g. Auto'splatform_update_agent/ org-chart edits) because its keyword-onlyworkspace_idparameter had no default and the dispatcher never passed it. This PR fixes the crash and hardens the gate to a deny-by-default, workspace-bound contract, and closes an actor-spoofing path.What was broken
can_actor_modify()requiredworkspace_idbutplatform_executornever passed it →TypeErroron every gated write since PR feat(heartbeat): wire report_to=auto via board task; surface Auto in … #303. Auto's org-chart writes failed with "missing workspace authorization/context requirement."What this PR does
is_system_agent=TrueAND a name onSYSTEM_BYPASS_ALLOWLIST(Auto, Auto CTO, onboarding agents, service actors). A strayis_system_agentflag alone is no longer a master key.escalation_target="auto"is set only on authority limits (out-of-subtree, unresolved owner, skill, broken hierarchy) so legitimate-but-unauthorized actors route to Auto for arbitration. Security failures get no escalation hint.exec_platformnow server-mints actor identity from the trusted runtimeagent_idonly — it strips any LLM-supplied_agent_id/_agent_namebefore reapplying, removing an impersonation path that bypassed the gate entirely.Auto retains org-chart authority via the allowlist bypass (it calls with a truthy runtime
agent_id).Test plan
pytest tests/security/test_hierarchy_permissions.py— 24/24 green (anonymous/unknown/cross-workspace/inactive deny, narrowed-allowlist bypass, subtree/owner scoping, cross-tenant target deny)python scripts/check_hierarchy_gate.py— CI gate green (19 gated / 28 allow-list / 46 mutating)platform_executor.py:552is the sole caller ofcan_actor_modify— no other call site crashes on the now-passedworkspace_idplatform_update_agent(org-chart write) on the live URLSummary by CodeRabbit
Release Notes