mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
Follow-up hardening on the request-id grant path. approve_request took the same lockout treatment as approve_code: gated by it, and recording a miss toward it. But the two paths defend different things. The lockout exists to stop guessing at the 8-char code space over a messaging channel; a request id is only ever obtained by an admin already authenticated to the store, so a miss means the row they clicked went stale. Counting those let a handful of clicks on a stale list lock the operator out of `hermes pairing approve` for an hour — the GUI DoSing the CLI. Also drops the `code`/`code_hash_prefix` compat fields from list_pending. The hash prefix is what admin surfaces mistook for an approvable code in the first place, and re-exporting the request id under the old `code` key just preserves the ambiguity; both consumers in the tree read `request_id` now. The 16-hex sniffing that had been copy-pasted into the CLI and the endpoint (where a chained conditional consulted it against the wrong field) moves to one owner, PairingStore.looks_like_request_id. The endpoint no longer reports a 429 on the request-id path, where lockout can't apply — a stale id surfaced as a bogus "locked out" while the platform sat locked for something else entirely.
40 lines
1.5 KiB
Python
40 lines
1.5 KiB
Python
"""``hermes pairing`` subcommand parser.
|
|
|
|
Extracted from ``hermes_cli/main.py:main()`` (god-file Phase 2 follow-up).
|
|
Handler injected to avoid importing ``main``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Callable
|
|
|
|
|
|
def build_pairing_parser(subparsers, *, cmd_pairing: Callable) -> None:
|
|
"""Attach the ``pairing`` subcommand to ``subparsers``."""
|
|
pairing_parser = subparsers.add_parser(
|
|
"pairing",
|
|
help="Manage DM pairing codes for user authorization",
|
|
description="Approve or revoke user access via pairing codes",
|
|
)
|
|
pairing_sub = pairing_parser.add_subparsers(dest="pairing_action")
|
|
|
|
pairing_sub.add_parser("list", help="Show pending + approved users")
|
|
|
|
pairing_approve_parser = pairing_sub.add_parser(
|
|
"approve", help="Approve a pairing request"
|
|
)
|
|
pairing_approve_parser.add_argument(
|
|
"platform", help="Platform name (telegram, discord, slack, whatsapp)"
|
|
)
|
|
pairing_approve_parser.add_argument(
|
|
"code",
|
|
metavar="request-id|code",
|
|
help="Request ID from 'pairing list', or the code the bot DM'd the user",
|
|
)
|
|
|
|
pairing_revoke_parser = pairing_sub.add_parser("revoke", help="Revoke user access")
|
|
pairing_revoke_parser.add_argument("platform", help="Platform name")
|
|
pairing_revoke_parser.add_argument("user_id", help="User ID to revoke")
|
|
|
|
pairing_sub.add_parser("clear-pending", help="Clear all pending codes")
|
|
pairing_parser.set_defaults(func=cmd_pairing)
|