13 KiB
MsgLib read-only sidecar contract
Date: 2026-07-10
Purpose
MsgLibReadSidecar is the bounded 32-bit .NET process used by the Go MCP layer to access copied or operator-local MsgLib.db files through the client-compatible System.Data.SQLite provider.
It exists because C26 proved the database opens with the bundled 32-bit SQLite provider and password 123, while a 64-bit probe fails at provider loading. Go should coordinate the process; the sidecar owns only the narrow Windows/.NET DB read boundary.
Protocol
- Protocol id:
isphere.msglib.v1 - Transport: one JSON request on stdin, one JSON response on stdout.
- Process architecture: x86.
- Database mode: read-only only.
- 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 itfalse. - DB mutation: never allowed.
Request envelope:
{
"protocol": "isphere.msglib.v1",
"request_id": "example-1",
"op": "self_check",
"args": {}
}
Response envelope:
{
"protocol": "isphere.msglib.v1",
"request_id": "example-1",
"op": "self_check",
"ok": true,
"data": {},
"error": null,
"warnings": []
}
Operations
self_check
Returns sidecar identity, protocol, runtime, process bitness, and capability flags.
Key response fields:
sidecar_namesidecar_versionprotocolruntimeprocess_bitsrequires_process_bitsdb_mutation_allowed=falsemessage_body_reads_allowed=truefor explicitlist_messages.include_bodyopt-in; verification keeps it disabled.
schema_summary
Validates provider load and read-only DB open, then returns schema metadata only.
Required args:
sqlite_dll_path: path to bundledSystem.Data.SQLite.dll.db_path: path to a copied/operator-localMsgLib.db.
Optional args:
password: default123.include_counts: defaulttrue; returns row counts only for target tables.max_tables: default128, clamped to1..256.target_tables: optional list; defaults to known display/message/file metadata tables.
Returned data:
metadata_only=trueread_only=truemessage_body_values_returned=falsesqlite_versiontables: table/view names only.columns: table column names/types only.target_row_counts: safe row counts for target tables only.
display_sources
Same safe provider/DB validation as schema_summary, but additionally maps schema availability to product-facing display source candidates.
Returned data adds:
display_sources[]entries with:sourcetableavailablerequired_columnspresent_columns
Initial display sources:
contacts_rosterfromTD_Roster.contacts_effigyfromTD_CustomEffigy.recent_displayfromtblRecent.person_message_namesfromtblPersonMsg.group_message_namesfromtblMsgGroupPersonMsg.work_group_authfromTD_WorkGroupAuth.received_file_metadatafromTD_ReceiveFileRecord.sent_file_metadatafromTD_SendFileRecord.
display_entities
Same safe provider/DB validation as display_sources, but returns bounded normalized contact/group display metadata.
Required args:
sqlite_dll_pathdb_pathentity_type:contactsorgroups
Optional args:
password: default123.query: optional string matched against allowlisted jid/name columns.limit: bounded to1..100; default25.
Returned data adds:
metadata_only=trueread_only=truemessage_body_values_returned=falseraw_rows_returned=falseentities[]entries with:entity_typesource_tablejiddisplay_nameconfidencematched_columns
Initial allowlisted identity sources:
- Contacts:
TD_Roster(JId,Nick),TD_CustomEffigy(PersonJid,PersonName),tblRecent(PersonId,PersonName),tblChatLevel(PersonId,PersonName), selectedtblPersonMsgid/name pairs only. - Groups:
TD_WorkGroupAuth(GroupJID,GroupName),TD_WorkGroupAuth(ChildGroupJid,GroupName), selectedtblMsgGroupPersonMsggroup/session id/name pairs only.
message_sources
Same safe provider/DB validation as display_sources, but reports whether candidate message tables are ready for a future DB-backed isphere_receive_messages source.
Required args:
sqlite_dll_pathdb_path
Optional args:
password: default123.
Returned data adds:
metadata_only=trueread_only=truemessage_body_values_returned=falseraw_rows_returned=falsefile_paths_returned=falsemessage_sources[]entries with:sourcetableroleavailablerequired_columnspresent_columnsrow_count
Initial message source candidates:
direct_messagesfromtblPersonMsg.group_messagesfromtblMsgGroupPersonMsg.system_messagesfromTD_SystemMessageRecord.group_receiptsfromTD_GroupReceiptMessage.received_file_metadatafromTD_ReceiveFileRecord.recent_conversation_indexfromtblRecent.
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_pathdb_path
Optional args:
password: default123.conversation_id: optional metadata filter.conversation_type:auto,direct,group, orsystem; defaultauto.query: optional metadata filter. Body columns are searched only wheninclude_body=true.since: optional timestamp lower bound using the DB timestamp column representation.cursor: unsupported initially; any non-empty value is rejected.limit: bounded to1..50; default20.include_body: defaultfalse.include_attachment_metadata: defaultfalse; returns filename/size metadata only, never path values or download refs.
Returned data adds:
read_only=truemessage_body_values_returned: equalsinclude_body.raw_rows_returned=falsefile_paths_returned=falsesource_tables[]messages[]entries with normalized fields:message_id/idconversation_idconversation_typesender_idsender_namereceiver_idtext/content_text(empty wheninclude_body=false)content_typetimestamp/created_atsubjectreadsource=local_readonlyraw_ref=msglib:<table>attachments[]withfile_id,file_name,size_bytes, and emptydownload_ref
next_cursor=null
Initial allowlisted message sources:
- Direct:
tblPersonMsg. - Group:
tblMsgGroupPersonMsg. - System:
TD_SystemMessageRecord. - Attachment metadata:
TD_ReceiveFileRecord, withFilePath/path-like values intentionally excluded.
Security and scope rules
- The sidecar must open DB files with read-only connection settings.
db_pathmust point to a file namedMsgLib.db.- The schema/display-source operations return schema, columns, counts, and display-source availability only.
display_entitiesmay return bounded contact/groupjidanddisplay_namemetadata only.message_sourcesmay return message-source table names, required/present column names, roles, availability flags, and row counts only.list_messagesmay return bounded normalized message metadata. It returnstext/content_textonly wheninclude_body=true; the standard verification path usesinclude_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.
Current implementation
Committed C27 implementation:
- Source:
native/MsgLibReadSidecar/. - Build script:
scripts/build-msglib-sidecar.ps1. - Verification script:
scripts/verify-msglib-sidecar.ps1. - Default verification builds an x86 executable and checks
self_check. - Evidence-backed verification with C26 paths checked provider load/read-only DB open and returned 8 display-source candidates.
Go client wrapper
Committed C28 implementation:
- Source:
internal/msglib/. ConfigFromEnvreadsISPHERE_MSGLIB_SIDECAR_EXE,ISPHERE_MSGLIB_SQLITE_DLL,ISPHERE_MSGLIB_DB, and optionalISPHERE_MSGLIB_PASSWORD.NewClientcreates a process-backed client for protocolisphere.msglib.v1.SelfCheckcallsself_checkand decodes sidecar identity, protocol, bitness, and read-only/no-mutation flags.DisplaySourcescallsdisplay_sourcesand decodes display-source availability metadata.- The client uses stdin/stdout JSON, request ids,
context.Context, per-call timeout, stderr capture, and typedSidecarErrorvalues. - Unit tests use a fake sidecar process; normal tests do not require real
System.Data.SQLite.dllor copiedMsgLib.db. - C28 does not register a new MCP tool and does not return message bodies, file paths, raw rows, contact row values, or group row values.
Committed C29 implementation:
- Sidecar op:
display_entities. - Go wrapper:
DisplayEntities(ctx, DisplayEntitiesOptions). - Verification script calls
display_entitiesonly when copied DB env paths are supplied, and prints only sanitizedentity_countplussource_tablessummaries. - Evidence-backed C29 verification against the copied DB returned contact/group entity counts and source-table names without printing entity values.
- C31 adds optional
scripts/verify-msglib-mcp-enrichment.ps1to prove MCP-level contact/group enrichment through the real sidecar while printing only counts andmsglib:<source_table>refs. C33 extends the same optional script to create a synthetic encrypted PacketReader fixture from internally selected MsgLib contact/group metadata and verify receive-messagesender_nameplusconversation.display_nameenrichment; the printed result remains limited to counts, booleans, and source refs.
Committed C36 implementation:
- Sidecar op:
message_sources. - Go wrapper:
MessageSources(ctx). - Verification script calls
message_sourcesonly when copied DB env paths are supplied, and prints only sanitizedmessage_source_countplus 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, clampslimitto1..50, rejects non-empty cursor, and never returns raw rows or file path values. scripts/verify-msglib-sidecar.ps1callslist_messagesonly when copied DB env paths are supplied, withinclude_body=false, and prints onlymessage_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:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\verify-msglib-sidecar.ps1
Evidence-backed provider verification is opt-in through environment variables and should use copied DB files only. The script also verifies display_sources and sanitized display_entities summaries when these variables are present:
$env:ISPHERE_MSGLIB_SQLITE_DLL = "<path-to-System.Data.SQLite.dll>"
$env:ISPHERE_MSGLIB_DB = "<path-to-copied-MsgLib.db>"
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\verify-msglib-sidecar.ps1
Optional MCP enrichment smoke, including receive-message display enrichment, is also opt-in through the same copied DB environment variables:
$env:ISPHERE_MSGLIB_SQLITE_DLL = "<path-to-System.Data.SQLite.dll>"
$env:ISPHERE_MSGLIB_DB = "<path-to-copied-MsgLib.db>"
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\verify-msglib-mcp-enrichment.ps1
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.