tractatus/scripts/verify-stripe-portal.js
TheFlow ac2db33732 fix(submissions): restructure Economist package and fix article display
- Create Economist SubmissionTracking package correctly:
  * mainArticle = full blog post content
  * coverLetter = 216-word SIR— letter
  * Links to blog post via blogPostId
- Archive 'Letter to The Economist' from blog posts (it's the cover letter)
- Fix date display on article cards (use published_at)
- Target publication already displaying via blue badge

Database changes:
- Make blogPostId optional in SubmissionTracking model
- Economist package ID: 68fa85ae49d4900e7f2ecd83
- Le Monde package ID: 68fa2abd2e6acd5691932150

Next: Enhanced modal with tabs, validation, export

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:47:42 +13:00

222 lines
9.1 KiB
JavaScript
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Verify Stripe Customer Portal Configuration
*
* This script checks if the Customer Portal is configured correctly
* and provides guidance on what needs to be set up.
*
* Usage:
* node scripts/verify-stripe-portal.js
*
* Environment:
* STRIPE_SECRET_KEY - Your Stripe secret key (test or live)
*/
require('dotenv').config();
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
async function verifyPortalConfiguration() {
console.log('\n🔍 Verifying Stripe Customer Portal Configuration\n');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
try {
// Determine if we're in test or live mode
const mode = process.env.STRIPE_SECRET_KEY.startsWith('sk_test_') ? 'TEST' : 'LIVE';
console.log(`📋 Mode: ${mode}\n`);
// Check for portal configurations
const configurations = await stripe.billingPortal.configurations.list({ limit: 10 });
if (configurations.data.length === 0) {
console.log('❌ No Customer Portal configurations found\n');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
console.log('⚠️ YOU NEED TO CONFIGURE THE CUSTOMER PORTAL\n');
printConfigurationSteps(mode);
return;
}
// Show existing configurations
console.log(`✅ Found ${configurations.data.length} portal configuration(s)\n`);
configurations.data.forEach((config, index) => {
console.log(`\n📦 Configuration #${index + 1}:`);
console.log(` ID: ${config.id}`);
console.log(` Active: ${config.active ? 'Yes ✅' : 'No ❌'}`);
console.log(` Default: ${config.is_default ? 'Yes ✅' : 'No ❌'}`);
console.log(` Created: ${new Date(config.created * 1000).toLocaleString()}`);
// Features
console.log('\n 📋 Enabled Features:');
// Customer update
if (config.features.customer_update) {
const emailEnabled = config.features.customer_update.allowed_updates.includes('email');
console.log(` • Email editing: ${emailEnabled ? '✅ Enabled' : '❌ Disabled'}`);
}
// Payment method update
if (config.features.payment_method_update) {
console.log(` • Payment method update: ✅ Enabled`);
} else {
console.log(` • Payment method update: ❌ Disabled`);
}
// Subscription cancellation
if (config.features.subscription_cancel) {
console.log(` • Subscription cancellation: ✅ Enabled`);
console.log(` Mode: ${config.features.subscription_cancel.mode || 'Not set'}`);
// Check for cancellation survey
if (config.features.subscription_cancel.cancellation_reason) {
console.log(` Cancellation survey: ✅ Enabled`);
console.log(` Survey enabled: ${config.features.subscription_cancel.cancellation_reason.enabled ? 'Yes ✅' : 'No ❌'}`);
if (config.features.subscription_cancel.cancellation_reason.options) {
console.log(` Survey options: ${config.features.subscription_cancel.cancellation_reason.options.length} options`);
}
} else {
console.log(` Cancellation survey: ❌ Not configured`);
}
} else {
console.log(` • Subscription cancellation: ❌ Disabled`);
}
// Invoice history
if (config.features.invoice_history) {
console.log(` • Invoice history: ✅ Enabled`);
} else {
console.log(` • Invoice history: ❌ Disabled`);
}
// Business profile
console.log('\n 🏢 Business Information:');
if (config.business_profile) {
console.log(` • Headline: ${config.business_profile.headline || 'Not set'}`);
console.log(` • Privacy policy URL: ${config.business_profile.privacy_policy_url || 'Not set'}`);
console.log(` • Terms of service URL: ${config.business_profile.terms_of_service_url || 'Not set'}`);
} else {
console.log(` • Not configured`);
}
});
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
// Verify against requirements
const defaultConfig = configurations.data.find(c => c.is_default) || configurations.data[0];
console.log('✅ VERIFICATION CHECKLIST:\n');
const checks = [];
// Check 1: Email editing
const emailEnabled = defaultConfig.features.customer_update?.allowed_updates?.includes('email');
checks.push({
name: 'Email editing enabled',
status: emailEnabled,
required: true
});
// Check 2: Payment method update
const paymentMethodEnabled = defaultConfig.features.payment_method_update?.enabled !== false;
checks.push({
name: 'Payment method update enabled',
status: paymentMethodEnabled,
required: true
});
// Check 3: Subscription cancellation
const cancelEnabled = defaultConfig.features.subscription_cancel?.enabled !== false;
checks.push({
name: 'Subscription cancellation enabled',
status: cancelEnabled,
required: true
});
// Check 4: Cancellation survey
const surveyEnabled = defaultConfig.features.subscription_cancel?.cancellation_reason?.enabled === true;
checks.push({
name: 'Exit survey configured',
status: surveyEnabled,
required: true
});
// Check 5: Invoice history
const invoiceEnabled = defaultConfig.features.invoice_history?.enabled !== false;
checks.push({
name: 'Invoice history enabled',
status: invoiceEnabled,
required: true
});
// Print checklist
checks.forEach(check => {
const icon = check.status ? '✅' : '❌';
const required = check.required ? '(REQUIRED)' : '(optional)';
console.log(` ${icon} ${check.name} ${required}`);
});
const allPassed = checks.filter(c => c.required).every(c => c.status);
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
if (allPassed) {
console.log('🎉 PORTAL CONFIGURATION COMPLETE!\n');
console.log(' All required features are enabled.');
console.log(' You can now use the Customer Portal.\n');
} else {
console.log('⚠️ PORTAL CONFIGURATION INCOMPLETE\n');
console.log(' Some required features are not enabled.');
printConfigurationSteps(mode);
}
} catch (error) {
console.error('❌ Error verifying portal configuration:', error.message);
if (error.type === 'StripeAuthenticationError') {
console.error('\n⚠ Authentication failed. Please check:');
console.error(' 1. STRIPE_SECRET_KEY is set in .env');
console.error(' 2. The key starts with sk_test_ or sk_live_');
console.error(' 3. The key is valid and not expired\n');
}
}
}
function printConfigurationSteps(mode) {
const dashboardUrl = mode === 'TEST'
? 'https://dashboard.stripe.com/test/settings/billing/portal'
: 'https://dashboard.stripe.com/settings/billing/portal';
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
console.log(`📍 CONFIGURE CUSTOMER PORTAL (${mode} MODE)\n`);
console.log(`Step 1: Open Dashboard`);
console.log(` ${dashboardUrl}\n`);
console.log(`Step 2: Enable Features (click each to enable)`);
console.log(` ☐ Customer can edit email`);
console.log(` ☐ Customer can update payment methods`);
console.log(` ☐ Customer can cancel subscriptions`);
console.log(` ☐ Customer can view invoice history\n`);
console.log(`Step 3: Configure Cancellation Survey`);
console.log(` ☐ Enable "Ask why they're cancelling"`);
console.log(` ☐ Add question: "Why are you cancelling?"`);
console.log(` ☐ Options:`);
console.log(` • Too expensive`);
console.log(` • No longer need it`);
console.log(` • Found alternative`);
console.log(` • Other`);
console.log(` ☐ Add optional question: "How can we improve?"`);
console.log(` Type: Text input (optional)\n`);
console.log(`Step 4: Business Information`);
console.log(` ☐ Business name: Tractatus AI Safety Framework`);
console.log(` ☐ Support email: support@agenticgovernance.digital\n`);
console.log(`Step 5: Save Configuration`);
console.log(` ☐ Click "Save" or "Activate"\n`);
console.log(`Step 6: Verify`);
console.log(` ☐ Run this script again to verify:\n`);
console.log(` node scripts/verify-stripe-portal.js\n`);
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
console.log('📖 Full guide: docs/STRIPE_PORTAL_CONFIGURATION_STEPS.md\n');
}
// Run verification
verifyPortalConfiguration().catch(console.error);