Org in a Box
Gateways

Device Pairing

How the DB-backed pairing system authorises users across all gateways.

Overview

Org in a Box uses a DB-backed pairing system instead of static allowlists. When an unknown user messages any gateway, they receive a one-time pairing code. The owner approves via the web admin panel or CLI — no .env editing required.

How It Works

Unknown user sends DM to bot

Gateway checks gateway_paired_users — not found

Rate limit check (1 code/user/10 min, max 3 pending/gateway)

Insert gateway_pairing_codes (code, expires_at = now + 1h)

NOTIFY orginabox_gateway_events → SSE pushes to admin/wizard

Bot replies: "Your Telegram ID: 123456789 · Your pairing code: ABCD1234"

Owner approves (web or CLI)

gateway_pairing_codes.consumed_at = now (atomic transaction)
gateway_paired_users row inserted

NOTIFY → wizard auto-advances to Done · admin table updates live

Next message from same user

gateway_paired_users check passes → agent-turn job enqueued

Code Properties

PropertyValue
Length8 characters
AlphabetABCDEFGHJKLMNPQRSTUVWXYZ23456789 (no 0/O/1/I ambiguous chars)
TTL1 hour
Rate limit1 new code per user per 10 minutes (including already-approved codes)
Max pending3 per gateway total
Storagegateway_pairing_codes Postgres table

Approval Channels

Web wizard (first-time setup)

/onboarding/3 — SSE stream from /v1/gateways/:id/events. Code appears automatically when the user messages the bot. One-click Approve auto-advances to Done.

Web admin (ongoing)

/admin/gateways → expand "Pending Requests" — live-updating table with Approve/Reject buttons.

CLI

# List pending codes
oiab gateway pairing-list

# Approve by code (gateway auto-detected from code)
oiab gateway pairing-approve --code ABCD1234

# Approve with explicit gateway
oiab gateway pairing-approve --gateway <uuid> --code ABCD1234

Managing Paired Users

# List all gateways with paired user counts
oiab gateway list

# Revoke a specific user
oiab gateway pairing-revoke --gateway <uuid> --user 123456789

Via web: /admin/gateways → expand "Paired Users" → click Revoke.

Database Tables

TablePurpose
gateway_configsOne row per gateway (bot token encrypted, webhook secret encrypted)
gateway_paired_usersApproved (gateway_id, external_user_id) pairs
gateway_pairing_codesPending codes with TTL and consumed-at tracking

Legacy Fallback

When GATEWAY_ID is not set in the gateway container's environment, pairing is skipped and all users are accepted (old behaviour). Set GATEWAY_ID to enforce pairing.

TELEGRAM_ALLOWED_USER_IDS still works as a secondary allowlist and is checked after the DB pairing table.

On this page