Helios
Security

TOTP enrolment (owner)

The platform owner has a single Telegram identity (`OWNER_TG_USER_ID`).

The platform owner has a single Telegram identity (OWNER_TG_USER_ID). That identity already authenticates every /v1/owner/* call via the bot's initData HMAC. TOTP layers a second factor on top: a six-digit code from any RFC-6238 authenticator app (1Password, Authy, Google Authenticator) must accompany every owner-route request.

Enabling

Phase 30 ships the verification half — the panel-driven enrolment flow lands later. Until then, enrolment is manual:

  1. Generate a secret:
    import pyotp
    secret = pyotp.random_base32()
  2. Set the env:
    OWNER_TOTP_ENABLED=true
    OWNER_TOTP_SECRET=<secret>
  3. Scan: build the provisioning URI manually and feed it to your authenticator app:
    uri = pyotp.TOTP(secret).provisioning_uri(
        name="owner@helios", issuer_name="Helios"
    )

After restarting the API service, every owner-route call (including GDPR ops, parameter overrides, and the Mini App's owner pages) demands an X-TOTP-Code header with the current 6-digit value.

Using

The Mini App's API client wraps the header automatically when the owner has enrolled — the page prompts for a code, caches it for the configured window, and re-prompts on expiry. From outside the Mini App (e.g. curl), include the header explicitly:

curl -H "X-Telegram-Init-Data: $INIT_DATA" \
     -H "X-TOTP-Code: $(oathtool --base32 --totp "$OWNER_TOTP_SECRET")" \
     ${PUBLIC_BASE_URL}/v1/owner/parameters

Behaviour matrix

OWNER_TOTP_ENABLEDCode headerResult
false (default)any/noneopen — TOTP off
trueabsent / empty403 TOTP: missing X-TOTP-Code header
truenot 6 digits403 TOTP: TOTP code must be 6 digits
truewrong code403 TOTP: invalid TOTP code
truecorrect code200

Non-owner users never see any TOTP messaging — they get the regular 403 owner only before the second-factor check runs, so the enrolment state of the owner isn't leaked.

Skew

pyotp.verify(code, valid_window=1) — accepts the previous and next 30-second window plus the current one. Tightens to zero for HSM-style setups by editing infrastructure/auth/totp.py. The default is the right tradeoff for one operator with one device.

Recovery

There is no built-in recovery code today. Lose your authenticator and you must flip OWNER_TOTP_ENABLED=false from a host with shell access, then re-enrol. Production setups should put a sealed offline copy of OWNER_TOTP_SECRET in a manager (1Password, Vault) with the rest of the AES master-key backup.

On this page