@tpsdev-ai/flair 0.4.7 → 0.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -357,93 +357,13 @@ server.http(async (request, nextLayer) => {
357
357
  }
358
358
  }
359
359
  }
360
- // ── SemanticSearch: agentId must match authenticated agent ─────────────────
361
- // Non-admin agents can only search their own memories (plus MemoryGrant access,
362
- // which is enforced inside SemanticSearch.ts using the x-tps-agent header).
363
- if (!request.tpsAgentIsAdmin &&
364
- method === "POST" &&
365
- (url.pathname === "/SemanticSearch" || url.pathname === "/SemanticSearch/")) {
366
- try {
367
- const clone = request.clone();
368
- const body = await clone.json();
369
- if (body?.agentId && body.agentId !== agentId) {
370
- return new Response(JSON.stringify({
371
- error: "forbidden: agentId must match authenticated agent",
372
- }), { status: 403, headers: { "Content-Type": "application/json" } });
373
- }
374
- }
375
- catch {
376
- return new Response(JSON.stringify({ error: "malformed_request_body" }), { status: 400, headers: { "Content-Type": "application/json" } });
377
- }
378
- }
379
- // ── BootstrapMemories: agentId must match authenticated agent ───────────────
380
- if (!request.tpsAgentIsAdmin &&
381
- method === "POST" &&
382
- (url.pathname === "/BootstrapMemories" || url.pathname === "/BootstrapMemories/")) {
383
- try {
384
- const clone = request.clone();
385
- const body = await clone.json();
386
- if (body?.agentId && body.agentId !== agentId) {
387
- return new Response(JSON.stringify({
388
- error: "forbidden: agentId must match authenticated agent",
389
- }), { status: 403, headers: { "Content-Type": "application/json" } });
390
- }
391
- }
392
- catch {
393
- return new Response(JSON.stringify({ error: "malformed_request_body" }), { status: 400, headers: { "Content-Type": "application/json" } });
394
- }
395
- }
396
- // ── Memory POST (create): agentId must match authenticated agent ────────────
397
- if (!request.tpsAgentIsAdmin &&
398
- method === "POST" &&
399
- (url.pathname === "/Memory" || url.pathname === "/Memory/")) {
400
- try {
401
- const clone = request.clone();
402
- const body = await clone.json();
403
- if (body?.agentId && body.agentId !== agentId) {
404
- return new Response(JSON.stringify({
405
- error: "forbidden: cannot create memories for another agent",
406
- }), { status: 403, headers: { "Content-Type": "application/json" } });
407
- }
408
- }
409
- catch {
410
- return new Response(JSON.stringify({ error: "malformed_request_body" }), { status: 400, headers: { "Content-Type": "application/json" } });
411
- }
412
- }
413
- // ── Soul POST/PUT: agentId must match authenticated agent ───────────────────
414
- if (!request.tpsAgentIsAdmin &&
415
- (method === "POST" || method === "PUT") &&
416
- (url.pathname === "/Soul" || url.pathname === "/Soul/" || url.pathname.startsWith("/Soul/"))) {
417
- try {
418
- const clone = request.clone();
419
- const body = await clone.json();
420
- if (body?.agentId && body.agentId !== agentId) {
421
- return new Response(JSON.stringify({
422
- error: "forbidden: cannot write another agent's soul",
423
- }), { status: 403, headers: { "Content-Type": "application/json" } });
424
- }
425
- }
426
- catch {
427
- return new Response(JSON.stringify({ error: "malformed_request_body" }), { status: 400, headers: { "Content-Type": "application/json" } });
428
- }
429
- }
430
- // ── Memory PUT: agentId must match authenticated agent ──────────────────────
431
- if (!request.tpsAgentIsAdmin &&
432
- method === "PUT" &&
433
- (url.pathname === "/Memory" || url.pathname === "/Memory/" || url.pathname.startsWith("/Memory/"))) {
434
- try {
435
- const clone = request.clone();
436
- const body = await clone.json();
437
- if (body?.agentId && body.agentId !== agentId) {
438
- return new Response(JSON.stringify({
439
- error: "forbidden: cannot write memories for another agent",
440
- }), { status: 403, headers: { "Content-Type": "application/json" } });
441
- }
442
- }
443
- catch {
444
- return new Response(JSON.stringify({ error: "malformed_request_body" }), { status: 400, headers: { "Content-Type": "application/json" } });
445
- }
446
- }
360
+ // ── Mutation scoping: agentId in body must match authenticated agent ────────
361
+ // The resource handlers also enforce this (defense-in-depth), but rejecting
362
+ // early avoids unnecessary work. We don't use request.clone().json() because
363
+ // Harper's Request is not a Web API Request — it wraps a Node.js stream.
364
+ // Instead, the resource-level check (e.g. BootstrapMemories line 58) handles
365
+ // body-level enforcement since it receives the parsed data from Harper's REST
366
+ // layer. The middleware's job is identity verification (done above).
447
367
  // ── Memory GET: non-admin can only read own memories (by ID) ────────────────
448
368
  if (!request.tpsAgentIsAdmin && method === "GET") {
449
369
  if (url.pathname.startsWith("/Memory/")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpsdev-ai/flair",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
4
4
  "description": "Identity, memory, and soul for AI agents. Cryptographic identity (Ed25519), semantic memory with local embeddings, and persistent personality — all in a single process.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",