From 30fa04cd8553ccf2a54f8aa1a4deff747569017a Mon Sep 17 00:00:00 2001 From: Klappy Date: Thu, 16 Apr 2026 01:02:03 +0000 Subject: [PATCH 1/3] feat: add consumer identification nudge for unidentified consumers --- workers/src/index.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/workers/src/index.ts b/workers/src/index.ts index 7e7f498..c70a4e1 100644 --- a/workers/src/index.ts +++ b/workers/src/index.ts @@ -20,6 +20,7 @@ import { z } from "zod"; import { handleUnifiedAction, type Env } from "./orchestrate"; import { ZipBaselineFetcher } from "./zip-baseline-fetcher"; import { RequestTracer } from "./tracing"; +import { parseConsumerLabel } from "./telemetry"; import { renderNotFoundPage } from "./not-found-ui"; import pkg from "../package.json"; @@ -27,6 +28,9 @@ export type { Env }; const BUILD_VERSION = pkg.version; +const CONSUMER_NUDGE = + "Tip: Add ?consumer=yourname to your oddkit URL to appear on the transparency leaderboard. See telemetry_policy for details."; + // ────────────────────────────────────────────────────────────────────────────── // Types // ────────────────────────────────────────────────────────────────────────────── @@ -111,7 +115,7 @@ async function fetchPromptContent(env: Env, path: string): Promise { +async function createServer(env: Env, tracer?: RequestTracer, consumerSource?: string): Promise { const server = new McpServer( { name: "oddkit", @@ -179,6 +183,9 @@ Use when: env, tracer, }); + if ((consumerSource === "user-agent" || consumerSource === "unknown") && result.assistant_text) { + result.assistant_text += "\n\n" + CONSUMER_NUDGE; + } return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; }, ); @@ -332,6 +339,9 @@ Use when: env, tracer, }); + if ((consumerSource === "user-agent" || consumerSource === "unknown") && result.assistant_text) { + result.assistant_text += "\n\n" + CONSUMER_NUDGE; + } return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; }, ); @@ -800,7 +810,8 @@ export default { ? request.clone() : null; - const server = await createServer(env, tracer); + const { source: consumerSource } = parseConsumerLabel(request, {}); + const server = await createServer(env, tracer, consumerSource); const handler = createMcpHandler(server, { route: "/mcp", corsOptions: { From 326a118e8b364859afe90db3c5b8a8eb64229c29 Mon Sep 17 00:00:00 2001 From: Klappy Date: Thu, 16 Apr 2026 01:15:58 +0000 Subject: [PATCH 2/3] fix: add privacy assurance to consumer nudge text Nudge now leads with what oddkit does NOT track (prompts, searches, responses) before asking the consumer to self-identify. --- workers/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workers/src/index.ts b/workers/src/index.ts index c70a4e1..7b522b0 100644 --- a/workers/src/index.ts +++ b/workers/src/index.ts @@ -29,7 +29,7 @@ export type { Env }; const BUILD_VERSION = pkg.version; const CONSUMER_NUDGE = - "Tip: Add ?consumer=yourname to your oddkit URL to appear on the transparency leaderboard. See telemetry_policy for details."; + "Tip: oddkit tracks tool usage (which tools, how often) but never your prompts, searches, or responses. Add ?consumer=yourname to your oddkit URL to appear on the public transparency leaderboard. See telemetry_policy for details."; // ────────────────────────────────────────────────────────────────────────────── // Types From be30f6d38d742d0e2113818d1b31206b91008f99 Mon Sep 17 00:00:00 2001 From: Klappy Date: Thu, 16 Apr 2026 02:24:02 +0000 Subject: [PATCH 3/3] docs: add inline comment explaining no-cache design MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts bugbot's session cache additions. The server is stateless by design — caching consumer identification across requests violates Vodka Architecture and doesn't even work reliably on Cloudflare Workers' distributed isolates. The query param is the stateless solution. Inline comment prevents future regression. --- workers/src/index.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/workers/src/index.ts b/workers/src/index.ts index 7b522b0..a473b1d 100644 --- a/workers/src/index.ts +++ b/workers/src/index.ts @@ -28,6 +28,23 @@ export type { Env }; const BUILD_VERSION = pkg.version; +// ────────────────────────────────────────────────────────────────────────────── +// Consumer identification nudge +// +// DO NOT add session caching, sticky identification, or per-session memory. +// This server is stateless by design (Vodka Architecture). Cloudflare Workers +// are globally distributed across isolates — module-level Maps don't survive +// across requests reliably. The query param (?consumer=yourname) is the +// stateless solution and works on every request, every isolate, every platform. +// +// If a consumer identifies via MCP clientInfo.name on initialize but not via +// query param, they WILL see this nudge on subsequent tools/call requests. +// That is correct behavior — the nudge tells them exactly how to stop seeing +// it. Caching would mask the problem instead of solving it. +// +// See: canon/principles/vodka-architecture, canon/constraints/telemetry-governance +// ────────────────────────────────────────────────────────────────────────────── + const CONSUMER_NUDGE = "Tip: oddkit tracks tool usage (which tools, how often) but never your prompts, searches, or responses. Add ?consumer=yourname to your oddkit URL to appear on the public transparency leaderboard. See telemetry_policy for details.";