From 300592d1b5d55556e292d8fd6f46ca9c1af51b70 Mon Sep 17 00:00:00 2001 From: "Timothy J. Aveni" Date: Sun, 12 Jul 2026 14:32:49 -0700 Subject: [PATCH] Add runtime auth tokens and canonical field keys --- src/index.ts | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 65f1474..f49b980 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,7 @@ import { createClient, type Client, type HandlerContext, + type Interceptor, } from "@connectrpc/connect"; import { connectNodeAdapter, @@ -569,6 +570,46 @@ export const protoFieldsToJs = ( ]), ); +const normalizeForCanonicalJson = (value: unknown): unknown => { + if (Array.isArray(value)) { + return value.map(normalizeForCanonicalJson); + } + if (!value || typeof value !== "object") { + return value; + } + return Object.fromEntries( + Object.entries(value) + .filter(([, entryValue]) => entryValue !== undefined) + .sort(([left], [right]) => left.localeCompare(right)) + .map(([key, entryValue]) => [key, normalizeForCanonicalJson(entryValue)]), + ); +}; + +export const canonicalFieldParams = ( + params: Record | undefined, +) => + JSON.stringify( + normalizeForCanonicalJson( + Object.fromEntries( + Object.entries(params ?? {}).map(([key, value]) => [ + key, + protoValueToJs(value), + ]), + ), + ), + ); + +export const fieldOperationKey = (params: { + objectId: string; + fieldName: string; + input?: Record; +}) => + [ + params.objectId, + params.fieldName, + Buffer.from(canonicalFieldParams(params.input)).toString("base64url"), + ].join(":"); + const derivedDependencyToProto = (dependency: DerivedDependency) => create(DerivedDependencySchema, { kind: dependency.kind, @@ -679,9 +720,20 @@ export const serveQuixosPackageRuntime = < const host = process.env.QUIXOS_RUNTIME_HOST ?? "127.0.0.1"; const port = Number(process.env.QUIXOS_RUNTIME_PORT ?? "0"); const caminoUrl = process.env.CAMINO_URL ?? "http://127.0.0.1:7310"; + const runtimeToken = process.env.CAMINO_RUNTIME_AUTH_TOKEN ?? ""; + const runtimeTokenInterceptor: Interceptor = (next) => async (request) => { + if (runtimeToken) { + request.header.set("x-camino-runtime-token", runtimeToken); + } + return await next(request); + }; const camino = createClient( CaminoService, - createConnectTransport({ baseUrl: caminoUrl, httpVersion: "1.1" }), + createConnectTransport({ + baseUrl: caminoUrl, + httpVersion: "1.1", + interceptors: runtimeToken ? [runtimeTokenInterceptor] : [], + }), ); const trackingCamino = createDependencyTrackingCaminoClient(camino);