Let hosts fix attribution headers on every engine request - #196
Conversation
…ort/mod.rs Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…/mod.rs,crates/tinymemory-integ Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…,crates/tinymemory-integrations Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…ort/mod_tests.rs,crates/tinymem Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…ort/mod_tests.rs Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
….md,docs/integration.md Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
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: Changes requested 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 merge
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 (8)
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughEngine settings and CortexEngine now accept fixed request headers. The transport validates the headers, rejects reserved or invalid entries, and attaches valid defaults to requests. ChangesFixed Request Headers
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant Registry
participant CortexEngine
participant HttpClient
Registry->>CortexEngine: Apply settings.headers with with_default_headers
CortexEngine->>HttpClient: Validate headers and replace defaults
HttpClient->>HttpClient: Attach default headers and authorization to request
Merge Risk: ⚪ Minimal · up to The remaining header-validation concern does not establish a request failure or contract violation. The change is mergeable after normal checks. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The new header option preserves the engine’s credential, actor and write-claim controls, and invalid configuration is rejected before installation. Remaining uncertainty concerns who controls host configuration, how remote services interpret custom headers, and whether those headers remain confined to the intended destination. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
A rabbit packed headers in a neat little row Comment |
There was a problem hiding this comment.
Requesting changes: 1 lane(s) blocking, worst finding is high.
Fix or reply to the findings below and push. The next review clears this automatically once they are gone — you should not need to dismiss anything by hand.
$0.0169 · 208,723 in / 13,068 out · 15,549 cached (7%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0084 · 99,418 in / 6,082 out · 8,220 cached (8%) · gpt-5.6-luna, glm-5.3-flash
security: $0.0055 · 81,916 in / 3,071 out · 7,329 cached (9%) · gpt-5.6-luna
tests: $0.0006 · 7,011 in / 410 out · 0 cached (0%) · glm-5.3-flash
description: $0.0006 · 6,846 in / 229 out · 0 cached (0%) · glm-5.3-flash
e2e: $0.0007 · 7,536 in / 593 out · 0 cached (0%) · glm-5.3-flash
| /// attribution (`x-sdk-name`). Never a credential: the transport refuses | ||
| /// `Authorization` and the other headers it sets itself. | ||
| #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] | ||
| pub headers: BTreeMap<String, String>, |
There was a problem hiding this comment.
Apply configured headers when building the engine
EngineSettings::headers is added to the public configuration and documented as being sent on every request, but the existing MemoryConfig::build path passes the settings to build_engine without any visible header application. The repository search shows this field is only declared here; the header-enabled API exists on CortexEngine, but no configuration code invokes it. As a result, a host can successfully deserialize and serialize headers while every request omits them, making the new configuration option ineffective. Forward the map through the registry/build path and call the engine's header configuration method, propagating invalid or reserved-header errors.
[RULE] unused-configuration ·
| @@ -166,6 +220,7 @@ impl HttpClient { | |||
| Ok(self | |||
| .inner | |||
| .request(method, url) | |||
There was a problem hiding this comment.
Drive the running engine with configured headers end to end
The new fixed-headers feature has two external surfaces: the "headers" key in engine configuration (parsed through the registry) and the header itself riding every HTTP request to the CortexDB backend. The only coverage is unit-level: fixed_headers_ride_every_request_beside_the_credential inspects a built Request object, and fixed_headers_are_applied_and_a_credential_header_is_refused only checks that build_engine returns Ok/Err. Nothing runs the actual engine against the live harness (integration/cortexdb's docker-compose + mock_inference.py) and asserts the mock server received x-sdk-name on a request, or that a configured reserved header fails engine construction in a real startup path. The candidate lines in mock_inference.py (Content-Length, end_headers) are pre-existing plumbing of the mock server, not tests of this feature — a test would have to start the compose stack with an engine configured with headers, issue a request through the engine, and have mock_inference record and assert the header arrived. Until then, a wiring regression (e.g. headers dropped when the request builder is assembled, or the registry not threading settings.headers) would pass CI silently.
[RULE] e2e-uncovered ·
Summary
A host can now fix non-credential headers that ride every request an engine makes:
CortexEngine::with_default_headers, orEngineSettings::headersthrough the registry andMemoryConfig.The TinyHumans backend expects every caller to send its product attribution (
x-sdk-nameand friends). Thetinyhumanswire had no way to do that, so OpenHuman's memory calls were the one backend caller without it. OpenHuman now passes its transport's attribution headers to the hosted engine; it sends nothing extra to a direct CortexDB.Related issue
None.
API or behavior changes
Additive:
CortexEngine::with_default_headers(headers) -> Result<Self>.EngineSettingsgainsheaders: BTreeMap<String, String>. It is skipped in JSON when empty and defaults to empty when absent. A struct literal without..Default::default()breaks.The transport refuses headers it owns with
Error::Config, so a host cannot override the credential or the write claim this way:AuthorizationandProxy-Authorization;Cookie,HostandContent-Length;Idempotency-KeyandX-Cortex-Actor.An invalid name or value (including CR/LF) is refused the same way. No refusal message echoes a value.
Validation
cargo fmt --all -- --check: cleancargo clippy --all-targets --all-features -- -D warnings: cleancargo build --all-targets --all-features: cleancargo test --all-features: all pass (integrations: 764)RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features: cleanTests
cortex::transporttests:Authorization.registrytest:build_engineappliesEngineSettings::headers, and refuses anAuthorizationheader without echoing it.Documentation
docs/integration.md, section 2: fixing attribution headers.crates/tinymemory-integrations/src/cortex/README.md, Transport section.Checklist
#[allow(...)],#[ignore], or relaxed lints.envcontents in the diff or the descriptionSummary by CodeRabbit