feat(mcp): model-free document upload via signed URL (#1378)

* feat(mcp): model-free document upload via signed URL (#748)

Adds gnubok_create_document_upload + gnubok_complete_document_upload so
document bytes reach storage through a short-lived signed PUT URL and
never pass through the model context. Fixes silent base64 corruption on
real-size PDFs and the context blowup on batch uploads.

- pending/ staage keys with TTL cleanup; completion validates magic
  bytes + SHA-256, moves bytes to the WORM key and adopts the reserved
  UUID as document id, making retries and concurrent completions
  idempotent
- legacy gnubok_upload_document kept for clients without file access,
  description now points to the signed-URL pair; shared mime resolution
  and inbox-item creation extracted
- both new tools mapped in TOOL_SCOPE_MAP (transactions:write) and
  MCP_TOOL_CAPABILITY_MAP (ai) so the paywall and scope gates hold
- payload guard ceiling 58.5K to 59K after trimming the create tool's
  outputSchema to upload_id/upload_url/expires_at

Fixes #748

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(mcp): satisfy capability-map lock and phantom-column scanner

The exact-entries lock in capability-maps.test.ts now includes the
signed-URL pair as dispatch-only AI tools, and the inbox insert uses a
literal payload (explicit UUID instead of a conditional spread) so the
no-phantom-columns scanner can resolve every column.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Mattsson
2026-08-03 18:41:05 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 00d4c8a49e
commit 5d7952a01e
9 changed files with 946 additions and 85 deletions
+2
View File
@@ -232,6 +232,8 @@ export const TOOL_SCOPE_MAP: Record<string, ApiKeyScope> = {
// Staged bulk retag of posted-line dimensions (dimensions PR6).
gnubok_tag_journal_lines: 'bookkeeping:write',
// Document inbox
gnubok_create_document_upload: 'transactions:write',
gnubok_complete_document_upload: 'transactions:write',
gnubok_upload_document: 'transactions:write',
gnubok_list_inbox_items: 'transactions:read',
gnubok_get_inbox_item: 'transactions:read',