Package com.tnsai.spi

Interface TenantAware


public interface TenantAware
Opt-in marker SPI for components that honour AgentBuilder.tenantId(...) — i.e. they keep one tenant's data observably separate from another's. Implementations declare the contract by implementing this interface; the framework's pre-flight validation pipeline (AGENT-V012, issue #235) reads instanceof TenantAware on every component the agent is wired to and complains when tenantId is set but a component cannot uphold the isolation contract.

Why a marker, not a method

Mirrors the Healthcheckable shape: MemoryStore, Tool, and McpClient are protected APIs across the monorepo, so adding a default method to each base interface would impose a contract on every existing implementation. Marker SPI keeps the choice explicit — a provider that hasn't decided what tenant isolation looks like for its backend stays silent, and validators downgrade gracefully via an instanceof TenantAware guard.

Implementing

For most stores the contract is "queries scoped by tenantId field / row-level filter / schema-per-tenant / database-per-tenant" — pick whichever your backend supports. The framework does not inspect the implementation strategy; it only trusts the marker.


 public final class MyTenantSafeMemoryStore
         implements MemoryStore, TenantAware {
     // queries automatically include "WHERE tenant_id = ?" filter
     // built from TenantContext.requireTenantId()
 }
 

Implementations MUST:

  • Treat the propagated tenant id as a hard isolation boundary — never return rows / events / cached results belonging to a different tenant, even by accident.
  • Reject calls without a tenant id when AgentBuilder configured one (defence-in-depth).
  • Be safe under concurrent access from differently-tenanted agents in the same JVM.

The contract is consumer-facing — the framework cannot mechanically verify it. Implementations should ship their own integration tests that prove cross-tenant queries return no data leakage.

Runtime propagation

Agent turns bind AgentBuilder.tenantId(...) to TenantContext. Tenant-aware memory stores can obtain the mandatory id through TenantContext.requireTenantId(); the framework also rejects missing or mismatched scopes before delegating to such a store. AGENT-V012 remains the build-time warning for unmarked stores. Tool-side hooks and tenant fields on audit events are outside this contract.

Since:
0.8.5 (issue #235)