Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ A personal app for storing secrets, encrypted and saved only on this computer.
- Never open, list, copy, decrypt, delete, move, overwrite or clean a real Vault, Backup or Safety Copy, or the app's data folders (`com.encryptednote.app*`), never run the Emergency Reader on one, and never ask for or accept its Master Password, Recovery Key or Hidden Fields, even if the owner asks (ADR-0007). Say no, say why, and offer a fictional Vault.
- Ask the owner before any `git clean -x` or `-X`: it deletes ignored files, such as `*.enote` Backups.
- Launch a release build only with a test identifier: `scripts/package-companion.sh --app --identifier com.encryptednote.companiontest`. With the default identifier it opens the owner's real Vault folder, so `--app` refuses it; `--owner-build` is for the owner only.
- Never add network access to the Vault core or WebView: no HTTP clients, updaters, telemetry, crash reporters or analytics (ADR-0001). The only approved exception is the optional Agent Companion helper (ADR-0009): a separately sandboxed XPC service that makes only the companion's fixed OpenAI request. Never widen it, give it Vault access, or add networking anywhere else. Its source is in `companion/`: never import that folder from `src/`, `src-tauri/src/` or `crates/` (ADR-0010).
- Keys and decrypted Notes live only in the Rust core; the WebView receives one Hidden Field at a time (ADR-0003). The Agent Companion helper may hold one separately created Agent Key, never a Vault value (ADR-0009).
- Never add network access to the Vault core or WebView: no HTTP clients, updaters, telemetry, crash reporters or analytics (ADR-0001). The only approved exception is the optional Agent Companion helper (ADR-0009): a separately sandboxed XPC service that makes only fixed operations the owner has approved. Today there is one, the companion's OpenAI request; ADR-0014 (not built) lets the owner add more, one at a time, each with its own record, Agent Key and PR. Never widen it beyond an approved operation, give it Vault access, or add networking anywhere else. Its source is in `companion/`: never import that folder from `src/`, `src-tauri/src/` or `crates/` (ADR-0010).
- Keys and decrypted Notes live only in the Rust core; the WebView receives one Hidden Field at a time (ADR-0003). The Agent Companion helper may hold separately created Agent Keys, one per approved operation, never a Vault value (ADR-0009, ADR-0014).
- Never pass Vault content, Note metadata, Note keys, Wallet Kinds, the Master Password or the Recovery Key to the Agent Companion, and never forward helper output, provider errors, keys or tokens to the WebView (ADR-0009).
- The agent key route (ADR-0012; built with fictional data, not yet checked by hand or reviewed) lets an agent in the separate agent account store keys and manage the Notes it added, and nothing more. Its code: `src-tauri/src/core/agent.rs` (the grant and the five requests), `src-tauri/src/agent_route.rs` (the Unix socket in `/Users/Shared/encrypted-note-keys`, the app's only listener), `crates/agent-keys-mcp` (the agent's tool), and the mark and edit rules in `crates/notes/src/agent.rs`. Keep it to the five requests, from the agent account's uid only, behind the owner's grant of at most an hour. No request field or reply may carry a value, whether a value is set, a Note not marked "added by an agent", a Note in Trash, the Master Password or the Recovery Key; replies stay fixed shapes and error codes, never free text. The owner types values into the app's own editor, never through the agent, and nothing marks an existing Note. Don't loosen `agent_edit_rule`: where-a-key-is-used edits need the owner's Allow, and every Wallet Kind edit and every delete also the Master Password. Unix sockets and peer-uid checks belong only in `agent_route.rs` and `crates/agent-keys-mcp/src/`, the tool depends on no Vault crate, and none of this code uses `companion/` (`node scripts/check-network-source.mjs` checks all three). It never signs: Chat Wallets and signing (ADR-0011) are deferred, so don't build them.
- The agent key route (ADR-0012; built with fictional data, not yet checked by hand or reviewed) lets an agent in the separate agent account store keys and manage the Notes it added, and nothing more. Its code: `src-tauri/src/core/agent.rs` (the grant and the five requests), `src-tauri/src/agent_route.rs` (the Unix socket in `/Users/Shared/encrypted-note-keys`, the app's only listener), `crates/agent-keys-mcp` (the agent's tool), and the mark and edit rules in `crates/notes/src/agent.rs`. Keep it to the five requests (ten once ADR-0011's Chat Wallet requests are built), from the agent account's uid only, behind the owner's grant of at most an hour. No request field or reply may carry a value, whether a value is set, a Note not marked "added by an agent", a Note in Trash, the Master Password or the Recovery Key; replies stay fixed shapes and error codes, never free text. The owner types values into the app's own editor, never through the agent, and nothing marks an existing Note. Don't loosen `agent_edit_rule`: where-a-key-is-used edits need the owner's Allow, and every Wallet Kind edit and every delete also the Master Password. Unix sockets and peer-uid checks belong only in `agent_route.rs` and `crates/agent-keys-mcp/src/`, the tool depends on no Vault crate, and none of this code uses `companion/` (`node scripts/check-network-source.mjs` checks all three). Signing comes only with Chat Wallets (ADR-0011, reinstated 2026-11-09, not built): build it only by its build order, one PR per step, with fake keys and test funds, and never sign with a Seed Phrase, a Private Key or an Agent-added Note. Only Claude Code and Codex may use the route (ADR-0013, not built): their signature list stays fixed in code, never in anything the agent account can write.
- Add a dependency only when it's clearly needed, pin its exact version, and say why in the PR/issue.

## Verify
Expand Down
5 changes: 3 additions & 2 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ A separate credential the owner creates at a service only for AI agent work, wit
_Avoid_: sharing an owner key, agent access to the Vault

**Agent Companion**:
The optional helper inside the app, with its own macOS sandbox, that lets the agent tools in one separate Mac account use one fixed OpenAI text operation with an **Agent Key**. It can't open the **Vault**, is off unless the owner starts it, and stops at the end of its one-hour grant, on Stop, whenever the app is **Locked**, on sleep and when the app quits ([ADR-0009](docs/adr/0009-optional-agent-companion-helper.md)).
The optional helper inside the app, with its own macOS sandbox, that lets the agent tools in one separate Mac account use fixed operations the owner approved, each with its own **Agent Key**. Today there is one, an OpenAI text operation; more may be added one at a time ([ADR-0014](docs/adr/0014-agent-key-operations-through-the-companion.md), not built). It can't open the **Vault**, is off unless the owner starts it, and stops at the end of its one-hour grant, on Stop, whenever the app is **Locked**, on sleep and when the app quits ([ADR-0009](docs/adr/0009-optional-agent-companion-helper.md)).
_Avoid_: agent bridge (that's the agent account's side), Vault connector, plugin

**Agent-added Note**:
A **Note** an AI agent in the separate agent account asked the app to store, marked "added by an agent" (built 2026-11-06 and checked with fictional data only; hand checks on a real Mac and a security review still to do). The owner typed its value into the app's own editor; the agent never saw it. While the owner's grant of at most an hour runs, the agent can list it (name and visible details, never a value), edit its details and ask to replace or delete it, but never read or use its value, and it can't see or touch any other **Note** or one in **Trash**. Edits that say where a key is used need the owner's Allow; every edit of a **Wallet Kind** and every delete also need the **Master Password**. Removing the mark takes it out of the agent's reach for good ([ADR-0012](docs/adr/0012-agents-store-and-manage-keys.md), [Agents storing keys](docs/agent-keys.md)).
_Avoid_: agent key (that's an **Agent Key**), agent Note, managed key

**Chat Wallet**:
Deferred (ADR-0011, not built): a key apart from the **Notes**, holding one private key for one Base account, made only for agent use and kept under its own key, apart from **Wallet Kinds**. It should sit at an address holding only a small amount. An agent in the separate agent account can ask the app to list, create, import, rename or send from one, but never sees the key. Every send must be a plain transfer within the owner's limits, to a listed recipient, approved with Touch ID and the **Master Password**. The app signs the transaction and the agent sends it ([ADR-0011](docs/adr/0011-chat-wallets.md)).
Reinstated 2026-11-09, not built ([ADR-0011](docs/adr/0011-chat-wallets.md)): a key apart from the **Notes**, holding one private key for one account on one EVM chain or on Solana, made only for agent use and kept under its own key, apart from **Wallet Kinds**. It should sit at an address holding only a small amount. Claude Code or Codex, in the separate agent account, can ask the app to list, create, import, rename or send from one that the owner's grant covers, but never sees the key. Every send must be a plain transfer within the owner's limits, to a listed recipient, approved with Touch ID and the **Master Password**. The app signs the transaction and the agent sends it ([ADR-0011](docs/adr/0011-chat-wallets.md)).
_Avoid_: agent wallet, hot wallet, using a **Seed Phrase** or **Private Key** from chat

### Screen privacy
Expand Down Expand Up @@ -138,6 +138,7 @@ _Avoid_: pinned, bookmarked, starred item
- The owner has one **Vault**; it moves between computers only when the owner copies the file by hand.
- The app gives AI agents no interface to the **Vault**, its **Notes**, their metadata, **Backups**, **Safety Copies** or the **Emergency Reader**, and agents are told never to use them. (The one exception is **Agent-added Notes**, through a local route only the separate agent account can use while the owner's grant runs: their names and visible details, never their values.) That limits the app, not the computer: what keeps an agent running in the owner's own Mac account away from these files is the owner's setup. The **Master Password** and **Recovery Key** never take part in agent work, and a **Wallet Kind**'s value never does: an agent may only ask to store one, which the owner types in with the **Master Password**, and, for one it added, ask to edit its visible details (the owner's Allow, then the **Master Password**), replace its value (typed by the owner, with the **Master Password**) or delete it (the **Master Password**) ([ADR-0012](docs/adr/0012-agents-store-and-manage-keys.md)).
- The **Agent Companion** is the only **Agent Key** integration inside the app; it runs apart from the **Vault** in its own sandbox and never receives Vault content. Any other **Agent Key** integration is separate from this app. Hiding the key still lets an agent perform every operation its provider scope permits, within its enforced limits; only the owner can independently approve scope or limit changes ([ADR-0007](docs/adr/0007-agents-use-separate-restricted-keys.md)).
- Only Claude Code and Codex, started in the separate agent account, may use the agent routes; the app checks their Apple code signatures ([ADR-0013](docs/adr/0013-only-claude-code-and-codex-use-the-agent-routes.md), not built). That check is a speed bump: the separate account is the boundary, so it holds only those two.
- Results from an external agent's allowed service actions may leave this computer, including for a cloud model provider; no Vault content or metadata may enter that route.
- Moving a **Vault** to the other computer means opening a **Backup** there. There is no separate "export" or "sync" concept.
- The app nudges the owner when changes have gone 7+ days without a **Backup**, and warns if a **Backup** is saved into a cloud-synced folder.
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0004-wallet-kinds-under-a-separate-key.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Wallet Kinds are encrypted under a separate key that unlocking doesn't open

> **Related: [ADR-0012](0012-agents-store-and-manage-keys.md) (2026-11-05; built 2026-11-06 with fictional data, hand checks and review still to do).** An agent may ask the app to store a **Seed Phrase** or **Private Key**. The owner types it into the app's own editor, with the **Master Password** as today, and it is sealed under the Wallet Key exactly as above. The agent never sees or uses it. ([ADR-0011](0011-chat-wallets.md), which would have signed with a separate Kind, is deferred.)
> **Related: [ADR-0012](0012-agents-store-and-manage-keys.md) (2026-11-05; built 2026-11-06 with fictional data, hand checks and review still to do).** An agent may ask the app to store a **Seed Phrase** or **Private Key**. The owner types it into the app's own editor, with the **Master Password** as today, and it is sealed under the Wallet Key exactly as above. The agent never sees or uses it. ([ADR-0011](0011-chat-wallets.md), reinstated 2026-11-09 and not built, signs only with Chat Wallets, a separate Kind under its own key. Wallet Kinds never sign for an agent.)

Showing a **Seed Phrase** or **Private Key** requires the **Master Password** again. If the whole **Vault** were already decrypted in memory, that prompt would be only a UI check in front of exposed data. So the **Hidden Fields** of **Wallet Kinds** are encrypted a second time under a separate random Wallet Key, and a normal unlock does not open it. Only the **Master Password** (a fresh Argon2id derivation, about 0.5 s) or the **Recovery Key** can unwrap the Wallet Key. It is held just long enough to show, add or edit one **Note** and is then wiped. Someone at an **Unlocked** computer, or anything reading the app's memory while it's merely **Unlocked**, can see Wallet Kind titles, chains and addresses, but not the words or keys.

Expand Down
6 changes: 5 additions & 1 deletion docs/adr/0007-agents-use-separate-restricted-keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
>
> **Amended by [ADR-0012](0012-agents-store-and-manage-keys.md) (2026-11-05; built 2026-11-06 with fictional data, hand checks and review still to do):** the owner approved a narrow agent route for **storing and managing** keys. An agent in the separate agent account may ask the app to store a key, which the owner types into the app's own editor, and may list, edit the details of, and ask to replace or delete only the Notes it added. It never receives a value, never sees any other Note, and never uses a key. So the app now has one agent interface, a local socket that only the agent account can use while the owner's grant runs ([Agents storing keys](../agent-keys.md)). Everything else here stands.
>
> **Deferred: [ADR-0011](0011-chat-wallets.md) (2026-11-05).** It had approved a second exception, the Chat Wallet route; the owner deferred it the same day, and none of it is built. An agent in the separate agent account may make six fixed requests about Chat Wallets, a new and separate Kind for keys at addresses that hold only small amounts. It can get back public addresses, limits left and signed transactions, each send approved by the owner with Touch ID and the Master Password. It never receives a key, an ordinary Note, metadata, Wallet Kinds, the Master Password or the Recovery Key. Everything else here stands.
> **Amended by [ADR-0011](0011-chat-wallets.md) (accepted 2026-11-05, deferred the same day, reinstated 2026-11-09; not built):** a second exception, Chat Wallets. Through ADR-0012's route, an agent may make five fixed requests about Chat Wallets, a new and separate Kind for keys on EVM chains or Solana, at addresses that hold only small amounts. It can get back public addresses, limits left and signed transactions, each send approved by the owner with Touch ID and the Master Password. It never receives a key, an ordinary Note, metadata, Wallet Kinds, the Master Password or the Recovery Key. Everything else here stands.
>
> **Amended by [ADR-0013](0013-only-claude-code-and-codex-use-the-agent-routes.md) (proposed 2026-11-09; not built):** only Claude Code and Codex, started in the separate agent account, may use the agent routes, checked by their Apple code signatures.
>
> **Amended by [ADR-0014](0014-agent-key-operations-through-the-companion.md) (proposed 2026-11-09; not built):** Agent Keys for more services may be used through the Agent Companion, one fixed, owner-approved operation at a time, each meeting the requirements below. The agent never holds the key.

Status: Accepted by the owner, 2026-10-21 ([issue #25](https://github.com/nniiovoo/encrypted-note/issues/25)).

Expand Down
2 changes: 2 additions & 0 deletions docs/adr/0008-agent-gateway-awaits-a-concrete-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

> **Amended by [ADR-0010](0010-companion-source-lives-in-this-repository.md) (2026-11-01):** the private repository named below was merged into this one as `companion/`, and its code is now public.

> **Amended by [ADR-0014](0014-agent-key-operations-through-the-companion.md) (proposed 2026-11-09; not built):** the companion may carry more fixed operations, one owner-approved operation at a time, each with its own Agent Key and its own record. The operation below stays the first.

Status: Service and operation selected by the owner, 2026-10-21; companion source published privately and development/preparation behavior verified with 30 fictional tests. Actual OS isolation, protected execution, provider controls, a real-key pilot and optional ChatGPT cloud connection remain pending. Refs [issue #28](https://github.com/nniiovoo/encrypted-note/issues/28).

The owner selected **OpenAI API text generation using one fixed model**, with a new separate restricted **Agent Key** and no owner-Vault access ([ADR-0007](0007-agents-use-separate-restricted-keys.md)). This replaces the earlier read-only-operation proposal. The selected implementation is a separate local companion whose primary interface is MCP over stdio.
Expand Down
2 changes: 2 additions & 0 deletions docs/adr/0009-optional-agent-companion-helper.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

> **Amended by [ADR-0010](0010-companion-source-lives-in-this-repository.md) (2026-11-01):** the companion's source moved into this repository as `companion/`, so "One pinned source" below no longer pins a commit, and packaging no longer fetches the companion with git. The policy and Node.js hashes, the helper, its sandbox and the entitlements are unchanged.

> **Amended by [ADR-0014](0014-agent-key-operations-through-the-companion.md) (proposed 2026-11-09; not built):** "make only the fixed `generate_text` request" becomes "make only fixed operations the owner has approved one at a time", each with its own Agent Key, its own record and a pinned policy. The helper's agent entry also gets [ADR-0013](0013-only-claude-code-and-codex-use-the-agent-routes.md)'s check that it was reached from Claude Code or Codex. What never reaches the helper is unchanged.

Status: Accepted by the owner, 2026-10-26 (integration design and scoped exceptions approved). Implemented with fictional data only; real credential provisioning, OS account changes, live provider calls and the ChatGPT connection remain owner actions.

The owner wants one place to manage the restricted OpenAI companion ([ADR-0008](0008-agent-gateway-awaits-a-concrete-api.md)) from inside encrypted-note, without giving it any part of the **Vault**. This records the one exception to "the app offers no agent interface" ([ADR-0007](0007-agents-use-separate-restricted-keys.md)), "no network code" ([ADR-0001](0001-local-only-vault-moved-by-hand.md)) and "every key in the Rust core" ([ADR-0003](0003-tauri-with-secrets-kept-in-rust.md)). Everything outside the exception stays as those decisions say.
Expand Down
Loading
Loading