feat: add msglib bounded message listing

This commit is contained in:
zhaoyilun
2026-07-10 08:54:11 +08:00
parent c0287fa2e6
commit 44d27879f6
8 changed files with 922 additions and 17 deletions

View File

@@ -14,8 +14,8 @@ It exists because C26 proved the database opens with the bundled 32-bit SQLite p
- Transport: one JSON request on stdin, one JSON response on stdout.
- Process architecture: x86.
- Database mode: read-only only.
- Raw rows: not returned by the first contract.
- Message bodies: not returned by the first contract.
- Raw rows: never returned.
- Message bodies: returned only when a future caller explicitly sets `list_messages.include_body=true`; current verification and MCP defaults keep it `false`.
- DB mutation: never allowed.
Request envelope:
@@ -58,7 +58,7 @@ Key response fields:
- `process_bits`
- `requires_process_bits`
- `db_mutation_allowed=false`
- `message_body_reads_allowed=false`
- `message_body_reads_allowed=true` for explicit `list_messages.include_body` opt-in; verification keeps it disabled.
### `schema_summary`
@@ -183,6 +183,58 @@ Initial message source candidates:
- `received_file_metadata` from `TD_ReceiveFileRecord`.
- `recent_conversation_index` from `tblRecent`.
### `list_messages`
Same safe provider/DB validation as `message_sources`, but returns a bounded normalized message list for future DB-backed receive-message work. C38 keeps this at sidecar/Go-wrapper level only; it is not wired into MCP receive by default.
Required args:
- `sqlite_dll_path`
- `db_path`
Optional args:
- `password`: default `123`.
- `conversation_id`: optional metadata filter.
- `conversation_type`: `auto`, `direct`, `group`, or `system`; default `auto`.
- `query`: optional metadata filter. Body columns are searched only when `include_body=true`.
- `since`: optional timestamp lower bound using the DB timestamp column representation.
- `cursor`: unsupported initially; any non-empty value is rejected.
- `limit`: bounded to `1..50`; default `20`.
- `include_body`: default `false`.
- `include_attachment_metadata`: default `false`; returns filename/size metadata only, never path values or download refs.
Returned data adds:
- `read_only=true`
- `message_body_values_returned`: equals `include_body`.
- `raw_rows_returned=false`
- `file_paths_returned=false`
- `source_tables[]`
- `messages[]` entries with normalized fields:
- `message_id` / `id`
- `conversation_id`
- `conversation_type`
- `sender_id`
- `sender_name`
- `receiver_id`
- `text` / `content_text` (empty when `include_body=false`)
- `content_type`
- `timestamp` / `created_at`
- `subject`
- `read`
- `source=local_readonly`
- `raw_ref=msglib:<table>`
- `attachments[]` with `file_id`, `file_name`, `size_bytes`, and empty `download_ref`
- `next_cursor=null`
Initial allowlisted message sources:
- Direct: `tblPersonMsg`.
- Group: `tblMsgGroupPersonMsg`.
- System: `TD_SystemMessageRecord`.
- Attachment metadata: `TD_ReceiveFileRecord`, with `FilePath`/path-like values intentionally excluded.
## Security and scope rules
- The sidecar must open DB files with read-only connection settings.
@@ -190,7 +242,8 @@ Initial message source candidates:
- The schema/display-source operations return schema, columns, counts, and display-source availability only.
- `display_entities` may return bounded contact/group `jid` and `display_name` metadata only.
- `message_sources` may return message-source table names, required/present column names, roles, availability flags, and row counts only.
- It does not return message bodies, message text, file path values, attachment contents, or raw row sets.
- `list_messages` may return bounded normalized message metadata. It returns `text`/`content_text` only when `include_body=true`; the standard verification path uses `include_body=false`.
- It does not return file path values, attachment contents, raw row sets, sends, downloads, hooks, injection, or DB writes.
- It does not implement send, file download, mark-read, login, hooks, injection, or DB writes.
- The Go MCP layer remains the coordinator; this process is a bounded local reader.
@@ -232,6 +285,14 @@ Committed C36 implementation:
- Verification script calls `message_sources` only when copied DB env paths are supplied, and prints only sanitized `message_source_count` plus message-source summaries containing source/table/role/availability/row-count metadata.
- Evidence-backed C36 verification against the copied DB returned six message-source summaries without printing message body values, file path values, raw rows, or copied DB contents.
Committed C38 implementation:
- Sidecar op: `list_messages`.
- Go wrapper: `ListMessages(ctx, ListMessagesOptions)`.
- The op reads only allowlisted direct/group/system message tables and optional received-file metadata from a copied `MsgLib.db`, clamps `limit` to `1..50`, rejects non-empty cursor, and never returns raw rows or file path values.
- `scripts/verify-msglib-sidecar.ps1` calls `list_messages` only when copied DB env paths are supplied, with `include_body=false`, and prints only `message_list_count`, `message_list_sources`, safety booleans, and omission booleans.
- Evidence-backed C38 smoke returned normalized message count/source-table evidence without printing message text, body values, file paths, download refs, raw rows, sends, downloads, hooks, injection, or DB writes.
## Verification
Default verification builds and checks `self_check` only:
@@ -257,3 +318,5 @@ powershell -NoProfile -ExecutionPolicy Bypass -File scripts\verify-msglib-mcp-en
```
Expected printed evidence is sanitized: contact/group counts, `msglib:<source_table>` refs, `message_source_count`, message-source table/role/row-count summaries, `receive_display_smoke=true`, populated-field booleans, and no entity values, message bodies, file path values, or raw rows.
C38 provider verification additionally prints `message_list_count`, `message_list_sources`, `message_list_body_values_returned=false`, `message_list_raw_rows_returned=false`, `message_list_file_paths_returned=false`, `message_list_content_values_omitted=true`, and `message_list_download_refs_omitted=true`.