Repository navigation
fix(import): keep v1 taint as a taint:external_sync tag - #201
Conversation
v1 stamped every memory_docs row with a taint (internal or external_sync) and kept externally synced content out of external-effect tool decisions. The importer documented the column as probed but never read it, so Gmail/Slack/Notion content synced in v1 arrived in v2 indistinguishable from the user's own memory. Probe memory_docs.taint and tag every item from a row whose taint is not `internal` with `taint:external_sync` (EXTERNAL_SYNC_TAG, exported), in documents, learnings and global rows. The decode fails closed like v1's own; a store from before the column reads as internal, as v1 read it. The tag rides in MemoryMeta, which the CortexDB engine stores whole in its envelope, so no engine change is needed. Refs tinyhumansai/openhuman#7005.
Tiny Sweeper reviewTiny Sweeper reviewed this change across 6 lane(s) and found 2 active actionable finding(s). Detailed lane evidence and any incomplete work are listed below. State: Ready for maintainer review Review snapshot
Completeness: Complete What changedThe review could not produce a supported behavioral summary; inspect the cited changed surface and lane details below. FeaturesNone identified with supported citations. TestsNo supported feature-to-test mapping was produced. Test execution is not inferred. Findings
Before mergeNone. Agent review detailscritique
security
tests
commits
description
e2e
Evidence and run details
|
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 🧰 Additional context used📚 Code guidelines (1)No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (7)
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe importer detects the optional ChangesMemory document taint import
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~15 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to No actionable merge-blocking issue is established for this change; it is mergeable after normal checks. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The change preserves external-content markers across newly imported documents, learnings and global facts without adding tool authority. No introduced security vulnerability was established. Protection still depends on the receiving application honoring the marker, and upgrading does not automatically repair older untagged imports. Retained concerns Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 78.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 6 files. (1 skipped: 1 unsupported.)
A rabbit checks each row with care, Comment ✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
|
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0039 · 227,918 in / 14,178 out · 24,842 cached (11%) · gpt-5.6-luna, glm-5.3-flash, deepseek-v4.1-flash
critique: $0.0027 · 130,194 in / 8,587 out · 12,283 cached (9%) · gpt-5.6-luna, glm-5.3-flash
security: $0.0008 · 64,703 in / 2,571 out · 3,668 cached (6%) · gpt-5.6-luna
tests: $0.0001 · 8,236 in / 292 out · 64 cached (1%) · glm-5.3-flash
description: $0.0001 · 8,180 in / 167 out · 0 cached (0%) · glm-5.3-flash
e2e: $0.0001 · 8,916 in / 778 out · 8,827 cached (99%) · glm-5.3-flash
| let mut meta = import_meta(ws, format!("memory_docs:{}", row.document_id)); | ||
| let mut tags = convert::string_array(&row.tags_json); | ||
| push_unique(&mut tags, format!("ns:{logical}")); | ||
| mark_taint(row, &mut tags); |
There was a problem hiding this comment.
Reserve the external-sync tag before adding it
tags already contains values decoded from tags_json, so an internal row with tags_json containing "taint:external_sync" is treated by downstream consumers as externally synced even though row.external is false. Since this tag is introduced as the marker that makes content untrusted, remove any pre-existing instance of EXTERNAL_SYNC_TAG before calling mark_taint at each of the three call sites, or otherwise ensure the marker is exclusive to rows with external == true.
[RULE] reserved-marker-collision ·
Move vendor/tinymemory to the commit of tinyhumansai/tinymemory#201: the v1 importer now tags items from externally synced memory_docs rows with taint:external_sync (import::EXTERNAL_SYNC_TAG) instead of dropping the v1 taint. The other 25 commits since the old pin are memory-eval examples, docs and scripts; no library API changes. Part of #7005.
Summary
The legacy (v1, TinyCortex) importer drops the
taintv1 kept on everymemory_docsrow. v1 stamped Gmail/Slack/Notion/Composio/MCP contentexternal_syncand refused external-effect tools on context containing it; after import that content is indistinguishable from the user's own memory.The importer now probes
memory_docs.taintand tags every item from a row whose taint is notinternalwithtaint:external_sync(exported asimport::EXTERNAL_SYNC_TAG). This covers all three item types amemory_docsrow can become: documents, learnings andglobalfacts. The module docs already claimed the column was probed; now it is.Related issue
Refs tinyhumansai/openhuman#7005 (its first acceptance item: whether taint and provenance survive the move to hosted CortexDB).
API or behavior changes
tinymemory_integrations::import::EXTERNAL_SYNC_TAG("taint:external_sync"). Additive, not breaking.MemoryTaint::from_db_str: onlyinternal(trimmed, case-insensitive) is trusted, while an unknown or empty value counts as external. A store from before thetaintcolumn reads as allinternal, which is how v1 read it.MemoryMeta, which the CortexDB engine stores whole in its v2 envelope.episodic_log,user_profileand the chunk store have no taint in v1 and are unchanged.Validation
cargo fmt --all -- --checkcargo clippy --all-targets --all-features -- -D warningscargo build --all-targets --all-featurescargo test --all-features: all suites pass (legacy_import: 31 passed)Tests
tags_externally_synced_rows_in_every_memory_docs_section:external_syncon a document, a learning candidate and aglobalrow; an unknown value and an empty value (fail closed);internalandInternalstay untagged.a_store_without_the_taint_column_reads_as_internal: an early v1 store gets no tag.decodes_taint_failing_closed: unit test of the decoder.tainttointernal, so every existing mapping assertion is unchanged.Not covered here: enforcing the tag. The host decides what an
external_syncitem may influence, so that belongs in OpenHuman.Documentation
src/import/README.mdgains a Taint section and listsmemory_docs.taintamong the probed columns, and theimportmodule docs mention the tag.Checklist
#[allow(...)],#[ignore], or relaxed lints.envcontents in the diff or the descriptionSummary by CodeRabbit
internal, including blank or unknown values. This also applies to global entries.