←LXXVII
Signaculum

Rubi Project

Self-hosted integrations that let an AI agent act for you, only with your approval.

Status
Pre-alpha
Licence
MIT, open source
Written in
Go
Repository
github.com/Deikus-LXXVII/rubi
01

Overview

Rubi gives an AI agent real integrations, starting with mail, and keeps the owner in control. The agent can request any action. Only the owner can unlock Rubi or approve a sensitive action, and Rubi checks each approval cryptographically.

No project servers

Rubi runs on the agent's machine. The panel is a static site.

Your key

Rubi encrypts everything it stores. It starts locked and opens only with your passkey or password.

Signed approvals

A sensitive action runs only after you sign that exact action. You set the level for each action.

Plugins

Each integration is a separate signed plugin with its own updates and permissions.

02

Architecture

The panel on your device holds the keys. The daemon on the agent's machine holds the data. Everything between them is encrypted end to end, so the carriers see only ciphertext.

Your devicePanelStatic site, no backendPasskey or passwordDerives keys locallyPreviews and approvalsCarriersUntrustedRubi GatewaySix public Nostr relaysQuick tunnel, as a fallbackor your own TailscaleAgent machineRubi daemonVault, encrypted at restPolicy and approvalsPlugins, one process eachEvent bus → agent webhookMCP server, loopback onlyAI agentend-to-end encrypted: carriers see only ciphertextMCP · local
Fig. 2The agent reaches Rubi only through a local MCP server and never talks to the panel.
03

Anatomy of the daemon

The same system, drawn as a machine. The agent's computer is opened up, with the daemon's modules inside. Hover over a module to read what it does.

AGENT MACHINEMAILEVENTSAGENT
Fig. 1VaultRubi encrypts everything it stores under a random data key. Without the owner's key, nobody can read or change it.
04

Approving an action

The agent does not describe the action you approve. Rubi builds the preview from its own stored copy of the action, and your passkey signs a hash of that copy.

AgentRubiPanelYou01prepare_send(email)02stores the exact action03awaiting_approval + link04passes you the link05opens it06fetches the stored action07preview, rendered by Rubi08Face ID09signature over that exact action10verifies, runs it once11approval.decided + result
Fig. 3A strong approval. At the chat level, the agent shows buttons instead of a link.
challenge = SHA-256( canonical_json({ instance, action_id, integration, kind, params_digest, nonce, expires }) )
05

Keys

The keys that can unlock Rubi never reach the agent's machine. The panel unwraps the data key on your device and passes it to Rubi for one session.

KeyWhatWhere it livesPurpose
IKInstance identityOn the agent machine, unencrypted, because it is needed before unlockLets the panel authenticate Rubi and encrypt to it. Pinned at the first pairing
DEKData key, 256-bitOn the agent machine only wrapped; in memory while unlockedEncrypts the vault: secrets, config, policy, state
KEKKey from the passkeyNever stored. The browser derives it from the passkey each timeWraps the data key
KEKKey from the passwordNever stored. The browser derives it with Argon2idWraps the data key, as a fallback
AKApproval credentialInside the vaultVerifies approval signatures
06

Policy

Each action has one of three levels. None runs at once, chat asks with buttons, and strong needs the panel and your passkey. Actions that protect Rubi itself are fixed at strong.

ActionNoneChatStrong
Unlock after a restartFixed
Change levels, plugins, passwords, webhookFixed
Install, update or remove a pluginFixed
Send an email
Create a draft
Read or search
default you can choose itFixed cannot be lowered
07

Transport

Rubi and the panel both open outgoing connections, so neither has an inbound address to attack. Carriers can delay or drop messages, but they cannot read or forge them.

DefaultRubi GatewayFallbackSix public relaysAfter 90 s with no relayQuick tunnelif downnone answerOr, chosen at installYour own Tailscale, no relays
Fig. 4Every request is also encrypted to Rubi's identity key, on top of HTTPS.
6public relays at once
90 sbefore the tunnel fallback
128-bitone-time pairing code
15 minfor the pairing code to be used
08

Plugins

A plugin is a release in its own repository. It can be written in any language and talks to Rubi over an open JSON-RPC protocol. Installing a plugin shows its permissions and needs a strong approval.

AssetContent
rubi-plugin.jsonThe manifest: fields, secrets, actions and their default levels, events, network egress, tools
<id>-<os>-<arch>.tar.gzThe plugin for one platform
SHA256SUMSHashes of every asset
SHA256SUMS.sigEd25519 signature by the publisher's key from the manifest
09

Where it stands

Pre-alpha. The foundations work end to end, but Rubi is not ready for real data yet.

Works today

  • The core and the panel
  • Signed releases with one-tap updates
  • The plugin store
  • iCloud Mail: read, search, drafts, approved send, reply notices

Next

  • Ready for real data
  • More plugins in the store