Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.d/interpretation-run-retrieval-cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- `orchestrator_live` `tepp-interpretation-run-get get` mints a typed contextual-orchestrator `GET /v1/interpretation-runs/{idempotency_key}` onto spawned `tepp-orchestrator-loopback` TCP (ADR 0072). Metric-free hypothetical identities only (`claim_status=hypothetical`, `scientific_authority=false`). `tepp.scientific_acceptance.v1` never appears. Does not infer causality. Naruon and LineageWeave are refused. Not collection CLI, not GET-by-id HTTP-only, not persistence.
1 change: 1 addition & 0 deletions CHANGELOG.d/interpretation-run-retrieval-http.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- `orchestrator_live` loopback `GET /v1/interpretation-runs/{idempotency_key}` returns one accepted hypothetical interpretation-run identity on `tepp-orchestrator-loopback` without POST replay (ADR 0071). Metric-free identities only (`claim_status=hypothetical`, `scientific_authority=false`). `tepp.scientific_acceptance.v1` never appears. Does not infer causality. Naruon and LineageWeave are refused. Not collection GET, not collection CLI, not persistence.
2 changes: 2 additions & 0 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ TEPP's approved PRD v0.4 and implementation plan are the primary product baselin
| Orchestrator live HTTP doctoring | [`docs/research/orchestrator-live-http.md`](docs/research/orchestrator-live-http.md) |
| Interpretation-run CLI doctoring | [`docs/research/interpretation-run-cli.md`](docs/research/interpretation-run-cli.md) |
| Interpretation-run collection GET doctoring | [`docs/research/interpretation-run-collection-http.md`](docs/research/interpretation-run-collection-http.md) |
| Interpretation-run GET-by-id doctoring | [`docs/research/interpretation-run-retrieval-http.md`](docs/research/interpretation-run-retrieval-http.md) |
| Interpretation-run retrieval CLI doctoring | [`docs/research/interpretation-run-retrieval-cli.md`](docs/research/interpretation-run-retrieval-cli.md) |
Comment on lines +18 to +19

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Duplicated documentation map diverges

The canonical map repeats its heading and table later, but the new retrieval links appear only in the first copy. Readers can encounter inconsistent indexes.

Devin Review

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

| UML/runtime/scientific flows | [`docs/UML.md`](docs/UML.md) |
| Logical/physical ERD | [`docs/ERD.md`](docs/ERD.md) |
| Security policy | [`SECURITY.md`](SECURITY.md) |
Expand Down
6 changes: 6 additions & 0 deletions crates/orchestrator_live/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,11 @@ path = "src/bin/tepp_interpretation_runs.rs"
test = false
bench = false

[[bin]]
name = "tepp-interpretation-run-get"
path = "src/bin/tepp_interpretation_run_get.rs"
test = false
bench = false

[lints]
workspace = true
34 changes: 34 additions & 0 deletions crates/orchestrator_live/src/bin/tepp_interpretation_run_get.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//! Operator CLI for loopback contextual-orchestrator interpretation-run GET-by-id.

use std::io::{self, IsTerminal};
use std::process::ExitCode;

use orchestrator_live::{
execute_interpretation_run_retrieval_cli, read_interpretation_run_retrieval_cli_stdin,
render_interpretation_run_retrieval_cli_stdout, InterpretationRunRetrievalCliInvocation,
OrchestratorLiveError,
};

fn main() -> ExitCode {
match run() {
Ok(()) => ExitCode::SUCCESS,
Err(_) => ExitCode::FAILURE,
}
}

fn run() -> Result<(), OrchestratorLiveError> {
let args: Vec<String> = std::env::args().skip(1).collect();
match args.first().map(String::as_str) {
Some("get") => run_get(&args),
_ => Err(OrchestratorLiveError::InvalidWirePayload),
}
}

fn run_get(args: &[String]) -> Result<(), OrchestratorLiveError> {
let body = read_interpretation_run_retrieval_cli_stdin(io::stdin().is_terminal(), io::stdin())?;
let invocation = InterpretationRunRetrievalCliInvocation::from_args(args, body)?;
let response = execute_interpretation_run_retrieval_cli(&invocation)?;
let stdout = render_interpretation_run_retrieval_cli_stdout(&invocation, &response)?;
println!("{stdout}");
Ok(())
}
24 changes: 21 additions & 3 deletions crates/orchestrator_live/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::io::{Read, Write};

use crate::error::OrchestratorLiveError;
use crate::request::{
DEFAULT_INTERPRETATION_BYTE_LIMIT, host_implies_table_access, require_nonempty,
host_implies_table_access, require_nonempty, DEFAULT_INTERPRETATION_BYTE_LIMIT,
};

/// Maximum request-line plus header bytes accepted before the body.
Expand Down Expand Up @@ -211,6 +211,17 @@ pub(crate) fn refuse_collection_get_headers(
Ok(())
}

/// GET-by-id admits empty bodies and refuses pagination plus `idempotency-key`.
pub(crate) fn refuse_retrieval_get_headers(
headers: &HashMap<String, String>,
) -> Result<(), OrchestratorLiveError> {
refuse_collection_get_headers(headers)?;
if headers.contains_key("tepp-page-limit") || headers.contains_key("tepp-page-cursor") {
return Err(OrchestratorLiveError::InvalidWirePayload);
}
Ok(())
}

fn refuse_common_live_headers(
headers: &HashMap<String, String>,
) -> Result<(), OrchestratorLiveError> {
Expand Down Expand Up @@ -280,8 +291,8 @@ pub(crate) fn status_for(error: OrchestratorLiveError) -> (u16, &'static str) {
mod tests {
use super::{
declared_content_length, header_is_credential, map_io_error, parse_headers,
parse_request_line, refuse_collection_get_headers, refuse_live_headers, split_header_line,
split_request, status_for,
parse_request_line, refuse_collection_get_headers, refuse_live_headers,
refuse_retrieval_get_headers, split_header_line, split_request, status_for,
};
use crate::error::OrchestratorLiveError;
use std::collections::HashMap;
Expand Down Expand Up @@ -457,6 +468,13 @@ mod tests {
);
headers.remove("idempotency-key");
refuse_collection_get_headers(&headers).expect("collection headers");
refuse_retrieval_get_headers(&headers).expect("retrieval headers");
headers.insert("tepp-page-limit".into(), "1".into());
assert_eq!(
refuse_retrieval_get_headers(&headers),
Err(OrchestratorLiveError::InvalidWirePayload)
);
headers.remove("tepp-page-limit");
headers.insert("tepp-consumer".into(), "naruon".into());
assert_eq!(
refuse_collection_get_headers(&headers),
Expand Down
Loading
Loading