# The Routerless State Machine: Using Game Architecture as a Security Primitive
The most common way SaaS products protect premium content is authentication. Log in, check subscription status, return 403 if not subscribed, return content if subscribed.
The weakness: the content URL is still knowable. If you can authenticate once, or reverse-engineer the API call pattern, you can access content at will.
K53 Drill Master takes a different approach. The premium game mode doesn't have a URL to scrape. The game state lives in memory. Navigation is not routing: it's state transitions in a finite state machine.
The Architecture
K53 Drill Master has 11 game modes. The premium modes (SM-2 adaptive review, full simulation, weak spot targeting) are not at routes like /drill/adaptive. They're states in a React state machine.
type GameState =
| { phase: 'menu' }
| { phase: 'auth_gate'; requiredTier: 'premium' }
| { phase: 'mode_select'; availableModes: GameMode[] }
| { phase: 'loading'; modeId: GameModeId }
| { phase: 'active'; session: GameSession }
| { phase: 'result'; summary: SessionSummary }
| { phase: 'review'; cards: ReviewCard[] };
The state machine transitions between these phases based on events. There is no /active URL. There is no /result URL. If you try to directly navigate to any game state, you land on the menu phase, which checks your subscription and gates accordingly.
Why This Is Security, Not Just Architecture
Traditional content gating:
- User requests
/drill/adaptive/session/abc123 - Server checks auth
- Server returns content or 403
Routerless state machine:
- User enters game mode (a state transition, not a navigation)
- The gate check is part of the transition function: it cannot be bypassed
- The session content is assembled in memory during the active phase
- If the user refreshes, they return to the menu, not to mid-session state
- There is no URL to share, to scrape, or to enumerate
This is not security through obscurity. The subscription check is still rigorous. But the attack surface is reduced: there's nothing for a scraper to enumerate, no API endpoint that returns premium content by ID, no session URL that can be shared to bypass the gate.
The Premium Gate Implementation
function canTransition(from: GameState, event: GameEvent, user: User): boolean {
if (event.type === 'START_PREMIUM_MODE' && !user.isPremium) {
return false; // Transition blocked, state machine enforces this, not the router
}
return true;
}
function transition(state: GameState, event: GameEvent, user: User): GameState {
if (!canTransition(state, event, user)) {
return { phase: 'auth_gate', requiredTier: 'premium' };
}
// ... normal transitions
}
The auth_gate state renders the upgrade prompt. The transition function returns it on any attempt to enter a premium mode without the right subscription. The URL does not change. The content was never fetched.
What This Taught Me About Security Architecture
Security decisions made at the architecture layer are more robust than security decisions made at the implementation layer. A rate limiter can be bypassed. An authentication check can be misconfigured. A state machine that structurally cannot produce premium content for an unpaid user is qualitatively different.
Not every product needs a routerless state machine. K53 needed one because the premium content is the product, not access to a feature, but access to the algorithm that adapts to your specific knowledge gaps. Protecting that required thinking about the architecture before thinking about the authentication.
Where in your product could architecture replace a fragile security check?
Reader Insights
0 responses
No insights yet. Be the first!