Ownership, Device Sharing & Per-Tenant API
A system that manages customers' computers has to answer two opposing questions at once: how do you keep different tenants from seeing one another, while at the same time still allowing device sharing between users without losing ownership. Here's how we solved both.
Tenant isolation — the foundation
Every device (DEVICE) is tied to a single workspace, and every query in the system — listing, connecting, deleting, and even the WebSocket — is filtered by that same workspace. We verified this not only in code but live against the database: 0 out of 12 devices with no assignment, and cross-tenant access is simply impossible. Even the device password is encrypted with the workspace's key, so a device belonging to one tenant cannot be decrypted with another tenant's key.
Per-user ownership
Within the same organization, every user is a separate tenant: the device belongs to whoever connected it (owner_id), and it is private to them by default. This is the separation that was missing when every team member could see everything — now an unshared device stays with its owner alone.
Sharing — explicit and per-device
Sharing is a deliberate action: the owner picks a user in the organization and shares a single device with them (device_grants) or all of their devices (account_grants), choosing between full control and view-only. The shared device is accessible to both and behaves identically — except for one thing:
The dashboard has a "🔗 Shared Devices" area with two tabs — what I've shared out, and what's shared with me — so managing access is clear and convenient. The crypto hasn't changed: the Worker still decrypts with the workspace key, and the grant row is the permission. There's no key exchange and no rotation — the same trust model, just focused per-device instead of per-organization.
Per-tenant API and MCP
Every tenant can issue their own API key (drk_…) that grants programmatic access at exactly the same scope they have in the dashboard — no more. The key is tenant-isolated by definition. It powers both REST (/api/v1/*) and a hosted MCP server (/api/mcp), so you can connect an AI agent (like Claude) and give it tools: to list devices, to see what's shared, and to obtain a one-time connection token. Everything sits behind the same permission — an agent can't see a device you can't see.
3D connections map
And finally, a FROG-style view: all your devices and servers as nodes around a center ("us"), wrapped in a translucent protective shield, with inbound/outbound arrows showing traffic, a monitoring pulse that repeats across all connectivity, and color coding by each device's health. Customer-focused: each tenant sees only their own connections. This isn't decoration — it's a way to grasp at a glance what's connected, what's protected, and what needs attention.