← back to Crankd
server.js
66 lines
'use strict';
require('dotenv').config();
const express = require('express');
const path = require('path');
const { aiDisclosurePreamble, preflight, boolEnv } = require('./lib/compliance');
const PORT = parseInt(process.env.PORT || '9821', 10);
const app = express();
app.use(express.json({ limit: '256kb' }));
app.use(express.urlencoded({ extended: false }));
app.use((_req, res, next) => {
res.set('Cache-Control', 'no-store');
next();
});
app.get('/healthz', (_req, res) => {
res.json({
ok: true,
service: 'crankd',
port: PORT,
steve_only_mode: boolEnv('COMPLIANCE_STEVE_ONLY_MODE', true),
opt_in_required: boolEnv('COMPLIANCE_REQUIRE_OPT_IN', true),
ai_disclosure_required: boolEnv('COMPLIANCE_AI_DISCLOSURE_REQUIRED', true),
});
});
// 404-guard: never serve snapshot/backup files from the static root
const SNAPSHOT_PATH_RE = /(?:\.bak(?:\.|$)|\.pre-|\/\.pre-)/i;
app.use((req, res, next) => {
if (SNAPSHOT_PATH_RE.test(req.path)) return res.status(404).type('text/plain').send('not found');
next();
});
// Public landing
app.use('/', express.static(path.join(__dirname, 'public'), { extensions: ['html'] }));
// --- Compliance pre-flight (dry-run; no Twilio call yet) ---
app.post('/api/preflight', (req, res) => {
const { recipient, opt_in_record, has_recording_consent, dnc_clean } = req.body || {};
if (!recipient) return res.status(400).json({ ok: false, error: 'recipient required' });
const result = preflight({ recipient, opt_in_record, has_recording_consent, dnc_clean });
res.json({
...result,
preamble: aiDisclosurePreamble(),
});
});
// --- Place call (HARD-DISABLED in v0.1; flip CRANKD_ENABLE_DIAL=1 only after wiring) ---
app.post('/api/call', (req, res) => {
if (!/^(1|true)$/i.test(process.env.CRANKD_ENABLE_DIAL || '')) {
return res.status(503).json({
ok: false,
error: 'dialing_disabled_in_v0_1',
hint: 'Wire opt-in flow + DNC scrub + recipient allowlist first, then set CRANKD_ENABLE_DIAL=1.',
});
}
return res.status(501).json({ ok: false, error: 'not_implemented' });
});
app.listen(PORT, () => {
console.log(`[crankd] listening on :${PORT}`);
console.log(`[crankd] steve_only_mode=${boolEnv('COMPLIANCE_STEVE_ONLY_MODE', true)} opt_in=${boolEnv('COMPLIANCE_REQUIRE_OPT_IN', true)}`);
});