From 26f03aac99f5b3244a170c6e4664613173e0685a Mon Sep 17 00:00:00 2001 From: stefanbaxter Date: Thu, 20 Aug 2026 19:14:08 +0000 Subject: [PATCH] =?UTF-8?q?feat(099):=20synmetrix=20D7=20=E2=80=94=20send?= =?UTF-8?q?=20semantic=20events=20with=20the=20FFT=20platform=20write=20ke?= =?UTF-8?q?y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #73 landed the query log / Hasura triggers / D6 source, but the D7 send-path change was staged separately and never merged — so synmetrix still sent with the caller token (tenant partition) instead of the FFT platform key. eventEmitter.js now sends with FFT_INGRESS_WRITE_KEY → fftech.is (partition fftech.is); the caller/tenant is populate-only (OWNED_BY + tenant_partition). Falls back to the pre-D7 path when the key is unset. node --check clean. Co-Authored-By: Claude Opus 4.8 --- services/cubejs/src/utils/eventEmitter.js | 51 ++++++++++++++++------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/services/cubejs/src/utils/eventEmitter.js b/services/cubejs/src/utils/eventEmitter.js index f1ec5e1c..fb390089 100644 --- a/services/cubejs/src/utils/eventEmitter.js +++ b/services/cubejs/src/utils/eventEmitter.js @@ -15,13 +15,16 @@ import { hostname } from "os"; * (FR-007). Every failure branch drops a single structured stderr line as a * last-resort observation and returns `{ ok: false }`. * - * Credential (FR-074 / A4): synmetrix is a background/service caller. If the - * caller forwards its own token (`emitSemanticEvent(env, { token })`) that is - * used verbatim as the ingression `writekey`. Otherwise a short-lived - * FraiOS-shaped service token is minted from the shared `TOKEN_SECRET` - * (HS256 via `jose`, mirroring `mintHasuraToken.js`) so the record still bills - * to the operating tenant. A credential is never invented to fill a gap: with - * no forwarded token and no `TOKEN_SECRET`, the event is skipped + counted. + * Credential (D7 / FR-006a): semantic events are the platform owner's internal + * telemetry, so emission SENDS with the shared FFT platform write key + * (`FFT_INGRESS_WRITE_KEY`, partition `fftech.is`) → the event collects on FFT's + * stream. The caller/tenant context is populate-only: it fills the involves + * (`OWNED_BY`) and the `tenant_partition` dimension, never the send credential. + * Only when the FFT key is unset does emission fall back to the pre-D7 path — a + * forwarded token, else a short-lived service token minted from `TOKEN_SECRET` + * (HS256 via `jose`, mirroring `mintHasuraToken.js`). A credential is never + * invented: with no platform key, no forwarded token and no `TOKEN_SECRET`, the + * event is skipped + counted. * * Endpoint: `{INGRESSION_HOST}/api/s/{envelope.type||'log'}` — `INGRESSION_HOST` * defaults to the FraiOS inbox (matches ai-service `config.py`). @@ -759,17 +762,35 @@ export async function emitSemanticEvent( ? envelope.involves.find((i) => i?.role === "OWNED_BY") : null; - let writekey = token; + // D7 — the tenant this event concerns (populate identity). The top-level partition is + // the FFT collection stream once ingress stamps it, so the customer partition also + // rides as the tenant_partition dimension for per-tenant access-granting. + const tenantPartition = partition ?? envelope.partition ?? null; + if (tenantPartition) { + envelope.dimensions = { + ...(envelope.dimensions || {}), + tenant_partition: envelope.dimensions?.tenant_partition ?? tenantPartition, + }; + } + + // D7 — semantic events are the platform owner's internal telemetry: SEND with the + // shared FFT platform write key (partition `fftech.is`), not a per-tenant/service + // token. The caller/tenant context is populate-only. Fall back to the legacy + // token/service-mint only when the FFT key is unset so nothing breaks before it is + // provisioned. + let writekey = (process.env.FFT_INGRESS_WRITE_KEY || "").trim() || null; if (!writekey) { - writekey = await mintServiceToken({ - accountId: accountId ?? ownerInvolve?.id ?? null, - partition: partition ?? envelope.partition ?? null, - userId, - }); + writekey = + token || + (await mintServiceToken({ + accountId: accountId ?? ownerInvolve?.id ?? null, + partition: tenantPartition, + userId, + })); } if (!writekey) { - // A4: no forwarded credential and none can be minted — skip + count, - // never invent one. + // A4: no platform key, no forwarded credential and none can be minted — skip + + // count, never invent one. logSkip("no_writekey", envelope); return { ok: false }; }