Skip to content

REVISE PR #435: the store and HTTP halves are sound, but the CLI caller discards the new revoked signal so the defect survives - #445

Open
jaylfc wants to merge 1 commit into
masterfrom
exec/tsk-d6giky
Open

REVISE PR #435: the store and HTTP halves are sound, but the CLI caller discards the new revoked signal so the defect survives#445
jaylfc wants to merge 1 commit into
masterfrom
exec/tsk-d6giky

Conversation

@jaylfc

@jaylfc jaylfc commented Aug 31, 2026

Copy link
Copy Markdown
Owner

CARD TITLE (intent, not commit subject): REVISE PR #435: the store and HTTP halves are sound, but the CLI caller discards the new revoked signal so the defect survives

Autonomous build of board card tsk-d6giky.

Store layer (collections.py) captures DELETE rowcount and sets
col["revoked"] = removed > 0. HTTP handler pops revoked from the inner
collection and returns it at the envelope top level. CLI caller reads
revoked, prints a distinguishable noop message to stderr, and returns 1
when no grant matched.

docs/collections.md endpoint table updated to reflect {"collection": ...,
"revoked": ...} response shape. HTTP tests assert revoked is True on a
matching grantee, False on a non-matching grantee, and absent from the
inner collection object in both cases. Store tests cover both outcomes.
New CLI test verifies noop revoke returns rc=1 with 'no grant matched'
on stderr while the grant survives.

Verified: tests/test_collections_cli.py 6 passed, tests/test_collections_store.py
+test_collections_http.py 42 passed.

Docs-Reviewed: collections endpoint change is documented in docs/collections.md; A2A handlers in http_server.py are unaffected

Files:
docs/collections.md | 2 +-
taosmd/cli.py | 4 +++
taosmd/collections.py | 7 +++--
taosmd/http_server.py | 3 ++-
tests/test_collections_cli.py | 13 ++++++++++
tests/test_collections_http.py | 39 ++++++++++++++++++++++++++++
tests/test_collections_store.py | 26 +++++++++++++++++++
8 files changed, 98 insertions(+), 4 deletions(-)

Summary by CodeRabbit

  • Bug Fixes

    • Collection grant revocation now clearly indicates whether a grant was actually removed.
    • The CLI reports an error and exits non-zero when no grant matches, instead of indicating a successful revocation.
    • HTTP responses now include a top-level revoked status while preserving collection details.
  • Documentation

    • Updated collection API documentation to describe the revoked response field.
  • Tests

    • Added coverage for successful and unmatched revocation scenarios across CLI, HTTP, and collection operations.

…revoke

Store layer (collections.py) captures DELETE rowcount and sets
col["revoked"] = removed > 0. HTTP handler pops revoked from the inner
collection and returns it at the envelope top level. CLI caller reads
revoked, prints a distinguishable noop message to stderr, and returns 1
when no grant matched.

docs/collections.md endpoint table updated to reflect {"collection": ...,
"revoked": ...} response shape. HTTP tests assert revoked is True on a
matching grantee, False on a non-matching grantee, and absent from the
inner collection object in both cases. Store tests cover both outcomes.
New CLI test verifies noop revoke returns rc=1 with 'no grant matched'
on stderr while the grant survives.

Verified: tests/test_collections_cli.py 6 passed, tests/test_collections_store.py
+test_collections_http.py 42 passed.

Docs-Reviewed: collections endpoint change is documented in docs/collections.md; A2A handlers in http_server.py are unaffected
@gitar-bot

gitar-bot Bot commented Aug 31, 2026

Copy link
Copy Markdown

Important

You are using the Gitar free plan. Upgrade to unlock code review, CI analysis, auto-apply, custom automations, and more.

Gitar

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a9422d91-82c8-4b90-964b-a7101a3261ed

📥 Commits

Reviewing files that changed from the base of the PR and between 0baa9af and ee0ff4f.

📒 Files selected for processing (8)
  • changelog.d/tsk-d6giky-cli-revoked-signal.md
  • docs/collections.md
  • taosmd/cli.py
  • taosmd/collections.py
  • taosmd/http_server.py
  • tests/test_collections_cli.py
  • tests/test_collections_http.py
  • tests/test_collections_store.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The revoke flow now reports whether a grant was removed. The HTTP response exposes this status, and the CLI reports no-match revocations with a non-zero exit code and stderr output. Store, HTTP, and CLI tests cover both matching and non-matching grants.

Changes

Grant revoke result

Layer / File(s) Summary
Record grant removal
taosmd/collections.py, tests/test_collections_store.py
CollectionStore.revoke returns revoked: True when a grant is removed and revoked: False when no grant matches. Store tests verify both cases.
Propagate revoke status
taosmd/http_server.py, taosmd/cli.py, tests/test_collections_http.py, tests/test_collections_cli.py, docs/collections.md, changelog.d/tsk-d6giky-cli-revoked-signal.md
The HTTP endpoint returns revoked beside collection. The CLI returns code 1 and writes a no-match message to stderr when the value is false. Tests and documentation cover the response and command behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to ee0ff

