#5 Gateway Trust Model: - Token validation now uses protected endpoints, not health checks - Unknown services rejected (no fallback to unprotected endpoint) - Trust model documented in docs/trust-model.md #8 CI Enforcement: - Added .gitea/workflows/security.yml with: - Dependency audit (npm audit --audit-level=high for budget) - Secret scanning (checks for tracked .env/.db, hardcoded secrets) - Dockerfile lint (non-root USER, HEALTHCHECK presence) #9 Performance Hardening: - Budget /summary: 1-minute in-memory cache (avoids repeated account fan-out) - Gateway /api/dashboard: 30-second per-user cache (50x faster on repeat) - Inventory health endpoint added before auth middleware Closes #5, #8, #9
This commit is contained in:
@@ -545,9 +545,16 @@ app.get('/transfer-payees', requireReady, async (_req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// ---- Dashboard summary ----------------------------------------------------
|
||||
// ---- Dashboard summary (cached) -------------------------------------------
|
||||
|
||||
let summaryCache = { data: null, expiresAt: 0 };
|
||||
const SUMMARY_TTL_MS = 60 * 1000; // 1 minute cache
|
||||
|
||||
app.get('/summary', requireReady, async (_req, res) => {
|
||||
// Return cached summary if fresh
|
||||
if (summaryCache.data && Date.now() < summaryCache.expiresAt) {
|
||||
return res.json(summaryCache.data);
|
||||
}
|
||||
try {
|
||||
// Total balance across all accounts
|
||||
const accounts = await api.getAccounts();
|
||||
@@ -592,7 +599,7 @@ app.get('/summary', requireReady, async (_req, res) => {
|
||||
.sort((a, b) => a.amount - b.amount) // most negative first
|
||||
.slice(0, 10);
|
||||
|
||||
res.json({
|
||||
const result = {
|
||||
month,
|
||||
totalBalance,
|
||||
totalBalanceDollars: centsToDollars(totalBalance),
|
||||
@@ -603,7 +610,9 @@ app.get('/summary', requireReady, async (_req, res) => {
|
||||
topCategories,
|
||||
accountCount: accounts.length,
|
||||
transactionCount: allTxns.length,
|
||||
});
|
||||
};
|
||||
summaryCache = { data: result, expiresAt: Date.now() + SUMMARY_TTL_MS };
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error('[budget] GET /summary error:', err);
|
||||
res.status(500).json({ error: err.message });
|
||||
|
||||
Reference in New Issue
Block a user