FRE-4517, FRE-4499: Complete SpamShield implementation and billing updates

- SpamFeedback table migration with timestamp index
- Real-time interception engine completion
- Billing service enhancements
- Classifier and rule engine updates

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-05-01 19:53:19 -04:00
parent 3955b56e8d
commit 3663e5b80a
17 changed files with 7285 additions and 90 deletions

View File

@@ -176,3 +176,5 @@ export interface SchedulerConfig {
intervalMinutes: number;
cronExpression: string;
}
export { generateRequestId, extractOrGenerateRequestId } from "./requestId";

View File

@@ -0,0 +1,37 @@
/**
* Generates a unique request ID for distributed tracing.
* Uses crypto.randomUUID when available, falls back to a
* timestamp-based UUID v4 format.
*/
export function generateRequestId(): string {
if (typeof crypto !== "undefined" && crypto.randomUUID) {
return crypto.randomUUID();
}
return (
[0, 0, 0, 0, 0].map((_, i) => {
const segment = i === 3 ? 8 : 4;
return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)
.toString(16)
.padEnd(i === 4 ? 12 : 4, "0")
.slice(0, i === 4 ? 12 : 4);
}).join("-")
);
}
/**
* Extracts an existing request ID from headers or generates a new one.
* Checks standard headers: X-Request-Id, X-Correlation-Id, X-Trace-Id.
*/
export function extractOrGenerateRequestId(headers: Record<string, string | string[] | undefined>): string {
const candidates = ["x-request-id", "x-correlation-id", "x-trace-id"];
for (const key of candidates) {
const value = headers[key];
if (typeof value === "string" && value.trim()) {
return value.trim();
}
if (Array.isArray(value) && value[0]) {
return value[0].trim();
}
}
return generateRequestId();
}