JiwaAI
Blog
โ†All posts
architecture
engineering
ai
cost-optimization

Building Admin-Only Features Without a Permissions System

Jiwa AI Teamยท

The $1.13 Button Problem

Some features shouldn't be in everyone's hands. When you're running an AI pipeline that costs over a dollar per invocation โ€” three Gemini Image Edit calls, three Kontext naturalizations, three Seedance video generations, and an ffmpeg stitch โ€” you need to control who can trigger it.

We recently shipped our DNA Reel generator: a fifteen-second vertical video produced entirely by AI, featuring a virtual influencer presenting a real product with native Indonesian audio. The quality is remarkable. The cost is real. And during active development, it belongs behind a gate.

The question was: what kind of gate?

Why Not a Full Role System

The obvious answer โ€” a database role, a permission flag, an admin panel โ€” introduces meaningful complexity for what is fundamentally a temporary boundary. Role systems need UI to manage them, migration scripts to maintain them, and session logic to enforce them.

We're moving fast. The feature needs to be tested by a known set of people. The set is small. It will grow, but not rapidly. A full RBAC implementation would take longer to build than the reel pipeline itself.

The Phone Whitelist Pattern

Our auth system already captures phone numbers โ€” every user signs in via WhatsApp OTP. So we already have a reliable, verified identity signal that doesn't require any additional infrastructure.

The approach: a comma-separated environment variable listing trusted phone numbers. One function reads it, splits on commas, checks membership. Any API route that needs protection calls that function after authentication. The UI layer reads an isAdmin flag from the same API response that loads the business data โ€” no extra network round trip, no client-side secret exposure.

The result: a feature that's completely invisible to regular users, costs nothing to maintain, and takes about thirty seconds to grant access to a new trusted tester.

Fixing the Generation Flow

Shipping the gate also surfaced a subtler issue. The reel generator originally assumed posts had already been generated โ€” it found the assigned influencer by looking at the most recent post. That was a reasonable assumption during early development, but it meant the button error message ("Generate posts first") was misleading.

We wanted reels to be a first-class action, triggerable without prerequisites. The fix: a three-tier fallback. First, try to find an influencer from existing posts. Second, check the business's stored influencer matches. Third, fall back to any available influencer. This way, the feature works from day one of a business's existence on the platform.

We also fixed the seed script to populate reference image URLs by default. Influencers were being seeded with empty reference arrays โ€” a gap that would cause generation to fail even when an influencer was found. Now the profile image serves as the baseline reference, and the more precise face+body segmented slots can be layered on top through the expression generation script.

The Environment Variable as Feature Flag

There's a broader pattern here worth naming. Environment variables are an underrated feature flag mechanism, especially for teams moving at speed. They're instantly revocable, require no deployment for value changes (only for new consumers), and create a clear audit trail via source control and secret manager history.

The phone whitelist lives in DEV_PHONES. When the reel feature is ready for general availability, we remove the check. No database migration, no UI change, no permission record to clean up.

Looking Ahead

The reel pipeline is the beginning of a video-first content strategy. Fifteen seconds today; longer formats, multi-scene narratives, and localized audio tracks are on the roadmap. The admin gate gives us room to iterate on quality and cost before opening the feature broadly.

When we do open it, the removal will be a one-line diff. That's intentional.