Skip to content

feat(api): list accepted temporal-context identities on loopback GET - #449

Closed
seonghobae wants to merge 1 commit into
mainfrom
feat/temporal-context-collection-get-gap-003a
Closed

feat(api): list accepted temporal-context identities on loopback GET#449
seonghobae wants to merge 1 commit into
mainfrom
feat/temporal-context-collection-get-gap-003a

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

GAP-003A unique operator-visible slice: loopback GET /v1/temporal-context enumerates accepted LineageWeave temporal-context identities on AnalysisRunLiveService / tepp-loopback.

  • Empty body. Present idempotency-key header fails closed.
  • Public bind / unpublished consumer / credential flags fail closed.
  • Metric-free receipts with inference_status=temporal_association_only. Event labels, actor lists, timeline events, evidence text, findings, RMSE, bias, coverage, SE-gate, causal scores, and tepp.scientific_acceptance.v1 never appear.
  • POST without idempotency-key stays backward compatible and is not listed.
  • Stacked vs main. Does not unstack a CLI onto this HTTP surface.
  • ADR 0081 (0026–0080 occupied). Does not reuse 0026–0080.

Explicitly not

Another temporal-context CLI (#414), project-history collection GET (#424), project-history cancel CLI (#448), export collection GET (#443), export cancel CLI (#446), interpretation-run collection GET (#433), interpretation-run cancel CLI (#442), Leiden, Driver p.16, GAP-010 Figma/export, persistence/Compose (#287).

Does not add GET to NaruonLiveService. Does not open naruon on this LineageWeave-owned adapter. Does not weaken fail-closed. Does not infer causality. No Buyer language. HTTP 200 is not an ADR 0014 claim.

Test plan

  • cargo test -p tepp_api --lib temporal_context_collection
  • cargo test -p tepp_api --test temporal_context_collection_http_contract
  • cargo clippy -p tepp_api --all-targets -- -D warnings
  • cargo doc -p tepp_api --no-deps
  • python3 scripts/validate_documentation.py
  • python3 scripts/check_docstrings.py

Devin Review

Publish GET /v1/temporal-context so operators enumerate metric-free
LineageWeave identities minted by POST with an idempotency-key header.
Event labels, actor lists, and tepp.scientific_acceptance.v1 never appear.
Naruon is refused. NaruonLiveService stays POST-only. ADR 0081.
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 49 minutes.

Check out review usage here.

View limit details

Limit 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.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 93f2d719-e39d-422f-b8f7-a104c2bfd57f

📥 Commits

Reviewing files that changed from the base of the PR and between 1bc02f5 and 228c764.

📒 Files selected for processing (11)
  • CHANGELOG.d/temporal-context-collection-get.md
  • DOCUMENTATION.md
  • crates/tepp_api/src/analysis_run_live.rs
  • crates/tepp_api/src/lib.rs
  • crates/tepp_api/src/temporal_context_collection_http.rs
  • crates/tepp_api/tests/temporal_context_collection_http_contract.rs
  • docs/API_CONTRACT.md
  • docs/TRACEABILITY.md
  • docs/adr/0081-temporal-context-collection-get.md
  • docs/adr/README.md
  • docs/research/temporal-context-collection-get.md

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.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 6 potential issues.

Devin Review

Comment on lines +198 to +200
} else {
self.accepted_temporal_contexts.insert(replay_key, item);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Failed posts remain listed as accepted

When response serialization exceeds its limit, accept_temporal_context records the identity before returning 413. Later collection reads falsely list the request as accepted.

Prompt for agents
In crates/tepp_api/src/analysis_run_live.rs, accept_temporal_context mutates accepted_temporal_contexts before build_temporal_context and TemporalContextResponse::to_json complete. A request can fit the 64 KiB input limit yet expand beyond the 64 KiB response limit because event identities are repeated across timeline, relation, gap, and source arrays. Build and serialize the successful response before committing the collection identity. Preserve replay/conflict behavior without recording any request whose POST response fails.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +194 to +197
if let Some(stored) = self.accepted_temporal_contexts.get(&replay_key) {
if stored.knowledge_cutoff != item.knowledge_cutoff {
return Err(ApiError::InvalidWirePayload);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Reused keys return different results

Reusing an idempotency key with the same cutoff but different events passes accept_temporal_context. One accepted identity can therefore produce conflicting results.

Prompt for agents
The temporal-context registry stores only TemporalContextCollectionItem, so replay validation can compare only knowledge_cutoff. Store the complete validated TemporalContextRequest, or a canonical digest of every request field, alongside the collection item. Accept an existing idempotency key only when the full request matches; reject changed events, subject_post_id, consumer_code, or other semantics.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +209 to +211
if payload.contains("tepp.scientific_acceptance.v1") {
return Err(ApiError::InvalidWirePayload);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Valid identity disables collection reads

An idempotency key containing tepp.scientific_acceptance.v1 passes item validation. refuse_metrics_on_temporal_context_collection_payload then rejects pages containing it, so collection reads fail.

Prompt for agents
The raw substring ban treats string values as forbidden schema artifacts, while TemporalContextCollectionItem accepts the same text as an idempotency key. Make validation consistent: either reject this reserved marker when identities are minted, before insertion, or detect scientific-acceptance structure semantically without rejecting opaque string values. Add a POST-then-GET regression test for an idempotency key containing the marker.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +183 to +191
for item in &self.contexts {
item.validate()?;
}
if let Some(cursor) = &self.next_cursor {
require_nonempty(cursor)?;
if cursor.len() > TEMPORAL_CONTEXT_COLLECTION_CURSOR_MAX_LEN {
return Err(ApiError::LimitExceeded);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Malformed collection pages pass validation

TemporalContextCollection::validate accepts malformed cutoffs, duplicate or unsorted identities, and unrelated cursors. Consumers can treat invalid pagination data as a valid collection response.

Prompt for agents
Strengthen TemporalContextCollection and TemporalContextCollectionItem validation in crates/tepp_api/src/temporal_context_collection_http.rs. Parse every knowledge_cutoff with the same RFC 3339 temporal type used by TemporalContextRequest. Require contexts to be strictly increasing by idempotency_key, which rejects duplicates, and require next_cursor to equal the final row identity when present. Define and validate empty-page cursor behavior, then add malformed from_json tests.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

next_request_serial: u64,
accepted_runs: HashMap<String, (AnalysisRunRequest, AnalysisRunAccepted)>,
accepted_project_histories: HashMap<String, (ProjectHistoryRequest, ProjectHistoryProjection)>,
accepted_temporal_contexts: HashMap<String, TemporalContextCollectionItem>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Registry growth lacks a bound

Each distinct POST permanently grows accepted_temporal_contexts. Add an entry limit or eviction policy before using this loopback service as a long-running process.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +169 to +170
let payload = to_json(self)?;
require_byte_limit(&payload, DEFAULT_PROJECT_HISTORY_BYTE_LIMIT)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Serialization limit applies after allocation

to_json builds the complete page before checking its byte limit. Use bounded serialization to preserve the repository’s untrusted-payload resource contract.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Closing as research_lineage_only / fold_into_landing_vehicle under the Temporal Event Knowledge / Analysis Run read-model vehicle, not as a standalone route/ADR. The review found real defects that must be preserved in the folded implementation: POST state must not commit before response construction succeeds; idempotent replay must bind the full canonical request/digest rather than cutoff only; opaque identities must not be broken by raw scientific-marker substring filtering; collection items/pages need RFC3339 cutoff, strict ordering/duplicate rejection and cursor invariants; registry growth and serialization must be bounded before allocation. These are RED acceptance criteria for the coherent landing vehicle. Closing this micro-PR removes unsafe WIP without claiming the defects are fixed on protected main.

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