fix: derive internal dynamic rectification token

This commit is contained in:
732642856
2026-07-20 01:37:06 +08:00
parent 64fcb62f83
commit 2a82f7f9fd
4 changed files with 32 additions and 1 deletions
@@ -0,0 +1,14 @@
import { createHash } from "node:crypto";
export function resolveDynamicRectificationToken(
configuredToken: string | undefined,
serviceRoleKey: string | undefined,
): string | null {
const configured = configuredToken?.trim();
if (configured) return configured;
const serviceRole = serviceRoleKey?.trim();
if (!serviceRole) return null;
return createHash("sha256")
.update(`jyotisha-dynamic-rectification-v1:${serviceRole}`)
.digest("hex");
}
@@ -5,6 +5,7 @@ import {
createJourneyEngineWire,
} from "./birth-time-journey-engine-model.ts";
import type { BirthTimeJourneyEngine } from "./birth-time-journey-service.ts";
import { resolveDynamicRectificationToken } from "./birth-time-dynamic-token.ts";
export {
BirthTimeJourneyEngineConfigurationError,
@@ -16,7 +17,10 @@ export function createJyotishBirthTimeJourneyEngine(
): BirthTimeJourneyEngine {
return createJourneyEngineMethods(createJourneyEngineWire({
apiBase,
dynamicToken: process.env.JYOTISH_DYNAMIC_RECTIFICATION_TOKEN ?? null,
dynamicToken: resolveDynamicRectificationToken(
process.env.JYOTISH_DYNAMIC_RECTIFICATION_TOKEN,
process.env.SUPABASE_SERVICE_ROLE_KEY,
),
fetchImpl: fetch,
}));
}
@@ -9,6 +9,7 @@ import {
eventScorePayload,
} from "../src/lib/birth-time-journey-engine-model.ts";
import type { JourneyEngineFetch } from "../src/lib/birth-time-journey-engine-model.ts";
import { resolveDynamicRectificationToken } from "../src/lib/birth-time-dynamic-token.ts";
test("journey engine serializes only stored event-scoring inputs", () => {
const payload = eventScorePayload({
@@ -191,6 +192,12 @@ test("missing dynamic token fails both endpoints before fetch", async () => {
assert.equal(harness.calls.length, 0);
});
test("dynamic token derives only from a server-side service role fallback", () => {
assert.equal(resolveDynamicRectificationToken("configured-token", "service-role"), "configured-token");
assert.match(resolveDynamicRectificationToken(undefined, "service-role") ?? "", /^[a-f0-9]{64}$/);
assert.equal(resolveDynamicRectificationToken(undefined, undefined), null);
});
test("legacy wire calls never receive dynamic authorization", async () => {
const calls: { readonly path: string; readonly init: RequestInit }[] = [];
const engine = createJourneyEngineMethods(createJourneyEngineWire({
+6
View File
@@ -1510,6 +1510,12 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
def _require_dynamic_rectification_token(self):
configured = os.environ.get('JYOTISH_DYNAMIC_RECTIFICATION_TOKEN', '').strip()
if not configured:
service_role = os.environ.get('SUPABASE_SERVICE_ROLE_KEY', '').strip()
if service_role:
configured = hashlib.sha256(
f'jyotisha-dynamic-rectification-v1:{service_role}'.encode('utf-8')
).hexdigest()
supplied = self._job_access_token()
matches = secrets.compare_digest(supplied, configured)
if not configured or not matches: