Skip to content

feat(server): tenant-aware write paths and pluggable tenant resolver (4/7)#182

Draft
abhinav-galileo wants to merge 1 commit intoabhi/rfc-1-1-pr3-runtime-resolutionfrom
abhi/rfc-1-1-pr4-tenant-aware-writes
Draft

feat(server): tenant-aware write paths and pluggable tenant resolver (4/7)#182
abhinav-galileo wants to merge 1 commit intoabhi/rfc-1-1-pr3-runtime-resolutionfrom
abhi/rfc-1-1-pr4-tenant-aware-writes

Conversation

@abhinav-galileo
Copy link
Copy Markdown
Collaborator

@abhinav-galileo abhinav-galileo commented Apr 20, 2026

Stacked on top of #181. Kept in draft until the full stack has been validated end-to-end.

Summary

  • Introduces TenantResolver Protocol and HeaderTenantResolver default implementation in tenancy.py.
  • set_tenant_resolver(...) lets deployments with their own tenant identity source (e.g. auth claims) swap in an alternative resolver at startup.
  • Agent (initAgent), control (create_control), and policy (create_policy) creation now persist the resolved tenant explicitly instead of relying solely on the DB default.
  • Association inserts into agent_policies and agent_controls record the owning agent's tenant_id, not the request-scoped one. This keeps association rows consistent with the parent agent under all tenant mechanisms.
  • Read paths remain unscoped (matches the stance from the bottom of the stack).

Design notes

  • The resolver seam is intentionally small: one method, resolve(x_tenant_id). This keeps the OSS code free of auth-specific types and lets extensions grow without forcing OSS code to adopt them.
  • The process-wide resolver is installed once at startup. Tests that swap it via a fixture restore the prior resolver in teardown.
  • Default behavior is unchanged: no header -> default-tenant.

Intentional non-goals (deferred)

  • Tenant-scoped reads on agent/control/policy endpoints. Still out of scope because it would require changing primary keys or adding tenant predicates to many existing queries.
  • Removing global uniqueness on Agent.name, Control.name, Policy.name. Cross-tenant name collisions still apply. Tests use distinct names per tenant rather than depending on tenant-scoped uniqueness.
  • Specific auth-driven resolver implementations.

Test plan

  • make check clean locally (562 server tests including 9 new)
  • New coverage:
    • Writes without a header land in default-tenant for agent/control/policy
    • Writes with X-Tenant-Id land in the resolved tenant
    • agent_policies / agent_controls rows inherit the agent's tenant_id
    • Whitespace header normalizes to default-tenant
    • TenantResolver Protocol is runtime-checkable
    • Installed resolver override is honored by the dependency
  • All existing tests pass unmodified (behavior preservation)
  • Validated on integration branch with PR1-PR4 merged

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@abhinav-galileo abhinav-galileo force-pushed the abhi/rfc-1-1-pr3-runtime-resolution branch from 24b421b to 55a647d Compare April 20, 2026 19:44
@abhinav-galileo abhinav-galileo force-pushed the abhi/rfc-1-1-pr4-tenant-aware-writes branch from 4d165f6 to 0c1787e Compare April 20, 2026 19:46
@abhinav-galileo abhinav-galileo changed the title (4/N) feat(server): tenant-aware write paths + pluggable tenant resolver feat(server): tenant-aware write paths and pluggable tenant resolver (4/4) Apr 20, 2026
@abhinav-galileo abhinav-galileo force-pushed the abhi/rfc-1-1-pr3-runtime-resolution branch 2 times, most recently from 5222252 to 1f581f1 Compare April 20, 2026 20:31
@abhinav-galileo abhinav-galileo force-pushed the abhi/rfc-1-1-pr4-tenant-aware-writes branch from 0c1787e to 2532c58 Compare April 20, 2026 20:34
@abhinav-galileo abhinav-galileo force-pushed the abhi/rfc-1-1-pr3-runtime-resolution branch from 1f581f1 to 41e3d21 Compare April 20, 2026 20:47
@abhinav-galileo abhinav-galileo force-pushed the abhi/rfc-1-1-pr4-tenant-aware-writes branch from 2532c58 to 0bc87a8 Compare April 20, 2026 20:47
@abhinav-galileo abhinav-galileo force-pushed the abhi/rfc-1-1-pr3-runtime-resolution branch from 41e3d21 to af42b84 Compare April 20, 2026 20:48
Agent, control, and policy creation now read the effective tenant via a
get_tenant_id dependency backed by a pluggable TenantResolver. Default
resolver reads X-Tenant-Id header and falls back to DEFAULT_TENANT_ID so
callers that omit the header continue to work. Association inserts into
agent_policies and agent_controls record the owning agent's tenant_id.
Deployments with their own tenant identity source can swap the resolver
at startup via set_tenant_resolver. Read paths remain unscoped.
@abhinav-galileo abhinav-galileo force-pushed the abhi/rfc-1-1-pr4-tenant-aware-writes branch from 0bc87a8 to 5cb6d26 Compare April 20, 2026 20:49
@abhinav-galileo abhinav-galileo changed the title feat(server): tenant-aware write paths and pluggable tenant resolver (4/4) feat(server): tenant-aware write paths and pluggable tenant resolver (4/5) Apr 20, 2026
@abhinav-galileo abhinav-galileo changed the title feat(server): tenant-aware write paths and pluggable tenant resolver (4/5) feat(server): tenant-aware write paths and pluggable tenant resolver (4/6) Apr 20, 2026
@abhinav-galileo abhinav-galileo changed the title feat(server): tenant-aware write paths and pluggable tenant resolver (4/6) feat(server): tenant-aware write paths and pluggable tenant resolver (4/7) Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant