Building a Tiered License Gate for MemStack: From Free to Pro with Grace Periods
Just wrapped up a marathon 90-minute session building out the complete license validation system for MemStack. What started as a simple "check if they have a pro key" turned into a full tiered access system with grace periods and tamper detection.
The Journey from Simple to Sophisticated
I began with a straightforward goal: gate MemStack's MCP tools behind a Pro license. But as I worked through the implementation with my multi-agent setup (Manager, Builder, Reviewer via agent-bridge), the requirements evolved into something much more nuanced.
Version 1: Basic Pro Gate
First iteration was clean and simple:
- Built
license.pywith async validation against my AdminStack API - Added in-memory caching with server-controlled TTL
- Implemented per-key locks to prevent duplicate API calls
- License key sourced from env var or
~/.memstack/license.json - Graceful degradation for network issues, immediate rejection for HTTP 4xx errors
The Reviewer caught 6 issues including a nasty async race condition. All 11 unit tests passed after fixes.
Version 2: Tiered Access Strategy
Then I realized a binary pro/no-pro gate was too harsh. Users need a taste before they buy:
- No key: Fully blocked with "Get your free key at memstack.pro" message
- Free key: Access to 77 out of 80 skills
- Pro key: Full access to all 80 skills
The three Pro-exclusive skills I held back: consolidate, context-db, and api-docs - the power user features.
I also added email capture to the activate_license tool for contact tracking in AdminStack. The Reviewer caught some skill name leakage issues for unauthorized users that I had to patch up.
Version 3: The Grace Period Challenge
Here's where it got interesting. Existing users had been using MemStack for free, and I didn't want to rug-pull them. Solution: 14-day grace period with full Pro access.
The implementation details got tricky:
- Grace state stored in
~/.memstack/grace-period.json - In-memory caching, refreshed daily (not on every tool call)
- Threading locks to prevent file creation races
- Explicit
grace_expiredfield to avoid sentinel value ambiguity
Reviewer caught two critical bugs here that could have caused nasty race conditions.
Version 4: HMAC Tamper Detection
Because this is a local file system, what's stopping someone from just editing the grace period JSON? Enter HMAC-SHA256 signing:
- Machine-specific secret:
HMAC(hostname + username, "memstack-grace-v1") - Legacy files auto-migrated on first read
- Tampered files immediately blocked with integrity failure
- Cached machine secret via
@functools.lru_cache
Of course, the Reviewer found a crash bug where I was unpacking a 3-tuple into 2 variables. Classic.
The Architecture Decisions
Some key choices I made:
Gate at MCP server level: Most robust approach. Skills are completely inaccessible without proper licensing, not just warned about.
Graceful degradation strategy: Network errors allow stale cache usage, but HTTP 4xx errors (invalid keys, etc.) are immediate rejections.
Machine-tied secrets: No external key management needed. The HMAC secret is deterministic but machine-specific.
Grace period = Pro access: Since existing users had full access before, the grace period grants Pro-level access to all 80 skills.
What's Next
The core system is done and pushed, but there's more to build:
- Landing page at memstack.pro with free key signup
- AdminStack UI for license management (create, revoke, upgrade)
- Move the Pro-exclusive skill list to config instead of hardcoded
- End-to-end testing of the email capture flow
- Usage analytics to see which skills people actually use by tier
This was one of those sessions where the scope creep was actually good creep. What started as a simple gate turned into a thoughtful user experience that respects existing users while creating a clear upgrade path.
Now I need to go fix that python3 → python bug in the memstack-pro hooks that I somehow left uncommitted. The little things always get you.