Pure authorization module added in crates/polymarket-fetch/src/authz.rs as Task 2 of the autotrade foundation plan on branch autotrade-foundation. Provides owner-scope gating for Telegram commands that can trigger real trades.
Location
- File:
crates/polymarket-fetch/src/authz.rs - Module declared in
main.rsalongside the other top-levelmoddeclarations
Public Surface
| Item | Kind | Purpose |
|---|---|---|
Scope | enum | Public or Owner — the authorization level a command requires |
Authz | enum | Allowed or Denied — the result of an authorization check |
OwnerSet | struct | Wraps HashSet<i64> of Telegram user IDs permitted as owners |
authorize(scope, user_id, owners) | fn | Returns Authz::Allowed iff scope is Public OR the user ID is in the owner set |
scope_for(command) | fn | Maps a command name string to its required Scope |
scope_for routing
"autotrade"→Scope::Owner- anything else →
Scope::Public
New owner-only commands from future tasks are added here. This is the single routing table for command authorization.
OwnerSet::parse_csv
Parses a comma-separated string of i64 Telegram user IDs. Garbage tokens (non-numeric, empty, whitespace) are silently ignored rather than panicking. Intended to accept the TELEGRAM_OWNER_IDS environment variable directly.
Design Notes
Intentionally pure
The module has zero I/O — no env reads, no DB, no async. Every function is deterministic and tested in isolation. The environment variable parsing happens at the call site (
main.rs/ wiring layer in Task 3), not here.
Temporary dead-code suppression
#![allow(dead_code)]is set at the module level because nothing inmain.rsconsumesauthzyet. Task 3 (Wire owner-auth into run_command) will import and call these functions; at that point the allow can be removed. Do not remove it earlier or the build will warn on all 6 public items.
Clippy Compliance
The module compiles clean under clippy --workspace --all-targets -- -D warnings (pedantic + nursery profile used by scripts/gate.sh). Key attributes applied:
#[must_use]onOwnerSet::contains,OwnerSet::is_empty,authorize, andscope_for— required by clippy pedantic
Tests
6 unit tests, all passing:
parse_csv_empty— empty string yields empty setparse_csv_garbage_ignored— non-numeric tokens dropped silentlypublic_scope_always_allowed—Scope::Publicwith any user ID →Allowedowner_scope_allowed_for_owner— known ID in set →Allowedowner_scope_denied_for_stranger— unknown ID →Deniedscope_for_autotrade—"autotrade"maps toScope::Owner
Relationship to Autotrade Plan
This is Task 2 of the autotrade foundation. The full task sequence:
- Task 1 — vendor + pin
rs-clob-client-v2intocrates/polymarket-clob/ - Task 2 —
authz.rs(this note) - Task 3 — wire
authz::authorize+authz::scope_forintorun_commandinmain.rs; the#![allow(dead_code)]is removed here
The module is referenced in the broader engine design under the “Control” section — owner-only Telegram, OFF/DRY_RUN/LIVE kill-switch, scope-gated command dispatch.