Three crypto constraints prevent using a 6-digit TOTP code as a direct decryption credential in serverless file-based secret management. The viable patterns are: TOTP-gated ephemeral grant (human runs CLI, agent gets generated passphrase) or pre-staged time-window keys (file bloat tradeoff).
While designing TOTP-based permission escalation for pocket_protector (a serverless, file-based secret manager using NaCl SealedBox + Argon2id), discovered three fundamental constraints that make naive TOTP-as-passphrase impossible:
The 20-bit problem: A 6-digit TOTP code has ~20 bits of entropy (10^6 possibilities). An attacker with the encrypted file can brute-force all codes for any time window in under a second. Even with Argon2id at SENSITIVE cost (~0.8s/attempt), exhaustion takes ~9 days single-core per window — inadequate for high-value secrets.
The serverless verification problem: Standard TOTP is an authentication protocol — a server verifies the code and releases access. In a serverless file-based system, there is no server. Decryption is purely local crypto: if you have the right bytes, it works. There is no entity to "verify against" and conditionally release key material.
The agent-has-the-file problem: If the agent has both the YAML file and the TOTP shared secret (needed to verify the code locally), nothing prevents it from computing the HMAC for any time window and decrypting without a human. The code only proves human presence to an honest agent.
The viable pattern: Use TOTP as an authorization gate on a human-initiated CLI command that creates a time-limited ephemeral owner entry (raw-key custodian with expires metadata). The human verifies the TOTP locally; the agent receives a generated ephemeral passphrase. The TOTP code never becomes a cryptographic credential — it gates the grant ceremony. Soft expiry (TTL check in code) prevents replay from chat logs; hard revocation requires domain key rotation after the grant expires.
For the literal '6 digits = decrypt' UX without a server: Pre-stage encrypted copies of the domain private key for each future time window, using SecretBox(Argon2id(TOTP_code || agent_domain_privkey, salt_per_window)). The agent's existing domain key (256 bits) mixed into the KDF prevents file-only brute-force; the TOTP code adds time-variation. File bloat is ~80 bytes × windows (2880/24h ≈ 230KB). This is the only serverless approach where the agent receives just 6 digits.