P2 slice 4: access

Agent tokens (wb_ and 64 hex digits), one book and one name each, kept
only as SHA-256 in a chain log and in the OS keyring; made, listed and
revoked only through the admin socket (`wanderbooks token ...`). The
door checks them, scopes cover every tool, every call is in the access
log (fail closed), and the owner passphrase is an Argon2id hash.
Setup's terminal test waits for its prompts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-20 11:14:20 -06:00
1 parent a298d154b6
commit d1f3ad891a
28 files changed
+5504 -116

No files matched your search

+10
View File
@@ -56,6 +56,8 @@ pub const MARKER_FILE: &str = ".wanderbooks-root";
pub const BOOKS_DIR: &str = "books";
/// The sockets and runtime state (plan 3.9).
pub const RUN_DIR: &str = "run";
/// Who may reach the books: principals and the owner passphrase.
pub const AUTH_DIR: &str = "auth";
/// Old copies moved aside at adoption, never deleted (plan 5.5).
pub const LEGACY_DIR: &str = "legacy";
/// A book's TIN vault folder, in its own folder.
@@ -513,6 +515,14 @@ impl Root {
&self.path
}
/// The root's `auth/` folder (its principals and the owner passphrase),
/// made 0700 if missing and refused if it isn't private.
pub fn auth_dir(&self) -> Result<PathBuf, RootError> {
self.private_subdir(AUTH_DIR, false)
.map(|(dir, _)| dir)
.map_err(|e| self.hide(e))
}
/// The root's `run/` folder (its sockets and locks), made 0700 if
/// missing and refused if it isn't private.
pub fn run_dir(&self) -> Result<PathBuf, RootError> {