You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(security): reject ':' in tenant ids, count only POSTs for eve rate limit (#5)
* fix(security): reject ':' in tenant ids; count only POSTs for eve rate limit
Harden the per-user key boundary and fix the eve rate-limit double-count,
plus stale-doc cleanup. Folded into the existing tenant-isolation changeset.
Tenant isolation
- AgentMemory/ChatHistory/ToolCache now reject a ':' (the key separator) in
userId/sessionId/toolName. The whole isolation model rests on the key shape
`<prefix>:<userId>:<...>`, and only emptiness was validated — a ':' let keys
collide across users (e.g. user "a"+session "b:c" reached user "a:b"+session
"c" via the direct-key getChat/saveChat/deleteChat/forget paths).
- Added unit tests for the rejection across all three primitives.
eve rate limiting
- createRateLimitAuth counts only POST requests. eve drives each turn as two
authenticated requests (the message POST + a follow-up GET .../stream) and
the auth walk runs on both, so a turn was charged twice. Now one turn = one
token; session-read GETs fall through unthrottled. Documented in the README
and docstring; updated tests (a bare Request defaults to GET).
Docs
- Document deriving userId from a verified auth source (Clerk, Auth.js,
Supabase Auth, Auth0, ...), never a client-supplied value; added DEMO-ONLY
warnings to the ai-sdk-demo routes that trust an x-user-id header.
- Fixed stale references: search-tools `{@link withIndex}` -> ReactiveSearchIndex;
ai-sdk memory "scope" -> "userId"; corrected CLAUDE.md's superseded
namespace key-naming note.
* docs(eve): drop @upstash/agentkit-sdk from install (it's already a dependency)
Copy file name to clipboardExpand all lines: .changeset/harden-tenant-isolation.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,10 +8,10 @@ Tenant-isolation hardening, a type-safe reactive search index, and a consistent
8
8
9
9
**Tenant isolation**
10
10
11
-
-`ChatHistory` is keyed per user (`<prefix>:<userId>:<sessionId>`), so a chat can never be read or overwritten by a different user. Every method takes a single object; `userId`/`sessionId` are required and validated non-empty.
12
-
-`AgentMemory` requires a non-empty `userId` on every call (no silent shared bucket); `add`/`recall` take a single object param.
13
-
-`ToolCache` keys are `<prefix>:<userId>:<toolName>:<hash>` — scoped per user, then per tool.
14
-
-`createRateLimit`/`createRateLimitAuth` require an explicit `limiter` (removed `limit`/`window`); eve's `createRateLimitAuth` requires `identifier` (no implicit global bucket).
11
+
-`ChatHistory` is keyed per user (`<prefix>:<userId>:<sessionId>`), so a chat can never be read or overwritten by a different user. Every method takes a single object; `userId`/`sessionId` are required, validated non-empty, and rejected if they contain the `:` key separator (which would otherwise let keys collide across users).
12
+
-`AgentMemory` requires a non-empty `userId` on every call (no silent shared bucket) and rejects a `:` in `userId`; `add`/`recall` take a single object param.
13
+
-`ToolCache` keys are `<prefix>:<userId>:<toolName>:<hash>` — scoped per user, then per tool; `userId`/`toolName` are rejected if they contain `:`.
14
+
-`createRateLimit`/`createRateLimitAuth` require an explicit `limiter` (removed `limit`/`window`); eve's `createRateLimitAuth` requires `identifier` (no implicit global bucket) and counts only `POST` requests, so a turn (a message `POST` plus its follow-up stream `GET`) is charged once, not twice.
15
15
- The eve sandbox denies network egress by default.
-[x] ai-sdk: add `cachedTools` (map of `tool()`-built tools, namespace defaults to map key) alongside `cachedTool`; `cachePrefix` → `namespace`; dropped `toolCache` from the config.
210
214
-[x]`cachedTool`/`cachedTools` are fully type-safe (config extends the AI SDK `tool()` type — input/output inference, no `any`).
211
215
-[x] Search tools: ensure the index (create + `waitIndexing`, memoized) before running each tool — a missing Upstash index returns `null`/`-1` rather than throwing, so we ensure up front.
212
216
-[x]`createMemoryTools` (ai-sdk) + eve memory tools: `scope` → `namespace` (string or per-call function). Core `AgentMemory` add/recall/forget use `namespace`.
213
217
-[x] Rate limiting: `namespace` is a plain string; prefix `agentkit:rateLimit`.
0 commit comments