Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/cloudflare/src/utils/internalStorageKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ export function targetsCloudflareInternalKey(key: string | undefined, allowlist?

// Framework-managed KV namespaces:
// - `cf_` — agents / ai-chat internal state (mirrors the internal SQL table convention)
// - `cf:` — agents chat-recovery entries (`cf:chat-recovery:*`, `cf:chat:*`); the same reserved
// `cf` namespace, but colon-separated instead of underscore-separated
// - `__ps_` — partyserver internals (e.g. `__ps_name`)
// - `/` — MCP OAuth client state (`/<clientName>/<serverId>/{token,client_info,state,...}`),
// read on every MCP tool call. User keys on an Agent rarely use a leading slash; if one does,
// the allowlist opts it back in.
const isFrameworkKey = key.startsWith('cf_') || key.startsWith('__ps_') || key.startsWith('/');
const isFrameworkKey =
key.startsWith('cf_') || key.startsWith('cf:') || key.startsWith('__ps_') || key.startsWith('/');
if (!isFrameworkKey) {
return false;
}
Expand Down
11 changes: 11 additions & 0 deletions packages/cloudflare/test/instrumentDurableObjectStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,17 @@ describe('instrumentDurableObjectStorage', () => {
expect(startSpanSpy).not.toHaveBeenCalled();
});

it('does not create a span for cf:-prefixed chat-recovery keys', async () => {
const startSpanSpy = vi.spyOn(sentryCore, 'startSpan');
const instrumented = instrumentDurableObjectStorage(createMockStorage());

await instrumented.put('cf:chat-recovery:progress', 1);
await instrumented.get('cf:chat-recovery:incident:abc');
await instrumented.list({ prefix: 'cf:chat-recovery:incident:' });

expect(startSpanSpy).not.toHaveBeenCalled();
});

it('does not create a span for a cf_-prefixed put with object entries', async () => {
const startSpanSpy = vi.spyOn(sentryCore, 'startSpan');
const instrumented = instrumentDurableObjectStorage(createMockStorage());
Expand Down
6 changes: 6 additions & 0 deletions packages/cloudflare/test/utils/internalStorageKey.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ describe('targetsCloudflareInternalKey', () => {
expect(targetsCloudflareInternalKey('cf_mcp_servers')).toBe(true);
});

it('matches cf:-prefixed keys (agents chat-recovery namespace)', () => {
expect(targetsCloudflareInternalKey('cf:chat-recovery:incident:abc')).toBe(true);
expect(targetsCloudflareInternalKey('cf:chat-recovery:progress')).toBe(true);
expect(targetsCloudflareInternalKey('cf:chat:recovering')).toBe(true);
});

it('matches __ps_-prefixed keys', () => {
expect(targetsCloudflareInternalKey('__ps_name')).toBe(true);
});
Expand Down
Loading