Skip to content

feat(telegram): council human-as-seat ballot tap handler (DIVE-1566)#10

Merged
lodar merged 1 commit into
mainfrom
dive-1566-cvote-tap
Jul 20, 2026
Merged

feat(telegram): council human-as-seat ballot tap handler (DIVE-1566)#10
lodar merged 1 commit into
mainfrom
dive-1566-cvote-tap

Conversation

@lodar

@lodar lodar commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Sub-task 4/4 of DIVE-1548 (human-as-seat voting). Adds the plugin half that makes the CLI's cvote: ballot buttons live, mirroring the shipped DIVE-1546 founder-veto tap.

What

  • council.tsparseCvoteTap / CVOTE_RE: pure parser for cvote:<ref>:<code>:<nonce> (ref = ballot task-id prefix ≤12, code ∈ {a,r,e}, nonce = 32 hex). Length + charset anchored, fits Telegram's 64-byte callback_data cap without prefixing (unlike the veto's PREFIX'd digest).
  • server.tscallback_query:data handler: private-chat-only + allowFrom-vetted, shells sudo 5dive council ballot-tap --ref --vote --nonce (the DIVE-1565 bridge → prefix-accepts the unique OPEN human ballot, sha256-verifies the nonce vs the stored digest fail-closed, closes the SAME CNCL-18 ballot task with the COUNCIL-VOTE line the convener already polls — no second write path). Edits the message to a nonce-free confirmation + strips the keyboard so a one-time nonce can't be re-tapped. Fully fail-soft; raw nonce never echoed.

Security

  • One-time DIVE-916 nonce rides ONLY in callback_data; the ballot body stores just its sha256 digest, the text is blind. The nonce IS the authentication (bridge refuses a mismatch, only the seat-holder ever received the raw nonce). Defense in depth: allowFrom + private-chat requirement.

Notes

  • Inert until the CLI (DIVE-1564) delivers a cvote: button. Completes DIVE-1548, so it earns a version cut: 0.5.29.
  • Baseline telegram only; fork-parity port to telegram-{grok,agy,codex,pi} deferred (DIVE-1371/1558 pattern) — same deferral as the DIVE-1546 veto tap, which is also baseline-only.

Tests

  • council.test.ts: +6 cases (per-code parse, numeric ref, veto/cl:* non-confusion, malformed fail-closed, 64-byte cap). Full suite 317/0 green.

🤖 Generated with Claude Code

….29 (DIVE-1566)

Sub-task 4/4 of DIVE-1548. parseCvoteTap parser (council.ts) + cvote:<ref>:<code>:<nonce>
callback_query handler (server.ts) mirroring the DIVE-1546 veto tap: private-chat-only +
allowFrom, shells the DIVE-1565 'council ballot-tap' bridge, edits msg nonce-free + strips
keyboard, fail-soft. Inert until the CLI (DIVE-1564) sends a cvote: button. Baseline only;
fork-parity port deferred (DIVE-1371/1558 pattern), same as the veto tap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lodar
lodar merged commit c580961 into main Jul 20, 2026
2 checks passed
@lodar
lodar deleted the dive-1566-cvote-tap branch July 23, 2026 15:48
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