104 lines
4.7 KiB
TypeScript
104 lines
4.7 KiB
TypeScript
/**
|
|
* Platform Service — Fastify server entry point.
|
|
*
|
|
* Modules: auth, audit, notifications, feature flags, blob,
|
|
* invitations, referrals, promos (merged from growth-service),
|
|
* subscriptions, usage, plans, licenses, stripe (merged from billing-service),
|
|
* items, comments, votes, public (merged from tracker-service).
|
|
* Port: 4003 (configurable via PORT env var).
|
|
*/
|
|
|
|
// Resolve secrets from Azure Key Vault BEFORE config parsing
|
|
import { resolveKeyVaultSecrets, LYSNR_SECRETS } from '@bytelyst/config';
|
|
await resolveKeyVaultSecrets([
|
|
LYSNR_SECRETS.COSMOS_KEY,
|
|
LYSNR_SECRETS.COSMOS_ENDPOINT,
|
|
LYSNR_SECRETS.JWT_SECRET,
|
|
LYSNR_SECRETS.STRIPE_SECRET_KEY,
|
|
LYSNR_SECRETS.STRIPE_WEBHOOK_SECRET,
|
|
LYSNR_SECRETS.BILLING_INTERNAL_KEY,
|
|
LYSNR_SECRETS.AZURE_BLOB_CONNECTION_STRING,
|
|
LYSNR_SECRETS.AZURE_BLOB_ACCOUNT_KEY,
|
|
]);
|
|
|
|
import { createServiceApp, startService } from '@bytelyst/fastify-core';
|
|
import { authRoutes } from './modules/auth/routes.js';
|
|
import { auditRoutes } from './modules/audit/routes.js';
|
|
import { notificationRoutes } from './modules/notifications/routes.js';
|
|
import { flagRoutes } from './modules/flags/routes.js';
|
|
import { rateLimitRoutes } from './modules/ratelimit/routes.js';
|
|
import { blobRoutes } from './modules/blob/routes.js';
|
|
import { invitationRoutes } from './modules/invitations/routes.js';
|
|
import { referralRoutes } from './modules/referrals/routes.js';
|
|
import { promoRoutes } from './modules/promos/routes.js';
|
|
import { subscriptionRoutes } from './modules/subscriptions/routes.js';
|
|
import { usageRoutes } from './modules/usage/routes.js';
|
|
import { planRoutes } from './modules/plans/routes.js';
|
|
import { licenseRoutes } from './modules/licenses/routes.js';
|
|
import { stripeRoutes } from './modules/stripe/routes.js';
|
|
import { itemRoutes } from './modules/items/routes.js';
|
|
import { commentRoutes } from './modules/comments/routes.js';
|
|
import { voteRoutes } from './modules/votes/routes.js';
|
|
import { publicRoutes } from './modules/public/routes.js';
|
|
import { initCosmosIfNeeded } from './lib/cosmos-init.js';
|
|
import { config } from './lib/config.js';
|
|
|
|
await initCosmosIfNeeded();
|
|
|
|
const app = await createServiceApp({
|
|
name: 'platform-service',
|
|
version: '0.1.0',
|
|
description: 'Auth, audit, notifications, feature flags, rate limiting, invitations, referrals, promos, subscriptions, usage, plans, licenses, stripe',
|
|
corsOrigin: config.CORS_ORIGIN,
|
|
swagger: {
|
|
title: 'Platform Service',
|
|
description: 'Auth, audit, notifications, feature flags, rate limiting, invitations, referrals, promos, subscriptions, usage, plans, licenses, stripe',
|
|
port: config.PORT,
|
|
},
|
|
metrics: true,
|
|
});
|
|
|
|
// Register route modules
|
|
await app.register(authRoutes, { prefix: '/api' });
|
|
await app.register(auditRoutes, { prefix: '/api' });
|
|
await app.register(notificationRoutes, { prefix: '/api' });
|
|
await app.register(flagRoutes, { prefix: '/api' });
|
|
await app.register(rateLimitRoutes, { prefix: '/api' });
|
|
await app.register(blobRoutes, { prefix: '/api' });
|
|
// Growth modules (merged from growth-service)
|
|
await app.register(invitationRoutes, { prefix: '/api' });
|
|
await app.register(referralRoutes, { prefix: '/api' });
|
|
await app.register(promoRoutes, { prefix: '/api' });
|
|
// Billing modules (merged from billing-service)
|
|
// Scoped with internal key auth guard when BILLING_INTERNAL_KEY is set (Gap 3)
|
|
const BILLING_KEY = config.BILLING_INTERNAL_KEY;
|
|
if (BILLING_KEY) {
|
|
await app.register(async (billingScope) => {
|
|
billingScope.addHook('onRequest', async (req, reply) => {
|
|
const key = req.headers['x-internal-key'];
|
|
if (key !== BILLING_KEY) {
|
|
reply.code(401).send({ error: 'Unauthorized — missing or invalid X-Internal-Key' });
|
|
}
|
|
});
|
|
await billingScope.register(subscriptionRoutes, { prefix: '/api' });
|
|
await billingScope.register(usageRoutes, { prefix: '/api' });
|
|
await billingScope.register(planRoutes, { prefix: '/api' });
|
|
await billingScope.register(licenseRoutes, { prefix: '/api' });
|
|
});
|
|
} else {
|
|
await app.register(subscriptionRoutes, { prefix: '/api' });
|
|
await app.register(usageRoutes, { prefix: '/api' });
|
|
await app.register(planRoutes, { prefix: '/api' });
|
|
await app.register(licenseRoutes, { prefix: '/api' });
|
|
}
|
|
// Stripe routes outside billing scope (webhook has its own signature verification)
|
|
await app.register(stripeRoutes, { prefix: '/api' });
|
|
// Tracker modules (merged from tracker-service)
|
|
await app.register(itemRoutes, { prefix: '/api' });
|
|
await app.register(commentRoutes, { prefix: '/api' });
|
|
await app.register(voteRoutes, { prefix: '/api' });
|
|
// Public routes — no auth, registered at top level
|
|
await app.register(publicRoutes, { prefix: '/api' });
|
|
|
|
await startService(app, { port: config.PORT, host: config.HOST });
|