/*
RFC-1031: Canary traffic router — deterministic hash-based routing
using Sha256Digest of canonical JSON input bytes (RFC-0849).
- Does not execute components — only makes routing decisions.
- Does not monitor health — that is the health monitor's job.
- RFC-1031: initial implementation — deterministic canary routing via Sha256Digest.
*/
import { byteHash } from "@warpgogol/werkstatt-shared/fingerprint";
import type { Sha256Digest } from "@warpgogol/werkstatt-shared/fingerprint";
const HASH_PREFIX_LENGTH = "sha256:".length;
const ROUTING_HASH_HEX_CHARS = 12;
const ROUTING_MODULUS = 100;
export interface CanaryRouter {
routeToCandidate(input: unknown, trafficPercent: number): boolean;
getRoutingHash(input: unknown): Sha256Digest;
}
export function createCanaryRouter(): CanaryRouter {
return {
routeToCandidate(input: unknown, trafficPercent: number): boolean {
if (trafficPercent <= 0) return false;
if (trafficPercent >= 100) return true;
const hash = this.getRoutingHash(input);
const hashNum = parseInt(
hash.slice(HASH_PREFIX_LENGTH, HASH_PREFIX_LENGTH + ROUTING_HASH_HEX_CHARS),
16,
);
return hashNum % ROUTING_MODULUS < trafficPercent;
},
getRoutingHash(input: unknown): Sha256Digest {
const canonicalBytes = JSON.stringify(input);
return byteHash(canonicalBytes) as Sha256Digest;
},
};
}