The change reports whether a grant was actually revoked and makes the CLI return a distinct failure status for no-op revocations; no actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 6 files. (2 skipped: … 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 identifies the main CLI defect involving the new revoked signal. It is related to the changes, but it describes the prior defect rather than the implemented fix.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 6 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ 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-d6giky

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.

Comment thread taosmd/http_server.py
self._send_json(404, {"error": str(exc)})
return
self._send_json(200, {"collection": col})
revoked = col.pop("revoked")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Asymmetric default on col.pop("revoked") is fragile

The CLI uses col.pop("revoked", False) (safe), but this HTTP handler uses bare col.pop("revoked") — a KeyError will be raised if any future caller (test mock, alternate store, a wrapper that strips the field, or a regression that drops the assignment in CollectionStore.revoke) returns a col dict without the key. The two consumers should agree; mirror the CLI's defensive default so a single bad call site cannot 500 the whole endpoint.

Suggested change
revoked = col.pop("revoked")
revoked = col.pop("revoked", False)

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread taosmd/cli.py
revoked = col.pop("revoked", False)
if not revoked:
print(f"noop: no grant matched for {args.agent}", file=sys.stderr)
return 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Document or unify exit codes for collections revoke

This branch returns 1 for "no grant matched", while the surrounding except CollectionNotFoundError / except ValueError blocks return 2 for errors. A user reading _collections_revoke cannot tell from the code that 1 specifically means "noop / nothing to do" and 2 means "real error" — and the conventions used by the rest of the CLI are not stated anywhere. Either add a short comment clarifying the rc=1 vs rc=2 split, or unify with the existing 2 so callers don't need to distinguish. Tests pin rc == 1, so any unification must update them too.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Aug 31, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
taosmd/http_server.py 2457 col.pop("revoked") lacks the defensive default its sibling CLI consumer uses; a missing key will 500 the endpoint

SUGGESTION

File Line Issue
taosmd/cli.py 1095 collections revoke returns rc=1 for noop and rc=2 for errors with no documentation of the split; consider unifying or documenting
Files Reviewed (8 files)
  • changelog.d/tsk-d6giky-cli-revoked-signal.md - 0 issues
  • docs/collections.md - 0 issues
  • taosmd/cli.py - 1 issue
  • taosmd/collections.py - 0 issues
  • taosmd/http_server.py - 1 issue
  • tests/test_collections_cli.py - 0 issues
  • tests/test_collections_http.py - 0 issues
  • tests/test_collections_store.py - 0 issues

Fix these issues in Kilo Cloud


Reviewed by minimax-m3:free · Input: 30.8K · Output: 2.9K · Cached: 210.1K

@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@jaylfc

jaylfc commented Aug 31, 2026

Copy link
Copy Markdown
Owner Author

Reviewed, clean. Branch is fresh off master as the card asked (merge-base is 0baa9af9, not the closed parent), and the trial merge is a clean fast-forward.

The decisive question was whether the revoked signal survives to the CLI surface, since that is where the parent died. Driven end to end against a real store, exit status captured per arm:

revoke <cid> dev        -> rc=0  "grants: (none)"
revoke <cid> not-dev    -> rc=1  stderr "noop: no grant matched for not-dev"
double revoke of dev    -> rc=1

With master's cli.py restored into the same harness, all three arms return rc=0 with byte-identical stdout, which reproduces the parent's defect exactly and shows the probe can see it. test_revoke_noop_returns_nonzero is red against master's cli.py and green here.

Caller enumeration rather than a grep for the symbol: CollectionStore.revoke has one production caller, service.py:1858; service.collections_revoke has two, cli.py:1090 and http_server.py:2452. No MCP tool and no dashboard consumer. Every caller propagates the value.

Seven mutations by line number across the store, HTTP and CLI branches separately, failed and error counts read from the summary in the same command, baseline 48 passed: all seven killed, zero survivors, zero collection errors. That includes the pop-to-get mutant, so the assertion that revoked does not leak into the response envelope is load bearing rather than decorative.

Suite on the merged tree is 1809 passed / 10 skipped / 7 errors against the 1804 / 10 / 7 baseline on 0baa9af9, so +5 for exactly five added tests. Ruff clean, deleted-symbols guard clean, no conflict markers, no mode changes, no deletions, no em dashes in the added lines. I read the CI job's step list rather than the combined status: Lint ran and succeeded, then Tests ran and succeeded.

One thing to consider folding in before this merges, since it is a one-line change in a file this PR already touches. http_server.py:153 still documents this endpoint as returning {"collection": {...}}, which is the same staleness that was blocker 2 for the parent. It is not cosmetic by convention there: line 156 of the same table does carry an envelope extra. No gate can catch it, because the doc-gate rule for http_server.py points at a different file.

Also worth knowing for merge ordering: this and #443 can both land, and neither duplicates the other. Their subjects are disjoint, and the only conflict is tests/test_collections_http.py, where both append tests at the same point. Whichever goes second resolves a trivial append.

Leaving this for your merge decision.

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