Skip to content

Fold tsk-2bkd56: lead card-edit via project_tasks_update, not scope collapse (PR 2240 remainder) - #2244

Merged
jaylfc merged 3 commits into
devfrom
exec/tsk-b6ugu5
Aug 2, 2026
Merged

Fold tsk-2bkd56: lead card-edit via project_tasks_update, not scope collapse (PR 2240 remainder)#2244
jaylfc merged 3 commits into
devfrom
exec/tsk-b6ugu5

Conversation

@jaylfc

@jaylfc jaylfc commented Aug 2, 2026

Copy link
Copy Markdown
Owner

CARD TITLE (intent, not commit subject): Fold tsk-2bkd56: lead card-edit via project_tasks_update, not scope collapse (PR 2240 remainder)

Autonomous build of board card tsk-b6ugu5.

Files:
pyproject.toml | 2 +-
tests/test_agent_internal_mint.py | 38 ++++++-
tests/test_routes_projects_agent_tasks.py | 164 ++++++++++++++++++++++++++++--
tinyagentos/init.py | 2 +-
tinyagentos/auth_middleware.py | 2 +-
tinyagentos/routes/agent_registry.py | 31 +++---
tinyagentos/routes/projects.py | 25 +++--
9 files changed, 225 insertions(+), 118 deletions(-)

Removes-Intentionally: tests/test_routes_projects_agent_tasks.py:TestAgentCanDriveOwnBoard.test_patch_task_is_session_only

Summary by CodeRabbit

  • New Features

    • Lead agents can update their own or lead-owned project cards.
    • Updates support card titles, descriptions, labels, and priority.
    • The seeded lead agent now includes the required project-scoped update access.
  • Bug Fixes

    • Agents can no longer modify card status or other protected fields.
    • Unauthorized or unsupported updates now receive a clear permission response.
  • Documentation

    • Documented the new access scope, ownership rules, permissions, and human-only fields.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Lead agents now receive the project-scoped project_tasks_update scope. They can update their own or lead-owned task cards in four fields. Protected fields return HTTP 403, and reseeding preserves the grant without duplicates.

Changes

Project task updates

Layer / File(s) Summary
Scope seeding and project binding
tinyagentos/routes/agent_registry.py, tests/test_agent_internal_mint.py, docs/agent-coordination.md
Adds project_tasks_update to the seeded lead agent, documents its project binding, and verifies idempotent reseeding.
PATCH authorization and field restrictions
tinyagentos/routes/projects.py, tinyagentos/auth_middleware.py
Restricts agent PATCH updates to title, body, labels, and priority. Protected fields, including status, return HTTP 403.
Route and seed regression coverage
tests/test_routes_projects_agent_tasks.py, CHANGELOG.md
Tests permitted updates, persistence, protected fields, non-lead agents, read-only tokens, admin behavior, and separate claimable-task permissions.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LeadAgent
  participant TaskRoute
  participant TaskStore
  LeadAgent->>TaskRoute: PATCH task with project_tasks_update
  TaskRoute->>TaskRoute: Check ownership and editable fields
  TaskRoute->>TaskStore: Persist title, body, labels, or priority
  TaskStore-->>LeadAgent: Updated task
Loading

Possibly related PRs

  • jaylfc/taOS#2240: Both PRs modify project task PATCH authorization and field restrictions.

Suggested reviewers: hognek

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies lead-card editing through project_tasks_update and scope separation, which matches the primary changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch exec/tsk-b6ugu5

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gitar-bot

gitar-bot Bot commented Aug 2, 2026

Copy link
Copy Markdown

Gitar is working

Gitar

@jaylfc

jaylfc commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

nemotron-ultra-kilo review

VERDICT: Approved with minor concerns — scope separation is solid, tests are thorough, but field validation has a potential None-bypass and missing status-field rejection test.

  • tinyagentos/routes/projects.py:817 — Field validation allows agents to set non-editable fields to None (PATCH semantics: explicit null ≠ omitted). The check getattr(payload, f) is not None passes for None, so an agent could PATCH {"parent_task_id": null} and clear a field it shouldn't touch. Should check f in payload.model_fields_set or similar.

  • tinyagentos/routes/projects.py:825 — The parent_task_id check after the agent field guard is now dead code for agents (caught earlier at line 820), but remains for session/admin path. Not a bug, slightly confusing.

  • tests/test_routes_projects_agent_tasks.py — Missing test: agent with project_tasks_update attempting to PATCH status field should return 403 (since status was removed from _AGENT_EDITABLE_FIELDS). Also missing tests for element_id and multi-field PATCH with mixed editable/non-editable fields.

  • tinyagentos/auth_middleware.py:81 — Comment says whitelist is title, body, labels, priority but code in projects.py:773 matches; consistent.

  • tests/test_agent_internal_mint.py:375 — New idempotency test is good; verifies project_tasks_update survives re-seed.

  • Version bump in uv.lock is correct (b44 → b45).
    VERDICT: Approved with minor concerns — scope separation is solid, tests are thorough, but field validation has a potential None-bypass and missing status-field rejection test.

  • tinyagentos/routes/projects.py:817 — Field validation allows agents to set non-editable fields to None (PATCH semantics: explicit null ≠ omitted). The check getattr(payload, f) is not None passes for None, so an agent could PATCH {"parent_task_id": null} and clear a field it shouldn't touch. Should check f in payload.model_fields_set or similar.

  • tinyagentos/routes/projects.py:825 — The parent_task_id check after the agent field guard is now dead code for agents (caught earlier at line 820), but remains for session/admin path. Not a bug, slightly confusing.

  • tests/test_routes_projects_agent_tasks.py — Missing test: agent with project_tasks_update attempting to PATCH status field should return 403 (since status was removed from _AGENT_EDITABLE_FIELDS). Also missing tests for element_id and multi-field PATCH with mixed editable/non-editable fields.

  • tinyagentos/auth_middleware.py:81 — Comment says whitelist is title, body, labels, priority but code in projects.py:773 matches; consistent.

  • tests/test_agent_internal_mint.py:375 — New idempotency test is good; verifies project_tasks_update survives re-seed.

  • Version bump in uv.lock is correct (b44 → b45).

