// D-KaP v1 reference implementation — TypeScript
// Source of truth: C:/tmp/sh-epoch-ceo/src/lib/brief-seal.ts
import { RAS_ROOT, PHI } from "./constants";
const PHI_PAD = String(PHI);
const enc = new TextEncoder();
async function sha256Hex(input: string): Promise<string> {
const buf = await crypto.subtle.digest("SHA-256", enc.encode(input));
return Array.from(new Uint8Array(buf))
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
}
export async function sealSection(
body: string,
bullets: string[] | undefined,
kind: BriefSection["kind"],
): Promise<string> {
const material = [
`kind:${kind}`,
`body:${body}`,
`bullets:${(bullets ?? []).join("\n")}`,
`ras:${RAS_ROOT}`,
`phi:${PHI_PAD}`,
].join("|");
return sha256Hex(material);
}
export async function sealBrief(
sectionSeals: string[],
recipientFingerprint: string,
): Promise<string> {
const sorted = [...sectionSeals].sort();
const material = [
`sections:${sorted.join(",")}`,
`recipient:${recipientFingerprint}`,
`ras:${RAS_ROOT}`,
`phi:${PHI_PAD}`,
].join("|");
return sha256Hex(material);
}
export async function bundleMerkle(briefSeals: string[]): Promise<string> {
if (briefSeals.length === 0) {
return sha256Hex(`empty:${RAS_ROOT}|${PHI_PAD}`);
}
let layer = await Promise.all(
briefSeals.sort().map((s) => sha256Hex(`leaf:${s}`))
);
while (layer.length > 1) {
if (layer.length % 2 === 1) layer.push(layer[layer.length - 1]!);
const next: string[] = [];
for (let i = 0; i < layer.length; i += 2) {
next.push(await sha256Hex(`pair:${layer[i]}:${layer[i + 1]}`));
}
layer = next;
}
return layer[0]!;
}