Skip to content

Add Supermemory, Mem0, and Cognee memory adapters - #8

Merged
senamakel merged 1 commit into
mainfrom
memory-backends
Aug 12, 2026
Merged

Add Supermemory, Mem0, and Cognee memory adapters#8
senamakel merged 1 commit into
mainfrom
memory-backends

Conversation

@senamakel

@senamakel senamakel commented Aug 12, 2026

Copy link
Copy Markdown
Member

Summary

Adds native TinyMemory adapters for the self-hosted Supermemory, Mem0, and Cognee APIs. The adapters preserve TinyMemory namespaces, categories, sessions, and taint/provenance while delegating recall to each engine's native search API.

Includes a pinned Docker Compose integration harness, deterministic OpenAI-compatible inference fixture, API-shaped adapter tests, and a live conformance runner covering the mandatory Core, Recall, and Portability capabilities.

Related issue

None.

API or behavior changes

Adds the public tinymemory-remote workspace crate with SupermemoryMemory, Mem0Memory, and CogneeMemory, plus provider constructors for each. The built-in registry now reserves supermemory, mem0, and cognee as trusted external driver IDs. This is additive and non-breaking.

Validation

Commands actually run, with their outcome:

  • cargo fmt --all -- --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo build --all-targets --all-features
  • cargo test --all-features
  • Live Docker conformance: Supermemory Core, Recall, and Portability
  • Live Docker conformance: Mem0 Core, Recall, and Portability
  • Live Docker conformance: Cognee Core, Recall, and Portability

Tests

Adds API-shaped unit tests for all three native protocols. Each exercises provider auditing, store/upsert/get, taint preservation, native recall, forget, health, and provenance. The live conformance example additionally verifies portability paging against the real self-hosted services.

Documentation

Updates the root README with the remote adapter surface and adds integration/remote-engines/README.md with Docker and conformance instructions.

Checklist

  • The change is focused on one logical change
  • No new #[allow(...)], #[ignore], or relaxed lints
  • No secrets, tokens, or .env contents in the diff or the description

Summary by CodeRabbit

  • New Features

    • Added remote memory adapters for Supermemory, Mem0, and Cognee.
    • Preserves metadata and taint information across storage, retrieval, search, and deletion.
    • Added health checks, authentication support, namespace handling, and native provider search.
    • Added Docker-based integration testing and a remote-provider conformance harness.
  • Documentation

    • Documented supported remote engines, setup instructions, configuration, and usage examples.
  • Bug Fixes

    • Trusted, configured external drivers can now be admitted through the registry.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@senamakel, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 30 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1fe73feb-802c-421b-bf5b-7a1d274270b0

📥 Commits

Reviewing files that changed from the base of the PR and between 82c2a21 and 97c5f1a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • Cargo.toml
  • README.md
  • adapters/remote/Cargo.toml
  • adapters/remote/examples/conformance.rs
  • adapters/remote/src/cognee.rs
  • adapters/remote/src/cognee_test.rs
  • adapters/remote/src/common.rs
  • adapters/remote/src/lib.rs
  • adapters/remote/src/mem0.rs
  • adapters/remote/src/mem0_test.rs
  • adapters/remote/src/supermemory.rs
  • adapters/remote/src/supermemory_test.rs
  • integration/remote-engines/README.md
  • integration/remote-engines/docker-compose.yml
  • integration/remote-engines/mock-inference.Dockerfile
  • integration/remote-engines/mock_inference.py
  • integration/remote-engines/supermemory.Dockerfile
  • src/registry/mod.rs
  • src/registry/test.rs
📝 Walkthrough

Walkthrough

This PR adds a new tinymemory-remote crate with Supermemory, Mem0, and Cognee adapters, shared HTTP-backed memory logic, registry support for external remote drivers, a conformance example, and Docker-based integration tooling plus documentation for remote engine testing.

Changes

Remote adapter support

