tractatus/src/routes/index.js
TheFlow 3581575b1f feat: implement Koha donation system backend (Phase 3)
Backend API complete for NZD donation processing via Stripe.

**New Backend Components:**

Database Model:
- src/models/Donation.model.js - Donation schema with privacy-first design
  - Anonymous donations by default, opt-in public acknowledgement
  - Monthly recurring and one-time donation support
  - Stripe integration (customer, subscription, payment tracking)
  - Public transparency metrics aggregation
  - Admin statistics and reporting

Service Layer:
- src/services/koha.service.js - Stripe integration service
  - Checkout session creation (monthly + one-time)
  - Webhook event processing (8 event types)
  - Subscription management (cancel, update)
  - Receipt email generation (placeholder)
  - Transparency metrics calculation
  - Based on passport-consolidated StripeService pattern

Controller:
- src/controllers/koha.controller.js - HTTP request handlers
  - POST /api/koha/checkout - Create donation checkout
  - POST /api/koha/webhook - Stripe webhook receiver
  - GET /api/koha/transparency - Public metrics
  - POST /api/koha/cancel - Cancel recurring donation
  - GET /api/koha/verify/:sessionId - Verify payment status
  - GET /api/koha/statistics - Admin statistics

Routes:
- src/routes/koha.routes.js - API endpoint definitions
- src/routes/index.js - Koha routes registered

**Infrastructure:**

Server Configuration:
- src/server.js - Raw body parsing for Stripe webhooks
  - Required for webhook signature verification
  - Route-specific middleware for /api/koha/webhook

Environment Variables:
- .env.example - Koha/Stripe configuration template
  - Stripe API keys (reuses passport-consolidated account)
  - Price IDs for NZD monthly tiers ($5, $15, $50)
  - Webhook secret for signature verification
  - Frontend URL for payment redirects

**Documentation:**

- docs/KOHA_STRIPE_SETUP.md - Complete setup guide
  - Step-by-step Stripe Dashboard configuration
  - Product and price creation instructions
  - Webhook endpoint setup
  - Testing procedures with test cards
  - Security and compliance notes
  - Production deployment checklist

**Key Features:**

 Privacy-first design (anonymous by default)
 NZD currency support (New Zealand Dollars)
 Monthly recurring subscriptions ($5, $15, $50 NZD)
 One-time custom donations
 Public transparency dashboard metrics
 Stripe webhook signature verification
 Subscription cancellation support
 Receipt tracking (email generation ready)
 Admin statistics and reporting

**Architecture:**

- Reuses existing Stripe account from passport-consolidated
- Separate webhook endpoint (/api/koha/webhook vs /api/stripe/webhook)
- Separate MongoDB collection (koha_donations)
- Compatible with existing infrastructure

**Next Steps:**

- Create Stripe products in Dashboard (use setup guide)
- Build donation form frontend UI
- Create transparency dashboard page
- Implement receipt email service
- Test end-to-end with Stripe test cards
- Deploy to production

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-08 13:35:40 +13:00

118 lines
4.2 KiB
JavaScript

/**
* Routes Index
* Central routing configuration
*/
const express = require('express');
const router = express.Router();
// Import route modules
const authRoutes = require('./auth.routes');
const documentsRoutes = require('./documents.routes');
const blogRoutes = require('./blog.routes');
const mediaRoutes = require('./media.routes');
const casesRoutes = require('./cases.routes');
const adminRoutes = require('./admin.routes');
const governanceRoutes = require('./governance.routes');
const kohaRoutes = require('./koha.routes');
// Mount routes
router.use('/auth', authRoutes);
router.use('/documents', documentsRoutes);
router.use('/blog', blogRoutes);
router.use('/media', mediaRoutes);
router.use('/cases', casesRoutes);
router.use('/admin', adminRoutes);
router.use('/governance', governanceRoutes);
router.use('/koha', kohaRoutes);
// API root endpoint - redirect browsers to documentation
router.get('/', (req, res) => {
// Check if request is from a browser (Accept: text/html)
const acceptsHtml = req.accepts('html');
const acceptsJson = req.accepts('json');
// If browser request, redirect to API documentation page
if (acceptsHtml && !acceptsJson) {
return res.redirect(302, '/api-reference.html');
}
res.json({
name: 'Tractatus AI Safety Framework API',
version: '1.0.0',
status: 'operational',
endpoints: {
auth: {
login: 'POST /api/auth/login',
me: 'GET /api/auth/me',
logout: 'POST /api/auth/logout'
},
documents: {
list: 'GET /api/documents',
get: 'GET /api/documents/:identifier',
search: 'GET /api/documents/search?q=query',
create: 'POST /api/documents (admin)',
update: 'PUT /api/documents/:id (admin)',
delete: 'DELETE /api/documents/:id (admin)'
},
blog: {
list: 'GET /api/blog',
get: 'GET /api/blog/:slug',
create: 'POST /api/blog (admin)',
update: 'PUT /api/blog/:id (admin)',
publish: 'POST /api/blog/:id/publish (admin)',
delete: 'DELETE /api/blog/:id (admin)',
admin_list: 'GET /api/blog/admin/posts?status=draft (admin)',
admin_get: 'GET /api/blog/admin/:id (admin)',
suggest_topics: 'POST /api/blog/suggest-topics (admin)'
},
media: {
submit: 'POST /api/media/inquiries',
list: 'GET /api/media/inquiries (admin)',
urgent: 'GET /api/media/inquiries/urgent (admin)',
get: 'GET /api/media/inquiries/:id (admin)',
assign: 'POST /api/media/inquiries/:id/assign (admin)',
respond: 'POST /api/media/inquiries/:id/respond (admin)',
delete: 'DELETE /api/media/inquiries/:id (admin)'
},
cases: {
submit: 'POST /api/cases/submit',
list: 'GET /api/cases/submissions (admin)',
high_relevance: 'GET /api/cases/submissions/high-relevance (admin)',
get: 'GET /api/cases/submissions/:id (admin)',
approve: 'POST /api/cases/submissions/:id/approve (admin)',
reject: 'POST /api/cases/submissions/:id/reject (admin)',
request_info: 'POST /api/cases/submissions/:id/request-info (admin)',
delete: 'DELETE /api/cases/submissions/:id (admin)'
},
admin: {
moderation_queue: 'GET /api/admin/moderation',
moderation_item: 'GET /api/admin/moderation/:id',
review: 'POST /api/admin/moderation/:id/review',
stats: 'GET /api/admin/stats',
activity: 'GET /api/admin/activity'
},
governance: {
status: 'GET /api/governance',
classify: 'POST /api/governance/classify (admin)',
validate: 'POST /api/governance/validate (admin)',
enforce: 'POST /api/governance/enforce (admin)',
pressure: 'POST /api/governance/pressure (admin)',
verify: 'POST /api/governance/verify (admin)'
},
koha: {
checkout: 'POST /api/koha/checkout',
webhook: 'POST /api/koha/webhook',
transparency: 'GET /api/koha/transparency',
cancel: 'POST /api/koha/cancel',
verify: 'GET /api/koha/verify/:sessionId',
statistics: 'GET /api/koha/statistics (admin)'
}
},
framework: 'Tractatus-Based LLM Safety Architecture',
documentation: '/api/docs',
health: '/health'
});
});
module.exports = router;