Commit Graph
22 Commits
Author SHA1 Message Date
iamdoubz 2582d8947f Merge branch 'worktree-agent-af937df502b61b006' into feature_chore_bug_005
# Conflicts:
#	src-tauri/src/storage/mod.rs
2026-07-07 01:15:08 -05:00
iamdoubz 57e757f01f revert(mcp): bind_loopback/serve back to pub(crate) (T10.4)
No longer need to be pub now that the e2e test that required it is
reverted -- restores the tighter, originally-intended encapsulation.
2026-07-07 00:56:20 -05:00
iamdoubz 71824d44cc fix(mcp): make bind_loopback/serve/HttpServerHandle pub for the e2e test (T10.4)
Widens visibility from pub(crate) to pub so tests/mcp_server_test.rs
(an external integration-test crate, per CLAUDE.md's "cross-service
tests in /tests") can drive the real HTTP transport end-to-end. This
does not weaken the loopback guarantee: bind_loopback still refuses
non-loopback regardless of caller -- only its visibility changed.
2026-07-07 00:47:55 -05:00
iamdoubz ec8b12f636 fix(mcp): collapse nested if-let per clippy (T10.4) 2026-07-07 00:31:32 -05:00
iamdoubz 71c4c6ecf0 style(mcp): rustfmt 2026-07-07 00:29:54 -05:00
iamdoubz 386be75658 style(mcp): rustfmt 2026-07-07 00:29:52 -05:00
iamdoubz 36a28dc096 style(mcp): rustfmt 2026-07-07 00:29:50 -05:00
iamdoubz 07072551c0 style(mcp): rustfmt 2026-07-07 00:29:49 -05:00
iamdoubz e0112ec8c4 style(mcp): rustfmt 2026-07-07 00:29:48 -05:00
iamdoubz 45e34284e9 fix(mcp): use HttpServerHandle.local_addr instead of a second lookup (T10.4)
Fixes a dead_code warning (clippy -D warnings would fail on it) --
server.rs was calling listener.local_addr() itself before handing the
listener to http_transport::serve(), leaving the handle's own
local_addr field unread.
2026-07-07 00:27:56 -05:00
iamdoubz eb2aa2a0d6 fix(mcp): pass the GUI's AppHandle as Some(..) to the handler (T10.4)
Follows the previous commit's WaMcpHandler::new signature change.
2026-07-07 00:23:27 -05:00
iamdoubz 49cc1e6cd3 fix(mcp): WaMcpHandler's AppHandle is optional (T10.4)
The --mcp-stdio child process (main.rs, next commits) has no running
Tauri app/window to emit "mcp://access" events to -- only the GUI
instance's HTTP transport does. The mcp_access_log DB row is still
written unconditionally either way (FR-MCP-5); only the live event is
skipped when there's no AppHandle.
2026-07-07 00:23:20 -05:00
iamdoubz bd9b5ba3cc feat(mcp): RmcpServer wires token+transport+handler together (T10.4)
start() mints/stores a fresh token, then either binds the loopback HTTP
listener (bind_loopback + http_transport::serve) or, for stdio, just
records "enabled" and hands back the whishassist.exe --mcp-stdio command
line the agent's client config should spawn -- there is nothing to run
in-process for stdio (see mcp::stdio_transport). stop() tears down the
HTTP listener if any and deletes the stored token. instance() is a
process-wide singleton (OnceLock) so separate Tauri command invocations
(set_mcp_enabled/mcp_status/set_mcp_scope) share the same running state.
2026-07-07 00:22:35 -05:00
iamdoubz 58d565907b feat(mcp): McpToolDescriptor is Copy (T10.4)
Needed so RmcpServer::tools() can hand back TOOL_DESCRIPTORS without a
manual field-by-field clone (next commit).
2026-07-07 00:21:58 -05:00
iamdoubz 5f690f4b74 feat(mcp): stdio transport adapter (T10.4, FR-MCP-6)
serve_once() runs one MCP session over the current process's stdin/
stdout to completion -- the entry point main.rs's --mcp-stdio flag calls
into (next commit). No bearer-token check here: spawning this process
at all requires the same local-user privilege as any other command, so
process-spawn capability is the trust boundary for stdio, not a header.
2026-07-07 00:21:16 -05:00
iamdoubz 851e89720d feat(mcp): auth token in the OS credential store, not settings/DB (T10.4, FR-MCP-1)
Mirrors sync::credentials: mint_and_store() generates a fresh 32-byte
random token per set_mcp_enabled call and writes it via `keyring`
(Windows Credential Manager); the token is never persisted to
settings.json/wa.db/logs. verify() is a constant-time compare so token
checking doesn't leak timing information about a partial match
(NFR-SEC-5).
2026-07-07 00:20:39 -05:00
iamdoubz 9eed88e5bd feat(mcp): loopback bind + bearer-token gate for Streamable HTTP (T10.4, FR-MCP-1/6)
bind_loopback() refuses to bind anything that doesn't resolve to a
loopback address -- unit tested directly (non-loopback IP, unparseable
host, and a real 127.0.0.1:0 bind). serve() runs a hyper HTTP/1 accept
loop in front of rmcp's StreamableHttpService (a bare tower_service, not
an axum app); every request needs `Authorization: Bearer <token>`
(constant-time compared via mcp::token::verify) before it ever reaches
the MCP service -- an unauthenticated request never reaches rmcp at all.
2026-07-07 00:20:14 -05:00
iamdoubz 14868d4e5c feat(mcp): ServerHandler implementing the four MCP tools (T10.5)
WaMcpHandler wires list_recent_meetings/get_transcript/get_action_items/
get_feature_brief to Store, re-checking ExposeScope + the recordings
gate independently in every handler (FR-MCP-3) and logging every read
via record_mcp_access + an "mcp://access" event (FR-MCP-5) before scope
is even evaluated, so the audit trail is "what was asked for", not just
"what was returned". get_feature_brief calls through the existing
commands::get_feature_brief stub per the M1/M2 integration contract --
it always errors right now since M1's brief storage isn't implemented
in this worktree yet; the `selected`-scope exposed-flag check is left
as a marked TODO for when M1 lands.
2026-07-07 00:17:56 -05:00
iamdoubz fc93f8e14f feat(mcp): scope-control logic, unit tested (T10.7, FR-MCP-3)
Pure functions (no DB, no cargo feature gate) so scope control is
testable without a running server: meetings_visible/brief_visible/
recording_gate_ok/meeting_allowed. Documents the conservative choice for
`selected` scope on meetings/transcript/action-items -- there's no
per-meeting selection flag in the schema yet (only feature_briefs.exposed
does), so `selected` behaves like `none` there until a real "pick which
meetings" mechanism exists, rather than silently behaving like `all`.
2026-07-07 00:14:50 -05:00
iamdoubz c73245f293 feat(mcp): trait/config plumbing for the real server (T10.4)
ExposeScope/McpTransport gain as_str/parse (privacy-safe fallback: an
unparsed scope becomes None, not All/Selected) so commands.rs can read
them out of Settings' string fields. Declares the mcp submodules
(scope always compiled; handler/http_transport/server/stdio_transport/
token behind the `mcp` cargo feature) and removes the todo!() RmcpServer
stub -- its real implementation moves to mcp::server in the next commits.
2026-07-07 00:14:32 -05:00
iamdoubz 02834e9cd2 Phase 1 2026-06-30 22:17:30 -05:00
iamdoubz aae22a0e23 Add all scaffolding, design, and decision documentation AKA first commit 2026-06-30 16:12:55 -05:00