Add public key token storage for non-revocable publishable keys#8
Add public key token storage for non-revocable publishable keys#8
Conversation
Non-revocable keys create a UX problem: if users lose the token, they're locked out forever since they can't delete and recreate the key. This is especially problematic with limit: 1 configurations. This adds a `public: true` option for key types that stores the plaintext token in metadata, allowing users to view it again in the dashboard. Security: Token storage ONLY happens when BOTH conditions are met: - public: true is set in the key type configuration - revocable: false is set (non-revocable keys only) This double-check ensures secret keys are NEVER stored, even if someone accidentally sets public: true on them (since secret keys are revocable by default). Changes: - Add public_key_type? and viewable_token methods to ApiKey model - Store token in metadata during creation for public keys - Add Show/Copy buttons in dashboard for public keys - Document public option in configuration, initializer, and README - Add 20 tests including 10 security tests verifying secret keys are never stored under any circumstances Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PR Review: Add Public Key Token Storage for Non-Revocable Publishable KeysSummaryThis PR addresses a critical UX issue with non-revocable publishable keys by allowing them to store plaintext tokens for later viewing. The implementation is well-designed with strong security safeguards. Code Quality ✅Strengths:
Minor suggestions:
Security Analysis 🔒Excellent security implementation:
Potential security consideration:
Performance Considerations ⚡Good:
Minor concern:
Test Coverage ✅Outstanding test coverage:
Potential Bugs 🐛None identified - The implementation appears solid. The defensive programming approach with multiple nil checks and guard clauses prevents edge case failures. API Design 💎Excellent API design:
Documentation 📚Exceptional documentation:
RecommendationsHigh PriorityNone - the PR is production-ready as-is. Medium Priority
Low Priority
ConclusionRecommendation: ✅ APPROVE This is an excellent PR that solves a real UX problem with strong security safeguards. The code quality is high, test coverage is comprehensive, and documentation is exceptional. The minor suggestions above are optional improvements that don't block merging. Great work on the security-first approach with the double-check requirement and comprehensive security testing! 🤖 Reviewed with Claude Code |
- Change "Create new secret key" button to "Create new API key" - Change "Secret Key" column header to "API Key" - Change default key name from "Secret key" to show key type or "API key" - Make token display message conditional for public keys (they can view again) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary
public: trueoption to key_types config that stores plaintext token in metadata for later viewingpublic: trueANDrevocable: falseThe Problem
Non-revocable keys create a lockout scenario: if a user creates a publishable key, doesn't copy it immediately, and closes the page—they're stuck forever. They can't recover the token (we only store the hash) and can't delete the key to create a new one (it's non-revocable). With
limit: 1, they'd be permanently locked out.The Solution
For publishable keys designed to be embedded in client apps, there's no security benefit to hiding the token—they're meant to be public! (Stripe lets you view publishable keys anytime.) The
public: trueoption stores the token in metadata so users can view it again.Security
Token storage requires BOTH conditions:
public: truein configrevocable: falsein configThis ensures secret keys are NEVER stored, even if misconfigured. Added 10 dedicated security tests verifying this.
Changes
lib/api_keys/models/api_key.rbpublic_key_type?,viewable_tokenmethods + storage logicapp/views/api_keys/keys/_key_row.html.erblib/api_keys/configuration.rbpublicoption in YARD docslib/generators/api_keys/templates/initializer.rbpublicoption with security warningREADME.mdtest/key_types_test.rbTest plan
public: truedo NOT store token🤖 Generated with Claude Code