Automated first-pass review by the nemotron-ultra-kilo lane. The lead still reviews before merge.

@jaylfc

jaylfc commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Reviewed against fold card tsk-b6ugu5: on-spec. Scope stays project_tasks_update (route untouched), lead seed gains the grant with a re-seed re-assert test, and the regression pin is real - I ran it green on this branch (62 passed), then collapsed the PATCH scope to project_tasks locally exactly as PR 2240 did and the pin went RED. deleted-symbols-gate red was the intentional removal of test_patch_task_is_session_only (it asserted the pre-#2184 session-only design; the new pin supersedes it) - waived via Removes-Intentionally trailer now in the body. Kilo red is today's rate-limit noise. Merging when the gate re-runs green.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_routes_projects_agent_tasks.py`:
- Line 241: Update the assignment from _mint_agent in the affected test to bind
the unused first return value as _cid instead of cid, while preserving token
usage and the existing test behavior.

In `@tinyagentos/routes/projects.py`:
- Around line 818-824: Update the agent-field validation in
tinyagentos/routes/projects.py lines 818-824 to inspect
payload.model_fields_set, rejecting every supplied field outside
_AGENT_EDITABLE_FIELDS even when its value is null. Add regression cases in
tests/test_routes_projects_agent_tasks.py lines 206-234 asserting 403 responses
for status, element_id, and a payload containing body with status set to null.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1752e04e-f007-4ce0-adab-ae027f3b49d4

📥 Commits

Reviewing files that changed from the base of the PR and between 1193b6b and e2890a9.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • docs/agent-coordination.md
  • tests/test_agent_internal_mint.py
  • tests/test_routes_projects_agent_tasks.py
  • tinyagentos/auth_middleware.py
  • tinyagentos/routes/agent_registry.py
  • tinyagentos/routes/projects.py

its cards -> 403."""
pid = await _new_project(ctx, "alpha")
tid = await _new_task(ctx, pid)
cid, token = await _mint_agent(ctx, pid, scopes=("project_tasks_update",))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the unused cid binding.

The test does not use cid. Rename it to _cid to satisfy Ruff RUF059.

Proposed fix
-        cid, token = await _mint_agent(ctx, pid, scopes=("project_tasks_update",))
+        _cid, token = await _mint_agent(ctx, pid, scopes=("project_tasks_update",))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cid, token = await _mint_agent(ctx, pid, scopes=("project_tasks_update",))
_cid, token = await _mint_agent(ctx, pid, scopes=("project_tasks_update",))
🧰 Tools
🪛 Ruff (0.16.0)

[warning] 241-241: Unpacked variable cid is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_routes_projects_agent_tasks.py` at line 241, Update the assignment
from _mint_agent in the affected test to bind the unused first return value as
_cid instead of cid, while preserving token usage and the existing test
behavior.

Source: Linters/SAST tools

Comment on lines 818 to 824
if is_agent:
for f in payload.model_fields:
if f not in _AGENT_EDITABLE_FIELDS and getattr(payload, f) is not None:
return JSONResponse(
{"error": f"field {f!r} is not editable by agents"},
status_code=400,
status_code=403,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Validate protected agent fields by request presence. The current non-null check permits an agent to include a protected field with null in an otherwise valid PATCH request. Use payload.model_fields_set and add regression coverage for this boundary.

  • tinyagentos/routes/projects.py#L818-L824: reject every supplied field outside _AGENT_EDITABLE_FIELDS, including fields supplied as null.
  • tests/test_routes_projects_agent_tasks.py#L206-L234: add 403 cases for status, element_id, and {"body": "...", "status": null}.
📍 Affects 2 files
  • tinyagentos/routes/projects.py#L818-L824 (this comment)
  • tests/test_routes_projects_agent_tasks.py#L206-L234
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/projects.py` around lines 818 - 824, Update the
agent-field validation in tinyagentos/routes/projects.py lines 818-824 to
inspect payload.model_fields_set, rejecting every supplied field outside
_AGENT_EDITABLE_FIELDS even when its value is null. Add regression cases in
tests/test_routes_projects_agent_tasks.py lines 206-234 asserting 403 responses
for status, element_id, and a payload containing body with status set to null.

@kilo-code-bot

kilo-code-bot Bot commented Aug 2, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No New Issues Found | Recommendation: Merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 0
Files Reviewed (7 files)
  • CHANGELOG.md
  • docs/agent-coordination.md
  • tests/test_agent_internal_mint.py
  • tests/test_routes_projects_agent_tasks.py
  • tinyagentos/auth_middleware.py
  • tinyagentos/routes/agent_registry.py
  • tinyagentos/routes/projects.py

Note: The existing nemotron-ultra-kilo review (comment ID 5159735065) already raised the None-bypass concern in tinyagentos/routes/projects.py:820. No additional inline findings were identified.


Reviewed by step-3.7-flash · Input: 95.7K · Output: 39.2K · Cached: 1.2M

@jaylfc
jaylfc merged commit 9d9feae into dev Aug 2, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant