Skip to content

feat: revoke button and notices for scheduled grants (part 2 of #108) - #114

Merged
groupsky merged 1 commit into
mainfrom
feat/preapprove-108-part2
Oct 28, 2026
Merged

groupsky merged 1 commit into
mainfrom
feat/preapprove-108-part2

Conversation

@groupsky

Copy link
Copy Markdown
Contributor

Refs #108. Part 2 of 2. Part 1 was #112.

What it does

  • Revoke button. After Approve, the message of a scheduled grant keeps a Revoke button until the grant ends. A Revoke ends the grant at once: grant_ended with the new cause revoked (button data r: + request ID, audit.AnswerRevoke).
  • Message on every end. When a grant ends (used up, time over, cancel, Revoke, a later Deny, a broker stop), its message says how and when, and the button goes away. A failed edit that adds the button is tried again (3 tries, 10 s and 20 s apart) while the grant lives.
  • "Not used" notice. A grant that reaches its end with uses left sends one silent notice. It obeys the Telegram limit of 20 notices per 60 s. It does not count toward the limit per client. If it fails, the failure is logged; the audit log still has grant_ended.
  • Stop notice. On a broker stop, one notice lists the dropped grants (up to 20). None is sent when there are none. Stop order: polling stops, grants are dropped, every request is denied, the messages are updated (5 s), then the notice (5 s).
  • Docs: DESIGN.md sections 7, 8, 9 and 15, and the answers to open questions 1 and 5. THREAT-MODEL.md T35. docs/setup.md. docs/manual-telegram-test.md has a new optional Check 14.

How a Revoke tap is checked

A Revoke tap gets every check of an Approve or Deny tap: the approver user, the private chat, not inline, strict data, and in the core the grant of that request ID on that message. It skips the check for a changed message, because a Revoke can only take a right away. Telegram sends no content for a message older than 48 hours, so this check would refuse a real Revoke on an old grant. The one exception: a Revoke on a message whose request may still wait is refused as a changed message, with the alert.

Security review

The security-reviewer agent reviewed the change, then each round of fixes. No critical or high findings. Fixed:

  1. Medium: a Revoke on a message older than 48 h sent a false "bot token may be stolen" alert. Now a Revoke skips the changed-message check (see above).
  2. A Revoke after an edit with an unknown result sent a false alert. Fixed by the same rule. The edit_date rule for the broker's own edit was removed.
  3. At a stop, an edit that adds the button could use the whole 5 s, so the end edit never went out. Now an edit that adds the button is skipped when its grant is gone, past its end, or has an end edit waiting.
  4. A late tap with another request's ID on a grant message gave no alert. Now it is refused as a changed message, with the alert.
  5. The end text could go over the Telegram limit. The body of a pre-approval is now fitted with room for two end lines.
  6. Someone with the bot token could put Revoke data on a waiting message without an alert. Now that is refused, with the alert.
  7. A failed edit that adds the button was never tried again. Now it is retried (bounded).
  8. A late tap could write the old "approved" text after the end edit. The end edit now takes editMu. This one-line fix has no test: a test would need a hook or a sleep.
  9. Docs and timeouts: the stop budget now counts the new 10 s (still under 80 s). One test now waits with a time limit.

Tests

  • CI=true go test -race ./... passes on Go 1.27.1 and Go 1.26.0. go vet and golangci-lint run --build-tags e2e are clean.
  • The new tests pass with -count=20 -cpu 1,2,4. Each fails without its fix, except item 8.
  • The "not used" notice is tested through the fake Telegram server (TestCoreNotUsedNotice).
  • The stop notice is tested in internal/broker with a fake notice function, and in the core with the fake approver. There is no child-process test in cmd/nodkey.
  • Check 14 of the manual Telegram test was not run with a real bot.

No new dependencies.

- The message of a scheduled grant keeps a Revoke button until the grant
  ends. A Revoke ends the grant (grant_ended, cause revoked). It passes
  the user, chat, data and message checks; it skips the changed-message
  check, because it only takes a right away, except on a message whose
  request may still wait.
- When a grant ends for any cause, also a later Deny, its message says
  how and when, and the button goes away.
- A grant that reaches its end with uses left sends a "not used" notice.
- On a broker stop, one notice lists the dropped grants. The stop denies
  every request before it updates the messages and sends the notice.

Refs #108
@groupsky
groupsky merged commit 89d07e9 into main Oct 28, 2026
7 checks passed
@groupsky
groupsky deleted the feat/preapprove-108-part2 branch October 28, 2026 21:46
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