feat(api): retrieve accepted temporal-context identities by id - #451
feat(api): retrieve accepted temporal-context identities by id#451seonghobae wants to merge 1 commit into
Conversation
Publish GET /v1/temporal-context/{idempotency_key} so operators fetch one
metric-free LineageWeave identity without POST replay. Event labels and
actor lists never appear. Collection GET stays closed. Naruon is refused.
NaruonLiveService stays POST-only. ADR 0083.
|
Warning Review limit reachedNext included review available in 30 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (11)
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. Comment |
| if let Some(stored) = self.accepted_temporal_contexts.get(&replay_key) { | ||
| if stored.knowledge_cutoff != item.knowledge_cutoff { | ||
| return Err(ApiError::InvalidWirePayload); | ||
| } |
There was a problem hiding this comment.
🟡 Conflicting retries share one identity
When a key is reused with different events but the same cutoff, accept_temporal_context treats both submissions as matching. The retry returns different context under one identity instead of failing closed.
Prompt for agents
The temporal-context replay registry in crates/tepp_api/src/analysis_run_live.rs stores only TemporalContextRetrieved and compares only knowledge_cutoff. Store enough validated request state to compare the complete TemporalContextRequest on a repeated consumer/idempotency key. Return the original result for an exact replay and reject any changed request, including changes to events or subject_post_id.
Was this helpful? React with 👍 or 👎 to provide feedback.
| } else { | ||
| self.accepted_temporal_contexts.insert(replay_key, item); |
There was a problem hiding this comment.
🟡 Failed submissions become retrievable
When response serialization fails, accepted_temporal_contexts.insert has already registered the identity. The failed submission then becomes retrievable as accepted.
Prompt for agents
In accept_temporal_context, complete temporal-context construction and response serialization before mutating accepted_temporal_contexts. Only commit the identity after every fallible response step succeeds, while preserving exact replay and conflict behavior.
Was this helpful? React with 👍 or 👎 to provide feedback.
| if payload.contains("tepp.scientific_acceptance.v1") | ||
| || payload.contains("event_label") | ||
| || payload.contains("actor_references") | ||
| || payload.contains("timeline_events") | ||
| { |
There was a problem hiding this comment.
🟡 Opaque keys become unreadable
Valid opaque keys can contain reserved-looking text such as event_label. to_json rejects those stored identities, so their POST succeeds but every GET returns 400.
| if payload.contains("tepp.scientific_acceptance.v1") | |
| || payload.contains("event_label") | |
| || payload.contains("actor_references") | |
| || payload.contains("timeline_events") | |
| { | |
| let value: serde_json::Value = | |
| serde_json::from_str(payload).map_err(|_| ApiError::InvalidWirePayload)?; |
Was this helpful? React with 👍 or 👎 to provide feedback.
| TEMPORAL_CONTEXT_RETRIEVAL_CONTRACT_VERSION, | ||
| )?; | ||
| validate_temporal_context_registry_identity(&self.idempotency_key)?; | ||
| require_nonempty(&self.knowledge_cutoff)?; |
There was a problem hiding this comment.
🟡 Malformed cutoffs pass validation
TemporalContextRetrieved::new accepts any nonempty cutoff instead of an RFC 3339 timestamp. Consumers can accept malformed retrieval payloads as validated identities.
Prompt for agents
Validate TemporalContextRetrieved.knowledge_cutoff with the same RFC 3339 knowledge-cutoff domain parser used by TemporalContextRequest. Apply this validation in the shared validate method so both construction and JSON parsing reject malformed timestamps.
Was this helpful? React with 👍 or 👎 to provide feedback.
| if let Some(idempotency_key) = headers.get("idempotency-key") { | ||
| let item = TemporalContextRetrieved::new( | ||
| idempotency_key.clone(), | ||
| context_request.knowledge_cutoff.clone(), | ||
| TEMPORAL_CONTEXT_RETRIEVAL_INFERENCE_STATUS, | ||
| )?; |
There was a problem hiding this comment.
| const FORBIDDEN_RETRIEVAL_KEYS: [&str; 16] = [ | ||
| "rmse", | ||
| "rmse_standard_error", | ||
| "mean_bias", | ||
| "bias_standard_error", | ||
| "interval_coverage", | ||
| "coverage_wilson_lower", | ||
| "coverage_wilson_upper", | ||
| "temporal_order_accuracy", | ||
| "se_gate_accepted", | ||
| "se_gate_k", | ||
| "scientific_acceptance", | ||
| "report", | ||
| "terminal_result", | ||
| "evidence_text", | ||
| "findings", | ||
| "causal_score", | ||
| ]; |
| if method == "GET" { | ||
| return self.get_temporal_context(path, &headers, body); | ||
| } |
Folded into #452
Closed as
superseded_by_fold, not discarded. #452's head contains this PR as its direct ancestor and has been retargeted to protectedmain, so the temporal-context retrieval GET implementation/tests and this review history remain intact while queue WIP is reduced. Sibling stored-request vehicle #464 also retains this ancestry.Canonical retrieval landing vehicle: #452 (
feat(api): consolidate temporal-context retrieval GET and CLI).Do not reopen unless a surviving folded head demonstrably loses unique behavior or evidence.