Layer / File(s) Summary
Workspace and registry enablement
Cargo.toml, adapters/remote/Cargo.toml, adapters/remote/src/lib.rs, src/registry/*, README.md
Adds adapters/remote to the workspace, creates the new crate, re-exports remote backends and provider factories, reserves and admits the new external driver IDs, updates registry tests, and documents the remote adapter layout and usage.
Shared remote memory contract
adapters/remote/src/common.rs, adapters/remote/examples/conformance.rs
Adds the validated HttpClient, StoredEntry, Dialect, and generic RemoteMemory implementation. The conformance example exercises health, store, get, recall, export, and forget flows against a selected remote provider.
Supermemory adapter
adapters/remote/src/supermemory.rs, adapters/remote/src/supermemory_test.rs
Adds the Supermemory adapter and dialect for metadata encoding, paginated listing, upsert, search, delete, and health checks. The test server and end-to-end test cover contract behavior and taint preservation.
Mem0 adapter
adapters/remote/src/mem0.rs, adapters/remote/src/mem0_test.rs
Adds the Mem0 adapter and dialect for authenticated CRUD, metadata mapping, search, delete, and health behavior. The fixture server and contract test validate replacement, recall, and idempotent forgetting.
Cognee adapter
adapters/remote/src/cognee.rs, adapters/remote/src/cognee_test.rs
Adds the Cognee adapter with dataset discovery, multipart JSON uploads, record parsing, recall handling for multiple response shapes, delete logic, and health checks. The mock-server test validates storage, recall, taint preservation, and repeated deletion.
Remote engine integration harness
integration/remote-engines/*
Adds Docker Compose profiles for Supermemory, Mem0, Cognee, and a shared mock inference service, plus container images and runbook documentation for remote-engine conformance testing.

Estimated code review effort: 5 (Critical) | ~100 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Runner as Conformance runner
  participant Adapter as Remote adapter
  participant Engine as Remote engine API
  participant Mock as mock_inference

  Runner->>Adapter: construct provider and run checks
  Adapter->>Engine: health()
  Engine-->>Adapter: healthy response
  Runner->>Adapter: store(namespace, key, content, taint)
  Adapter->>Engine: upsert via HTTP
  Engine-->>Adapter: stored entry
  Runner->>Adapter: recall(query, filters)
  Adapter->>Engine: search via HTTP
  Engine-->>Adapter: matching entries
  Engine->>Mock: inference request when configured
  Mock-->>Engine: deterministic response
  Runner->>Adapter: export/list and forget
  Adapter->>Engine: list and delete
  Engine-->>Adapter: updated state
Loading

Possibly related PRs

  • tinyhumansai/tinymemory#1: This PR extends the registry, provider wiring, and Memory contract path that the earlier work introduced.

Poem

I hopped through ports and paths today,
Three remote burrows joined the way.
Mem0, Cognee, Supermemory too,
All answer calls the same way through.
With mock-fed dreams and tests in line,
this little rabbit says, “Works fine.”

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.54% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the three primary memory adapters added by the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@senamakel senamakel self-assigned this Aug 12, 2026
@senamakel
senamakel merged commit c86128d into main Aug 12, 2026
11 checks passed
@senamakel
senamakel deleted the memory-backends branch August 12, 2026 12:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 19

🧹 Nitpick comments (8)
adapters/remote/src/supermemory_test.rs (1)

67-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The search handler discards the request body.

search ignores the payload, so the test cannot detect a regression in the request shape built at adapters/remote/src/supermemory.rs lines 276-288. The q, limit, containerTag, and threshold fields stay unverified.

Accept the body and assert the fields.

♻️ Proposed change to assert the search request shape
-async fn search(State(state): State<AppState>) -> Json<Value> {
-    let results = state.0.lock().expect("state lock").iter().map(|r| json!({"id": r["id"], "memory": r["memory"], "metadata": r["metadata"], "similarity": 0.95})).collect::<Vec<_>>();
+async fn search(State(state): State<AppState>, Json(body): Json<Value>) -> Json<Value> {
+    assert_eq!(body["searchMode"], "memories");
+    assert!(body["q"].is_string());
+    assert!(body["limit"].is_u64());
+    let results = state
+        .0
+        .lock()
+        .expect("state lock")
+        .iter()
+        .map(|r| {
+            json!({
+                "id": r["id"],
+                "memory": r["memory"],
+                "metadata": r["metadata"],
+                "createdAt": r["createdAt"],
+                "similarity": 0.95
+            })
+        })
+        .collect::<Vec<_>>();
     Json(json!({"results": results}))
 }

Adding createdAt to each result also lets the test assert a non-empty timestamp on recall entries.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/remote/src/supermemory_test.rs` around lines 67 - 70, Update the
search handler to accept and deserialize the request body, then assert the
expected q, limit, containerTag, and threshold values before producing results.
Extend the returned test result data with createdAt so recall entries can also
verify a non-empty timestamp, while preserving the existing result response
structure.
integration/remote-engines/README.md (1)

34-38: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document how to reset the persisted state.

The engines keep their records in named volumes. A second conformance run then observes records from the previous run, so result counts can differ between runs. Document the reset command next to the down command.

 ```sh
 docker compose -f integration/remote-engines/docker-compose.yml down

+Remove the named volumes before a fresh conformance run:
+
+sh +docker compose -f integration/remote-engines/docker-compose.yml down -v +




As per coding guidelines: "Tests must be deterministic and independent of network, wall-clock time, and execution order."

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @integration/remote-engines/README.md around lines 34 - 38, Update the
remote-engines README near the existing docker compose down command to document
resetting persisted state before a fresh conformance run. Add the docker compose
down -v command so named volumes are removed, while retaining the existing
command for stopping the harness without volume deletion.


</details>

<!-- cr-comment:v1:36465428e16f201931f6a831 -->

_Source: Coding guidelines_

</blockquote></details>
<details>
<summary>integration/remote-engines/mock_inference.py (3)</summary><blockquote>

`54-56`: _🩺 Stability & Availability_ | _🔵 Trivial_ | _⚡ Quick win_

**Return HTTP 400 for an unparsable body.**

`json.loads` raises on a malformed body. The handler then aborts without a response, and the calling engine observes a reset connection instead of a status code. That makes a wiring failure hard to diagnose.

```diff
     def do_POST(self):
         length = int(self.headers.get("Content-Length", "0"))
-        request = json.loads(self.rfile.read(length) or b"{}")
+        try:
+            request = json.loads(self.rfile.read(length) or b"{}")
+        except json.JSONDecodeError:
+            self.send_json(400, {"error": "invalid JSON body"})
+            return
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/remote-engines/mock_inference.py` around lines 54 - 56, Update
do_POST to catch JSON parsing failures from json.loads and respond with HTTP 400
for malformed request bodies, including the required response completion steps;
preserve the existing "{}" fallback for empty bodies and continue normal
processing for valid JSON.

109-109: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Start the server under a __main__ guard.

The server starts during module import. That prevents importing schema_value or embedding from a test. Move the call into a guarded block.

-ThreadingHTTPServer(("0.0.0.0", 8080), Handler).serve_forever()
+if __name__ == "__main__":
+    ThreadingHTTPServer(("0.0.0.0", 8080), Handler).serve_forever()

Note on the Ruff S104 hint for this line: the bind to all interfaces is required inside the container, and the Compose service publishes no host port. No change is needed for that hint.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/remote-engines/mock_inference.py` at line 109, Move the
ThreadingHTTPServer startup call out of module-level execution and into an if
__name__ == "__main__" guard, preserving the existing ("0.0.0.0", 8080),
Handler, and serve_forever behavior. Do not change the bind address.

Source: Linters/SAST tools


11-11: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify the enum check.

Ruff reports RUF019 for the key check before the subscript.

-    if "enum" in schema and schema["enum"]:
+    if schema.get("enum"):
         return schema["enum"][0]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/remote-engines/mock_inference.py` at line 11, Update the enum
condition in the schema handling logic to avoid the redundant key-existence
check flagged by Ruff RUF019, while preserving the current behavior of only
processing non-empty enum values.

Source: Linters/SAST tools

integration/remote-engines/supermemory.Dockerfile (1)

3-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

curl has no consumer, and the service has no healthcheck.

The image installs curl, but nothing in this file or in integration/remote-engines/docker-compose.yml uses it. The supermemory service declares no healthcheck, unlike mock-inference and postgres. Add a healthcheck that uses curl, or drop the package.

♻️ Proposed healthcheck for the Compose service
     environment:
       OPENAI_API_KEY: ${OPENAI_API_KEY:-local-superrag-only}
       SUPERMEMORY_DATA_DIR: /data
       PORT: 6767
+    healthcheck:
+      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:6767/"]
+      interval: 5s
+      timeout: 5s
+      retries: 20

The adapter health check performs GET on the endpoint root, per adapters/remote/src/supermemory.rs line 326, so the same path suits the container healthcheck.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/remote-engines/supermemory.Dockerfile` around lines 3 - 7, Use
the existing curl installation by adding a supermemory service healthcheck in
docker-compose.yml that performs a GET request against the container’s root
endpoint, matching the adapter health-check path; configure suitable healthcheck
timing and failure settings consistent with mock-inference and postgres, or
remove curl if no healthcheck is added.
adapters/remote/src/cognee_test.rs (2)

106-131: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the fields that the adapter derives, not only the content.

The test checks content and taint. It does not check the values that cognee.rs computes on the read path:

  • entry.timestamp proves the created_at fallback at adapters/remote/src/cognee.rs Lines 175-184 works. The fixture supplies a fixed created_at, so the assertion stays deterministic.
  • entry.score proves the recall score at adapters/remote/src/cognee.rs Line 294 is attached. The fixture returns 0.8.
  • entry.namespace and entry.session_id prove the envelope round-trips namespace and session identity.
💚 Proposed additional assertions
     assert_eq!(entry.content, "knowledge graph");
     assert_eq!(entry.taint, MemoryTaint::ExternalSync);
+    assert_eq!(entry.namespace.as_deref(), Some("project"));
+    assert_eq!(entry.session_id.as_deref(), Some("session"));
+    assert_eq!(entry.timestamp, "2026-08-12T00:00:00Z");
+    let recalled = driver
+        .recall(
+            "graph",
+            3,
+            &OwnedRecallOpts {
+                namespace: Some("project".into()),
+                ..OwnedRecallOpts::default()
+            },
+            None,
+        )
+        .await
+        .expect("recall");
+    assert_eq!(recalled.len(), 1);
+    assert_eq!(recalled[0].score, Some(0.8));
     assert_eq!(
         driver
             .recall(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/remote/src/cognee_test.rs` around lines 106 - 131, Extend the cognee
adapter test assertions after retrieving entry to validate the derived fields:
assert the deterministic timestamp from the fixture’s created_at fallback, the
recall score of 0.8, and the round-tripped namespace and session_id. Keep the
existing content, taint, recall-count, forget, and health assertions unchanged.

32-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the two documented decode branches, and check the path parameters.

Two branches in adapters/remote/src/cognee.rs carry explanatory comments but no test:

  • Line 162 accepts a name ending in .tinymemory because Cognee strips the trailing .json. The fixture at Line 35 returns only the .tinymemory.json form, so the stripped form is never exercised.
  • Lines 300-305 decode newline-delimited envelopes from coalesced CHUNKS results. The recall fixture at Line 68 always returns a single envelope, so the loop never runs.

The handlers also ignore {dataset} and {data}, so the test cannot detect a wrong URL or a broken remote_id split in delete_entry. Extract the path parameters and assert they equal dataset-1 and data-1.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/remote/src/cognee_test.rs` around lines 32 - 47, Update the Cognee
test fixtures and handlers `data` and `raw` to cover both documented decode
branches: return a `.tinymemory` name variant and make the `recall` response
contain coalesced newline-delimited envelopes. Extract `{dataset}` and `{data}`
path parameters in the handlers and assert they equal `dataset-1` and `data-1`,
ensuring URL construction and `delete_entry` remote-ID splitting are validated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@adapters/remote/Cargo.toml`:
- Around line 4-5: Update the package metadata in the crate’s Cargo.toml: remove
the hand-edited version value so the release-owned version is inherited, and
change the edition from "2021" to "2024".

In `@adapters/remote/examples/conformance.rs`:
- Around line 44-47: Replace the SystemTime-based suffix in the conformance
fixture with fixed deterministic namespace and content values, or a
deterministic run identifier supplied by the harness. Update the namespace and
content construction near the key constants while preserving the native
round-trip behavior and avoiding wall-clock dependence.

In `@adapters/remote/src/cognee.rs`:
- Around line 228-251: Update upsert so the multipart upload to api/v1/remember
completes successfully before calling delete_entry on the existing record.
Preserve the current error propagation for upload failures, and only remove the
superseded record after a successful response so failed uploads retain the
previous value.
- Around line 221-229: Update upsert to replace the broad self.entries()
existence scan with the same target-dataset lookup used by delete at Line 312,
using entry.namespace and entry.key to find only the matching record before
calling delete_entry. Preserve the existing deletion behavior when a matching
entry exists.

In `@adapters/remote/src/common.rs`:
- Around line 391-400: Update matches_filters so the session_id predicate allows
entries from other sessions when RecallOpts::cross_session is true, while
retaining the existing session match requirement when it is false. Preserve the
namespace and category filters, including the category restriction for
conversational cross-session results.
- Around line 391-400: Resolve a missing opts.namespace to GLOBAL_NAMESPACE
before invoking Dialect::search, while preserving explicitly provided
namespaces. Update matches_filters to compare every entry against that same
resolved namespace so recall cannot return cross-namespace results.
- Around line 53-57: Update HttpClient::new in adapters/remote/src/common.rs
(lines 53-57) to reject HTTP endpoints when Auth contains credentials, while
continuing to allow credential-free HTTP and HTTPS endpoints; preserve the
existing invalid-scheme validation. Review the related credential handling at
adapters/remote/src/common.rs lines 77-80 and update the README.md example at
line 83 to use HTTPS or omit the credential.

In `@adapters/remote/src/mem0_test.rs`:
- Line 3: Remove the module-level clippy::expect_used suppression in
mem0_test.rs, then retain expect only where needed in test code and update each
expect message to clearly state the invariant, such as the AppState mutex not
being poisoned.
- Around line 66-72: Update the search fixture’s search handler to parse the
request body and filter records by the submitted filters.user_id namespace
instead of returning every record. Add a second namespace record and assert
Mem0Dialect::search returns only the people-scoped entry. After replacement,
also assert entry.session_id is Some("s2") and entry.taint is
MemoryTaint::Internal.
- Around line 83-89: Replace the loopback TcpListener and spawned axum server in
the test with an injected transport or mock connector. Preserve the existing
HTTP request/response shape assertions while removing TCP binding, port
allocation, and task scheduling dependencies.

In `@adapters/remote/src/mem0.rs`:
- Around line 176-205: Make upsert in the upsert method atomic for each logical
(namespace, key): prefer a Mem0 server-side atomic upsert or unique constraint,
and handle its conflict/update behavior so concurrent calls cannot create
duplicate remote records. If the API lacks that support, serialize the entries
lookup and POST/PUT sequence per logical key and add a concurrent-store test
verifying only one remote record exists and the final content is current.
- Around line 31-35: Update the HttpClient configuration used by Mem0Dialect in
RemoteMemory::new so API-key clients do not forward X-API-Key across
cross-origin redirects. Disable redirect following or restrict it to same-origin
HTTPS redirects while preserving the existing endpoint and API-key setup in
HttpClient::api_key.
- Around line 31-35: Update Mem0Dialect::new to reject api_key-protected
endpoints using the http scheme before constructing HttpClient, while allowing
https endpoints and unauthenticated http loopback endpoints for local
development. Preserve the existing HttpClient::api_key error propagation and
RemoteMemory construction for accepted inputs.
- Around line 111-120: Remove the hard-coded 1,000-record assumption from
RemoteMem0::values and provide a complete server-side enumeration path that
retrieves all memories, preserving visibility for list, count, get, forget, and
upsert lookup operations. Upgrade or use a Mem0 API supporting pagination, or
implement equivalent pagination/server-side listing, and add deterministic
coverage with more than 1,000 records.

In `@adapters/remote/src/supermemory.rs`:
- Around line 228-233: The upsert and delete paths scan all namespaces
unnecessarily. In adapters/remote/src/supermemory.rs#L228-L233, add or reuse a
namespace-scoped helper for the Supermemory list request, pass entry.namespace
via containerTags, and match the returned records by key only; apply the same
helper in adapters/remote/src/supermemory.rs#L302-L310 using the namespace
argument, matching by key only. Ensure the helper handles pagination within the
specified namespace.

In `@integration/remote-engines/docker-compose.yml`:
- Around line 98-101: Update the Docker Compose volume handling for
supermemory-data, mem0-postgres, and cognee-data so repeated conformance runs
start with clean state. Prefer anonymous volumes for these conformance profiles,
or document an explicit volume-reset step in the associated README when
retaining named volumes.
- Line 13: Bind the unauthenticated mem0 and cognee service ports to loopback
instead of all host interfaces. In
integration/remote-engines/docker-compose.yml:13-13, preserve the existing port
mapping unless it is one of the affected services; update
integration/remote-engines/docker-compose.yml:40-40 from 8888:8000 to
127.0.0.1:8888:8000 and integration/remote-engines/docker-compose.yml:81-81 from
8001:8000 to 127.0.0.1:8001:8000.

In `@integration/remote-engines/mock-inference.Dockerfile`:
- Around line 1-7: Update both
integration/remote-engines/mock-inference.Dockerfile (lines 1-7) and
integration/remote-engines/supermemory.Dockerfile (lines 1-12) to create a
non-root runtime user after package installation and switch to it with USER
before the entrypoint; additionally grant that user write access to /data in
supermemory.Dockerfile before switching users.

In `@integration/remote-engines/README.md`:
- Around line 18-24: Update the documented docker compose commands for the mem0
and cognee profiles to include --wait after --build, ensuring conformance runs
only after the engine services pass their declared healthchecks.

---

Nitpick comments:
In `@adapters/remote/src/cognee_test.rs`:
- Around line 106-131: Extend the cognee adapter test assertions after
retrieving entry to validate the derived fields: assert the deterministic
timestamp from the fixture’s created_at fallback, the recall score of 0.8, and
the round-tripped namespace and session_id. Keep the existing content, taint,
recall-count, forget, and health assertions unchanged.
- Around line 32-47: Update the Cognee test fixtures and handlers `data` and
`raw` to cover both documented decode branches: return a `.tinymemory` name
variant and make the `recall` response contain coalesced newline-delimited
envelopes. Extract `{dataset}` and `{data}` path parameters in the handlers and
assert they equal `dataset-1` and `data-1`, ensuring URL construction and
`delete_entry` remote-ID splitting are validated.

In `@adapters/remote/src/supermemory_test.rs`:
- Around line 67-70: Update the search handler to accept and deserialize the
request body, then assert the expected q, limit, containerTag, and threshold
values before producing results. Extend the returned test result data with
createdAt so recall entries can also verify a non-empty timestamp, while
preserving the existing result response structure.

In `@integration/remote-engines/mock_inference.py`:
- Around line 54-56: Update do_POST to catch JSON parsing failures from
json.loads and respond with HTTP 400 for malformed request bodies, including the
required response completion steps; preserve the existing "{}" fallback for
empty bodies and continue normal processing for valid JSON.
- Line 109: Move the ThreadingHTTPServer startup call out of module-level
execution and into an if __name__ == "__main__" guard, preserving the existing
("0.0.0.0", 8080), Handler, and serve_forever behavior. Do not change the bind
address.
- Line 11: Update the enum condition in the schema handling logic to avoid the
redundant key-existence check flagged by Ruff RUF019, while preserving the
current behavior of only processing non-empty enum values.

In `@integration/remote-engines/README.md`:
- Around line 34-38: Update the remote-engines README near the existing docker
compose down command to document resetting persisted state before a fresh
conformance run. Add the docker compose down -v command so named volumes are
removed, while retaining the existing command for stopping the harness without
volume deletion.

In `@integration/remote-engines/supermemory.Dockerfile`:
- Around line 3-7: Use the existing curl installation by adding a supermemory
service healthcheck in docker-compose.yml that performs a GET request against
the container’s root endpoint, matching the adapter health-check path; configure
suitable healthcheck timing and failure settings consistent with mock-inference
and postgres, or remove curl if no healthcheck is added.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1fe73feb-802c-421b-bf5b-7a1d274270b0

📥 Commits

Reviewing files that changed from the base of the PR and between 82c2a21 and 97c5f1a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • Cargo.toml
  • README.md
  • adapters/remote/Cargo.toml
  • adapters/remote/examples/conformance.rs
  • adapters/remote/src/cognee.rs
  • adapters/remote/src/cognee_test.rs
  • adapters/remote/src/common.rs
  • adapters/remote/src/lib.rs
  • adapters/remote/src/mem0.rs
  • adapters/remote/src/mem0_test.rs
  • adapters/remote/src/supermemory.rs
  • adapters/remote/src/supermemory_test.rs
  • integration/remote-engines/README.md
  • integration/remote-engines/docker-compose.yml
  • integration/remote-engines/mock-inference.Dockerfile
  • integration/remote-engines/mock_inference.py
  • integration/remote-engines/supermemory.Dockerfile
  • src/registry/mod.rs
  • src/registry/test.rs

Comment on lines +4 to +5
version = "0.1.0"
edition = "2021"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use the release-owned version and Rust 2024.

Line 4 hand-edits the package version. Line 5 selects Rust 2021. Inherit the release-managed version and set the crate edition to Rust 2024.

As per coding guidelines: “This is a Rust 2024 library crate rooted at Cargo.toml” and “Do not hand-edit the version field in Cargo.toml.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/remote/Cargo.toml` around lines 4 - 5, Update the package metadata
in the crate’s Cargo.toml: remove the hand-edited version value so the
release-owned version is inherited, and change the edition from "2021" to
"2024".

Source: Coding guidelines

Comment on lines +44 to +47
let suffix = SystemTime::now().duration_since(UNIX_EPOCH)?.as_nanos();
let namespace = format!("tinymemory-conformance-{suffix}");
let key = "native-round-trip";
let content = format!("TinyMemory native adapter conformance marker {suffix}");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Remove wall-clock data from the conformance fixture.

SystemTime changes the namespace and expected content on every run. Use fixed fixture values, or accept a deterministic run identifier from the harness. This makes failures reproducible.

As per coding guidelines: “Tests must be deterministic and independent of network, wall-clock time, and execution order.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/remote/examples/conformance.rs` around lines 44 - 47, Replace the
SystemTime-based suffix in the conformance fixture with fixed deterministic
namespace and content values, or a deterministic run identifier supplied by the
harness. Update the namespace and content construction near the key constants
while preserving the native round-trip behavior and avoiding wall-clock
dependence.

Source: Coding guidelines

Comment on lines +221 to +229
async fn upsert(&self, entry: StoredEntry) -> anyhow::Result<()> {
if let Some(existing) = self
.entries()
.await?
.into_iter()
.find(|item| item.namespace == entry.namespace && item.key == entry.key)
{
self.delete_entry(&existing).await?;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Narrow the existence lookup in upsert to the target dataset.

self.entries() enumerates every tinymemory__ dataset and issues one raw GET per record in each of them. Every single store therefore costs one datasets request plus one data-listing and one raw fetch per stored record across all namespaces. The cost grows with total store size, not with the record being written.

delete at Line 312 already uses the narrow path. Reuse it here.

♻️ Proposed fix to scope the lookup to one dataset
     async fn upsert(&self, entry: StoredEntry) -> anyhow::Result<()> {
-        if let Some(existing) = self
-            .entries()
-            .await?
-            .into_iter()
-            .find(|item| item.namespace == entry.namespace && item.key == entry.key)
-        {
-            self.delete_entry(&existing).await?;
+        if let Some(dataset) = self.find_dataset(&entry.namespace).await? {
+            if let Some(existing) = self
+                .dataset_entries(&dataset)
+                .await?
+                .into_iter()
+                .find(|item| item.key == entry.key)
+            {
+                self.delete_entry(&existing).await?;
+            }
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async fn upsert(&self, entry: StoredEntry) -> anyhow::Result<()> {
if let Some(existing) = self
.entries()
.await?
.into_iter()
.find(|item| item.namespace == entry.namespace && item.key == entry.key)
{
self.delete_entry(&existing).await?;
}
async fn upsert(&self, entry: StoredEntry) -> anyhow::Result<()> {
if let Some(dataset) = self.find_dataset(&entry.namespace).await? {
if let Some(existing) = self
.dataset_entries(&dataset)
.await?
.into_iter()
.find(|item| item.key == entry.key)
{
self.delete_entry(&existing).await?;
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/remote/src/cognee.rs` around lines 221 - 229, Update upsert to
replace the broad self.entries() existence scan with the same target-dataset
lookup used by delete at Line 312, using entry.namespace and entry.key to find
only the matching record before calling delete_entry. Preserve the existing
deletion behavior when a matching entry exists.

Comment on lines +228 to +251
self.delete_entry(&existing).await?;
}
let body = serde_json::to_vec(&entry)?;
let form = multipart::Form::new()
.text("datasetName", Self::dataset_name(&entry.namespace))
.text("run_in_background", "false")
.part(
"data",
multipart::Part::bytes(body)
.file_name(Self::filename(&entry.key))
.mime_str("application/json")?,
);
let response = self
.client
.multipart("api/v1/remember")?
.multipart(form)
.send()
.await?;
if !response.status().is_success() {
return Err(anyhow!(
"memory API api/v1/remember returned HTTP {}",
response.status()
));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

upsert can lose the previous record when the upload fails.

delete_entry removes the existing record before the multipart upload runs. If api/v1/remember returns a non-success status or the request fails, the adapter returns an error and the old value is already gone. The caller sees a failed store but the key no longer resolves.

Cognee has no in-place update endpoint, so ordering matters. Upload first, then delete the superseded record. If the upload succeeds and the delete fails, the reader still sees a valid record, and the stale duplicate can be reconciled on the next upsert.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/remote/src/cognee.rs` around lines 228 - 251, Update upsert so the
multipart upload to api/v1/remember completes successfully before calling
delete_entry on the existing record. Preserve the current error propagation for
upload failures, and only remove the superseded record after a successful
response so failed uploads retain the previous value.

Comment on lines +53 to +57
fn new(endpoint: &str, auth: Auth) -> anyhow::Result<Self> {
let mut endpoint = Url::parse(endpoint).context("memory endpoint is not a valid URL")?;
if !matches!(endpoint.scheme(), "http" | "https") {
bail!("memory endpoint must use http or https");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- common.rs ---'
cat -n adapters/remote/src/common.rs | sed -n '1,130p'

printf '%s\n' '--- README example ---'
cat -n README.md | sed -n '70,92p'

printf '%s\n' '--- HttpClient construction and endpoint/auth call sites ---'
rg -n -C 3 'HttpClient::new|SupermemoryMemory::new|CogneeMemory::new|Auth::(Bearer|ApiKey|None)|memory endpoint|endpoint:' adapters README.md Cargo.toml

printf '%s\n' '--- remote module outline ---'
ast-grep outline adapters/remote/src/common.rs

Repository: tinyhumansai/tinymemory

Length of output: 15054


Sensitive Data Exposure (CWE-319): Cleartext Transmission of Sensitive Information

Reachability: External

Reachability path
● Entry
  integration/remote-engines/mock_inference.py:8
  schema_value
│
▼
● Sink
  adapters/remote/src/common.rs

Reject credentialed HTTP endpoints.

HttpClient accepts http and attaches bearer tokens or API keys to outgoing requests. Reject non-HTTPS endpoints when credentials are present. Update the README example to use HTTPS or omit the credential.

📍 Affects 2 files
  • adapters/remote/src/common.rs#L53-L57 (this comment)
  • adapters/remote/src/common.rs#L77-L80
  • README.md#L83-L83
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/remote/src/common.rs` around lines 53 - 57, Update HttpClient::new
in adapters/remote/src/common.rs (lines 53-57) to reject HTTP endpoints when
Auth contains credentials, while continuing to allow credential-free HTTP and
HTTPS endpoints; preserve the existing invalid-scheme validation. Review the
related credential handling at adapters/remote/src/common.rs lines 77-80 and
update the README.md example at line 83 to use HTTPS or omit the credential.

Comment on lines +228 to +233
async fn upsert(&self, entry: StoredEntry) -> anyhow::Result<()> {
let existing = self
.memories()
.await?
.into_iter()
.find(|item| item.namespace == entry.namespace && item.key == entry.key);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

upsert and delete use a full-corpus scan for a single-key lookup. memories() lists every container tag, then paginates 200 records per tag. Both call sites already know the namespace, so the tag discovery and the cross-namespace pagination are unnecessary. Extract a namespace-scoped helper that sends containerTags: [namespace] to v4/memories/list, and use it at both sites.

  • adapters/remote/src/supermemory.rs#L228-L233: replace the memories() call with the namespace-scoped lookup for entry.namespace, then match on key only.
  • adapters/remote/src/supermemory.rs#L302-L310: replace the memories() call with the namespace-scoped lookup for the namespace argument, then match on key only.
📍 Affects 1 file
  • adapters/remote/src/supermemory.rs#L228-L233 (this comment)
  • adapters/remote/src/supermemory.rs#L302-L310
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/remote/src/supermemory.rs` around lines 228 - 233, The upsert and
delete paths scan all namespaces unnecessarily. In
adapters/remote/src/supermemory.rs#L228-L233, add or reuse a namespace-scoped
helper for the Supermemory list request, pass entry.namespace via containerTags,
and match the returned records by key only; apply the same helper in
adapters/remote/src/supermemory.rs#L302-L310 using the namespace argument,
matching by key only. Ensure the helper handles pagination within the specified
namespace.

OPENAI_API_KEY: ${OPENAI_API_KEY:-local-superrag-only}
SUPERMEMORY_DATA_DIR: /data
PORT: 6767
ports: ["6767:6767"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
file="integration/remote-engines/docker-compose.yml"
cat -n "$file" | sed -n '1,95p'
printf '\n--- relevant service definitions ---\n'
rg -n -C 8 '6767:6767|8888:8000|8001:8000|AUTH_DISABLED|REQUIRE_AUTHENTICATION|ports:' "$file"

Repository: tinyhumansai/tinymemory

Length of output: 6086


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- remote-engine files ---'
git ls-files 'integration/remote-engines/*'
printf '%s\n' '--- service servers and authentication references ---'
rg -n -C 3 '6767|AUTH_DISABLED|REQUIRE_AUTHENTICATION|ENABLE_BACKEND_ACCESS_CONTROL|listen|bind|axum|actix|warp|Authorization|Bearer|auth' integration/remote-engines -g '*.rs' -g '*.py' -g '*.ts' -g '*.js' -g '*.md' -g '*.yml' -g '*.yaml' -g 'Dockerfile*'
printf '%s\n' '--- compose usage and endpoint assumptions ---'
rg -n -C 3 'docker compose|remote-engines|8888|8001|6767|mem0|cognee|supermemory' README.md integration -g '*.md' -g '*.yml' -g '*.yaml' -g '*.rs' -g '*.py' -g '*.ts' -g '*.js'

Repository: tinyhumansai/tinymemory

Length of output: 12468


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import re
from pathlib import Path

text = Path("integration/remote-engines/docker-compose.yml").read_text()
services = {}
current = None
for line in text.splitlines():
    m = re.match(r"^  ([A-Za-z0-9_-]+):\s*$", line)
    if m:
        current = m.group(1)
        services[current] = {}
        continue
    if current:
        m = re.match(r'^    ports:\s*\["([^"]+)"\]', line)
        if m:
            services[current]["port"] = m.group(1)
        m = re.match(r'^      (AUTH_DISABLED|REQUIRE_AUTHENTICATION|ENABLE_BACKEND_ACCESS_CONTROL):\s*"?([^"]+)"?', line)
        if m:
            services[current][m.group(1)] = m.group(2)

for name, cfg in services.items():
    if "port" not in cfg:
        continue
    parts = cfg["port"].split(":")
    host = parts[0] if len(parts) == 3 else "0.0.0.0"
    print(name, "mapping=", cfg["port"], "host_bind=", host, "settings=", {
        k: v for k, v in cfg.items() if k != "port"
    })
PY

Repository: tinyhumansai/tinymemory

Length of output: 436


Security Misconfiguration (CWE-1327)

Reachability: External

Bind the mem0 and cognee ports to loopback. Both services publish ports on all host interfaces and disable authentication. Change ["8888:8000"] to ["127.0.0.1:8888:8000"] and ["8001:8000"] to ["127.0.0.1:8001:8000"].

📍 Affects 1 file
  • integration/remote-engines/docker-compose.yml#L13-L13 (this comment)
  • integration/remote-engines/docker-compose.yml#L40-L40
  • integration/remote-engines/docker-compose.yml#L81-L81
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/remote-engines/docker-compose.yml` at line 13, Bind the
unauthenticated mem0 and cognee service ports to loopback instead of all host
interfaces. In integration/remote-engines/docker-compose.yml:13-13, preserve the
existing port mapping unless it is one of the affected services; update
integration/remote-engines/docker-compose.yml:40-40 from 8888:8000 to
127.0.0.1:8888:8000 and integration/remote-engines/docker-compose.yml:81-81 from
8001:8000 to 127.0.0.1:8001:8000.

Comment on lines +98 to +101
volumes:
supermemory-data:
mem0-postgres:
cognee-data:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Named volumes make repeated conformance runs order-dependent.

The three engines persist state in named volumes. The README documents down without -v, so a second conformance run observes records written by the first run. Recall assertions that count results can then change between runs.

Document a reset step, or use anonymous volumes for the conformance profiles.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/remote-engines/docker-compose.yml` around lines 98 - 101, Update
the Docker Compose volume handling for supermemory-data, mem0-postgres, and
cognee-data so repeated conformance runs start with clean state. Prefer
anonymous volumes for these conformance profiles, or document an explicit
volume-reset step in the associated README when retaining named volumes.

Comment on lines +1 to +7
FROM python:3.13-alpine

WORKDIR /app
COPY mock_inference.py .

EXPOSE 8080
CMD ["python", "mock_inference.py"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- Dockerfiles ---'
for f in integration/remote-engines/mock-inference.Dockerfile integration/remote-engines/supermemory.Dockerfile; do
  if [ -f "$f" ]; then
    echo "### $f"
    cat -n "$f"
  else
    echo "MISSING $f"
  fi
done
printf '%s\n' '--- Related runtime/config references ---'
rg -n --glob '!node_modules' --glob '!dist' --glob '!build' \
  'mock_inference|supermemory|SUPERMEMORY_DATA_DIR|USER nobody|useradd|adduser|dockerfile|ports:|6767|8080' \
  integration docker-compose.yml README.md 2>/dev/null || true
printf '%s\n' '--- Compose service context ---'
if [ -f docker-compose.yml ]; then
  cat -n docker-compose.yml | sed -n '1,110p'
fi

Repository: tinyhumansai/tinymemory

Length of output: 3711


🏁 Script executed:

#!/bin/bash
set -eu
for f in integration/remote-engines/mock-inference.Dockerfile integration/remote-engines/supermemory.Dockerfile; do
  echo "### $f"
  cat -n "$f"
done
rg -n 'SUPERMEMORY_DATA_DIR|supermemory|mock_inference|USER nobody|useradd|adduser' integration docker-compose.yml README.md 2>/dev/null || true

Repository: tinyhumansai/tinymemory

Length of output: 2196


🏁 Script executed:

#!/bin/bash
set -eu
echo '--- Compose service definitions ---'
cat -n integration/remote-engines/docker-compose.yml | sed -n '1,105p'
echo '--- Mock server implementation ---'
cat -n integration/remote-engines/mock_inference.py | sed -n '1,145p'
echo '--- Repository USER directives ---'
rg -n --glob '*Dockerfile*' '^[[:space:]]*USER([[:space:]]|$)' . || true

Repository: tinyhumansai/tinymemory

Length of output: 8626


🏁 Script executed:

#!/bin/bash
set -eu
cat -n integration/remote-engines/docker-compose.yml | sed -n '1,105p'
cat -n integration/remote-engines/mock_inference.py | sed -n '1,145p'
rg -n --glob '*Dockerfile*' '^[[:space:]]*USER([[:space:]]|$)' . || true

Repository: tinyhumansai/tinymemory

Length of output: 8520


Security Misconfiguration (CWE-250)

Reachability: External

Run both services as non-root users. Neither Dockerfile declares USER, so both entrypoints run as uid 0 by default. Add a non-root user after installation, and grant that user write access to /data in the Supermemory image before switching users.

🧰 Tools
🪛 Trivy (0.72.0)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

📍 Affects 2 files
  • integration/remote-engines/mock-inference.Dockerfile#L1-L7 (this comment)
  • integration/remote-engines/supermemory.Dockerfile#L1-L12
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/remote-engines/mock-inference.Dockerfile` around lines 1 - 7,
Update both integration/remote-engines/mock-inference.Dockerfile (lines 1-7) and
integration/remote-engines/supermemory.Dockerfile (lines 1-12) to create a
non-root runtime user after package installation and switch to it with USER
before the entrypoint; additionally grant that user write access to /data in
supermemory.Dockerfile before switching users.

Source: Linters/SAST tools

Comment on lines +18 to +24
docker compose -f integration/remote-engines/docker-compose.yml \
--profile mem0 up -d --build
cargo run -p tinymemory-remote --example conformance -- mem0 http://localhost:8888

docker compose -f integration/remote-engines/docker-compose.yml \
--profile cognee up -d --build
cargo run -p tinymemory-remote --example conformance -- cognee http://localhost:8001

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

The documented commands start the conformance run before the engines are ready.

up -d --build returns as soon as the containers start. Mem0 still runs alembic upgrade head, and Cognee still initializes its stores. The conformance example then fails with a connection error.

Use --wait once the engine services declare healthchecks.

 docker compose -f integration/remote-engines/docker-compose.yml \
-  --profile mem0 up -d --build
+  --profile mem0 up -d --build --wait
 cargo run -p tinymemory-remote --example conformance -- mem0 http://localhost:8888

 docker compose -f integration/remote-engines/docker-compose.yml \
-  --profile cognee up -d --build
+  --profile cognee up -d --build --wait
 cargo run -p tinymemory-remote --example conformance -- cognee http://localhost:8001
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
docker compose -f integration/remote-engines/docker-compose.yml \
--profile mem0 up -d --build
cargo run -p tinymemory-remote --example conformance -- mem0 http://localhost:8888
docker compose -f integration/remote-engines/docker-compose.yml \
--profile cognee up -d --build
cargo run -p tinymemory-remote --example conformance -- cognee http://localhost:8001
docker compose -f integration/remote-engines/docker-compose.yml \
--profile mem0 up -d --build --wait
cargo run -p tinymemory-remote --example conformance -- mem0 http://localhost:8888
docker compose -f integration/remote-engines/docker-compose.yml \
--profile cognee up -d --build --wait
cargo run -p tinymemory-remote --example conformance -- cognee http://localhost:8001
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/remote-engines/README.md` around lines 18 - 24, Update the
documented docker compose commands for the mem0 and cognee profiles to include
--wait after --build, ensuring conformance runs only after the engine services
pass their declared healthchecks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant