Category: spec-conformance Severity: blocker
Location: crates/arcp-runtime/src/runtime/server.rs:820-833
Spec: ARCP v1.1 §9.5
What
LeaseRequest.expires_at can be accepted into the job lease and echoed in job.accepted without checking that it is future at submission. No runtime operation path checks the lease expiry before dispatch or turns post-expiry operations into LEASE_EXPIRED.
Evidence
let lease = effective_lease(&payload);
let defer_accepted = self.inner.credential_provisioner.is_some() && lease.is_some();
let accepted_sent = if defer_accepted {
false
} else {
let mut accepted = Envelope::new(MessageType::JobAccepted(JobAcceptedPayload {
job_id: job_id.clone(),
credentials: vec![],
lease: lease.clone(),
}));
accepted.correlation_id = Some(correlation_id.clone());
accepted.session_id = Some(session_id.clone());
accepted.job_id = Some(job_id.clone());
let _ = out.send(accepted).await;
Proposed fix
Validate expires_at before job.accepted, reject invalid/past values with INVALID_REQUEST, and enforce expiry before each authority-bearing operation with LEASE_EXPIRED/final_status: error.
Acceptance criteria
Category: spec-conformance Severity: blocker
Location:
crates/arcp-runtime/src/runtime/server.rs:820-833Spec: ARCP v1.1 §9.5
What
LeaseRequest.expires_atcan be accepted into the job lease and echoed injob.acceptedwithout checking that it is future at submission. No runtime operation path checks the lease expiry before dispatch or turns post-expiry operations intoLEASE_EXPIRED.Evidence
Proposed fix
Validate
expires_atbeforejob.accepted, reject invalid/past values withINVALID_REQUEST, and enforce expiry before each authority-bearing operation withLEASE_EXPIRED/final_status: error.Acceptance criteria
LEASE_EXPIREDinstead of continuing.