Initial commit: TravelHub multi-tenant flight booking platform

Angular + Go + PostgreSQL sample with strict per-tenant isolation.

- Backend: Go API (basic auth, tenant-scoped repository layer, pgx pool)
- Frontend: Angular 22 SPA (search, checkout, bookings, dashboard)
- Database: schema, seed data and demo bookings migrations
- Tests: 311 across Go (integration), Angular (unit) and Playwright (e2e),
  plus a generated evidence report with PDF export
- Security: whitebox VAPT report under security/

Secrets (.env, tokens, DB credentials) are git-ignored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
nilesh.p
2026-09-13 11:38:01 +05:30
co-authored by Claude Opus 4.8
commit 4d3eb18a6c
129 changed files with 25424 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env node
/**
* Serves the evidence report over HTTP.
*
* The report is a plain folder of files and opens perfectly well from disk, but
* a localhost URL is easier to share with a colleague on the same machine, and
* some browsers treat file:// pages more suspiciously than http://.
*
* node scripts/serve-report.mjs http://localhost:9400
* node scripts/serve-report.mjs --port 8123
* node scripts/serve-report.mjs --no-open
*/
import { createServer } from 'node:http';
import { createReadStream, existsSync, statSync } from 'node:fs';
import { spawn } from 'node:child_process';
import { dirname, extname, join, normalize, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const DIR = join(ROOT, 'e2e', 'evidence-report');
const args = process.argv.slice(2);
const portFlag = args.indexOf('--port');
const PORT = portFlag !== -1 ? Number(args[portFlag + 1]) : 9400;
const shouldOpen = !args.includes('--no-open');
if (!existsSync(join(DIR, 'index.html'))) {
console.error(`No report at ${DIR}\nRun the suite first: npm run test:e2e`);
process.exit(1);
}
const TYPES = {
'.html': 'text/html; charset=utf-8',
'.md': 'text/markdown; charset=utf-8',
'.json': 'application/json; charset=utf-8',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.pdf': 'application/pdf',
'.css': 'text/css; charset=utf-8',
'.js': 'text/javascript; charset=utf-8',
};
const server = createServer((req, res) => {
const requested = decodeURIComponent((req.url ?? '/').split('?')[0]);
const relative = requested === '/' ? 'index.html' : requested.replace(/^\/+/, '');
// normalize collapses any ".." before it can escape the report directory.
const target = join(DIR, normalize(relative));
if (!target.startsWith(DIR)) {
res.writeHead(403).end('Forbidden');
return;
}
if (!existsSync(target) || statSync(target).isDirectory()) {
res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(`Not found: ${relative}\n\nThis server only holds the evidence report.`);
return;
}
res.writeHead(200, {
'Content-Type': TYPES[extname(target).toLowerCase()] ?? 'application/octet-stream',
'Cache-Control': 'no-store',
});
createReadStream(target).pipe(res);
});
server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error(
`Port ${PORT} is already in use.\n` +
`Try another: npm run report:serve -- --port ${PORT + 1}`,
);
process.exit(1);
}
throw err;
});
server.listen(PORT, () => {
const url = `http://localhost:${PORT}/`;
console.log(
[
'',
` Test report: ${url}`,
` PDF: ${url}TravelHub-test-report.pdf`,
` Markdown: ${url}report.md`,
'',
' Press Ctrl+C to stop.',
'',
].join('\n'),
);
if (shouldOpen) {
const [cmd, cmdArgs] =
process.platform === 'win32'
? ['cmd', ['/c', 'start', '', url]]
: process.platform === 'darwin'
? ['open', [url]]
: ['xdg-open', [url]];
spawn(cmd, cmdArgs, { detached: true, stdio: 'ignore' }).unref();
}
});