Files
proxmox/multi-chain-execution/src/api/admin-routes.ts
defiQUG fbda1b4beb
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands
- CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround
- CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check
- NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere
- MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates
- LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 15:46:57 -08:00

106 lines
3.4 KiB
TypeScript

/**
* Admin/ops API (protected). Policies, key rotation, circuit-breaker.
* Auth: ADMIN_API_KEY (x-admin-key or admin_key query) or JWT later.
* Audit: sends to dbis_core central audit when DBIS_CENTRAL_URL + ADMIN_CENTRAL_API_KEY set.
*/
import { Router, Request, Response, NextFunction } from 'express';
import { setCircuitBreaker } from './observability.js';
import { appendCentralAudit } from './central-audit.js';
const router: Router = Router();
const ADMIN_API_KEY = process.env.ADMIN_API_KEY;
let policies: Record<string, unknown> = {};
let lastKeyRotationAt: Date | null = null;
function getAdminSubject(req: Request): string {
return (req.headers['x-admin-subject'] as string) || 'multi-chain-execution';
}
function adminAuth(req: Request, res: Response, next: NextFunction): void {
if (!ADMIN_API_KEY) {
next();
return;
}
const key = req.headers['x-admin-key'] ?? req.query.admin_key;
if (key !== ADMIN_API_KEY) {
res.status(401).json({ error: 'Unauthorized' });
return;
}
next();
}
router.use(adminAuth);
router.post('/v1/admin/policies', (req: Request, res: Response) => {
const body = req.body as Record<string, unknown>;
if (body && typeof body === 'object') {
policies = { ...policies, ...body };
}
appendCentralAudit({
employeeId: getAdminSubject(req),
action: 'update_policies',
permission: 'admin:action',
resourceType: 'policies',
metadata: body,
ipAddress: req.ip || (req.headers['x-forwarded-for'] as string)?.split(',')[0],
userAgent: req.get('user-agent') ?? undefined,
}).catch(() => {});
res.status(200).json({ message: 'Policy update accepted', policies });
});
router.get('/v1/admin/policies', (_req: Request, res: Response) => {
res.status(200).json({ policies });
});
router.post('/v1/admin/keys/rotate', (req: Request, res: Response) => {
lastKeyRotationAt = new Date();
appendCentralAudit({
employeeId: getAdminSubject(req),
action: 'keys_rotate',
permission: 'admin:action',
resourceType: 'keys',
ipAddress: req.ip || (req.headers['x-forwarded-for'] as string)?.split(',')[0],
userAgent: req.get('user-agent') ?? undefined,
}).catch(() => {});
res.status(200).json({
message: 'Key rotation initiated',
rotated_at: lastKeyRotationAt.toISOString(),
});
});
router.get('/v1/admin/keys/status', (_req: Request, res: Response) => {
res.status(200).json({
last_rotation: lastKeyRotationAt?.toISOString() ?? null,
});
});
router.post('/v1/admin/circuit-breaker/on', (req: Request, res: Response) => {
setCircuitBreaker(true);
appendCentralAudit({
employeeId: getAdminSubject(req),
action: 'circuit_breaker_on',
permission: 'admin:action',
resourceType: 'circuit_breaker',
ipAddress: req.ip || (req.headers['x-forwarded-for'] as string)?.split(',')[0],
userAgent: req.get('user-agent') ?? undefined,
}).catch(() => {});
res.status(200).json({ message: 'Circuit breaker forced open' });
});
router.post('/v1/admin/circuit-breaker/off', (req: Request, res: Response) => {
setCircuitBreaker(false);
appendCentralAudit({
employeeId: getAdminSubject(req),
action: 'circuit_breaker_off',
permission: 'admin:action',
resourceType: 'circuit_breaker',
ipAddress: req.ip || (req.headers['x-forwarded-for'] as string)?.split(',')[0],
userAgent: req.get('user-agent') ?? undefined,
}).catch(() => {});
res.status(200).json({ message: 'Circuit breaker forced closed' });
});
export default router;