diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 56d2b3a04b..3174ce5ecd 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -665,6 +665,7 @@ "aws-lc-rs_1.16.2": "{\"dependencies\":[{\"name\":\"aws-lc-fips-sys\",\"optional\":true,\"req\":\"^0.13.1\"},{\"default_features\":false,\"name\":\"aws-lc-sys\",\"optional\":true,\"req\":\"^0.39.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^4.4\"},{\"kind\":\"dev\",\"name\":\"hex\",\"req\":\"^0.4.3\"},{\"kind\":\"dev\",\"name\":\"lazy_static\",\"req\":\"^1.5.0\"},{\"kind\":\"dev\",\"name\":\"paste\",\"req\":\"^1.0.15\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.11.1\"},{\"name\":\"untrusted\",\"optional\":true,\"req\":\"^0.7.1\"},{\"name\":\"zeroize\",\"req\":\"^1.8.1\"}],\"features\":{\"alloc\":[],\"asan\":[\"aws-lc-sys?/asan\",\"aws-lc-fips-sys?/asan\"],\"bindgen\":[\"aws-lc-sys?/bindgen\",\"aws-lc-fips-sys?/bindgen\"],\"default\":[\"aws-lc-sys\",\"alloc\",\"ring-io\",\"ring-sig-verify\"],\"dev-tests-only\":[],\"fips\":[\"dep:aws-lc-fips-sys\"],\"non-fips\":[\"aws-lc-sys\"],\"prebuilt-nasm\":[\"aws-lc-sys?/prebuilt-nasm\"],\"ring-io\":[\"dep:untrusted\"],\"ring-sig-verify\":[\"dep:untrusted\"],\"test_logging\":[],\"unstable\":[]}}", "aws-lc-sys_0.39.0": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"bindgen\",\"optional\":true,\"req\":\"^0.72.0\"},{\"features\":[\"parallel\"],\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.2.26\"},{\"kind\":\"build\",\"name\":\"cmake\",\"req\":\"^0.1.54\"},{\"kind\":\"build\",\"name\":\"dunce\",\"req\":\"^1.0.5\"},{\"kind\":\"build\",\"name\":\"fs_extra\",\"req\":\"^1.3.0\"}],\"features\":{\"all-bindings\":[],\"asan\":[],\"bindgen\":[\"dep:bindgen\"],\"default\":[\"all-bindings\"],\"disable-prebuilt-nasm\":[],\"fips\":[\"dep:bindgen\"],\"prebuilt-nasm\":[],\"ssl\":[\"bindgen\",\"all-bindings\"]}}", "aws-runtime_1.5.17": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"arbitrary\",\"req\":\"^1.3\"},{\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"features\":[\"http0-compat\"],\"name\":\"aws-sigv4\",\"req\":\"^1.3.7\"},{\"name\":\"aws-smithy-async\",\"req\":\"^1.2.7\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-smithy-async\",\"req\":\"^1.2.7\"},{\"name\":\"aws-smithy-eventstream\",\"optional\":true,\"req\":\"^0.60.14\"},{\"name\":\"aws-smithy-http\",\"req\":\"^0.62.6\"},{\"kind\":\"dev\",\"name\":\"aws-smithy-protocol-test\",\"req\":\"^0.63.7\"},{\"features\":[\"client\"],\"name\":\"aws-smithy-runtime\",\"req\":\"^1.9.5\"},{\"features\":[\"client\"],\"name\":\"aws-smithy-runtime-api\",\"req\":\"^1.9.3\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-smithy-runtime-api\",\"req\":\"^1.9.3\"},{\"name\":\"aws-smithy-types\",\"req\":\"^1.3.5\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-smithy-types\",\"req\":\"^1.3.5\"},{\"name\":\"aws-types\",\"req\":\"^1.3.11\"},{\"name\":\"bytes\",\"req\":\"^1.10.0\"},{\"kind\":\"dev\",\"name\":\"bytes-utils\",\"req\":\"^0.1.2\"},{\"kind\":\"dev\",\"name\":\"convert_case\",\"req\":\"^0.6.0\"},{\"name\":\"fastrand\",\"req\":\"^2.3.0\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"futures-util\",\"req\":\"^0.3.29\"},{\"name\":\"http-02x\",\"package\":\"http\",\"req\":\"^0.2.9\"},{\"name\":\"http-1x\",\"optional\":true,\"package\":\"http\",\"req\":\"^1.1.0\"},{\"name\":\"http-body-04x\",\"package\":\"http-body\",\"req\":\"^0.4.5\"},{\"name\":\"http-body-1x\",\"optional\":true,\"package\":\"http-body\",\"req\":\"^1.0.0\"},{\"name\":\"percent-encoding\",\"req\":\"^2.3.1\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.14\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.2\"},{\"name\":\"regex-lite\",\"optional\":true,\"req\":\"^0.1.5\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1\"},{\"features\":[\"macros\",\"rt\",\"time\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.23.1\"},{\"name\":\"tracing\",\"req\":\"^0.1.40\"},{\"features\":[\"env-filter\"],\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3.17\"},{\"kind\":\"dev\",\"name\":\"tracing-test\",\"req\":\"^0.2.4\"},{\"name\":\"uuid\",\"req\":\"^1\"}],\"features\":{\"event-stream\":[\"dep:aws-smithy-eventstream\",\"aws-sigv4/sign-eventstream\"],\"http-02x\":[],\"http-1x\":[\"dep:http-1x\",\"dep:http-body-1x\"],\"sigv4a\":[\"aws-sigv4/sigv4a\"],\"test-util\":[\"dep:regex-lite\"]}}", + "aws-sdk-signin_1.2.0": "{\"dependencies\":[{\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"name\":\"aws-runtime\",\"req\":\"^1.5.17\"},{\"name\":\"aws-smithy-async\",\"req\":\"^1.2.7\"},{\"name\":\"aws-smithy-http\",\"req\":\"^0.62.6\"},{\"name\":\"aws-smithy-json\",\"req\":\"^0.61.8\"},{\"features\":[\"client\"],\"name\":\"aws-smithy-runtime\",\"req\":\"^1.9.5\"},{\"features\":[\"client\",\"http-02x\"],\"name\":\"aws-smithy-runtime-api\",\"req\":\"^1.9.3\"},{\"name\":\"aws-smithy-types\",\"req\":\"^1.3.5\"},{\"name\":\"aws-types\",\"req\":\"^1.3.11\"},{\"name\":\"bytes\",\"req\":\"^1.4.0\"},{\"name\":\"fastrand\",\"req\":\"^2.0.0\"},{\"name\":\"http\",\"req\":\"^0.2.9\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"name\":\"regex-lite\",\"req\":\"^0.1.5\"},{\"features\":[\"macros\",\"test-util\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.23.1\"},{\"name\":\"tracing\",\"req\":\"^0.1\"}],\"features\":{\"behavior-version-latest\":[],\"default\":[\"rustls\",\"default-https-client\",\"rt-tokio\"],\"default-https-client\":[\"aws-smithy-runtime/default-https-client\"],\"gated-tests\":[],\"rt-tokio\":[\"aws-smithy-async/rt-tokio\",\"aws-smithy-types/rt-tokio\"],\"rustls\":[\"aws-smithy-runtime/tls-rustls\"],\"test-util\":[\"aws-credential-types/test-util\",\"aws-smithy-runtime/test-util\"]}}", "aws-sdk-sso_1.91.0": "{\"dependencies\":[{\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"name\":\"aws-runtime\",\"req\":\"^1.5.17\"},{\"name\":\"aws-smithy-async\",\"req\":\"^1.2.7\"},{\"name\":\"aws-smithy-http\",\"req\":\"^0.62.6\"},{\"name\":\"aws-smithy-json\",\"req\":\"^0.61.8\"},{\"features\":[\"client\"],\"name\":\"aws-smithy-runtime\",\"req\":\"^1.9.5\"},{\"features\":[\"client\",\"http-02x\"],\"name\":\"aws-smithy-runtime-api\",\"req\":\"^1.9.3\"},{\"name\":\"aws-smithy-types\",\"req\":\"^1.3.5\"},{\"name\":\"aws-types\",\"req\":\"^1.3.11\"},{\"name\":\"bytes\",\"req\":\"^1.4.0\"},{\"name\":\"fastrand\",\"req\":\"^2.0.0\"},{\"name\":\"http\",\"req\":\"^0.2.9\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"name\":\"regex-lite\",\"req\":\"^0.1.5\"},{\"features\":[\"macros\",\"test-util\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.23.1\"},{\"name\":\"tracing\",\"req\":\"^0.1\"}],\"features\":{\"behavior-version-latest\":[],\"default\":[\"rustls\",\"default-https-client\",\"rt-tokio\"],\"default-https-client\":[\"aws-smithy-runtime/default-https-client\"],\"gated-tests\":[],\"rt-tokio\":[\"aws-smithy-async/rt-tokio\",\"aws-smithy-types/rt-tokio\"],\"rustls\":[\"aws-smithy-runtime/tls-rustls\"],\"test-util\":[\"aws-credential-types/test-util\",\"aws-smithy-runtime/test-util\"]}}", "aws-sdk-ssooidc_1.93.0": "{\"dependencies\":[{\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"name\":\"aws-runtime\",\"req\":\"^1.5.17\"},{\"name\":\"aws-smithy-async\",\"req\":\"^1.2.7\"},{\"name\":\"aws-smithy-http\",\"req\":\"^0.62.6\"},{\"name\":\"aws-smithy-json\",\"req\":\"^0.61.8\"},{\"features\":[\"client\"],\"name\":\"aws-smithy-runtime\",\"req\":\"^1.9.5\"},{\"features\":[\"client\",\"http-02x\"],\"name\":\"aws-smithy-runtime-api\",\"req\":\"^1.9.3\"},{\"name\":\"aws-smithy-types\",\"req\":\"^1.3.5\"},{\"name\":\"aws-types\",\"req\":\"^1.3.11\"},{\"name\":\"bytes\",\"req\":\"^1.4.0\"},{\"name\":\"fastrand\",\"req\":\"^2.0.0\"},{\"name\":\"http\",\"req\":\"^0.2.9\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"name\":\"regex-lite\",\"req\":\"^0.1.5\"},{\"features\":[\"macros\",\"test-util\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.23.1\"},{\"name\":\"tracing\",\"req\":\"^0.1\"}],\"features\":{\"behavior-version-latest\":[],\"default\":[\"rustls\",\"default-https-client\",\"rt-tokio\"],\"default-https-client\":[\"aws-smithy-runtime/default-https-client\"],\"gated-tests\":[],\"rt-tokio\":[\"aws-smithy-async/rt-tokio\",\"aws-smithy-types/rt-tokio\"],\"rustls\":[\"aws-smithy-runtime/tls-rustls\"],\"test-util\":[\"aws-credential-types/test-util\",\"aws-smithy-runtime/test-util\"]}}", "aws-sdk-sts_1.95.0": "{\"dependencies\":[{\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-credential-types\",\"req\":\"^1.2.11\"},{\"name\":\"aws-runtime\",\"req\":\"^1.5.17\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-runtime\",\"req\":\"^1.5.17\"},{\"name\":\"aws-smithy-async\",\"req\":\"^1.2.7\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-smithy-async\",\"req\":\"^1.2.7\"},{\"name\":\"aws-smithy-http\",\"req\":\"^0.62.6\"},{\"features\":[\"test-util\",\"wire-mock\"],\"kind\":\"dev\",\"name\":\"aws-smithy-http-client\",\"req\":\"^1.1.5\"},{\"name\":\"aws-smithy-json\",\"req\":\"^0.61.8\"},{\"kind\":\"dev\",\"name\":\"aws-smithy-protocol-test\",\"req\":\"^0.63.7\"},{\"name\":\"aws-smithy-query\",\"req\":\"^0.60.9\"},{\"features\":[\"client\"],\"name\":\"aws-smithy-runtime\",\"req\":\"^1.9.5\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-smithy-runtime\",\"req\":\"^1.9.5\"},{\"features\":[\"client\",\"http-02x\"],\"name\":\"aws-smithy-runtime-api\",\"req\":\"^1.9.3\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-smithy-runtime-api\",\"req\":\"^1.9.3\"},{\"name\":\"aws-smithy-types\",\"req\":\"^1.3.5\"},{\"features\":[\"test-util\"],\"kind\":\"dev\",\"name\":\"aws-smithy-types\",\"req\":\"^1.3.5\"},{\"name\":\"aws-smithy-xml\",\"req\":\"^0.60.13\"},{\"name\":\"aws-types\",\"req\":\"^1.3.11\"},{\"name\":\"fastrand\",\"req\":\"^2.0.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"kind\":\"dev\",\"name\":\"futures-util\",\"req\":\"^0.3.25\"},{\"name\":\"http\",\"req\":\"^0.2.9\"},{\"kind\":\"dev\",\"name\":\"http-1x\",\"package\":\"http\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"name\":\"regex-lite\",\"req\":\"^0.1.5\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.0\"},{\"features\":[\"macros\",\"test-util\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.23.1\"},{\"name\":\"tracing\",\"req\":\"^0.1\"},{\"features\":[\"env-filter\",\"json\"],\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3.16\"}],\"features\":{\"behavior-version-latest\":[],\"default\":[\"rustls\",\"default-https-client\",\"rt-tokio\"],\"default-https-client\":[\"aws-smithy-runtime/default-https-client\"],\"gated-tests\":[],\"rt-tokio\":[\"aws-smithy-async/rt-tokio\",\"aws-smithy-types/rt-tokio\"],\"rustls\":[\"aws-smithy-runtime/tls-rustls\"],\"test-util\":[\"aws-credential-types/test-util\",\"aws-smithy-runtime/test-util\"]}}", @@ -686,6 +687,7 @@ "axum_0.7.9": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0\"},{\"name\":\"async-trait\",\"req\":\"^0.1.67\"},{\"name\":\"axum-core\",\"req\":\"^0.4.5\"},{\"name\":\"axum-macros\",\"optional\":true,\"req\":\"^0.4.2\"},{\"features\":[\"__private\"],\"kind\":\"dev\",\"name\":\"axum-macros\",\"req\":\"^0.4.1\"},{\"name\":\"base64\",\"optional\":true,\"req\":\"^0.22.1\"},{\"name\":\"bytes\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"futures-util\",\"req\":\"^0.3\"},{\"name\":\"http\",\"req\":\"^1.0.0\"},{\"name\":\"http-body\",\"req\":\"^1.0.0\"},{\"name\":\"http-body-util\",\"req\":\"^0.1.0\"},{\"name\":\"hyper\",\"optional\":true,\"req\":\"^1.1.0\"},{\"features\":[\"tokio\",\"server\",\"service\"],\"name\":\"hyper-util\",\"optional\":true,\"req\":\"^0.1.3\"},{\"name\":\"itoa\",\"req\":\"^1.0.5\"},{\"name\":\"matchit\",\"req\":\"^0.7\"},{\"name\":\"memchr\",\"req\":\"^2.4.1\"},{\"name\":\"mime\",\"req\":\"^0.3.16\"},{\"name\":\"multer\",\"optional\":true,\"req\":\"^3.0.0\"},{\"name\":\"percent-encoding\",\"req\":\"^2.1\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.7\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"quickcheck_macros\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"json\",\"stream\",\"multipart\"],\"kind\":\"dev\",\"name\":\"reqwest\",\"req\":\"^0.12\"},{\"name\":\"rustversion\",\"req\":\"^1.0.9\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\"},{\"features\":[\"raw_value\"],\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"raw_value\"],\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"serde_path_to_error\",\"optional\":true,\"req\":\"^0.1.8\"},{\"name\":\"serde_urlencoded\",\"optional\":true,\"req\":\"^0.7\"},{\"name\":\"sha1\",\"optional\":true,\"req\":\"^0.10\"},{\"name\":\"sync_wrapper\",\"req\":\"^1.0.0\"},{\"features\":[\"serde-human-readable\"],\"kind\":\"dev\",\"name\":\"time\",\"req\":\"^0.3\"},{\"features\":[\"time\"],\"name\":\"tokio\",\"optional\":true,\"package\":\"tokio\",\"req\":\"^1.25.0\"},{\"features\":[\"macros\",\"rt\",\"rt-multi-thread\",\"net\",\"test-util\"],\"kind\":\"dev\",\"name\":\"tokio\",\"package\":\"tokio\",\"req\":\"^1.25.0\"},{\"kind\":\"dev\",\"name\":\"tokio-stream\",\"req\":\"^0.1\"},{\"name\":\"tokio-tungstenite\",\"optional\":true,\"req\":\"^0.24.0\"},{\"kind\":\"dev\",\"name\":\"tokio-tungstenite\",\"req\":\"^0.24.0\"},{\"default_features\":false,\"features\":[\"util\"],\"name\":\"tower\",\"req\":\"^0.5.1\"},{\"features\":[\"util\",\"timeout\",\"limit\",\"load-shed\",\"steer\",\"filter\"],\"kind\":\"dev\",\"name\":\"tower\",\"package\":\"tower\",\"req\":\"^0.5.1\"},{\"features\":[\"add-extension\",\"auth\",\"catch-panic\",\"compression-br\",\"compression-deflate\",\"compression-gzip\",\"cors\",\"decompression-br\",\"decompression-deflate\",\"decompression-gzip\",\"follow-redirect\",\"fs\",\"limit\",\"map-request-body\",\"map-response-body\",\"metrics\",\"normalize-path\",\"propagate-header\",\"redirect\",\"request-id\",\"sensitive-headers\",\"set-header\",\"set-status\",\"timeout\",\"trace\",\"util\",\"validate-request\"],\"name\":\"tower-http\",\"optional\":true,\"req\":\"^0.6.0\"},{\"features\":[\"add-extension\",\"auth\",\"catch-panic\",\"compression-br\",\"compression-deflate\",\"compression-gzip\",\"cors\",\"decompression-br\",\"decompression-deflate\",\"decompression-gzip\",\"follow-redirect\",\"fs\",\"limit\",\"map-request-body\",\"map-response-body\",\"metrics\",\"normalize-path\",\"propagate-header\",\"redirect\",\"request-id\",\"sensitive-headers\",\"set-header\",\"set-status\",\"timeout\",\"trace\",\"util\",\"validate-request\"],\"kind\":\"dev\",\"name\":\"tower-http\",\"req\":\"^0.6.0\"},{\"name\":\"tower-layer\",\"req\":\"^0.3.2\"},{\"name\":\"tower-service\",\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"tracing\",\"req\":\"^0.1\"},{\"features\":[\"json\"],\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3\"},{\"features\":[\"serde\",\"v4\"],\"kind\":\"dev\",\"name\":\"uuid\",\"req\":\"^1.0\"}],\"features\":{\"__private_docs\":[\"axum-core/__private_docs\",\"tower/full\",\"dep:tower-http\"],\"default\":[\"form\",\"http1\",\"json\",\"matched-path\",\"original-uri\",\"query\",\"tokio\",\"tower-log\",\"tracing\"],\"form\":[\"dep:serde_urlencoded\"],\"http1\":[\"dep:hyper\",\"hyper?/http1\",\"hyper-util?/http1\"],\"http2\":[\"dep:hyper\",\"hyper?/http2\",\"hyper-util?/http2\"],\"json\":[\"dep:serde_json\",\"dep:serde_path_to_error\"],\"macros\":[\"dep:axum-macros\"],\"matched-path\":[],\"multipart\":[\"dep:multer\"],\"original-uri\":[],\"query\":[\"dep:serde_urlencoded\"],\"tokio\":[\"dep:hyper-util\",\"dep:tokio\",\"tokio/net\",\"tokio/rt\",\"tower/make\",\"tokio/macros\"],\"tower-log\":[\"tower/log\"],\"tracing\":[\"dep:tracing\",\"axum-core/tracing\"],\"ws\":[\"dep:hyper\",\"tokio\",\"dep:tokio-tungstenite\",\"dep:sha1\",\"dep:base64\"]}}", "axum_0.8.8": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0\"},{\"name\":\"axum-core\",\"req\":\"^0.5.5\"},{\"name\":\"axum-macros\",\"optional\":true,\"req\":\"^0.5.0\"},{\"name\":\"base64\",\"optional\":true,\"req\":\"^0.22.1\"},{\"name\":\"bytes\",\"req\":\"^1.0\"},{\"name\":\"form_urlencoded\",\"optional\":true,\"req\":\"^1.1.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"futures-util\",\"req\":\"^0.3\"},{\"name\":\"http\",\"req\":\"^1.0.0\"},{\"name\":\"http-body\",\"req\":\"^1.0.0\"},{\"name\":\"http-body-util\",\"req\":\"^0.1.0\"},{\"name\":\"hyper\",\"optional\":true,\"req\":\"^1.1.0\"},{\"features\":[\"client\"],\"kind\":\"dev\",\"name\":\"hyper\",\"req\":\"^1.1.0\"},{\"features\":[\"tokio\",\"server\",\"service\"],\"name\":\"hyper-util\",\"optional\":true,\"req\":\"^0.1.3\"},{\"name\":\"itoa\",\"req\":\"^1.0.5\"},{\"name\":\"matchit\",\"req\":\"=0.8.4\"},{\"name\":\"memchr\",\"req\":\"^2.4.1\"},{\"name\":\"mime\",\"req\":\"^0.3.16\"},{\"name\":\"multer\",\"optional\":true,\"req\":\"^3.0.0\"},{\"name\":\"percent-encoding\",\"req\":\"^2.1\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.7\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"quickcheck_macros\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"json\",\"stream\",\"multipart\"],\"name\":\"reqwest\",\"optional\":true,\"req\":\"^0.12\"},{\"default_features\":false,\"features\":[\"json\",\"stream\",\"multipart\"],\"kind\":\"dev\",\"name\":\"reqwest\",\"req\":\"^0.12\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.211\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.221\"},{\"name\":\"serde_core\",\"req\":\"^1.0.221\"},{\"features\":[\"raw_value\"],\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"raw_value\"],\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"serde_path_to_error\",\"optional\":true,\"req\":\"^0.1.8\"},{\"name\":\"serde_urlencoded\",\"optional\":true,\"req\":\"^0.7\"},{\"name\":\"sha1\",\"optional\":true,\"req\":\"^0.10\"},{\"name\":\"sync_wrapper\",\"req\":\"^1.0.0\"},{\"features\":[\"serde-human-readable\"],\"kind\":\"dev\",\"name\":\"time\",\"req\":\"^0.3\"},{\"features\":[\"time\"],\"name\":\"tokio\",\"optional\":true,\"package\":\"tokio\",\"req\":\"^1.44\"},{\"features\":[\"macros\",\"rt\",\"rt-multi-thread\",\"net\",\"test-util\"],\"kind\":\"dev\",\"name\":\"tokio\",\"package\":\"tokio\",\"req\":\"^1.44.2\"},{\"kind\":\"dev\",\"name\":\"tokio-stream\",\"req\":\"^0.1\"},{\"name\":\"tokio-tungstenite\",\"optional\":true,\"req\":\"^0.28.0\"},{\"kind\":\"dev\",\"name\":\"tokio-tungstenite\",\"req\":\"^0.28.0\"},{\"default_features\":false,\"features\":[\"util\"],\"name\":\"tower\",\"req\":\"^0.5.2\"},{\"features\":[\"util\",\"timeout\",\"limit\",\"load-shed\",\"steer\",\"filter\"],\"kind\":\"dev\",\"name\":\"tower\",\"package\":\"tower\",\"req\":\"^0.5.2\"},{\"features\":[\"add-extension\",\"auth\",\"catch-panic\",\"compression-br\",\"compression-deflate\",\"compression-gzip\",\"cors\",\"decompression-br\",\"decompression-deflate\",\"decompression-gzip\",\"follow-redirect\",\"fs\",\"limit\",\"map-request-body\",\"map-response-body\",\"metrics\",\"normalize-path\",\"propagate-header\",\"redirect\",\"request-id\",\"sensitive-headers\",\"set-header\",\"set-status\",\"timeout\",\"trace\",\"util\",\"validate-request\"],\"name\":\"tower-http\",\"optional\":true,\"req\":\"^0.6.0\"},{\"features\":[\"add-extension\",\"auth\",\"catch-panic\",\"compression-br\",\"compression-deflate\",\"compression-gzip\",\"cors\",\"decompression-br\",\"decompression-deflate\",\"decompression-gzip\",\"follow-redirect\",\"fs\",\"limit\",\"map-request-body\",\"map-response-body\",\"metrics\",\"normalize-path\",\"propagate-header\",\"redirect\",\"request-id\",\"sensitive-headers\",\"set-header\",\"set-status\",\"timeout\",\"trace\",\"util\",\"validate-request\"],\"kind\":\"dev\",\"name\":\"tower-http\",\"req\":\"^0.6.0\"},{\"name\":\"tower-layer\",\"req\":\"^0.3.2\"},{\"name\":\"tower-service\",\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"tracing\",\"req\":\"^0.1\"},{\"features\":[\"json\"],\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3\"},{\"features\":[\"serde\",\"v4\"],\"kind\":\"dev\",\"name\":\"uuid\",\"req\":\"^1.0\"}],\"features\":{\"__private\":[\"tokio\",\"http1\",\"dep:reqwest\"],\"__private_docs\":[\"axum-core/__private_docs\",\"tower/full\",\"dep:serde\",\"dep:tower-http\"],\"default\":[\"form\",\"http1\",\"json\",\"matched-path\",\"original-uri\",\"query\",\"tokio\",\"tower-log\",\"tracing\"],\"form\":[\"dep:form_urlencoded\",\"dep:serde_urlencoded\",\"dep:serde_path_to_error\"],\"http1\":[\"dep:hyper\",\"hyper?/http1\",\"hyper-util?/http1\"],\"http2\":[\"dep:hyper\",\"hyper?/http2\",\"hyper-util?/http2\"],\"json\":[\"dep:serde_json\",\"dep:serde_path_to_error\"],\"macros\":[\"dep:axum-macros\"],\"matched-path\":[],\"multipart\":[\"dep:multer\"],\"original-uri\":[],\"query\":[\"dep:form_urlencoded\",\"dep:serde_urlencoded\",\"dep:serde_path_to_error\"],\"tokio\":[\"dep:hyper-util\",\"dep:tokio\",\"tokio/net\",\"tokio/rt\",\"tower/make\",\"tokio/macros\"],\"tower-log\":[\"tower/log\"],\"tracing\":[\"dep:tracing\",\"axum-core/tracing\"],\"ws\":[\"dep:hyper\",\"tokio\",\"dep:tokio-tungstenite\",\"dep:sha1\",\"dep:base64\"]}}", "backtrace_0.3.76": "{\"dependencies\":[{\"default_features\":false,\"name\":\"addr2line\",\"req\":\"^0.25.0\",\"target\":\"cfg(not(all(windows, target_env = \\\"msvc\\\", not(target_vendor = \\\"uwp\\\"))))\"},{\"name\":\"cfg-if\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"cpp_demangle\",\"optional\":true,\"req\":\"^0.5.0\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.156\",\"target\":\"cfg(not(all(windows, target_env = \\\"msvc\\\", not(target_vendor = \\\"uwp\\\"))))\"},{\"kind\":\"dev\",\"name\":\"libloading\",\"req\":\"^0.8\"},{\"default_features\":false,\"name\":\"miniz_oxide\",\"req\":\"^0.8\",\"target\":\"cfg(not(all(windows, target_env = \\\"msvc\\\", not(target_vendor = \\\"uwp\\\"))))\"},{\"default_features\":false,\"features\":[\"read_core\",\"elf\",\"macho\",\"pe\",\"xcoff\",\"unaligned\",\"archive\"],\"name\":\"object\",\"req\":\"^0.37.0\",\"target\":\"cfg(not(all(windows, target_env = \\\"msvc\\\", not(target_vendor = \\\"uwp\\\"))))\"},{\"name\":\"rustc-demangle\",\"req\":\"^0.1.24\"},{\"default_features\":false,\"name\":\"ruzstd\",\"optional\":true,\"req\":\"^0.8.1\",\"target\":\"cfg(not(all(windows, target_env = \\\"msvc\\\", not(target_vendor = \\\"uwp\\\"))))\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"windows-link\",\"req\":\"^0.2\",\"target\":\"cfg(any(windows, target_os = \\\"cygwin\\\"))\"}],\"features\":{\"coresymbolication\":[],\"dbghelp\":[],\"default\":[\"std\"],\"dl_iterate_phdr\":[],\"dladdr\":[],\"kernel32\":[],\"libunwind\":[],\"ruzstd\":[\"dep:ruzstd\"],\"serialize-serde\":[\"serde\"],\"std\":[],\"unix-backtrace\":[]}}", + "base16ct_0.2.0": "{\"dependencies\":[],\"features\":{\"alloc\":[],\"std\":[\"alloc\"]}}", "base64-simd_0.8.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"base64\",\"req\":\"^0.20.0\"},{\"kind\":\"dev\",\"name\":\"const-str\",\"req\":\"^0.5.3\"},{\"features\":[\"js\"],\"kind\":\"dev\",\"name\":\"getrandom\",\"req\":\"^0.2.8\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"outref\",\"req\":\"^0.5.0\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.5\"},{\"name\":\"vsimd\",\"req\":\"^0.8.0\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3.33\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"}],\"features\":{\"alloc\":[\"vsimd/alloc\"],\"default\":[\"std\",\"detect\"],\"detect\":[\"vsimd/detect\"],\"std\":[\"alloc\",\"vsimd/std\"],\"unstable\":[\"vsimd/unstable\"]}}", "base64_0.21.7": "{\"dependencies\":[{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^3.2.25\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4.0\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"^1\"},{\"features\":[\"small_rng\"],\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.5\"},{\"kind\":\"dev\",\"name\":\"rstest\",\"req\":\"^0.13.0\"},{\"kind\":\"dev\",\"name\":\"rstest_reuse\",\"req\":\"^0.6.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"strum\",\"req\":\"^0.25\"}],\"features\":{\"alloc\":[],\"default\":[\"std\"],\"std\":[\"alloc\"]}}", "base64_0.22.1": "{\"dependencies\":[{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^3.2.25\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4.0\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"^1\"},{\"features\":[\"small_rng\"],\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.5\"},{\"kind\":\"dev\",\"name\":\"rstest\",\"req\":\"^0.13.0\"},{\"kind\":\"dev\",\"name\":\"rstest_reuse\",\"req\":\"^0.6.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"strum\",\"req\":\"^0.25\"}],\"features\":{\"alloc\":[],\"default\":[\"std\"],\"std\":[\"alloc\"]}}", @@ -797,6 +799,7 @@ "crossbeam-utils_0.8.21": "{\"dependencies\":[{\"name\":\"loom\",\"optional\":true,\"req\":\"^0.7.1\",\"target\":\"cfg(crossbeam_loom)\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8\"}],\"features\":{\"default\":[\"std\"],\"nightly\":[],\"std\":[]}}", "crossterm_winapi_0.9.1": "{\"dependencies\":[{\"features\":[\"winbase\",\"consoleapi\",\"processenv\",\"handleapi\",\"synchapi\",\"impl-default\"],\"name\":\"winapi\",\"req\":\"^0.3.8\",\"target\":\"cfg(windows)\"}],\"features\":{}}", "crunchy_0.2.4": "{\"dependencies\":[],\"features\":{\"default\":[\"limit_128\"],\"limit_1024\":[],\"limit_128\":[],\"limit_2048\":[],\"limit_256\":[],\"limit_512\":[],\"limit_64\":[],\"std\":[]}}", + "crypto-bigint_0.5.5": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1\"},{\"features\":[\"html_reports\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5\"},{\"default_features\":false,\"name\":\"der\",\"optional\":true,\"req\":\"^0.7\"},{\"name\":\"generic-array\",\"optional\":true,\"req\":\"^0.14\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"num-bigint\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"num-integer\",\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"num-traits\",\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"rand_chacha\",\"req\":\"^0.3\"},{\"name\":\"rand_core\",\"optional\":true,\"req\":\"^0.6.4\"},{\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"rand_core\",\"req\":\"^0.6\"},{\"default_features\":false,\"name\":\"rlp\",\"optional\":true,\"req\":\"^0.5\"},{\"default_features\":false,\"name\":\"serdect\",\"optional\":true,\"req\":\"^0.2\"},{\"default_features\":false,\"name\":\"subtle\",\"req\":\"^2.4\"},{\"default_features\":false,\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"alloc\":[\"serdect?/alloc\"],\"default\":[\"rand\"],\"extra-sizes\":[],\"rand\":[\"rand_core/std\"],\"serde\":[\"dep:serdect\"]}}", "crypto-common_0.1.7": "{\"dependencies\":[{\"features\":[\"more_lengths\"],\"name\":\"generic-array\",\"req\":\"=0.14.7\"},{\"name\":\"rand_core\",\"optional\":true,\"req\":\"^0.6\"},{\"name\":\"typenum\",\"req\":\"^1.14\"}],\"features\":{\"getrandom\":[\"rand_core/getrandom\"],\"std\":[]}}", "crypto_box_0.9.1": "{\"dependencies\":[{\"default_features\":false,\"name\":\"aead\",\"req\":\"^0.5.2\"},{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"blake2\",\"optional\":true,\"req\":\"^0.10\"},{\"name\":\"chacha20\",\"optional\":true,\"req\":\"^0.9\"},{\"default_features\":false,\"name\":\"crypto_secretbox\",\"req\":\"^0.1.1\"},{\"default_features\":false,\"features\":[\"zeroize\"],\"name\":\"curve25519-dalek\",\"req\":\"^4\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8\"},{\"kind\":\"dev\",\"name\":\"rmp-serde\",\"req\":\"^1\"},{\"name\":\"salsa20\",\"optional\":true,\"req\":\"^0.10\"},{\"default_features\":false,\"name\":\"serdect\",\"optional\":true,\"req\":\"^0.2\"},{\"default_features\":false,\"name\":\"subtle\",\"req\":\"^2\"},{\"default_features\":false,\"name\":\"zeroize\",\"req\":\"^1\"}],\"features\":{\"alloc\":[\"aead/alloc\"],\"chacha20\":[\"dep:chacha20\",\"crypto_secretbox/chacha20\"],\"default\":[\"alloc\",\"getrandom\",\"salsa20\"],\"getrandom\":[\"aead/getrandom\",\"rand_core\"],\"heapless\":[\"aead/heapless\"],\"rand_core\":[\"aead/rand_core\"],\"salsa20\":[\"dep:salsa20\",\"crypto_secretbox/salsa20\"],\"seal\":[\"dep:blake2\",\"alloc\"],\"serde\":[\"dep:serdect\"],\"std\":[\"aead/std\"]}}", "crypto_secretbox_0.1.1": "{\"dependencies\":[{\"default_features\":false,\"name\":\"aead\",\"req\":\"^0.5\"},{\"features\":[\"zeroize\"],\"name\":\"chacha20\",\"optional\":true,\"req\":\"^0.9\"},{\"default_features\":false,\"name\":\"cipher\",\"req\":\"^0.4\"},{\"default_features\":false,\"features\":[\"zeroize\"],\"name\":\"generic-array\",\"req\":\"^0.14.7\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"name\":\"poly1305\",\"req\":\"^0.8\"},{\"features\":[\"zeroize\"],\"name\":\"salsa20\",\"optional\":true,\"req\":\"^0.10\"},{\"default_features\":false,\"name\":\"subtle\",\"req\":\"^2\"},{\"default_features\":false,\"name\":\"zeroize\",\"req\":\"^1\"}],\"features\":{\"alloc\":[\"aead/alloc\"],\"default\":[\"alloc\",\"getrandom\",\"salsa20\"],\"getrandom\":[\"aead/getrandom\",\"rand_core\"],\"heapless\":[\"aead/heapless\"],\"rand_core\":[\"aead/rand_core\"],\"std\":[\"aead/std\",\"alloc\"],\"stream\":[\"aead/stream\"]}}", @@ -870,9 +873,11 @@ "dylint_linting_5.0.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"assert_cmd\",\"req\":\"^2.0\"},{\"name\":\"cargo_metadata\",\"req\":\"^0.23\"},{\"features\":[\"config\"],\"name\":\"dylint_internal\",\"req\":\"=5.0.0\"},{\"name\":\"paste\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"rustc_version\",\"req\":\"^0.4\"},{\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.23\"},{\"name\":\"thiserror\",\"req\":\"^2.0\"},{\"name\":\"toml\",\"req\":\"^0.9\"},{\"kind\":\"build\",\"name\":\"toml\",\"req\":\"^0.9\"}],\"features\":{\"constituent\":[]}}", "dylint_testing_5.0.0": "{\"dependencies\":[{\"name\":\"anyhow\",\"req\":\"^1.0\"},{\"name\":\"cargo_metadata\",\"req\":\"^0.23\"},{\"name\":\"compiletest_rs\",\"req\":\"^0.11\"},{\"name\":\"dylint\",\"req\":\"=5.0.0\"},{\"name\":\"dylint_internal\",\"req\":\"=5.0.0\"},{\"name\":\"env_logger\",\"req\":\"^0.11\"},{\"name\":\"once_cell\",\"req\":\"^1.21\"},{\"name\":\"regex\",\"req\":\"^1.11\"},{\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"tempfile\",\"req\":\"^3.23\"}],\"features\":{\"default\":[],\"deny_warnings\":[]}}", "dyn-clone_1.0.20": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"features\":[\"diff\"],\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.66\"}],\"features\":{}}", + "ecdsa_0.16.9": "{\"dependencies\":[{\"name\":\"der\",\"optional\":true,\"req\":\"^0.7\"},{\"default_features\":false,\"features\":[\"oid\"],\"name\":\"digest\",\"optional\":true,\"req\":\"^0.10.7\"},{\"default_features\":false,\"features\":[\"digest\",\"sec1\"],\"name\":\"elliptic-curve\",\"req\":\"^0.13.6\"},{\"default_features\":false,\"features\":[\"dev\"],\"kind\":\"dev\",\"name\":\"elliptic-curve\",\"req\":\"^0.13\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"name\":\"rfc6979\",\"optional\":true,\"req\":\"^0.4\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serdect\",\"optional\":true,\"req\":\"^0.2\"},{\"default_features\":false,\"features\":[\"oid\"],\"name\":\"sha2\",\"optional\":true,\"req\":\"^0.10\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"sha2\",\"req\":\"^0.10\"},{\"default_features\":false,\"features\":[\"rand_core\"],\"name\":\"signature\",\"req\":\"^2.0, <2.3\"},{\"default_features\":false,\"name\":\"spki\",\"optional\":true,\"req\":\"^0.7.2\"}],\"features\":{\"alloc\":[\"elliptic-curve/alloc\",\"signature/alloc\",\"spki/alloc\"],\"arithmetic\":[\"elliptic-curve/arithmetic\"],\"default\":[\"digest\"],\"dev\":[\"arithmetic\",\"digest\",\"elliptic-curve/dev\",\"hazmat\"],\"digest\":[\"dep:digest\",\"signature/digest\"],\"hazmat\":[],\"pem\":[\"elliptic-curve/pem\",\"pkcs8\"],\"pkcs8\":[\"digest\",\"elliptic-curve/pkcs8\",\"der\"],\"serde\":[\"elliptic-curve/serde\",\"serdect\"],\"signing\":[\"arithmetic\",\"digest\",\"hazmat\",\"rfc6979\"],\"std\":[\"alloc\",\"elliptic-curve/std\",\"signature/std\"],\"verifying\":[\"arithmetic\",\"digest\",\"hazmat\"]}}", "ed25519-dalek_2.2.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"blake2\",\"req\":\"^0.10\"},{\"features\":[\"html_reports\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5\"},{\"default_features\":false,\"features\":[\"digest\"],\"name\":\"curve25519-dalek\",\"req\":\"^4\"},{\"default_features\":false,\"features\":[\"digest\",\"rand_core\"],\"kind\":\"dev\",\"name\":\"curve25519-dalek\",\"req\":\"^4\"},{\"default_features\":false,\"name\":\"ed25519\",\"req\":\">=2.2, <2.3\"},{\"kind\":\"dev\",\"name\":\"hex\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"default_features\":false,\"name\":\"merlin\",\"optional\":true,\"req\":\"^3\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8\"},{\"default_features\":false,\"name\":\"rand_core\",\"optional\":true,\"req\":\"^0.6.4\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"rand_core\",\"req\":\"^0.6.4\"},{\"default_features\":false,\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"sha2\",\"req\":\"^0.10\"},{\"kind\":\"dev\",\"name\":\"sha3\",\"req\":\"^0.10\"},{\"default_features\":false,\"name\":\"signature\",\"optional\":true,\"req\":\">=2.0, <2.3\"},{\"default_features\":false,\"name\":\"subtle\",\"req\":\"^2.3.0\"},{\"kind\":\"dev\",\"name\":\"toml\",\"req\":\"^0.7\"},{\"default_features\":false,\"features\":[\"static_secrets\"],\"kind\":\"dev\",\"name\":\"x25519-dalek\",\"req\":\"^2\"},{\"default_features\":false,\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1.5\"}],\"features\":{\"alloc\":[\"curve25519-dalek/alloc\",\"ed25519/alloc\",\"serde?/alloc\",\"zeroize/alloc\"],\"asm\":[\"sha2/asm\"],\"batch\":[\"alloc\",\"merlin\",\"rand_core\"],\"default\":[\"fast\",\"std\",\"zeroize\"],\"digest\":[\"signature/digest\"],\"fast\":[\"curve25519-dalek/precomputed-tables\"],\"hazmat\":[],\"legacy_compatibility\":[\"curve25519-dalek/legacy_compatibility\"],\"pem\":[\"alloc\",\"ed25519/pem\",\"pkcs8\"],\"pkcs8\":[\"ed25519/pkcs8\"],\"rand_core\":[\"dep:rand_core\"],\"serde\":[\"dep:serde\",\"ed25519/serde\"],\"std\":[\"alloc\",\"ed25519/std\",\"serde?/std\",\"sha2/std\"],\"zeroize\":[\"dep:zeroize\",\"curve25519-dalek/zeroize\"]}}", "ed25519_2.2.3": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1\"},{\"features\":[\"rand_core\"],\"kind\":\"dev\",\"name\":\"ed25519-dalek\",\"req\":\"^2\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"name\":\"pkcs8\",\"optional\":true,\"req\":\"^0.10\"},{\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"rand_core\",\"req\":\"^0.6\"},{\"default_features\":false,\"features\":[\"signature\"],\"kind\":\"dev\",\"name\":\"ring-compat\",\"req\":\"^0.8\"},{\"default_features\":false,\"name\":\"serde\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"serde_bytes\",\"optional\":true,\"req\":\"^0.11\"},{\"default_features\":false,\"name\":\"signature\",\"req\":\"^2\"},{\"default_features\":false,\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"alloc\":[\"pkcs8?/alloc\"],\"default\":[\"std\"],\"pem\":[\"alloc\",\"pkcs8/pem\"],\"serde_bytes\":[\"serde\",\"dep:serde_bytes\"],\"std\":[\"pkcs8?/std\",\"signature/std\"]}}", "either_1.15.0": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"alloc\",\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.95\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.0\"}],\"features\":{\"default\":[\"std\"],\"std\":[],\"use_std\":[\"std\"]}}", + "elliptic-curve_0.13.8": "{\"dependencies\":[{\"name\":\"base16ct\",\"req\":\"^0.2\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"base64ct\",\"optional\":true,\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"rand_core\",\"generic-array\",\"zeroize\"],\"name\":\"crypto-bigint\",\"req\":\"^0.5\"},{\"name\":\"digest\",\"optional\":true,\"req\":\"^0.10\"},{\"default_features\":false,\"name\":\"ff\",\"optional\":true,\"req\":\"^0.13\"},{\"default_features\":false,\"features\":[\"zeroize\"],\"name\":\"generic-array\",\"req\":\"^0.14.6\"},{\"default_features\":false,\"name\":\"group\",\"optional\":true,\"req\":\"^0.13\"},{\"name\":\"hex-literal\",\"optional\":true,\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"default_features\":false,\"name\":\"hkdf\",\"optional\":true,\"req\":\"^0.12.1\"},{\"features\":[\"alloc\"],\"name\":\"pem-rfc7468\",\"optional\":true,\"req\":\"^0.7\"},{\"default_features\":false,\"name\":\"pkcs8\",\"optional\":true,\"req\":\"^0.10.2\"},{\"default_features\":false,\"name\":\"rand_core\",\"req\":\"^0.6.4\"},{\"features\":[\"subtle\",\"zeroize\"],\"name\":\"sec1\",\"optional\":true,\"req\":\"^0.7.1\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0.47\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serdect\",\"optional\":true,\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"sha2\",\"req\":\"^0.10\"},{\"kind\":\"dev\",\"name\":\"sha3\",\"req\":\"^0.10\"},{\"default_features\":false,\"name\":\"subtle\",\"req\":\"^2\"},{\"default_features\":false,\"name\":\"tap\",\"optional\":true,\"req\":\"^1.0.1\"},{\"default_features\":false,\"name\":\"zeroize\",\"req\":\"^1.7\"}],\"features\":{\"alloc\":[\"base16ct/alloc\",\"ff?/alloc\",\"group?/alloc\",\"pkcs8?/alloc\",\"sec1?/alloc\",\"zeroize/alloc\"],\"arithmetic\":[\"group\"],\"bits\":[\"arithmetic\",\"ff/bits\",\"dep:tap\"],\"default\":[\"arithmetic\"],\"dev\":[\"arithmetic\",\"dep:hex-literal\",\"pem\",\"pkcs8\"],\"ecdh\":[\"arithmetic\",\"digest\",\"dep:hkdf\"],\"group\":[\"dep:group\",\"ff\"],\"hash2curve\":[\"arithmetic\",\"digest\"],\"hazmat\":[],\"jwk\":[\"dep:base64ct\",\"dep:serde_json\",\"alloc\",\"serde\",\"zeroize/alloc\"],\"pem\":[\"dep:pem-rfc7468\",\"alloc\",\"arithmetic\",\"pkcs8\",\"sec1/pem\"],\"pkcs8\":[\"dep:pkcs8\",\"sec1\"],\"serde\":[\"dep:serdect\",\"alloc\",\"pkcs8\",\"sec1/serde\"],\"std\":[\"alloc\",\"rand_core/std\",\"pkcs8?/std\",\"sec1?/std\"],\"voprf\":[\"digest\"]}}", "ena_0.14.3": "{\"dependencies\":[{\"name\":\"dogged\",\"optional\":true,\"req\":\"^0.2.0\"},{\"name\":\"log\",\"req\":\"^0.4\"}],\"features\":{\"bench\":[],\"persistent\":[\"dogged\"]}}", "encode_unicode_1.0.0": "{\"dependencies\":[{\"default_features\":false,\"name\":\"ascii\",\"optional\":true,\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"lazy_static\",\"req\":\"^1.0\",\"target\":\"cfg(unix)\"},{\"features\":[\"https-native\"],\"kind\":\"dev\",\"name\":\"minreq\",\"req\":\"^2.6\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "encoding_rs_0.8.35": "{\"dependencies\":[{\"name\":\"any_all_workaround\",\"optional\":true,\"req\":\"^0.1.0\"},{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1.0\"},{\"name\":\"cfg-if\",\"req\":\"^1.0\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"}],\"features\":{\"alloc\":[],\"default\":[\"alloc\"],\"fast-big5-hanzi-encode\":[],\"fast-gb-hanzi-encode\":[],\"fast-hangul-encode\":[],\"fast-hanja-encode\":[],\"fast-kanji-encode\":[],\"fast-legacy-encode\":[\"fast-hangul-encode\",\"fast-hanja-encode\",\"fast-kanji-encode\",\"fast-gb-hanzi-encode\",\"fast-big5-hanzi-encode\"],\"less-slow-big5-hanzi-encode\":[],\"less-slow-gb-hanzi-encode\":[],\"less-slow-kanji-encode\":[],\"simd-accel\":[\"any_all_workaround\"]}}", @@ -903,6 +908,7 @@ "fax_derive_0.2.0": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1.0\"},{\"name\":\"quote\",\"req\":\"^1.0\"},{\"name\":\"syn\",\"req\":\"^2.0\"}],\"features\":{}}", "fd-lock_4.0.4": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1.0.0\"},{\"features\":[\"fs\"],\"name\":\"rustix\",\"req\":\"^1.0.0\",\"target\":\"cfg(unix)\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.0.8\"},{\"features\":[\"Win32_Foundation\",\"Win32_Storage_FileSystem\",\"Win32_System_IO\"],\"name\":\"windows-sys\",\"req\":\">=0.52.0, <0.60.0\",\"target\":\"cfg(windows)\"}],\"features\":{}}", "fdeflate_0.3.7": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"miniz_oxide\",\"req\":\"^0.7.1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.5\"},{\"name\":\"simd-adler32\",\"req\":\"^0.3.4\"}],\"features\":{}}", + "ff_0.13.1": "{\"dependencies\":[{\"default_features\":false,\"name\":\"bitvec\",\"optional\":true,\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"blake2b_simd\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"byteorder\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"ff_derive\",\"optional\":true,\"req\":\"^0.13.1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8\"},{\"default_features\":false,\"name\":\"rand_core\",\"req\":\"^0.6\"},{\"default_features\":false,\"features\":[\"i128\"],\"name\":\"subtle\",\"req\":\"^2.2.1\"}],\"features\":{\"alloc\":[],\"bits\":[\"bitvec\"],\"default\":[\"bits\",\"std\"],\"derive\":[\"byteorder\",\"ff_derive\"],\"derive_bits\":[\"bits\",\"ff_derive/bits\"],\"std\":[\"alloc\"]}}", "fiat-crypto_0.2.9": "{\"dependencies\":[],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "filedescriptor_0.8.3": "{\"dependencies\":[{\"name\":\"libc\",\"req\":\"^0.2\"},{\"name\":\"thiserror\",\"req\":\"^1.0\"},{\"features\":[\"winuser\",\"handleapi\",\"fileapi\",\"namedpipeapi\",\"processthreadsapi\",\"winsock2\",\"processenv\"],\"name\":\"winapi\",\"req\":\"^0.3\",\"target\":\"cfg(windows)\"}],\"features\":{}}", "filetime_0.2.27": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1.0.0\"},{\"name\":\"libc\",\"req\":\"^0.2.27\",\"target\":\"cfg(unix)\"},{\"name\":\"libredox\",\"req\":\"^0.1.0\",\"target\":\"cfg(target_os = \\\"redox\\\")\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{}}", @@ -1030,6 +1036,7 @@ "glob_0.3.3": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"tempdir\",\"req\":\"^0.3\"}],\"features\":{}}", "globset_0.4.18": "{\"dependencies\":[{\"name\":\"aho-corasick\",\"req\":\"^1.1.1\"},{\"features\":[\"derive\"],\"name\":\"arbitrary\",\"optional\":true,\"req\":\"^1.3.2\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"bstr\",\"req\":\"^1.6.2\"},{\"kind\":\"dev\",\"name\":\"glob\",\"req\":\"^0.3.1\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.20\"},{\"default_features\":false,\"features\":[\"std\",\"perf\",\"syntax\",\"meta\",\"nfa\",\"hybrid\"],\"name\":\"regex-automata\",\"req\":\"^0.4.0\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"regex-syntax\",\"req\":\"^0.8.0\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.188\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.107\"}],\"features\":{\"arbitrary\":[\"dep:arbitrary\"],\"default\":[\"log\"],\"serde1\":[\"serde\"],\"simd-accel\":[]}}", "gobject-sys_0.21.5": "{\"dependencies\":[{\"name\":\"glib-sys\",\"req\":\"^0.21\"},{\"name\":\"libc\",\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"shell-words\",\"req\":\"^1.0.0\"},{\"kind\":\"build\",\"name\":\"system-deps\",\"req\":\"^7\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{\"v2_58\":[],\"v2_62\":[\"v2_58\"],\"v2_66\":[\"v2_62\"],\"v2_68\":[\"v2_66\"],\"v2_70\":[\"v2_68\"],\"v2_72\":[\"v2_70\"],\"v2_74\":[\"v2_72\"],\"v2_76\":[\"v2_74\"],\"v2_78\":[\"v2_74\"],\"v2_80\":[\"v2_78\"],\"v2_82\":[\"v2_80\"],\"v2_84\":[\"v2_82\"],\"v2_86\":[\"v2_84\"]}}", + "group_0.13.0": "{\"dependencies\":[{\"default_features\":false,\"name\":\"ff\",\"req\":\"^0.13\"},{\"name\":\"memuse\",\"optional\":true,\"req\":\"^0.2\"},{\"default_features\":false,\"name\":\"rand\",\"optional\":true,\"req\":\"^0.8\"},{\"default_features\":false,\"name\":\"rand_core\",\"req\":\"^0.6\"},{\"name\":\"rand_xorshift\",\"optional\":true,\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"subtle\",\"req\":\"^2.2.1\"}],\"features\":{\"alloc\":[],\"default\":[\"alloc\"],\"tests\":[\"alloc\",\"rand\",\"rand_xorshift\"],\"wnaf-memuse\":[\"alloc\",\"memuse\"]}}", "gzip-header_1.0.0": "{\"dependencies\":[{\"name\":\"crc32fast\",\"req\":\"^1.2.1\"}],\"features\":{}}", "h2_0.4.13": "{\"dependencies\":[{\"name\":\"atomic-waker\",\"req\":\"^1.0.0\"},{\"name\":\"bytes\",\"req\":\"^1\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.10\"},{\"name\":\"fnv\",\"req\":\"^1.0.5\"},{\"default_features\":false,\"name\":\"futures-core\",\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"futures-sink\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"hex\",\"req\":\"^0.4.3\"},{\"name\":\"http\",\"req\":\"^1\"},{\"features\":[\"std\"],\"name\":\"indexmap\",\"req\":\"^2\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.3\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.4\"},{\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.0\"},{\"name\":\"slab\",\"req\":\"^0.4.2\"},{\"features\":[\"io-util\"],\"name\":\"tokio\",\"req\":\"^1\"},{\"features\":[\"rt-multi-thread\",\"macros\",\"sync\",\"net\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"tokio-rustls\",\"req\":\"^0.26\"},{\"features\":[\"codec\",\"io\"],\"name\":\"tokio-util\",\"req\":\"^0.7.1\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"req\":\"^0.1.35\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.3.2\"},{\"kind\":\"dev\",\"name\":\"webpki-roots\",\"req\":\"^1\"}],\"features\":{\"stream\":[],\"unstable\":[]}}", "h2_0.4.6": "{\"dependencies\":[{\"name\":\"atomic-waker\",\"req\":\"^1.0.0\"},{\"name\":\"bytes\",\"req\":\"^1\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.10\"},{\"name\":\"fnv\",\"req\":\"^1.0.5\"},{\"default_features\":false,\"name\":\"futures-core\",\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"futures-sink\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"hex\",\"req\":\"^0.4.3\"},{\"name\":\"http\",\"req\":\"^1\"},{\"features\":[\"std\"],\"name\":\"indexmap\",\"req\":\"^2\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.3\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.4\"},{\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.0\"},{\"name\":\"slab\",\"req\":\"^0.4.2\"},{\"features\":[\"io-util\"],\"name\":\"tokio\",\"req\":\"^1\"},{\"features\":[\"rt-multi-thread\",\"macros\",\"sync\",\"net\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"tokio-rustls\",\"req\":\"^0.26\"},{\"features\":[\"codec\",\"io\"],\"name\":\"tokio-util\",\"req\":\"^0.7.1\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"req\":\"^0.1.35\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.3.2\"},{\"kind\":\"dev\",\"name\":\"webpki-roots\",\"req\":\"^0.26\"}],\"features\":{\"stream\":[],\"unstable\":[]}}", @@ -1276,6 +1283,7 @@ "os_pipe_1.2.3": "{\"dependencies\":[{\"name\":\"libc\",\"req\":\"^0.2.62\",\"target\":\"cfg(not(windows))\"},{\"features\":[\"Win32_Foundation\",\"Win32_System_Pipes\",\"Win32_Security\"],\"name\":\"windows-sys\",\"req\":\">=0.28, <=0.61\",\"target\":\"cfg(windows)\"}],\"features\":{\"io_safety\":[]}}", "outref_0.5.2": "{\"dependencies\":[],\"features\":{}}", "owo-colors_4.3.0": "{\"dependencies\":[{\"name\":\"supports-color\",\"optional\":true,\"req\":\"^3.0.0\"},{\"name\":\"supports-color-2\",\"optional\":true,\"package\":\"supports-color\",\"req\":\"^2.0\"}],\"features\":{\"alloc\":[],\"supports-colors\":[\"dep:supports-color-2\",\"supports-color\"]}}", + "p256_0.13.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"blobby\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4\"},{\"default_features\":false,\"features\":[\"der\"],\"name\":\"ecdsa-core\",\"optional\":true,\"package\":\"ecdsa\",\"req\":\"^0.16\"},{\"default_features\":false,\"features\":[\"dev\"],\"kind\":\"dev\",\"name\":\"ecdsa-core\",\"package\":\"ecdsa\",\"req\":\"^0.16\"},{\"default_features\":false,\"features\":[\"hazmat\",\"sec1\"],\"name\":\"elliptic-curve\",\"req\":\"^0.13.1\"},{\"name\":\"hex-literal\",\"optional\":true,\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"name\":\"primeorder\",\"optional\":true,\"req\":\"^0.13\"},{\"features\":[\"dev\"],\"kind\":\"dev\",\"name\":\"primeorder\",\"req\":\"^0.13\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"features\":[\"getrandom\"],\"kind\":\"dev\",\"name\":\"rand_core\",\"req\":\"^0.6\"},{\"default_features\":false,\"name\":\"serdect\",\"optional\":true,\"req\":\"^0.2\"},{\"default_features\":false,\"name\":\"sha2\",\"optional\":true,\"req\":\"^0.10\"}],\"features\":{\"alloc\":[\"ecdsa-core?/alloc\",\"elliptic-curve/alloc\"],\"arithmetic\":[\"dep:primeorder\",\"elliptic-curve/arithmetic\"],\"bits\":[\"arithmetic\",\"elliptic-curve/bits\"],\"default\":[\"arithmetic\",\"ecdsa\",\"pem\",\"std\"],\"digest\":[\"ecdsa-core/digest\",\"ecdsa-core/hazmat\"],\"ecdh\":[\"arithmetic\",\"elliptic-curve/ecdh\"],\"ecdsa\":[\"arithmetic\",\"ecdsa-core/signing\",\"ecdsa-core/verifying\",\"sha256\"],\"expose-field\":[\"arithmetic\"],\"hash2curve\":[\"arithmetic\",\"elliptic-curve/hash2curve\"],\"jwk\":[\"elliptic-curve/jwk\"],\"pem\":[\"elliptic-curve/pem\",\"ecdsa-core/pem\",\"pkcs8\"],\"pkcs8\":[\"ecdsa-core?/pkcs8\",\"elliptic-curve/pkcs8\"],\"serde\":[\"ecdsa-core?/serde\",\"elliptic-curve/serde\",\"primeorder?/serde\",\"serdect\"],\"sha256\":[\"digest\",\"sha2\"],\"std\":[\"alloc\",\"ecdsa-core?/std\",\"elliptic-curve/std\"],\"test-vectors\":[\"dep:hex-literal\"],\"voprf\":[\"elliptic-curve/voprf\",\"sha2\"]}}", "parking_2.2.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"easy-parallel\",\"req\":\"^3.0.0\"},{\"name\":\"loom\",\"optional\":true,\"req\":\"^0.7\",\"target\":\"cfg(loom)\"}],\"features\":{}}", "parking_lot_0.12.5": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1.3.3\"},{\"name\":\"lock_api\",\"req\":\"^0.4.14\"},{\"name\":\"parking_lot_core\",\"req\":\"^0.9.12\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.3\"}],\"features\":{\"arc_lock\":[\"lock_api/arc_lock\"],\"deadlock_detection\":[\"parking_lot_core/deadlock_detection\"],\"default\":[],\"hardware-lock-elision\":[],\"nightly\":[\"parking_lot_core/nightly\",\"lock_api/nightly\"],\"owning_ref\":[\"lock_api/owning_ref\"],\"send_guard\":[],\"serde\":[\"lock_api/serde\"]}}", "parking_lot_core_0.9.12": "{\"dependencies\":[{\"name\":\"backtrace\",\"optional\":true,\"req\":\"^0.3.60\"},{\"name\":\"cfg-if\",\"req\":\"^1.0.0\"},{\"name\":\"libc\",\"req\":\"^0.2.95\",\"target\":\"cfg(unix)\"},{\"name\":\"petgraph\",\"optional\":true,\"req\":\"^0.6.0\"},{\"name\":\"redox_syscall\",\"req\":\"^0.5\",\"target\":\"cfg(target_os = \\\"redox\\\")\"},{\"name\":\"smallvec\",\"req\":\"^1.6.1\"},{\"name\":\"windows-link\",\"req\":\"^0.2.0\",\"target\":\"cfg(windows)\"}],\"features\":{\"deadlock_detection\":[\"petgraph\",\"backtrace\"],\"nightly\":[]}}", @@ -1325,6 +1333,7 @@ "predicates_3.1.3": "{\"dependencies\":[{\"name\":\"anstyle\",\"req\":\"^1.0.0\"},{\"name\":\"difflib\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"float-cmp\",\"optional\":true,\"req\":\"^0.10\"},{\"name\":\"normalize-line-endings\",\"optional\":true,\"req\":\"^0.3.0\"},{\"name\":\"predicates-core\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"predicates-tree\",\"req\":\"^1.0\"},{\"name\":\"regex\",\"optional\":true,\"req\":\"^1.0\"}],\"features\":{\"color\":[],\"default\":[\"diff\",\"regex\",\"float-cmp\",\"normalize-line-endings\",\"color\"],\"diff\":[\"dep:difflib\"],\"unstable\":[]}}", "pretty_assertions_1.4.1": "{\"dependencies\":[{\"name\":\"diff\",\"req\":\"^0.1.12\"},{\"name\":\"yansi\",\"req\":\"^1.0.1\"}],\"features\":{\"alloc\":[],\"default\":[\"std\"],\"std\":[],\"unstable\":[]}}", "prettyplease_0.2.37": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"indoc\",\"req\":\"^2\"},{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.80\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"proc-macro2\",\"req\":\"^1.0.80\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quote\",\"req\":\"^1.0.35\"},{\"default_features\":false,\"features\":[\"full\"],\"name\":\"syn\",\"req\":\"^2.0.105\"},{\"default_features\":false,\"features\":[\"clone-impls\",\"extra-traits\",\"parsing\",\"printing\",\"visit-mut\"],\"kind\":\"dev\",\"name\":\"syn\",\"req\":\"^2.0.105\"}],\"features\":{\"verbatim\":[\"syn/parsing\"]}}", + "primeorder_0.13.6": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"arithmetic\",\"sec1\"],\"name\":\"elliptic-curve\",\"req\":\"^0.13.7\"},{\"default_features\":false,\"name\":\"serdect\",\"optional\":true,\"req\":\"^0.2\"}],\"features\":{\"alloc\":[\"elliptic-curve/alloc\"],\"dev\":[],\"serde\":[\"elliptic-curve/serde\",\"serdect\"],\"std\":[\"alloc\",\"elliptic-curve/std\"]}}", "proc-macro-crate_3.4.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"proc-macro2\",\"req\":\"^1.0.94\"},{\"kind\":\"dev\",\"name\":\"quote\",\"req\":\"^1.0.39\"},{\"kind\":\"dev\",\"name\":\"syn\",\"req\":\"^2.0.99\"},{\"default_features\":false,\"features\":[\"parse\"],\"name\":\"toml_edit\",\"req\":\"^0.23.2\"}],\"features\":{}}", "proc-macro-error-attr2_2.0.0": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1\"},{\"name\":\"quote\",\"req\":\"^1\"}],\"features\":{}}", "proc-macro-error2_2.0.1": "{\"dependencies\":[{\"name\":\"proc-macro-error-attr2\",\"req\":\"=2.0.0\"},{\"name\":\"proc-macro2\",\"req\":\"^1\"},{\"name\":\"quote\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"syn\",\"optional\":true,\"req\":\"^2\"},{\"features\":[\"full\"],\"kind\":\"dev\",\"name\":\"syn\",\"req\":\"^2\"},{\"features\":[\"diff\"],\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.99\"}],\"features\":{\"default\":[\"syn-error\"],\"nightly\":[],\"syn-error\":[\"dep:syn\"]}}", @@ -1407,6 +1416,7 @@ "reqwest_0.12.28": "{\"dependencies\":[{\"name\":\"base64\",\"req\":\"^0.22\"},{\"kind\":\"dev\",\"name\":\"brotli_crate\",\"package\":\"brotli\",\"req\":\"^8\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"bytes\",\"req\":\"^1.2\"},{\"name\":\"cookie_crate\",\"optional\":true,\"package\":\"cookie\",\"req\":\"^0.18.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"cookie_store\",\"optional\":true,\"req\":\"^0.22.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"encoding_rs\",\"optional\":true,\"req\":\"^0.8\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.10\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"flate2\",\"req\":\"^1.0.13\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"futures-channel\",\"optional\":true,\"req\":\"^0.3\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"name\":\"futures-core\",\"req\":\"^0.3.28\"},{\"default_features\":false,\"name\":\"futures-util\",\"optional\":true,\"req\":\"^0.3.28\"},{\"default_features\":false,\"features\":[\"std\",\"alloc\"],\"kind\":\"dev\",\"name\":\"futures-util\",\"req\":\"^0.3.28\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"h2\",\"optional\":true,\"req\":\"^0.4\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"h3\",\"optional\":true,\"req\":\"^0.0.8\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"h3-quinn\",\"optional\":true,\"req\":\"^0.0.10\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"tokio\"],\"name\":\"hickory-resolver\",\"optional\":true,\"req\":\"^0.25\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"http\",\"req\":\"^1.1\"},{\"name\":\"http-body\",\"req\":\"^1\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"http-body-util\",\"req\":\"^0.1.2\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"http1\",\"client\"],\"name\":\"hyper\",\"req\":\"^1.1\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"http1\",\"http2\",\"client\",\"server\"],\"kind\":\"dev\",\"name\":\"hyper\",\"req\":\"^1.1.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"http1\",\"tls12\"],\"name\":\"hyper-rustls\",\"optional\":true,\"req\":\"^0.27.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"hyper-tls\",\"optional\":true,\"req\":\"^0.6\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"http1\",\"client\",\"client-legacy\",\"client-proxy\",\"tokio\"],\"name\":\"hyper-util\",\"req\":\"^0.1.12\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"http1\",\"http2\",\"client\",\"client-legacy\",\"server-auto\",\"server-graceful\",\"tokio\"],\"kind\":\"dev\",\"name\":\"hyper-util\",\"req\":\"^0.1.12\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"js-sys\",\"req\":\"^0.3.77\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0\"},{\"name\":\"log\",\"req\":\"^0.4.17\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"mime\",\"optional\":true,\"req\":\"^0.3.16\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"name\":\"mime_guess\",\"optional\":true,\"req\":\"^2.0\"},{\"name\":\"native-tls-crate\",\"optional\":true,\"package\":\"native-tls\",\"req\":\"^0.2.10\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"num_cpus\",\"req\":\"^1.0\"},{\"name\":\"once_cell\",\"optional\":true,\"req\":\"^1.18\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"percent-encoding\",\"req\":\"^2.3\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.11\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"rustls\",\"runtime-tokio\"],\"name\":\"quinn\",\"optional\":true,\"req\":\"^0.11.1\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"std\",\"tls12\"],\"name\":\"rustls\",\"optional\":true,\"req\":\"^0.23.4\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"rustls-native-certs\",\"optional\":true,\"req\":\"^0.8.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"std\"],\"name\":\"rustls-pki-types\",\"optional\":true,\"req\":\"^1.9.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"serde_json\",\"req\":\"^1.0\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"serde_urlencoded\",\"req\":\"^0.7.1\"},{\"features\":[\"futures\"],\"name\":\"sync_wrapper\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"net\",\"time\"],\"name\":\"tokio\",\"req\":\"^1.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"macros\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"tokio-native-tls\",\"optional\":true,\"req\":\"^0.3.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"tls12\"],\"name\":\"tokio-rustls\",\"optional\":true,\"req\":\"^0.26\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"io\"],\"name\":\"tokio-util\",\"optional\":true,\"req\":\"^0.7.9\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"retry\",\"timeout\",\"util\"],\"name\":\"tower\",\"req\":\"^0.5.2\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"limit\"],\"kind\":\"dev\",\"name\":\"tower\",\"req\":\"^0.5.2\"},{\"default_features\":false,\"features\":[\"follow-redirect\"],\"name\":\"tower-http\",\"req\":\"^0.6.8\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"tower-service\",\"req\":\"^0.3\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"url\",\"req\":\"^2.4\"},{\"name\":\"wasm-bindgen\",\"req\":\"^0.2.89\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"features\":[\"serde-serialize\"],\"kind\":\"dev\",\"name\":\"wasm-bindgen\",\"req\":\"^0.2.89\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"wasm-bindgen-futures\",\"req\":\"^0.4.18\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"wasm-streams\",\"optional\":true,\"req\":\"^0.4\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"features\":[\"AbortController\",\"AbortSignal\",\"Headers\",\"Request\",\"RequestInit\",\"RequestMode\",\"Response\",\"Window\",\"FormData\",\"Blob\",\"BlobPropertyBag\",\"ServiceWorkerGlobalScope\",\"RequestCredentials\",\"File\",\"ReadableStream\",\"RequestCache\"],\"name\":\"web-sys\",\"req\":\"^0.3.28\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"webpki-roots\",\"optional\":true,\"req\":\"^1\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"zstd_crate\",\"package\":\"zstd\",\"req\":\"^0.13\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"}],\"features\":{\"__rustls\":[\"dep:hyper-rustls\",\"dep:tokio-rustls\",\"dep:rustls\",\"__tls\"],\"__rustls-ring\":[\"hyper-rustls?/ring\",\"tokio-rustls?/ring\",\"rustls?/ring\",\"quinn?/ring\"],\"__tls\":[\"dep:rustls-pki-types\",\"tokio/io-util\"],\"blocking\":[\"dep:futures-channel\",\"futures-channel?/sink\",\"dep:futures-util\",\"futures-util?/io\",\"futures-util?/sink\",\"tokio/sync\"],\"brotli\":[\"tower-http/decompression-br\"],\"charset\":[\"dep:encoding_rs\",\"dep:mime\"],\"cookies\":[\"dep:cookie_crate\",\"dep:cookie_store\"],\"default\":[\"default-tls\",\"charset\",\"http2\",\"system-proxy\"],\"default-tls\":[\"dep:hyper-tls\",\"dep:native-tls-crate\",\"__tls\",\"dep:tokio-native-tls\"],\"deflate\":[\"tower-http/decompression-deflate\"],\"gzip\":[\"tower-http/decompression-gzip\"],\"hickory-dns\":[\"dep:hickory-resolver\",\"dep:once_cell\"],\"http2\":[\"h2\",\"hyper/http2\",\"hyper-util/http2\",\"hyper-rustls?/http2\"],\"http3\":[\"rustls-tls-manual-roots\",\"dep:h3\",\"dep:h3-quinn\",\"dep:quinn\",\"tokio/macros\"],\"json\":[\"dep:serde_json\"],\"macos-system-configuration\":[\"system-proxy\"],\"multipart\":[\"dep:mime_guess\",\"dep:futures-util\"],\"native-tls\":[\"default-tls\"],\"native-tls-alpn\":[\"native-tls\",\"native-tls-crate?/alpn\",\"hyper-tls?/alpn\"],\"native-tls-vendored\":[\"native-tls\",\"native-tls-crate?/vendored\"],\"rustls-tls\":[\"rustls-tls-webpki-roots\"],\"rustls-tls-manual-roots\":[\"rustls-tls-manual-roots-no-provider\",\"__rustls-ring\"],\"rustls-tls-manual-roots-no-provider\":[\"__rustls\"],\"rustls-tls-native-roots\":[\"rustls-tls-native-roots-no-provider\",\"__rustls-ring\"],\"rustls-tls-native-roots-no-provider\":[\"dep:rustls-native-certs\",\"hyper-rustls?/native-tokio\",\"__rustls\"],\"rustls-tls-no-provider\":[\"rustls-tls-manual-roots-no-provider\"],\"rustls-tls-webpki-roots\":[\"rustls-tls-webpki-roots-no-provider\",\"__rustls-ring\"],\"rustls-tls-webpki-roots-no-provider\":[\"dep:webpki-roots\",\"hyper-rustls?/webpki-tokio\",\"__rustls\"],\"socks\":[],\"stream\":[\"tokio/fs\",\"dep:futures-util\",\"dep:tokio-util\",\"dep:wasm-streams\"],\"system-proxy\":[\"hyper-util/client-proxy-system\"],\"trust-dns\":[],\"zstd\":[\"tower-http/decompression-zstd\"]}}", "resb_0.1.1": "{\"dependencies\":[{\"name\":\"indexmap\",\"optional\":true,\"req\":\"^2.0.0\"},{\"default_features\":false,\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.17\"},{\"name\":\"nom\",\"optional\":true,\"req\":\"^7.0.0\"},{\"default_features\":false,\"name\":\"potential_utf\",\"req\":\"^0.1.3\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde_core\",\"req\":\"^1.0.220\"}],\"features\":{\"default\":[],\"logging\":[\"dep:log\"],\"serialize\":[\"std\"],\"std\":[],\"text\":[\"dep:indexmap\",\"dep:nom\",\"std\"]}}", "resolv-conf_0.7.6": "{\"dependencies\":[],\"features\":{\"system\":[]}}", + "rfc6979_0.4.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.3\"},{\"default_features\":false,\"features\":[\"reset\"],\"name\":\"hmac\",\"req\":\"^0.12\"},{\"kind\":\"dev\",\"name\":\"sha2\",\"req\":\"^0.10\"},{\"default_features\":false,\"name\":\"subtle\",\"req\":\"^2\"}],\"features\":{}}", "ring_0.17.14": "{\"dependencies\":[{\"default_features\":false,\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.2.8\"},{\"default_features\":false,\"name\":\"cfg-if\",\"req\":\"^1.0.0\"},{\"name\":\"getrandom\",\"req\":\"^0.2.10\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.148\",\"target\":\"cfg(all(any(all(target_arch = \\\"aarch64\\\", target_endian = \\\"little\\\"), all(target_arch = \\\"arm\\\", target_endian = \\\"little\\\")), any(target_os = \\\"android\\\", target_os = \\\"linux\\\")))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.155\",\"target\":\"cfg(all(all(target_arch = \\\"aarch64\\\", target_endian = \\\"little\\\"), target_vendor = \\\"apple\\\", any(target_os = \\\"ios\\\", target_os = \\\"macos\\\", target_os = \\\"tvos\\\", target_os = \\\"visionos\\\", target_os = \\\"watchos\\\")))\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.148\",\"target\":\"cfg(any(unix, windows, target_os = \\\"wasi\\\"))\"},{\"name\":\"untrusted\",\"req\":\"^0.9\"},{\"default_features\":false,\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3.37\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", target_os = \\\"unknown\\\"))\"},{\"features\":[\"Win32_Foundation\",\"Win32_System_Threading\"],\"name\":\"windows-sys\",\"req\":\"^0.52\",\"target\":\"cfg(all(all(target_arch = \\\"aarch64\\\", target_endian = \\\"little\\\"), target_os = \\\"windows\\\"))\"}],\"features\":{\"alloc\":[],\"default\":[\"alloc\",\"dev_urandom_fallback\"],\"dev_urandom_fallback\":[],\"less-safe-getrandom-custom-or-rdrand\":[],\"less-safe-getrandom-espidf\":[],\"slow_tests\":[],\"std\":[\"alloc\"],\"test_logging\":[],\"unstable-testing-arm-no-hw\":[],\"unstable-testing-arm-no-neon\":[],\"wasm32_unknown_unknown_js\":[\"getrandom/js\"]}}", "rmcp-macros_0.15.0": "{\"dependencies\":[{\"name\":\"darling\",\"req\":\"^0.23\"},{\"name\":\"proc-macro2\",\"req\":\"^1\"},{\"name\":\"quote\",\"req\":\"^1\"},{\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"features\":[\"full\"],\"name\":\"syn\",\"req\":\"^2\"}],\"features\":{}}", "rmcp_0.15.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0\"},{\"name\":\"async-trait\",\"req\":\"^0.1.89\"},{\"kind\":\"dev\",\"name\":\"async-trait\",\"req\":\"^0.1\"},{\"name\":\"axum\",\"optional\":true,\"req\":\"^0.8\"},{\"name\":\"base64\",\"optional\":true,\"req\":\"^0.22\"},{\"name\":\"bytes\",\"optional\":true,\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"serde\",\"clock\",\"std\",\"oldtime\"],\"name\":\"chrono\",\"req\":\"^0.4.38\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", target_os = \\\"unknown\\\"))\"},{\"features\":[\"serde\"],\"name\":\"chrono\",\"req\":\"^0.4.38\",\"target\":\"cfg(not(all(target_family = \\\"wasm\\\", target_os = \\\"unknown\\\")))\"},{\"name\":\"futures\",\"req\":\"^0.3\"},{\"name\":\"http\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"http-body\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"http-body-util\",\"optional\":true,\"req\":\"^0.1\"},{\"default_features\":false,\"features\":[\"reqwest\"],\"name\":\"oauth2\",\"optional\":true,\"req\":\"^5.0\"},{\"name\":\"pastey\",\"optional\":true,\"req\":\"^0.2.0\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2\"},{\"features\":[\"tokio1\"],\"name\":\"process-wrap\",\"optional\":true,\"req\":\"^9.0\"},{\"name\":\"rand\",\"optional\":true,\"req\":\"^0.9\"},{\"default_features\":false,\"features\":[\"json\",\"stream\"],\"name\":\"reqwest\",\"optional\":true,\"req\":\"^0.12\"},{\"name\":\"rmcp-macros\",\"optional\":true,\"req\":\"^0.15.0\"},{\"features\":[\"chrono04\"],\"name\":\"schemars\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"chrono04\"],\"kind\":\"dev\",\"name\":\"schemars\",\"req\":\"^1.1.0\"},{\"features\":[\"derive\",\"rc\"],\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"sse-stream\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"thiserror\",\"req\":\"^2\"},{\"features\":[\"sync\",\"macros\",\"rt\",\"time\"],\"name\":\"tokio\",\"req\":\"^1\"},{\"features\":[\"full\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"name\":\"tokio-stream\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"tokio-util\",\"req\":\"^0.7\"},{\"name\":\"tower-service\",\"optional\":true,\"req\":\"^0.3\"},{\"name\":\"tracing\",\"req\":\"^0.1\"},{\"features\":[\"env-filter\",\"std\",\"fmt\"],\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3\"},{\"name\":\"url\",\"optional\":true,\"req\":\"^2.4\"},{\"features\":[\"v4\"],\"name\":\"uuid\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"__reqwest\":[\"dep:reqwest\"],\"auth\":[\"dep:oauth2\",\"__reqwest\",\"dep:url\"],\"client\":[\"dep:tokio-stream\"],\"client-side-sse\":[\"dep:sse-stream\",\"dep:http\"],\"default\":[\"base64\",\"macros\",\"server\"],\"elicitation\":[\"dep:url\"],\"macros\":[\"dep:rmcp-macros\",\"dep:pastey\"],\"reqwest\":[\"__reqwest\",\"reqwest?/rustls-tls\"],\"reqwest-native-tls\":[\"__reqwest\",\"reqwest?/native-tls\"],\"reqwest-tls-no-provider\":[\"__reqwest\",\"reqwest?/rustls-tls-no-provider\"],\"schemars\":[\"dep:schemars\"],\"server\":[\"transport-async-rw\",\"dep:schemars\",\"dep:pastey\"],\"server-side-http\":[\"uuid\",\"dep:rand\",\"dep:tokio-stream\",\"dep:http\",\"dep:http-body\",\"dep:http-body-util\",\"dep:bytes\",\"dep:sse-stream\",\"dep:axum\",\"tower\"],\"tower\":[\"dep:tower-service\"],\"transport-async-rw\":[\"tokio/io-util\",\"tokio-util/codec\"],\"transport-child-process\":[\"transport-async-rw\",\"tokio/process\",\"dep:process-wrap\"],\"transport-io\":[\"transport-async-rw\",\"tokio/io-std\"],\"transport-streamable-http-client\":[\"client-side-sse\",\"transport-worker\"],\"transport-streamable-http-client-reqwest\":[\"transport-streamable-http-client\",\"__reqwest\"],\"transport-streamable-http-server\":[\"transport-streamable-http-server-session\",\"server-side-http\",\"transport-worker\"],\"transport-streamable-http-server-session\":[\"transport-async-rw\",\"dep:tokio-stream\"],\"transport-worker\":[\"dep:tokio-stream\"]}}", @@ -1449,6 +1459,7 @@ "scratch_1.0.9": "{\"dependencies\":[],\"features\":{}}", "scrypt_0.11.0": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"rand_core\"],\"name\":\"password-hash\",\"optional\":true,\"req\":\"^0.5\"},{\"features\":[\"rand_core\"],\"kind\":\"dev\",\"name\":\"password-hash\",\"req\":\"^0.5\"},{\"name\":\"pbkdf2\",\"req\":\"^0.12\"},{\"default_features\":false,\"name\":\"salsa20\",\"req\":\"^0.10.2\"},{\"default_features\":false,\"name\":\"sha2\",\"req\":\"^0.10\"}],\"features\":{\"default\":[\"simple\",\"std\"],\"simple\":[\"password-hash\"],\"std\":[\"password-hash/std\"]}}", "sdd_3.0.10": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.6\"},{\"name\":\"loom\",\"optional\":true,\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1\"}],\"features\":{}}", + "sec1_0.7.3": "{\"dependencies\":[{\"default_features\":false,\"name\":\"base16ct\",\"optional\":true,\"req\":\"^0.2\"},{\"features\":[\"oid\"],\"name\":\"der\",\"optional\":true,\"req\":\"^0.7\"},{\"default_features\":false,\"name\":\"generic-array\",\"optional\":true,\"req\":\"^0.14.7\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"default_features\":false,\"name\":\"pkcs8\",\"optional\":true,\"req\":\"^0.10\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serdect\",\"optional\":true,\"req\":\"^0.2\"},{\"default_features\":false,\"name\":\"subtle\",\"optional\":true,\"req\":\"^2\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"},{\"default_features\":false,\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"alloc\":[\"der?/alloc\",\"pkcs8?/alloc\",\"zeroize?/alloc\"],\"default\":[\"der\",\"point\"],\"der\":[\"dep:der\",\"zeroize\"],\"pem\":[\"alloc\",\"der/pem\",\"pkcs8/pem\"],\"point\":[\"dep:base16ct\",\"dep:generic-array\"],\"serde\":[\"dep:serdect\"],\"std\":[\"alloc\",\"der?/std\"],\"zeroize\":[\"dep:zeroize\",\"der?/zeroize\"]}}", "seccompiler_0.5.0": "{\"dependencies\":[{\"name\":\"libc\",\"req\":\"^0.2.153\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.27\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0.9\"}],\"features\":{\"json\":[\"serde\",\"serde_json\"]}}", "secrecy_0.10.3": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"zeroize\",\"req\":\"^1.6\"}],\"features\":{}}", "secret-service_4.0.0": "{\"dependencies\":[{\"name\":\"aes\",\"optional\":true,\"req\":\"^0.8\"},{\"features\":[\"block-padding\",\"alloc\"],\"name\":\"cbc\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"futures-util\",\"req\":\"^0.3\"},{\"name\":\"generic-array\",\"req\":\"^0.14\"},{\"name\":\"hkdf\",\"optional\":true,\"req\":\"^0.12.0\"},{\"name\":\"num\",\"req\":\"^0.4.0\"},{\"name\":\"once_cell\",\"req\":\"^1\"},{\"name\":\"openssl\",\"optional\":true,\"req\":\"^0.10.40\"},{\"name\":\"rand\",\"req\":\"^0.8.1\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"req\":\"^1.0.103\"},{\"name\":\"sha2\",\"optional\":true,\"req\":\"^0.10.0\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"test-with\",\"req\":\"^0.8\"},{\"features\":[\"rt\",\"macros\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"zbus\",\"req\":\"^4\"}],\"features\":{\"crypto-openssl\":[\"dep:openssl\"],\"crypto-rust\":[\"dep:aes\",\"dep:cbc\",\"dep:sha2\",\"dep:hkdf\"],\"rt-async-io-crypto-openssl\":[\"zbus/async-io\",\"crypto-openssl\"],\"rt-async-io-crypto-rust\":[\"zbus/async-io\",\"crypto-rust\"],\"rt-tokio-crypto-openssl\":[\"zbus/tokio\",\"crypto-openssl\"],\"rt-tokio-crypto-rust\":[\"zbus/tokio\",\"crypto-rust\"]}}", diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index e2f54683ec..10b5cc2351 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -757,6 +757,7 @@ checksum = "96571e6996817bf3d58f6b569e4b9fd2e9d2fcf9f7424eed07b2ce9bb87535e5" dependencies = [ "aws-credential-types", "aws-runtime", + "aws-sdk-signin", "aws-sdk-sso", "aws-sdk-ssooidc", "aws-sdk-sts", @@ -767,15 +768,20 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", + "base64-simd", "bytes", "fastrand", "hex", "http 1.4.0", + "p256", + "rand 0.8.5", "ring", + "sha2", "time", "tokio", "tracing", "url", + "uuid", "zeroize", ] @@ -838,6 +844,28 @@ dependencies = [ "uuid", ] +[[package]] +name = "aws-sdk-signin" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c084bd63941916e1348cb8d9e05ac2e49bdd40a380e9167702683184c6c6be53" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "regex-lite", + "tracing", +] + [[package]] name = "aws-sdk-sso" version = "1.91.0" @@ -1180,6 +1208,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.21.7" @@ -4415,6 +4449,18 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -5128,6 +5174,20 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "ed25519" version = "2.2.3" @@ -5161,6 +5221,26 @@ dependencies = [ "serde", ] +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "ena" version = "0.14.3" @@ -5414,6 +5494,16 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -6808,6 +6898,17 @@ dependencies = [ "system-deps", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "gzip-header" version = "1.0.0" @@ -9307,6 +9408,18 @@ dependencies = [ "supports-color 3.0.2", ] +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "parking" version = "2.2.1" @@ -9736,6 +9849,15 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -10686,6 +10808,16 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.17.14" @@ -11145,6 +11277,20 @@ version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "seccompiler" version = "0.5.0" diff --git a/codex-rs/analytics/src/client.rs b/codex-rs/analytics/src/client.rs index 6d6d446560..6d46b2ce57 100644 --- a/codex-rs/analytics/src/client.rs +++ b/codex-rs/analytics/src/client.rs @@ -340,8 +340,9 @@ impl AnalyticsEventsClient { }); } - pub fn track_server_response(&self, response: ServerResponse) { + pub fn track_server_response(&self, completed_at_ms: u64, response: ServerResponse) { self.record_fact(AnalyticsFact::ServerResponse { + completed_at_ms, response: Box::new(response), }); } diff --git a/codex-rs/analytics/src/events.rs b/codex-rs/analytics/src/events.rs index 23afd83b75..eaa7daf8f8 100644 --- a/codex-rs/analytics/src/events.rs +++ b/codex-rs/analytics/src/events.rs @@ -18,6 +18,7 @@ use crate::facts::TurnStatus; use crate::facts::TurnSteerRejectionReason; use crate::facts::TurnSteerResult; use crate::facts::TurnSubmissionType; +use crate::now_unix_millis; use crate::now_unix_seconds; use codex_app_server_protocol::CodexErrorInfo; use codex_app_server_protocol::CommandExecutionSource; @@ -261,7 +262,7 @@ pub struct GuardianReviewTrackContext { approval_request_source: GuardianApprovalRequestSource, reviewed_action: GuardianReviewedAction, review_timeout_ms: u64, - started_at: u64, + pub started_at_ms: u64, started_instant: Instant, } @@ -283,7 +284,7 @@ impl GuardianReviewTrackContext { approval_request_source, reviewed_action, review_timeout_ms, - started_at: now_unix_seconds(), + started_at_ms: now_unix_millis(), started_instant: Instant::now(), } } @@ -316,7 +317,7 @@ impl GuardianReviewTrackContext { tool_call_count: None, time_to_first_token_ms: result.time_to_first_token_ms, completion_latency_ms: Some(self.started_instant.elapsed().as_millis() as u64), - started_at: self.started_at, + started_at: self.started_at_ms / 1_000, completed_at: Some(now_unix_seconds()), input_tokens: result.token_usage.as_ref().map(|usage| usage.input_tokens), cached_input_tokens: result diff --git a/codex-rs/analytics/src/facts.rs b/codex-rs/analytics/src/facts.rs index 861e6534a2..d0446e8c0c 100644 --- a/codex-rs/analytics/src/facts.rs +++ b/codex-rs/analytics/src/facts.rs @@ -296,6 +296,7 @@ pub(crate) enum AnalyticsFact { request: Box, }, ServerResponse { + completed_at_ms: u64, response: Box, }, Notification(Box), diff --git a/codex-rs/analytics/src/reducer.rs b/codex-rs/analytics/src/reducer.rs index d35fb96602..2ddb59c0cf 100644 --- a/codex-rs/analytics/src/reducer.rs +++ b/codex-rs/analytics/src/reducer.rs @@ -325,6 +325,7 @@ impl AnalyticsReducer { } => {} AnalyticsFact::ServerResponse { response: _response, + .. } => {} AnalyticsFact::Custom(input) => match input { CustomAnalyticsFact::SubAgentThreadStarted(input) => { diff --git a/codex-rs/app-server-protocol/schema/json/ClientRequest.json b/codex-rs/app-server-protocol/schema/json/ClientRequest.json index c60acbdf30..fe3738c887 100644 --- a/codex-rs/app-server-protocol/schema/json/ClientRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ClientRequest.json @@ -2091,8 +2091,18 @@ ], "type": "object" }, + "PluginShareUpdateDiscoverability": { + "enum": [ + "UNLISTED", + "PRIVATE" + ], + "type": "string" + }, "PluginShareUpdateTargetsParams": { "properties": { + "discoverability": { + "$ref": "#/definitions/PluginShareUpdateDiscoverability" + }, "remotePluginId": { "type": "string" }, @@ -2104,6 +2114,7 @@ } }, "required": [ + "discoverability", "remotePluginId", "shareTargets" ], @@ -3212,24 +3223,6 @@ ], "type": "object" }, - "SkillsListExtraRootsForCwd": { - "properties": { - "cwd": { - "type": "string" - }, - "extraUserRoots": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "cwd", - "extraUserRoots" - ], - "type": "object" - }, "SkillsListParams": { "properties": { "cwds": { @@ -3242,17 +3235,6 @@ "forceReload": { "description": "When true, bypass the skills cache and re-scan skills from disk.", "type": "boolean" - }, - "perCwdExtraUserRoots": { - "default": null, - "description": "Optional per-cwd extra roots to scan as user-scoped skills.", - "items": { - "$ref": "#/definitions/SkillsListExtraRootsForCwd" - }, - "type": [ - "array", - "null" - ] } }, "type": "object" @@ -6206,4 +6188,4 @@ } ], "title": "ClientRequest" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/CommandExecutionRequestApprovalParams.json b/codex-rs/app-server-protocol/schema/json/CommandExecutionRequestApprovalParams.json index ce587a7f10..5b6c4cd185 100644 --- a/codex-rs/app-server-protocol/schema/json/CommandExecutionRequestApprovalParams.json +++ b/codex-rs/app-server-protocol/schema/json/CommandExecutionRequestApprovalParams.json @@ -593,6 +593,11 @@ "null" ] }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this approval request started.", + "format": "int64", + "type": "integer" + }, "threadId": { "type": "string" }, @@ -602,6 +607,7 @@ }, "required": [ "itemId", + "startedAtMs", "threadId", "turnId" ], diff --git a/codex-rs/app-server-protocol/schema/json/FileChangeRequestApprovalParams.json b/codex-rs/app-server-protocol/schema/json/FileChangeRequestApprovalParams.json index f52e98cd0d..f17388aa53 100644 --- a/codex-rs/app-server-protocol/schema/json/FileChangeRequestApprovalParams.json +++ b/codex-rs/app-server-protocol/schema/json/FileChangeRequestApprovalParams.json @@ -18,6 +18,11 @@ "null" ] }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this approval request started.", + "format": "int64", + "type": "integer" + }, "threadId": { "type": "string" }, @@ -27,6 +32,7 @@ }, "required": [ "itemId", + "startedAtMs", "threadId", "turnId" ], diff --git a/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalParams.json b/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalParams.json index adb50dee43..1383da6124 100644 --- a/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalParams.json +++ b/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalParams.json @@ -297,6 +297,11 @@ "null" ] }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this approval request started.", + "format": "int64", + "type": "integer" + }, "threadId": { "type": "string" }, @@ -308,6 +313,7 @@ "cwd", "itemId", "permissions", + "startedAtMs", "threadId", "turnId" ], diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json index 5dc3c09a44..4e9e63d302 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json +++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json @@ -1963,6 +1963,11 @@ "action": { "$ref": "#/definitions/GuardianApprovalReviewAction" }, + "completedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review completed.", + "format": "int64", + "type": "integer" + }, "decisionSource": { "$ref": "#/definitions/AutoReviewDecisionSource" }, @@ -1973,6 +1978,11 @@ "description": "Stable identifier for this review.", "type": "string" }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review started.", + "format": "int64", + "type": "integer" + }, "targetItemId": { "description": "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", "type": [ @@ -1989,9 +1999,11 @@ }, "required": [ "action", + "completedAtMs", "decisionSource", "review", "reviewId", + "startedAtMs", "threadId", "turnId" ], @@ -2010,6 +2022,11 @@ "description": "Stable identifier for this review.", "type": "string" }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review started.", + "format": "int64", + "type": "integer" + }, "targetItemId": { "description": "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", "type": [ @@ -2028,6 +2045,7 @@ "action", "review", "reviewId", + "startedAtMs", "threadId", "turnId" ], diff --git a/codex-rs/app-server-protocol/schema/json/ServerRequest.json b/codex-rs/app-server-protocol/schema/json/ServerRequest.json index 51cab50810..9844eac0b8 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ServerRequest.json @@ -417,6 +417,11 @@ "null" ] }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this approval request started.", + "format": "int64", + "type": "integer" + }, "threadId": { "type": "string" }, @@ -426,6 +431,7 @@ }, "required": [ "itemId", + "startedAtMs", "threadId", "turnId" ], @@ -598,6 +604,11 @@ "null" ] }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this approval request started.", + "format": "int64", + "type": "integer" + }, "threadId": { "type": "string" }, @@ -607,6 +618,7 @@ }, "required": [ "itemId", + "startedAtMs", "threadId", "turnId" ], @@ -1587,6 +1599,11 @@ "null" ] }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this approval request started.", + "format": "int64", + "type": "integer" + }, "threadId": { "type": "string" }, @@ -1598,6 +1615,7 @@ "cwd", "itemId", "permissions", + "startedAtMs", "threadId", "turnId" ], diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 5e24845729..156f6ddc4a 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -2146,6 +2146,11 @@ "null" ] }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this approval request started.", + "format": "int64", + "type": "integer" + }, "threadId": { "type": "string" }, @@ -2155,6 +2160,7 @@ }, "required": [ "itemId", + "startedAtMs", "threadId", "turnId" ], @@ -2411,6 +2417,11 @@ "null" ] }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this approval request started.", + "format": "int64", + "type": "integer" + }, "threadId": { "type": "string" }, @@ -2420,6 +2431,7 @@ }, "required": [ "itemId", + "startedAtMs", "threadId", "turnId" ], @@ -3591,6 +3603,11 @@ "null" ] }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this approval request started.", + "format": "int64", + "type": "integer" + }, "threadId": { "type": "string" }, @@ -3602,6 +3619,7 @@ "cwd", "itemId", "permissions", + "startedAtMs", "threadId", "turnId" ], @@ -9878,6 +9896,11 @@ "action": { "$ref": "#/definitions/v2/GuardianApprovalReviewAction" }, + "completedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review completed.", + "format": "int64", + "type": "integer" + }, "decisionSource": { "$ref": "#/definitions/v2/AutoReviewDecisionSource" }, @@ -9888,6 +9911,11 @@ "description": "Stable identifier for this review.", "type": "string" }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review started.", + "format": "int64", + "type": "integer" + }, "targetItemId": { "description": "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", "type": [ @@ -9904,9 +9932,11 @@ }, "required": [ "action", + "completedAtMs", "decisionSource", "review", "reviewId", + "startedAtMs", "threadId", "turnId" ], @@ -9927,6 +9957,11 @@ "description": "Stable identifier for this review.", "type": "string" }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review started.", + "format": "int64", + "type": "integer" + }, "targetItemId": { "description": "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", "type": [ @@ -9945,6 +9980,7 @@ "action", "review", "reviewId", + "startedAtMs", "threadId", "turnId" ], @@ -12378,9 +12414,19 @@ ], "type": "object" }, + "PluginShareUpdateDiscoverability": { + "enum": [ + "UNLISTED", + "PRIVATE" + ], + "type": "string" + }, "PluginShareUpdateTargetsParams": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { + "discoverability": { + "$ref": "#/definitions/v2/PluginShareUpdateDiscoverability" + }, "remotePluginId": { "type": "string" }, @@ -12392,6 +12438,7 @@ } }, "required": [ + "discoverability", "remotePluginId", "shareTargets" ], @@ -12401,6 +12448,9 @@ "PluginShareUpdateTargetsResponse": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { + "discoverability": { + "$ref": "#/definitions/v2/PluginShareDiscoverability" + }, "principals": { "items": { "$ref": "#/definitions/v2/PluginSharePrincipal" @@ -12409,6 +12459,7 @@ } }, "required": [ + "discoverability", "principals" ], "title": "PluginShareUpdateTargetsResponse", @@ -14730,24 +14781,6 @@ ], "type": "object" }, - "SkillsListExtraRootsForCwd": { - "properties": { - "cwd": { - "type": "string" - }, - "extraUserRoots": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "cwd", - "extraUserRoots" - ], - "type": "object" - }, "SkillsListParams": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { @@ -14761,17 +14794,6 @@ "forceReload": { "description": "When true, bypass the skills cache and re-scan skills from disk.", "type": "boolean" - }, - "perCwdExtraUserRoots": { - "default": null, - "description": "Optional per-cwd extra roots to scan as user-scoped skills.", - "items": { - "$ref": "#/definitions/v2/SkillsListExtraRootsForCwd" - }, - "type": [ - "array", - "null" - ] } }, "title": "SkillsListParams", @@ -18389,4 +18411,4 @@ }, "title": "CodexAppServerProtocol", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index 6153a54eb9..3c5eb030c5 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -6489,6 +6489,11 @@ "action": { "$ref": "#/definitions/GuardianApprovalReviewAction" }, + "completedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review completed.", + "format": "int64", + "type": "integer" + }, "decisionSource": { "$ref": "#/definitions/AutoReviewDecisionSource" }, @@ -6499,6 +6504,11 @@ "description": "Stable identifier for this review.", "type": "string" }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review started.", + "format": "int64", + "type": "integer" + }, "targetItemId": { "description": "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", "type": [ @@ -6515,9 +6525,11 @@ }, "required": [ "action", + "completedAtMs", "decisionSource", "review", "reviewId", + "startedAtMs", "threadId", "turnId" ], @@ -6538,6 +6550,11 @@ "description": "Stable identifier for this review.", "type": "string" }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review started.", + "format": "int64", + "type": "integer" + }, "targetItemId": { "description": "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", "type": [ @@ -6556,6 +6573,7 @@ "action", "review", "reviewId", + "startedAtMs", "threadId", "turnId" ], @@ -8989,9 +9007,19 @@ ], "type": "object" }, + "PluginShareUpdateDiscoverability": { + "enum": [ + "UNLISTED", + "PRIVATE" + ], + "type": "string" + }, "PluginShareUpdateTargetsParams": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { + "discoverability": { + "$ref": "#/definitions/PluginShareUpdateDiscoverability" + }, "remotePluginId": { "type": "string" }, @@ -9003,6 +9031,7 @@ } }, "required": [ + "discoverability", "remotePluginId", "shareTargets" ], @@ -9012,6 +9041,9 @@ "PluginShareUpdateTargetsResponse": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { + "discoverability": { + "$ref": "#/definitions/PluginShareDiscoverability" + }, "principals": { "items": { "$ref": "#/definitions/PluginSharePrincipal" @@ -9020,6 +9052,7 @@ } }, "required": [ + "discoverability", "principals" ], "title": "PluginShareUpdateTargetsResponse", @@ -12616,24 +12649,6 @@ ], "type": "object" }, - "SkillsListExtraRootsForCwd": { - "properties": { - "cwd": { - "type": "string" - }, - "extraUserRoots": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "cwd", - "extraUserRoots" - ], - "type": "object" - }, "SkillsListParams": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { @@ -12647,17 +12662,6 @@ "forceReload": { "description": "When true, bypass the skills cache and re-scan skills from disk.", "type": "boolean" - }, - "perCwdExtraUserRoots": { - "default": null, - "description": "Optional per-cwd extra roots to scan as user-scoped skills.", - "items": { - "$ref": "#/definitions/SkillsListExtraRootsForCwd" - }, - "type": [ - "array", - "null" - ] } }, "title": "SkillsListParams", @@ -16274,4 +16278,4 @@ }, "title": "CodexAppServerProtocolV2", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewCompletedNotification.json index 98f44e50a2..991d4de050 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewCompletedNotification.json @@ -574,6 +574,11 @@ "action": { "$ref": "#/definitions/GuardianApprovalReviewAction" }, + "completedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review completed.", + "format": "int64", + "type": "integer" + }, "decisionSource": { "$ref": "#/definitions/AutoReviewDecisionSource" }, @@ -584,6 +589,11 @@ "description": "Stable identifier for this review.", "type": "string" }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review started.", + "format": "int64", + "type": "integer" + }, "targetItemId": { "description": "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", "type": [ @@ -600,9 +610,11 @@ }, "required": [ "action", + "completedAtMs", "decisionSource", "review", "reviewId", + "startedAtMs", "threadId", "turnId" ], diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewStartedNotification.json index 16e47c2d72..75ffeb753a 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewStartedNotification.json @@ -574,6 +574,11 @@ "description": "Stable identifier for this review.", "type": "string" }, + "startedAtMs": { + "description": "Unix timestamp (in milliseconds) when this review started.", + "format": "int64", + "type": "integer" + }, "targetItemId": { "description": "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", "type": [ @@ -592,6 +597,7 @@ "action", "review", "reviewId", + "startedAtMs", "threadId", "turnId" ], diff --git a/codex-rs/app-server-protocol/schema/json/v2/PluginShareUpdateTargetsParams.json b/codex-rs/app-server-protocol/schema/json/v2/PluginShareUpdateTargetsParams.json index 080ec980a1..f6b44c92eb 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/PluginShareUpdateTargetsParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/PluginShareUpdateTargetsParams.json @@ -23,9 +23,19 @@ "principalType" ], "type": "object" + }, + "PluginShareUpdateDiscoverability": { + "enum": [ + "UNLISTED", + "PRIVATE" + ], + "type": "string" } }, "properties": { + "discoverability": { + "$ref": "#/definitions/PluginShareUpdateDiscoverability" + }, "remotePluginId": { "type": "string" }, @@ -37,6 +47,7 @@ } }, "required": [ + "discoverability", "remotePluginId", "shareTargets" ], diff --git a/codex-rs/app-server-protocol/schema/json/v2/PluginShareUpdateTargetsResponse.json b/codex-rs/app-server-protocol/schema/json/v2/PluginShareUpdateTargetsResponse.json index 28fcb665ba..fe47f1f4af 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/PluginShareUpdateTargetsResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/PluginShareUpdateTargetsResponse.json @@ -1,6 +1,14 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { + "PluginShareDiscoverability": { + "enum": [ + "LISTED", + "UNLISTED", + "PRIVATE" + ], + "type": "string" + }, "PluginSharePrincipal": { "properties": { "name": { @@ -30,6 +38,9 @@ } }, "properties": { + "discoverability": { + "$ref": "#/definitions/PluginShareDiscoverability" + }, "principals": { "items": { "$ref": "#/definitions/PluginSharePrincipal" @@ -38,6 +49,7 @@ } }, "required": [ + "discoverability", "principals" ], "title": "PluginShareUpdateTargetsResponse", diff --git a/codex-rs/app-server-protocol/schema/json/v2/SkillsListParams.json b/codex-rs/app-server-protocol/schema/json/v2/SkillsListParams.json index 77d12e9175..a9a8a9ef8d 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/SkillsListParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/SkillsListParams.json @@ -1,25 +1,5 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "definitions": { - "SkillsListExtraRootsForCwd": { - "properties": { - "cwd": { - "type": "string" - }, - "extraUserRoots": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "cwd", - "extraUserRoots" - ], - "type": "object" - } - }, "properties": { "cwds": { "description": "When empty, defaults to the current session working directory.", @@ -31,17 +11,6 @@ "forceReload": { "description": "When true, bypass the skills cache and re-scan skills from disk.", "type": "boolean" - }, - "perCwdExtraUserRoots": { - "default": null, - "description": "Optional per-cwd extra roots to scan as user-scoped skills.", - "items": { - "$ref": "#/definitions/SkillsListExtraRootsForCwd" - }, - "type": [ - "array", - "null" - ] } }, "title": "SkillsListParams", diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/CommandExecutionRequestApprovalParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/CommandExecutionRequestApprovalParams.ts index ca2d0b0aa0..0e9100836a 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/CommandExecutionRequestApprovalParams.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/CommandExecutionRequestApprovalParams.ts @@ -8,6 +8,9 @@ import type { NetworkApprovalContext } from "./NetworkApprovalContext"; import type { NetworkPolicyAmendment } from "./NetworkPolicyAmendment"; export type CommandExecutionRequestApprovalParams = {threadId: string, turnId: string, itemId: string, /** + * Unix timestamp (in milliseconds) when this approval request started. + */ +startedAtMs: number, /** * Unique identifier for this specific approval callback. * * For regular shell/unified_exec approvals, this is null. diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/FileChangeRequestApprovalParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/FileChangeRequestApprovalParams.ts index c514ed6219..2db7be9ec4 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/FileChangeRequestApprovalParams.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/FileChangeRequestApprovalParams.ts @@ -3,6 +3,10 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. export type FileChangeRequestApprovalParams = { threadId: string, turnId: string, itemId: string, +/** + * Unix timestamp (in milliseconds) when this approval request started. + */ +startedAtMs: number, /** * Optional explanatory reason (e.g. request for extra write access). */ diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ItemGuardianApprovalReviewCompletedNotification.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ItemGuardianApprovalReviewCompletedNotification.ts index 5b162cf4b9..32d12be608 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ItemGuardianApprovalReviewCompletedNotification.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ItemGuardianApprovalReviewCompletedNotification.ts @@ -10,6 +10,14 @@ import type { GuardianApprovalReviewAction } from "./GuardianApprovalReviewActio * shape is expected to change soon. */ export type ItemGuardianApprovalReviewCompletedNotification = { threadId: string, turnId: string, +/** + * Unix timestamp (in milliseconds) when this review started. + */ +startedAtMs: number, +/** + * Unix timestamp (in milliseconds) when this review completed. + */ +completedAtMs: number, /** * Stable identifier for this review. */ diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ItemGuardianApprovalReviewStartedNotification.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ItemGuardianApprovalReviewStartedNotification.ts index 81ba2cdebf..92d34fdebc 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ItemGuardianApprovalReviewStartedNotification.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ItemGuardianApprovalReviewStartedNotification.ts @@ -9,6 +9,10 @@ import type { GuardianApprovalReviewAction } from "./GuardianApprovalReviewActio * shape is expected to change soon. */ export type ItemGuardianApprovalReviewStartedNotification = { threadId: string, turnId: string, +/** + * Unix timestamp (in milliseconds) when this review started. + */ +startedAtMs: number, /** * Stable identifier for this review. */ diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PermissionsRequestApprovalParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PermissionsRequestApprovalParams.ts index 308670a809..509f60923b 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/PermissionsRequestApprovalParams.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PermissionsRequestApprovalParams.ts @@ -4,4 +4,8 @@ import type { AbsolutePathBuf } from "../AbsolutePathBuf"; import type { RequestPermissionProfile } from "./RequestPermissionProfile"; -export type PermissionsRequestApprovalParams = { threadId: string, turnId: string, itemId: string, cwd: AbsolutePathBuf, reason: string | null, permissions: RequestPermissionProfile, }; +export type PermissionsRequestApprovalParams = { threadId: string, turnId: string, itemId: string, +/** + * Unix timestamp (in milliseconds) when this approval request started. + */ +startedAtMs: number, cwd: AbsolutePathBuf, reason: string | null, permissions: RequestPermissionProfile, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/SkillsListExtraRootsForCwd.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateDiscoverability.ts similarity index 62% rename from codex-rs/app-server-protocol/schema/typescript/v2/SkillsListExtraRootsForCwd.ts rename to codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateDiscoverability.ts index c18cd4ba1d..fd601987af 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/SkillsListExtraRootsForCwd.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateDiscoverability.ts @@ -2,4 +2,4 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type SkillsListExtraRootsForCwd = { cwd: string, extraUserRoots: Array, }; +export type PluginShareUpdateDiscoverability = "UNLISTED" | "PRIVATE"; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateTargetsParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateTargetsParams.ts index 53ef2b3025..eecd4be82b 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateTargetsParams.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateTargetsParams.ts @@ -2,5 +2,6 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { PluginShareTarget } from "./PluginShareTarget"; +import type { PluginShareUpdateDiscoverability } from "./PluginShareUpdateDiscoverability"; -export type PluginShareUpdateTargetsParams = { remotePluginId: string, shareTargets: Array, }; +export type PluginShareUpdateTargetsParams = { remotePluginId: string, discoverability: PluginShareUpdateDiscoverability, shareTargets: Array, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateTargetsResponse.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateTargetsResponse.ts index 3d6f6e9ee0..0ce722460f 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateTargetsResponse.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareUpdateTargetsResponse.ts @@ -1,6 +1,7 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PluginShareDiscoverability } from "./PluginShareDiscoverability"; import type { PluginSharePrincipal } from "./PluginSharePrincipal"; -export type PluginShareUpdateTargetsResponse = { principals: Array, }; +export type PluginShareUpdateTargetsResponse = { principals: Array, discoverability: PluginShareDiscoverability, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/SkillsListParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/SkillsListParams.ts index ad714a3297..4adeb38b3b 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/SkillsListParams.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/SkillsListParams.ts @@ -1,7 +1,6 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { SkillsListExtraRootsForCwd } from "./SkillsListExtraRootsForCwd"; export type SkillsListParams = { /** @@ -11,8 +10,4 @@ cwds?: Array, /** * When true, bypass the skills cache and re-scan skills from disk. */ -forceReload?: boolean, -/** - * Optional per-cwd extra roots to scan as user-scoped skills. - */ -perCwdExtraUserRoots?: Array | null, }; +forceReload?: boolean, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts index 950dd9839a..3cd919cb9f 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts @@ -287,6 +287,7 @@ export type { PluginSharePrincipalType } from "./PluginSharePrincipalType"; export type { PluginShareSaveParams } from "./PluginShareSaveParams"; export type { PluginShareSaveResponse } from "./PluginShareSaveResponse"; export type { PluginShareTarget } from "./PluginShareTarget"; +export type { PluginShareUpdateDiscoverability } from "./PluginShareUpdateDiscoverability"; export type { PluginShareUpdateTargetsParams } from "./PluginShareUpdateTargetsParams"; export type { PluginShareUpdateTargetsResponse } from "./PluginShareUpdateTargetsResponse"; export type { PluginSkillReadParams } from "./PluginSkillReadParams"; @@ -336,7 +337,6 @@ export type { SkillsChangedNotification } from "./SkillsChangedNotification"; export type { SkillsConfigWriteParams } from "./SkillsConfigWriteParams"; export type { SkillsConfigWriteResponse } from "./SkillsConfigWriteResponse"; export type { SkillsListEntry } from "./SkillsListEntry"; -export type { SkillsListExtraRootsForCwd } from "./SkillsListExtraRootsForCwd"; export type { SkillsListParams } from "./SkillsListParams"; export type { SkillsListResponse } from "./SkillsListResponse"; export type { SortDirection } from "./SortDirection"; diff --git a/codex-rs/app-server-protocol/src/protocol/common.rs b/codex-rs/app-server-protocol/src/protocol/common.rs index e72e3c14c7..87716e0c9a 100644 --- a/codex-rs/app-server-protocol/src/protocol/common.rs +++ b/codex-rs/app-server-protocol/src/protocol/common.rs @@ -1656,7 +1656,6 @@ mod tests { params: v2::SkillsListParams { cwds: Vec::new(), force_reload: false, - per_cwd_extra_user_roots: None, }, }; assert_eq!( @@ -2967,6 +2966,7 @@ mod tests { thread_id: "thr_123".to_string(), turn_id: "turn_123".to_string(), item_id: "call_123".to_string(), + started_at_ms: 0, approval_id: None, reason: None, network_approval_context: None, diff --git a/codex-rs/app-server-protocol/src/protocol/item_builders.rs b/codex-rs/app-server-protocol/src/protocol/item_builders.rs index 69ba331ce6..17e0f9aef4 100644 --- a/codex-rs/app-server-protocol/src/protocol/item_builders.rs +++ b/codex-rs/app-server-protocol/src/protocol/item_builders.rs @@ -243,6 +243,7 @@ pub fn guardian_auto_approval_review_notification( thread_id: conversation_id.to_string(), turn_id, review_id: assessment.id.clone(), + started_at_ms: assessment.started_at_ms, target_item_id: assessment.target_item_id.clone(), review, action, @@ -258,6 +259,10 @@ pub fn guardian_auto_approval_review_notification( thread_id: conversation_id.to_string(), turn_id, review_id: assessment.id.clone(), + started_at_ms: assessment.started_at_ms, + completed_at_ms: assessment + .completed_at_ms + .unwrap_or(assessment.started_at_ms), target_item_id: assessment.target_item_id.clone(), decision_source: assessment .decision_source diff --git a/codex-rs/app-server-protocol/src/protocol/thread_history.rs b/codex-rs/app-server-protocol/src/protocol/thread_history.rs index 1f45180c9e..1121d3a35b 100644 --- a/codex-rs/app-server-protocol/src/protocol/thread_history.rs +++ b/codex-rs/app-server-protocol/src/protocol/thread_history.rs @@ -2143,6 +2143,8 @@ mod tests { id: "review-guardian-exec".into(), target_item_id: Some("guardian-exec".into()), turn_id: "turn-1".into(), + started_at_ms: 1_000, + completed_at_ms: None, status: GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -2160,6 +2162,8 @@ mod tests { id: "review-guardian-exec".into(), target_item_id: Some("guardian-exec".into()), turn_id: "turn-1".into(), + started_at_ms: 1_000, + completed_at_ms: Some(1_042), status: GuardianAssessmentStatus::Denied, risk_level: Some(codex_protocol::protocol::GuardianRiskLevel::High), user_authorization: Some(codex_protocol::protocol::GuardianUserAuthorization::Low), @@ -2222,6 +2226,8 @@ mod tests { id: "review-guardian-execve".into(), target_item_id: Some("guardian-execve".into()), turn_id: "turn-1".into(), + started_at_ms: 2_000, + completed_at_ms: None, status: GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -2525,6 +2531,7 @@ mod tests { EventMsg::ApplyPatchApprovalRequest(ApplyPatchApprovalRequestEvent { call_id: "patch-call".into(), turn_id: turn_id.to_string(), + started_at_ms: 0, changes: [( PathBuf::from("README.md"), codex_protocol::protocol::FileChange::Add { diff --git a/codex-rs/app-server-protocol/src/protocol/v2/item.rs b/codex-rs/app-server-protocol/src/protocol/v2/item.rs index 2c3a926c91..0e22c48590 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/item.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/item.rs @@ -1073,6 +1073,9 @@ pub struct ItemStartedNotification { pub struct ItemGuardianApprovalReviewStartedNotification { pub thread_id: String, pub turn_id: String, + /// Unix timestamp (in milliseconds) when this review started. + #[ts(type = "number")] + pub started_at_ms: i64, /// Stable identifier for this review. pub review_id: String, /// Identifier for the reviewed item or tool call when one exists. @@ -1099,6 +1102,12 @@ pub struct ItemGuardianApprovalReviewStartedNotification { pub struct ItemGuardianApprovalReviewCompletedNotification { pub thread_id: String, pub turn_id: String, + /// Unix timestamp (in milliseconds) when this review started. + #[ts(type = "number")] + pub started_at_ms: i64, + /// Unix timestamp (in milliseconds) when this review completed. + #[ts(type = "number")] + pub completed_at_ms: i64, /// Stable identifier for this review. pub review_id: String, /// Identifier for the reviewed item or tool call when one exists. @@ -1248,6 +1257,9 @@ pub struct CommandExecutionRequestApprovalParams { pub thread_id: String, pub turn_id: String, pub item_id: String, + /// Unix timestamp (in milliseconds) when this approval request started. + #[ts(type = "number")] + pub started_at_ms: i64, /// Unique identifier for this specific approval callback. /// /// For regular shell/unified_exec approvals, this is null. @@ -1321,6 +1333,9 @@ pub struct FileChangeRequestApprovalParams { pub thread_id: String, pub turn_id: String, pub item_id: String, + /// Unix timestamp (in milliseconds) when this approval request started. + #[ts(type = "number")] + pub started_at_ms: i64, /// Optional explanatory reason (e.g. request for extra write access). #[ts(optional = nullable)] pub reason: Option, diff --git a/codex-rs/app-server-protocol/src/protocol/v2/permissions.rs b/codex-rs/app-server-protocol/src/protocol/v2/permissions.rs index 8ce47e58cb..86614a6aeb 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/permissions.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/permissions.rs @@ -826,6 +826,9 @@ pub struct PermissionsRequestApprovalParams { pub thread_id: String, pub turn_id: String, pub item_id: String, + /// Unix timestamp (in milliseconds) when this approval request started. + #[ts(type = "number")] + pub started_at_ms: i64, pub cwd: AbsolutePathBuf, pub reason: Option, pub permissions: RequestPermissionProfile, diff --git a/codex-rs/app-server-protocol/src/protocol/v2/plugin.rs b/codex-rs/app-server-protocol/src/protocol/v2/plugin.rs index 20d68e6e55..6f425b4a6a 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/plugin.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/plugin.rs @@ -15,7 +15,7 @@ use serde::Serialize; use std::path::PathBuf; use ts_rs::TS; -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct SkillsListParams { @@ -26,19 +26,6 @@ pub struct SkillsListParams { /// When true, bypass the skills cache and re-scan skills from disk. #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub force_reload: bool, - - /// Optional per-cwd extra roots to scan as user-scoped skills. - #[serde(default)] - #[ts(optional = nullable)] - pub per_cwd_extra_user_roots: Option>, -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] -#[serde(rename_all = "camelCase")] -#[ts(export_to = "v2/")] -pub struct SkillsListExtraRootsForCwd { - pub cwd: PathBuf, - pub extra_user_roots: Vec, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] @@ -231,6 +218,7 @@ pub struct PluginShareSaveResponse { #[ts(export_to = "v2/")] pub struct PluginShareUpdateTargetsParams { pub remote_plugin_id: String, + pub discoverability: PluginShareUpdateDiscoverability, pub share_targets: Vec, } @@ -239,6 +227,7 @@ pub struct PluginShareUpdateTargetsParams { #[ts(export_to = "v2/")] pub struct PluginShareUpdateTargetsResponse { pub principals: Vec, + pub discoverability: PluginShareDiscoverability, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] @@ -288,6 +277,17 @@ pub enum PluginShareDiscoverability { Private, } +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] +#[ts(export_to = "v2/")] +pub enum PluginShareUpdateDiscoverability { + #[serde(rename = "UNLISTED")] + #[ts(rename = "UNLISTED")] + Unlisted, + #[serde(rename = "PRIVATE")] + #[ts(rename = "PRIVATE")] + Private, +} + #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] #[ts(export_to = "v2/")] pub enum PluginSharePrincipalType { diff --git a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs index d6e49279ce..da0ad2c10e 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs @@ -277,6 +277,7 @@ fn command_execution_request_approval_rejects_relative_additional_permission_pat "threadId": "thr_123", "turnId": "turn_123", "itemId": "call_123", + "startedAtMs": 1, "command": "cat file", "cwd": absolute_path_string("tmp"), "commandActions": null, @@ -317,6 +318,7 @@ fn permissions_request_approval_uses_request_permission_profile() { "threadId": "thr_123", "turnId": "turn_123", "itemId": "call_123", + "startedAtMs": 1, "cwd": absolute_path_string("repo"), "reason": "Select a workspace root", "permissions": { @@ -379,6 +381,7 @@ fn permissions_request_approval_rejects_macos_permissions() { "threadId": "thr_123", "turnId": "turn_123", "itemId": "call_123", + "startedAtMs": 1, "cwd": absolute_path_string("repo"), "reason": "Select a workspace root", "permissions": { @@ -2505,33 +2508,20 @@ fn skills_list_params_serialization_uses_force_reload() { serde_json::to_value(SkillsListParams { cwds: Vec::new(), force_reload: false, - per_cwd_extra_user_roots: None, }) .unwrap(), - json!({ - "perCwdExtraUserRoots": null, - }), + json!({}), ); assert_eq!( serde_json::to_value(SkillsListParams { cwds: vec![PathBuf::from("/repo")], force_reload: true, - per_cwd_extra_user_roots: Some(vec![SkillsListExtraRootsForCwd { - cwd: PathBuf::from("/repo"), - extra_user_roots: vec![PathBuf::from("/shared/skills"), PathBuf::from("/tmp/x")], - }]), }) .unwrap(), json!({ "cwds": ["/repo"], "forceReload": true, - "perCwdExtraUserRoots": [ - { - "cwd": "/repo", - "extraUserRoots": ["/shared/skills", "/tmp/x"], - } - ], }), ); } @@ -2946,6 +2936,7 @@ fn plugin_share_params_and_response_serialization_use_camel_case_fields() { assert_eq!( serde_json::to_value(PluginShareUpdateTargetsParams { remote_plugin_id: "plugins~Plugin_00000000000000000000000000000000".to_string(), + discoverability: PluginShareUpdateDiscoverability::Unlisted, share_targets: vec![PluginShareTarget { principal_type: PluginSharePrincipalType::Group, principal_id: "group-1".to_string(), @@ -2954,6 +2945,7 @@ fn plugin_share_params_and_response_serialization_use_camel_case_fields() { .unwrap(), json!({ "remotePluginId": "plugins~Plugin_00000000000000000000000000000000", + "discoverability": "UNLISTED", "shareTargets": [{ "principalType": "group", "principalId": "group-1", @@ -2968,6 +2960,7 @@ fn plugin_share_params_and_response_serialization_use_camel_case_fields() { principal_id: "user-1".to_string(), name: "Gavin".to_string(), }], + discoverability: PluginShareDiscoverability::Unlisted, }) .unwrap(), json!({ @@ -2976,6 +2969,7 @@ fn plugin_share_params_and_response_serialization_use_camel_case_fields() { "principalId": "user-1", "name": "Gavin", }], + "discoverability": "UNLISTED", }), ); diff --git a/codex-rs/app-server-test-client/src/lib.rs b/codex-rs/app-server-test-client/src/lib.rs index edea431c61..e67f6e02f3 100644 --- a/codex-rs/app-server-test-client/src/lib.rs +++ b/codex-rs/app-server-test-client/src/lib.rs @@ -1945,6 +1945,7 @@ impl CodexClient { thread_id, turn_id, item_id, + started_at_ms: _, approval_id, reason, network_approval_context, @@ -2020,6 +2021,7 @@ impl CodexClient { thread_id, turn_id, item_id, + started_at_ms: _, reason, grant_root, } = params; diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md index 5dd75ee6f4..01982d7ee5 100644 --- a/codex-rs/app-server/README.md +++ b/codex-rs/app-server/README.md @@ -1485,21 +1485,13 @@ $skill-creator Add a new skill for triaging flaky CI and include step-by-step us ``` Use `skills/list` to fetch the available skills (optionally scoped by `cwds`, with `forceReload`). -You can also add `perCwdExtraUserRoots` to scan additional absolute paths as `user` scope for specific `cwd` entries. -Entries whose `cwd` is not present in `cwds` are ignored. `skills/list` might reuse a cached skills result per `cwd`; setting `forceReload` to `true` refreshes the result from disk. The server also emits `skills/changed` notifications when watched local skill files change. Treat this as an invalidation signal and re-run `skills/list` with your current params when needed. ```json { "method": "skills/list", "id": 25, "params": { "cwds": ["/Users/me/project", "/Users/me/other-project"], - "forceReload": true, - "perCwdExtraUserRoots": [ - { - "cwd": "/Users/me/project", - "extraUserRoots": ["/Users/me/shared-skills"] - } - ] + "forceReload": true } } { "id": 25, "result": { "data": [{ diff --git a/codex-rs/app-server/src/bespoke_event_handling.rs b/codex-rs/app-server/src/bespoke_event_handling.rs index 4faa040690..b4348f53bd 100644 --- a/codex-rs/app-server/src/bespoke_event_handling.rs +++ b/codex-rs/app-server/src/bespoke_event_handling.rs @@ -503,6 +503,7 @@ pub(crate) async fn apply_bespoke_event_handling( thread_id: conversation_id.to_string(), turn_id: event.turn_id.clone(), item_id: item_id.clone(), + started_at_ms: event.started_at_ms, reason: event.reason.clone(), grant_root: event.grant_root.clone(), }; @@ -534,6 +535,7 @@ pub(crate) async fn apply_bespoke_event_handling( call_id, approval_id, turn_id, + started_at_ms, command, cwd, reason, @@ -607,6 +609,7 @@ pub(crate) async fn apply_bespoke_event_handling( thread_id: conversation_id.to_string(), turn_id: turn_id.clone(), item_id: call_id.clone(), + started_at_ms, approval_id: approval_id.clone(), reason, network_approval_context, @@ -756,6 +759,7 @@ pub(crate) async fn apply_bespoke_event_handling( thread_id: conversation_id.to_string(), turn_id: request.turn_id.clone(), item_id: request.call_id.clone(), + started_at_ms: request.started_at_ms, cwd: request_cwd.clone(), reason: request.reason, permissions: request.permissions.into(), @@ -2241,6 +2245,9 @@ mod tests { id: format!("review-{id}"), target_item_id: Some(id.to_string()), turn_id: turn_id.to_string(), + started_at_ms: 1_000, + completed_at_ms: (!matches!(status, GuardianAssessmentStatus::InProgress)) + .then_some(1_042), status, risk_level, user_authorization, @@ -2305,6 +2312,8 @@ mod tests { id: "review-1".to_string(), target_item_id: Some("item-1".to_string()), turn_id: String::new(), + started_at_ms: 1_000, + completed_at_ms: None, status: codex_protocol::protocol::GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -2318,6 +2327,7 @@ mod tests { ServerNotification::ItemGuardianApprovalReviewStarted(payload) => { assert_eq!(payload.thread_id, conversation_id.to_string()); assert_eq!(payload.turn_id, "turn-from-event"); + assert_eq!(payload.started_at_ms, 1_000); assert_eq!(payload.review_id, "review-1"); assert_eq!(payload.target_item_id.as_deref(), Some("item-1")); assert_eq!( @@ -2348,6 +2358,8 @@ mod tests { id: "review-2".to_string(), target_item_id: Some("item-2".to_string()), turn_id: "turn-from-assessment".to_string(), + started_at_ms: 1_000, + completed_at_ms: Some(1_042), status: codex_protocol::protocol::GuardianAssessmentStatus::Denied, risk_level: Some(codex_protocol::protocol::GuardianRiskLevel::High), user_authorization: Some(codex_protocol::protocol::GuardianUserAuthorization::Low), @@ -2363,6 +2375,8 @@ mod tests { ServerNotification::ItemGuardianApprovalReviewCompleted(payload) => { assert_eq!(payload.thread_id, conversation_id.to_string()); assert_eq!(payload.turn_id, "turn-from-assessment"); + assert_eq!(payload.started_at_ms, 1_000); + assert_eq!(payload.completed_at_ms, 1_042); assert_eq!(payload.review_id, "review-2"); assert_eq!(payload.target_item_id.as_deref(), Some("item-2")); assert_eq!(payload.decision_source, AutoReviewDecisionSource::Agent); @@ -2398,6 +2412,8 @@ mod tests { id: "review-3".to_string(), target_item_id: None, turn_id: "turn-from-assessment".to_string(), + started_at_ms: 1_000, + completed_at_ms: Some(1_042), status: codex_protocol::protocol::GuardianAssessmentStatus::Aborted, risk_level: None, user_authorization: None, diff --git a/codex-rs/app-server/src/outgoing_message.rs b/codex-rs/app-server/src/outgoing_message.rs index a7420f8c78..cbe196cd98 100644 --- a/codex-rs/app-server/src/outgoing_message.rs +++ b/codex-rs/app-server/src/outgoing_message.rs @@ -2,6 +2,8 @@ use std::collections::HashMap; use std::sync::Arc; use std::sync::atomic::AtomicI64; use std::sync::atomic::Ordering; +use std::time::SystemTime; +use std::time::UNIX_EPOCH; use codex_analytics::AnalyticsEventsClient; use codex_app_server_protocol::ClientResponsePayload; @@ -357,8 +359,10 @@ impl OutgoingMessageSender { match entry { Some((id, entry)) => { + let completed_at_ms = now_unix_timestamp_ms(); if let Ok(response) = entry.request.response_from_result(result.clone()) { - self.analytics_events_client.track_server_response(response); + self.analytics_events_client + .track_server_response(completed_at_ms, response); } if let Err(err) = entry.callback.send(Ok(result)) { warn!("could not notify callback for {id:?} due to: {err:?}"); @@ -648,6 +652,15 @@ impl OutgoingMessageSender { } } +fn now_unix_timestamp_ms() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_millis() + .try_into() + .unwrap_or_default() +} + #[cfg(test)] mod tests { use std::time::Duration; @@ -903,6 +916,7 @@ mod tests { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), item_id: "item-1".to_string(), + started_at_ms: 0, approval_id: None, reason: None, network_approval_context: None, @@ -1195,6 +1209,7 @@ mod tests { thread_id: thread_id.to_string(), turn_id: "turn-1".to_string(), item_id: "call-2".to_string(), + started_at_ms: 0, reason: None, grant_root: None, }, diff --git a/codex-rs/app-server/src/request_processors.rs b/codex-rs/app-server/src/request_processors.rs index 1e8b865021..5e3a056840 100644 --- a/codex-rs/app-server/src/request_processors.rs +++ b/codex-rs/app-server/src/request_processors.rs @@ -125,6 +125,7 @@ use codex_app_server_protocol::PluginSharePrincipalType; use codex_app_server_protocol::PluginShareSaveParams; use codex_app_server_protocol::PluginShareSaveResponse; use codex_app_server_protocol::PluginShareTarget; +use codex_app_server_protocol::PluginShareUpdateDiscoverability; use codex_app_server_protocol::PluginShareUpdateTargetsParams; use codex_app_server_protocol::PluginShareUpdateTargetsResponse; use codex_app_server_protocol::PluginSkillReadParams; diff --git a/codex-rs/app-server/src/request_processors/catalog_processor.rs b/codex-rs/app-server/src/request_processors/catalog_processor.rs index b26748d551..89082492c1 100644 --- a/codex-rs/app-server/src/request_processors/catalog_processor.rs +++ b/codex-rs/app-server/src/request_processors/catalog_processor.rs @@ -382,44 +382,12 @@ impl CatalogRequestProcessor { &self, params: SkillsListParams, ) -> Result { - let SkillsListParams { - cwds, - force_reload, - per_cwd_extra_user_roots, - } = params; + let SkillsListParams { cwds, force_reload } = params; let cwds = if cwds.is_empty() { vec![self.config.cwd.to_path_buf()] } else { cwds }; - let cwd_set: HashSet = cwds.iter().cloned().collect(); - - let mut extra_roots_by_cwd: HashMap> = HashMap::new(); - for entry in per_cwd_extra_user_roots.unwrap_or_default() { - if !cwd_set.contains(&entry.cwd) { - warn!( - cwd = %entry.cwd.display(), - "ignoring per-cwd extra roots for cwd not present in skills/list cwds" - ); - continue; - } - - let mut valid_extra_roots = Vec::new(); - for root in entry.extra_user_roots { - let root = - AbsolutePathBuf::from_absolute_path_checked(root.as_path()).map_err(|_| { - invalid_request(format!( - "skills/list perCwdExtraUserRoots extraUserRoots paths must be absolute: {}", - root.display() - )) - })?; - valid_extra_roots.push(root); - } - extra_roots_by_cwd - .entry(entry.cwd) - .or_default() - .extend(valid_extra_roots); - } let config = self.load_latest_config(/*fallback_cwd*/ None).await?; let auth = self.auth_manager.auth().await; @@ -436,7 +404,6 @@ impl CatalogRequestProcessor { let mut data = futures::stream::iter(cwds.into_iter().enumerate()) .map(|(index, cwd)| { let config = &config; - let extra_roots_by_cwd = &extra_roots_by_cwd; let fs = fs.clone(); let plugins_manager = &plugins_manager; let skills_manager = &skills_manager; @@ -458,9 +425,6 @@ impl CatalogRequestProcessor { ); } }; - let extra_roots = extra_roots_by_cwd - .get(&cwd) - .map_or(&[][..], std::vec::Vec::as_slice); let effective_skill_roots = if workspace_codex_plugins_enabled { let plugins_input = config.plugins_config_input(); plugins_manager @@ -479,12 +443,7 @@ impl CatalogRequestProcessor { config.bundled_skills_enabled(), ); let outcome = skills_manager - .skills_for_cwd_with_extra_user_roots( - &skills_input, - force_reload, - extra_roots, - fs, - ) + .skills_for_cwd(&skills_input, force_reload, fs) .await; let errors = errors_to_info(&outcome.errors); let skills = skills_to_info(&outcome.skills, &outcome.disabled_paths); diff --git a/codex-rs/app-server/src/request_processors/plugins.rs b/codex-rs/app-server/src/request_processors/plugins.rs index cc5de4058a..65bb390851 100644 --- a/codex-rs/app-server/src/request_processors/plugins.rs +++ b/codex-rs/app-server/src/request_processors/plugins.rs @@ -133,6 +133,33 @@ fn remote_plugin_share_discoverability( } } +fn remote_plugin_share_update_discoverability( + discoverability: PluginShareUpdateDiscoverability, +) -> codex_core_plugins::remote::RemotePluginShareUpdateDiscoverability { + match discoverability { + PluginShareUpdateDiscoverability::Unlisted => { + codex_core_plugins::remote::RemotePluginShareUpdateDiscoverability::Unlisted + } + PluginShareUpdateDiscoverability::Private => { + codex_core_plugins::remote::RemotePluginShareUpdateDiscoverability::Private + } + } +} + +fn validate_client_plugin_share_targets( + targets: &[PluginShareTarget], +) -> Result<(), JSONRPCErrorError> { + if targets + .iter() + .any(|target| target.principal_type == PluginSharePrincipalType::Workspace) + { + return Err(invalid_request( + "shareTargets cannot include workspace principals; use discoverability UNLISTED for workspace link access", + )); + } + Ok(()) +} + fn remote_plugin_share_targets( targets: Vec, ) -> Vec { @@ -729,9 +756,17 @@ impl PluginRequestProcessor { } if remote_plugin_id.is_some() && (discoverability.is_some() || share_targets.is_some()) { return Err(invalid_request( - "discoverability and shareTargets are only supported when creating a plugin share; use plugin/share/updateTargets to update share targets", + "discoverability and shareTargets are only supported when creating a plugin share; use plugin/share/updateTargets to update share settings", )); } + if discoverability == Some(PluginShareDiscoverability::Listed) { + return Err(invalid_request( + "discoverability LISTED is not supported for plugin/share/save; use UNLISTED or PRIVATE", + )); + } + if let Some(share_targets) = share_targets.as_ref() { + validate_client_plugin_share_targets(share_targets)?; + } let remote_plugin_service_config = RemotePluginServiceConfig { chatgpt_base_url: config.chatgpt_base_url.clone(), @@ -765,11 +800,14 @@ impl PluginRequestProcessor { let (config, auth) = self.load_plugin_share_config_and_auth().await?; let PluginShareUpdateTargetsParams { remote_plugin_id, + discoverability, share_targets, } = params; if remote_plugin_id.is_empty() || !is_valid_remote_plugin_id(&remote_plugin_id) { return Err(invalid_request("invalid remote plugin id")); } + validate_client_plugin_share_targets(&share_targets)?; + let requested_share_targets = share_targets.clone(); let remote_plugin_service_config = RemotePluginServiceConfig { chatgpt_base_url: config.chatgpt_base_url.clone(), @@ -779,6 +817,7 @@ impl PluginRequestProcessor { auth.as_ref(), &remote_plugin_id, remote_plugin_share_targets(share_targets), + remote_plugin_share_update_discoverability(discoverability), ) .await .map_err(|err| { @@ -790,7 +829,14 @@ impl PluginRequestProcessor { .principals .into_iter() .map(plugin_share_principal_from_remote) + .filter(|principal| { + requested_share_targets.iter().any(|target| { + target.principal_type == principal.principal_type + && target.principal_id == principal.principal_id + }) + }) .collect(), + discoverability: remote_plugin_share_discoverability_to_info(result.discoverability), }) } @@ -1487,6 +1533,22 @@ fn remote_plugin_share_context_to_info( } } +fn remote_plugin_share_discoverability_to_info( + discoverability: codex_core_plugins::remote::RemotePluginShareDiscoverability, +) -> PluginShareDiscoverability { + match discoverability { + codex_core_plugins::remote::RemotePluginShareDiscoverability::Listed => { + PluginShareDiscoverability::Listed + } + codex_core_plugins::remote::RemotePluginShareDiscoverability::Unlisted => { + PluginShareDiscoverability::Unlisted + } + codex_core_plugins::remote::RemotePluginShareDiscoverability::Private => { + PluginShareDiscoverability::Private + } + } +} + fn remote_plugin_detail_to_info( detail: RemoteCatalogPluginDetail, apps: Vec, diff --git a/codex-rs/app-server/src/transport_tests.rs b/codex-rs/app-server/src/transport_tests.rs index 1600b8be87..5790e46a17 100644 --- a/codex-rs/app-server/src/transport_tests.rs +++ b/codex-rs/app-server/src/transport_tests.rs @@ -258,6 +258,7 @@ async fn command_execution_request_approval_strips_additional_permissions_withou thread_id: "thr_123".to_string(), turn_id: "turn_123".to_string(), item_id: "call_123".to_string(), + started_at_ms: 0, approval_id: None, reason: Some("Need extra read access".to_string()), network_approval_context: None, @@ -322,6 +323,7 @@ async fn command_execution_request_approval_keeps_additional_permissions_with_ca thread_id: "thr_123".to_string(), turn_id: "turn_123".to_string(), item_id: "call_123".to_string(), + started_at_ms: 0, approval_id: None, reason: Some("Need extra read access".to_string()), network_approval_context: None, diff --git a/codex-rs/app-server/tests/suite/v2/plugin_share.rs b/codex-rs/app-server/tests/suite/v2/plugin_share.rs index 09b39ca241..dc1f56d487 100644 --- a/codex-rs/app-server/tests/suite/v2/plugin_share.rs +++ b/codex-rs/app-server/tests/suite/v2/plugin_share.rs @@ -219,7 +219,7 @@ async fn plugin_share_save_forwards_access_policy() -> Result<()> { .and(body_json(json!({ "file_id": "file_123", "etag": "\"upload_etag_123\"", - "discoverability": "PRIVATE", + "discoverability": "UNLISTED", "share_targets": [ { "principal_type": "user", @@ -227,7 +227,7 @@ async fn plugin_share_save_forwards_access_policy() -> Result<()> { }, { "principal_type": "workspace", - "principal_id": "workspace-1", + "principal_id": "account-123", }, ], }))) @@ -247,16 +247,12 @@ async fn plugin_share_save_forwards_access_policy() -> Result<()> { "plugin/share/save", Some(json!({ "pluginPath": expected_plugin_path, - "discoverability": "PRIVATE", + "discoverability": "UNLISTED", "shareTargets": [ { "principalType": "user", "principalId": "user-1", }, - { - "principalType": "workspace", - "principalId": "workspace-1", - }, ], })), ) @@ -279,6 +275,124 @@ async fn plugin_share_save_forwards_access_policy() -> Result<()> { Ok(()) } +#[tokio::test] +async fn plugin_share_save_rejects_listed_discoverability() -> Result<()> { + let codex_home = TempDir::new()?; + let plugin_root = TempDir::new()?; + let plugin_path = write_test_plugin(plugin_root.path(), "demo-plugin")?; + let server = MockServer::start().await; + write_remote_plugin_config(codex_home.path(), &format!("{}/backend-api", server.uri()))?; + write_chatgpt_auth( + codex_home.path(), + ChatGptAuthFixture::new("chatgpt-token") + .account_id("account-123") + .chatgpt_user_id("user-123") + .chatgpt_account_id("account-123"), + AuthCredentialsStoreMode::File, + )?; + + let mut mcp = McpProcess::new(codex_home.path()).await?; + timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??; + let request_id = mcp + .send_raw_request( + "plugin/share/save", + Some(json!({ + "pluginPath": AbsolutePathBuf::try_from(plugin_path)?, + "discoverability": "LISTED", + })), + ) + .await?; + + let error: JSONRPCError = timeout( + DEFAULT_TIMEOUT, + mcp.read_stream_until_error_message(RequestId::Integer(request_id)), + ) + .await??; + + assert_eq!(error.error.code, -32600); + assert_eq!( + error.error.message, + "discoverability LISTED is not supported for plugin/share/save; use UNLISTED or PRIVATE" + ); + Ok(()) +} + +#[tokio::test] +async fn plugin_share_rejects_workspace_targets_from_client() -> Result<()> { + let codex_home = TempDir::new()?; + let plugin_root = TempDir::new()?; + let plugin_path = write_test_plugin(plugin_root.path(), "demo-plugin")?; + let server = MockServer::start().await; + write_remote_plugin_config(codex_home.path(), &format!("{}/backend-api", server.uri()))?; + write_chatgpt_auth( + codex_home.path(), + ChatGptAuthFixture::new("chatgpt-token") + .account_id("account-123") + .chatgpt_user_id("user-123") + .chatgpt_account_id("account-123"), + AuthCredentialsStoreMode::File, + )?; + + let mut mcp = McpProcess::new(codex_home.path()).await?; + timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??; + let request_id = mcp + .send_raw_request( + "plugin/share/save", + Some(json!({ + "pluginPath": AbsolutePathBuf::try_from(plugin_path)?, + "discoverability": "UNLISTED", + "shareTargets": [ + { + "principalType": "workspace", + "principalId": "account-123", + }, + ], + })), + ) + .await?; + + let error: JSONRPCError = timeout( + DEFAULT_TIMEOUT, + mcp.read_stream_until_error_message(RequestId::Integer(request_id)), + ) + .await??; + + assert_eq!(error.error.code, -32600); + assert_eq!( + error.error.message, + "shareTargets cannot include workspace principals; use discoverability UNLISTED for workspace link access" + ); + + let request_id = mcp + .send_raw_request( + "plugin/share/updateTargets", + Some(json!({ + "remotePluginId": "plugins_123", + "discoverability": "UNLISTED", + "shareTargets": [ + { + "principalType": "workspace", + "principalId": "account-123", + }, + ], + })), + ) + .await?; + + let error: JSONRPCError = timeout( + DEFAULT_TIMEOUT, + mcp.read_stream_until_error_message(RequestId::Integer(request_id)), + ) + .await??; + + assert_eq!(error.error.code, -32600); + assert_eq!( + error.error.message, + "shareTargets cannot include workspace principals; use discoverability UNLISTED for workspace link access" + ); + Ok(()) +} + #[tokio::test] async fn plugin_share_save_rejects_access_policy_for_existing_plugin() -> Result<()> { let codex_home = TempDir::new()?; @@ -323,7 +437,7 @@ async fn plugin_share_save_rejects_access_policy_for_existing_plugin() -> Result assert_eq!(error.error.code, -32600); assert_eq!( error.error.message, - "discoverability and shareTargets are only supported when creating a plugin share; use plugin/share/updateTargets to update share targets" + "discoverability and shareTargets are only supported when creating a plugin share; use plugin/share/updateTargets to update share settings" ); Ok(()) } @@ -420,24 +534,39 @@ async fn plugin_share_update_targets_updates_share_targets() -> Result<()> { )?; Mock::given(method("PUT")) - .and(path("/backend-api/public/plugins/plugins_123/shares")) + .and(path("/backend-api/ps/plugins/plugins_123/shares")) .and(header("authorization", "Bearer chatgpt-token")) .and(header("chatgpt-account-id", "account-123")) .and(body_json(json!({ + "discoverability": "UNLISTED", "targets": [ { "principal_type": "user", "principal_id": "user-1", }, + { + "principal_type": "workspace", + "principal_id": "account-123", + }, ], }))) .respond_with(ResponseTemplate::new(200).set_body_json(json!({ "principals": [ + { + "principal_type": "user", + "principal_id": "owner-1", + "name": "Owner", + }, { "principal_type": "user", "principal_id": "user-1", "name": "Gavin", }, + { + "principal_type": "workspace", + "principal_id": "account-123", + "name": "Workspace", + }, ], }))) .expect(1) @@ -451,6 +580,7 @@ async fn plugin_share_update_targets_updates_share_targets() -> Result<()> { "plugin/share/updateTargets", Some(json!({ "remotePluginId": "plugins_123", + "discoverability": "UNLISTED", "shareTargets": [ { "principalType": "user", @@ -476,6 +606,7 @@ async fn plugin_share_update_targets_updates_share_targets() -> Result<()> { principal_id: "user-1".to_string(), name: "Gavin".to_string(), }], + discoverability: codex_app_server_protocol::PluginShareDiscoverability::Unlisted, } ); Ok(()) diff --git a/codex-rs/app-server/tests/suite/v2/skills_list.rs b/codex-rs/app-server/tests/suite/v2/skills_list.rs index aedcdff572..36f687578c 100644 --- a/codex-rs/app-server/tests/suite/v2/skills_list.rs +++ b/codex-rs/app-server/tests/suite/v2/skills_list.rs @@ -11,7 +11,6 @@ use codex_app_server_protocol::PluginListParams; use codex_app_server_protocol::PluginListResponse; use codex_app_server_protocol::RequestId; use codex_app_server_protocol::SkillsChangedNotification; -use codex_app_server_protocol::SkillsListExtraRootsForCwd; use codex_app_server_protocol::SkillsListParams; use codex_app_server_protocol::SkillsListResponse; use codex_app_server_protocol::ThreadStartParams; @@ -133,44 +132,6 @@ fn write_cached_remote_plugin_with_skill( Ok(skill_path) } -#[tokio::test] -async fn skills_list_includes_skills_from_per_cwd_extra_user_roots() -> Result<()> { - let codex_home = TempDir::new()?; - let cwd = TempDir::new()?; - let extra_root = TempDir::new()?; - write_skill(&extra_root, "extra-skill")?; - - let mut mcp = McpProcess::new(codex_home.path()).await?; - timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??; - - let request_id = mcp - .send_skills_list_request(SkillsListParams { - cwds: vec![cwd.path().to_path_buf()], - force_reload: true, - per_cwd_extra_user_roots: Some(vec![SkillsListExtraRootsForCwd { - cwd: cwd.path().to_path_buf(), - extra_user_roots: vec![extra_root.path().to_path_buf()], - }]), - }) - .await?; - - let response: JSONRPCResponse = timeout( - DEFAULT_TIMEOUT, - mcp.read_stream_until_response_message(RequestId::Integer(request_id)), - ) - .await??; - let SkillsListResponse { data } = to_response(response)?; - assert_eq!(data.len(), 1); - assert_eq!(data[0].cwd.as_path(), cwd.path()); - assert!( - data[0] - .skills - .iter() - .any(|skill| skill.name == "extra-skill") - ); - Ok(()) -} - #[tokio::test] async fn skills_list_loads_remote_installed_plugin_skills_from_cache() -> Result<()> { let codex_home = TempDir::new()?; @@ -266,7 +227,6 @@ async fn skills_list_loads_remote_installed_plugin_skills_from_cache() -> Result .send_skills_list_request(SkillsListParams { cwds: vec![cwd.path().to_path_buf()], force_reload: true, - per_cwd_extra_user_roots: None, }) .await?; let stale_skills_list_response: JSONRPCResponse = timeout( @@ -317,7 +277,6 @@ async fn skills_list_loads_remote_installed_plugin_skills_from_cache() -> Result .send_skills_list_request(SkillsListParams { cwds: vec![cwd.path().to_path_buf()], force_reload: false, - per_cwd_extra_user_roots: None, }) .await?; let skills_list_response: JSONRPCResponse = timeout( @@ -392,7 +351,6 @@ async fn skills_list_excludes_plugin_skills_when_workspace_codex_plugins_disable .send_skills_list_request(SkillsListParams { cwds: vec![repo_root.path().to_path_buf()], force_reload: true, - per_cwd_extra_user_roots: None, }) .await?; @@ -424,9 +382,13 @@ async fn skills_list_excludes_plugin_skills_when_workspace_codex_plugins_disable async fn skills_list_skips_cwd_roots_when_environment_disabled() -> Result<()> { let codex_home = TempDir::new()?; let cwd = TempDir::new()?; - let extra_root = TempDir::new()?; write_skill(&codex_home, "home-skill")?; - write_skill(&extra_root, "extra-skill")?; + let repo_skill_dir = cwd.path().join(".codex/skills/repo-skill"); + std::fs::create_dir_all(&repo_skill_dir)?; + std::fs::write( + repo_skill_dir.join("SKILL.md"), + "---\nname: repo-skill\ndescription: from repo root\n---\n\n# Body\n", + )?; let mut mcp = McpProcess::new_with_env( codex_home.path(), @@ -439,10 +401,6 @@ async fn skills_list_skips_cwd_roots_when_environment_disabled() -> Result<()> { .send_skills_list_request(SkillsListParams { cwds: vec![cwd.path().to_path_buf()], force_reload: true, - per_cwd_extra_user_roots: Some(vec![SkillsListExtraRootsForCwd { - cwd: cwd.path().to_path_buf(), - extra_user_roots: vec![extra_root.path().to_path_buf()], - }]), }) .await?; @@ -465,41 +423,7 @@ async fn skills_list_skips_cwd_roots_when_environment_disabled() -> Result<()> { data[0] .skills .iter() - .all(|skill| skill.name != "extra-skill") - ); - Ok(()) -} - -#[tokio::test] -async fn skills_list_rejects_relative_extra_user_roots() -> Result<()> { - let codex_home = TempDir::new()?; - let cwd = TempDir::new()?; - - let mut mcp = McpProcess::new(codex_home.path()).await?; - timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??; - - let request_id = mcp - .send_skills_list_request(SkillsListParams { - cwds: vec![cwd.path().to_path_buf()], - force_reload: true, - per_cwd_extra_user_roots: Some(vec![SkillsListExtraRootsForCwd { - cwd: cwd.path().to_path_buf(), - extra_user_roots: vec![std::path::PathBuf::from("relative/skills")], - }]), - }) - .await?; - - let err = timeout( - DEFAULT_TIMEOUT, - mcp.read_stream_until_error_message(RequestId::Integer(request_id)), - ) - .await??; - assert!( - err.error - .message - .contains("perCwdExtraUserRoots extraUserRoots paths must be absolute"), - "unexpected error: {}", - err.error.message + .all(|skill| skill.name != "repo-skill") ); Ok(()) } @@ -517,7 +441,6 @@ async fn skills_list_accepts_relative_cwds() -> Result<()> { .send_skills_list_request(SkillsListParams { cwds: vec![relative_cwd.clone()], force_reload: true, - per_cwd_extra_user_roots: None, }) .await?; @@ -549,7 +472,6 @@ async fn skills_list_preserves_requested_cwd_order() -> Result<()> { second_cwd.path().to_path_buf(), ], force_reload: true, - per_cwd_extra_user_roots: None, }) .await?; @@ -571,61 +493,19 @@ async fn skills_list_preserves_requested_cwd_order() -> Result<()> { Ok(()) } -#[tokio::test] -async fn skills_list_ignores_per_cwd_extra_roots_for_unknown_cwd() -> Result<()> { - let codex_home = TempDir::new()?; - let requested_cwd = TempDir::new()?; - let unknown_cwd = TempDir::new()?; - let extra_root = TempDir::new()?; - write_skill(&extra_root, "ignored-extra-skill")?; - - let mut mcp = McpProcess::new(codex_home.path()).await?; - timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??; - - let request_id = mcp - .send_skills_list_request(SkillsListParams { - cwds: vec![requested_cwd.path().to_path_buf()], - force_reload: true, - per_cwd_extra_user_roots: Some(vec![SkillsListExtraRootsForCwd { - cwd: unknown_cwd.path().to_path_buf(), - extra_user_roots: vec![extra_root.path().to_path_buf()], - }]), - }) - .await?; - - let response: JSONRPCResponse = timeout( - DEFAULT_TIMEOUT, - mcp.read_stream_until_response_message(RequestId::Integer(request_id)), - ) - .await??; - let SkillsListResponse { data } = to_response(response)?; - assert_eq!(data.len(), 1); - assert_eq!(data[0].cwd.as_path(), requested_cwd.path()); - assert!( - data[0] - .skills - .iter() - .all(|skill| skill.name != "ignored-extra-skill") - ); - Ok(()) -} - #[tokio::test] async fn skills_list_uses_cached_result_until_force_reload() -> Result<()> { let codex_home = TempDir::new()?; let cwd = TempDir::new()?; - let extra_root = TempDir::new()?; - write_skill(&extra_root, "late-extra-skill")?; let mut mcp = McpProcess::new(codex_home.path()).await?; timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??; - // Seed the cwd cache first without extra roots. + // Seed the cwd cache before the cwd-local skill exists. let first_request_id = mcp .send_skills_list_request(SkillsListParams { cwds: vec![cwd.path().to_path_buf()], force_reload: false, - per_cwd_extra_user_roots: None, }) .await?; let first_response: JSONRPCResponse = timeout( @@ -642,14 +522,17 @@ async fn skills_list_uses_cached_result_until_force_reload() -> Result<()> { .all(|skill| skill.name != "late-extra-skill") ); + let skill_dir = cwd.path().join(".codex/skills/late-extra-skill"); + std::fs::create_dir_all(&skill_dir)?; + std::fs::write( + skill_dir.join("SKILL.md"), + "---\nname: late-extra-skill\ndescription: late skill\n---\n\n# Body\n", + )?; + let second_request_id = mcp .send_skills_list_request(SkillsListParams { cwds: vec![cwd.path().to_path_buf()], force_reload: false, - per_cwd_extra_user_roots: Some(vec![SkillsListExtraRootsForCwd { - cwd: cwd.path().to_path_buf(), - extra_user_roots: vec![extra_root.path().to_path_buf()], - }]), }) .await?; let second_response: JSONRPCResponse = timeout( @@ -670,10 +553,6 @@ async fn skills_list_uses_cached_result_until_force_reload() -> Result<()> { .send_skills_list_request(SkillsListParams { cwds: vec![cwd.path().to_path_buf()], force_reload: true, - per_cwd_extra_user_roots: Some(vec![SkillsListExtraRootsForCwd { - cwd: cwd.path().to_path_buf(), - extra_user_roots: vec![extra_root.path().to_path_buf()], - }]), }) .await?; let third_response: JSONRPCResponse = timeout( diff --git a/codex-rs/aws-auth/Cargo.toml b/codex-rs/aws-auth/Cargo.toml index 9e49f7bbe5..6bb5a69ae9 100644 --- a/codex-rs/aws-auth/Cargo.toml +++ b/codex-rs/aws-auth/Cargo.toml @@ -13,7 +13,7 @@ path = "src/lib.rs" workspace = true [dependencies] -aws-config = { workspace = true } +aws-config = { workspace = true, features = ["credentials-login"] } aws-credential-types = { workspace = true } aws-sigv4 = { workspace = true } aws-types = { workspace = true } diff --git a/codex-rs/core-plugins/src/remote.rs b/codex-rs/core-plugins/src/remote.rs index b2da554fd5..4316976284 100644 --- a/codex-rs/core-plugins/src/remote.rs +++ b/codex-rs/core-plugins/src/remote.rs @@ -35,6 +35,7 @@ pub use share::RemotePluginSharePrincipal; pub use share::RemotePluginSharePrincipalType; pub use share::RemotePluginShareSaveResult; pub use share::RemotePluginShareTarget; +pub use share::RemotePluginShareUpdateDiscoverability; pub use share::RemotePluginShareUpdateTargetsResult; pub use share::delete_remote_plugin_share; pub use share::list_remote_plugin_shares; diff --git a/codex-rs/core-plugins/src/remote/share.rs b/codex-rs/core-plugins/src/remote/share.rs index 22751a7ad2..d69d22ea52 100644 --- a/codex-rs/core-plugins/src/remote/share.rs +++ b/codex-rs/core-plugins/src/remote/share.rs @@ -32,7 +32,7 @@ pub struct RemotePluginShareAccessPolicy { pub share_targets: Option>, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum RemotePluginShareDiscoverability { Listed, @@ -40,6 +40,13 @@ pub enum RemotePluginShareDiscoverability { Private, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum RemotePluginShareUpdateDiscoverability { + Unlisted, + Private, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum RemotePluginSharePrincipalType { @@ -64,6 +71,7 @@ pub struct RemotePluginSharePrincipal { #[derive(Debug, Clone, PartialEq, Eq)] pub struct RemotePluginShareUpdateTargetsResult { pub principals: Vec, + pub discoverability: RemotePluginShareDiscoverability, } #[derive(Debug, Clone, PartialEq, Eq, Serialize)] @@ -100,12 +108,14 @@ struct RemoteWorkspacePluginCreateResponse { #[derive(Debug, Clone, PartialEq, Eq, Serialize)] struct RemotePluginShareUpdateTargetsRequest { + discoverability: RemotePluginShareUpdateDiscoverability, targets: Vec, } #[derive(Debug, Clone, PartialEq, Eq, Deserialize)] struct RemotePluginShareUpdateTargetsResponse { principals: Vec, + discoverability: Option, } pub async fn save_remote_plugin_share( @@ -137,6 +147,9 @@ pub async fn save_remote_plugin_share( .etag .ok_or(RemotePluginCatalogError::MissingUploadEtag)?; put_workspace_plugin_upload(&upload.upload_url, archive_bytes).await?; + let share_targets = access_policy.share_targets; + let share_targets = + ensure_unlisted_workspace_target(auth, access_policy.discoverability, share_targets)?; let response = finalize_workspace_plugin_upload( config, auth, @@ -145,7 +158,7 @@ pub async fn save_remote_plugin_share( file_id: upload.file_id, etag, discoverability: access_policy.discoverability, - share_targets: access_policy.share_targets, + share_targets, }, ) .await?; @@ -245,19 +258,64 @@ pub async fn update_remote_plugin_share_targets( auth: Option<&CodexAuth>, remote_plugin_id: &str, targets: Vec, + discoverability: RemotePluginShareUpdateDiscoverability, ) -> Result { let auth = ensure_chatgpt_auth(auth)?; + let target_discoverability = match discoverability { + RemotePluginShareUpdateDiscoverability::Unlisted => { + RemotePluginShareDiscoverability::Unlisted + } + RemotePluginShareUpdateDiscoverability::Private => { + RemotePluginShareDiscoverability::Private + } + }; + let targets = + ensure_unlisted_workspace_target(auth, Some(target_discoverability), Some(targets))? + .unwrap_or_default(); let base_url = config.chatgpt_base_url.trim_end_matches('/'); - let url = format!("{base_url}/public/plugins/{remote_plugin_id}/shares"); + let url = format!("{base_url}/ps/plugins/{remote_plugin_id}/shares"); let client = build_reqwest_client(); - let request = authenticated_request(client.put(&url), auth)? - .json(&RemotePluginShareUpdateTargetsRequest { targets }); + let request = authenticated_request(client.put(&url), auth)?.json( + &RemotePluginShareUpdateTargetsRequest { + discoverability, + targets, + }, + ); let response: RemotePluginShareUpdateTargetsResponse = send_and_decode(request, &url).await?; Ok(RemotePluginShareUpdateTargetsResult { principals: response.principals, + // TODO: Remove this fallback once deployed plugin-service responses always include + // discoverability per the API schema. + discoverability: response.discoverability.unwrap_or(target_discoverability), }) } +fn ensure_unlisted_workspace_target( + auth: &CodexAuth, + discoverability: Option, + targets: Option>, +) -> Result>, RemotePluginCatalogError> { + if discoverability != Some(RemotePluginShareDiscoverability::Unlisted) { + return Ok(targets); + } + let account_id = auth.get_account_id().ok_or_else(|| { + RemotePluginCatalogError::UnexpectedResponse( + "workspace plugin share requires an account id".to_string(), + ) + })?; + let mut targets = targets.unwrap_or_default(); + if !targets.iter().any(|target| { + target.principal_type == RemotePluginSharePrincipalType::Workspace + && target.principal_id == account_id + }) { + targets.push(RemotePluginShareTarget { + principal_type: RemotePluginSharePrincipalType::Workspace, + principal_id: account_id, + }); + } + Ok(Some(targets)) +} + async fn fetch_created_workspace_plugins( config: &RemotePluginServiceConfig, auth: &CodexAuth, diff --git a/codex-rs/core-plugins/src/remote/share/tests.rs b/codex-rs/core-plugins/src/remote/share/tests.rs index 84e698f9dc..35909a8b19 100644 --- a/codex-rs/core-plugins/src/remote/share/tests.rs +++ b/codex-rs/core-plugins/src/remote/share/tests.rs @@ -204,7 +204,7 @@ async fn save_remote_plugin_share_creates_workspace_plugin() { .and(body_json(json!({ "file_id": "file_123", "etag": "\"upload_etag_123\"", - "discoverability": "PRIVATE", + "discoverability": "UNLISTED", "share_targets": [ { "principal_type": "user", @@ -212,7 +212,7 @@ async fn save_remote_plugin_share_creates_workspace_plugin() { }, { "principal_type": "workspace", - "principal_id": "workspace-1", + "principal_id": "account_id", }, ], }))) @@ -231,17 +231,11 @@ async fn save_remote_plugin_share_creates_workspace_plugin() { &plugin_path, /*remote_plugin_id*/ None, RemotePluginShareAccessPolicy { - discoverability: Some(RemotePluginShareDiscoverability::Private), - share_targets: Some(vec![ - RemotePluginShareTarget { - principal_type: RemotePluginSharePrincipalType::User, - principal_id: "user-1".to_string(), - }, - RemotePluginShareTarget { - principal_type: RemotePluginSharePrincipalType::Workspace, - principal_id: "workspace-1".to_string(), - }, - ]), + discoverability: Some(RemotePluginShareDiscoverability::Unlisted), + share_targets: Some(vec![RemotePluginShareTarget { + principal_type: RemotePluginSharePrincipalType::User, + principal_id: "user-1".to_string(), + }]), }, ) .await @@ -401,10 +395,11 @@ async fn update_remote_plugin_share_targets_updates_targets() { let auth = test_auth(); Mock::given(method("PUT")) - .and(path("/backend-api/public/plugins/plugins_123/shares")) + .and(path("/backend-api/ps/plugins/plugins_123/shares")) .and(header("authorization", "Bearer Access Token")) .and(header("chatgpt-account-id", "account_id")) .and(body_json(json!({ + "discoverability": "UNLISTED", "targets": [ { "principal_type": "user", @@ -414,6 +409,10 @@ async fn update_remote_plugin_share_targets_updates_targets() { "principal_type": "group", "principal_id": "group-1", }, + { + "principal_type": "workspace", + "principal_id": "account_id", + }, ], }))) .respond_with(ResponseTemplate::new(200).set_body_json(json!({ @@ -429,6 +428,7 @@ async fn update_remote_plugin_share_targets_updates_targets() { "name": "Engineering", }, ], + "discoverability": "UNLISTED", }))) .expect(1) .mount(&server) @@ -448,6 +448,7 @@ async fn update_remote_plugin_share_targets_updates_targets() { principal_id: "group-1".to_string(), }, ], + RemotePluginShareUpdateDiscoverability::Unlisted, ) .await .unwrap(); @@ -467,6 +468,65 @@ async fn update_remote_plugin_share_targets_updates_targets() { name: "Engineering".to_string(), }, ], + discoverability: RemotePluginShareDiscoverability::Unlisted, + } + ); +} + +#[tokio::test] +async fn update_remote_plugin_share_targets_falls_back_to_requested_discoverability() { + let server = MockServer::start().await; + let config = test_config(&server); + let auth = test_auth(); + + Mock::given(method("PUT")) + .and(path("/backend-api/ps/plugins/plugins_123/shares")) + .and(header("authorization", "Bearer Access Token")) + .and(header("chatgpt-account-id", "account_id")) + .and(body_json(json!({ + "discoverability": "PRIVATE", + "targets": [ + { + "principal_type": "user", + "principal_id": "user-1", + }, + ], + }))) + .respond_with(ResponseTemplate::new(200).set_body_json(json!({ + "principals": [ + { + "principal_type": "user", + "principal_id": "user-1", + "name": "Gavin", + }, + ], + }))) + .expect(1) + .mount(&server) + .await; + + let result = update_remote_plugin_share_targets( + &config, + Some(&auth), + "plugins_123", + vec![RemotePluginShareTarget { + principal_type: RemotePluginSharePrincipalType::User, + principal_id: "user-1".to_string(), + }], + RemotePluginShareUpdateDiscoverability::Private, + ) + .await + .unwrap(); + + assert_eq!( + result, + RemotePluginShareUpdateTargetsResult { + principals: vec![RemotePluginSharePrincipal { + principal_type: RemotePluginSharePrincipalType::User, + principal_id: "user-1".to_string(), + name: "Gavin".to_string(), + }], + discoverability: RemotePluginShareDiscoverability::Private, } ); } diff --git a/codex-rs/core-skills/src/manager.rs b/codex-rs/core-skills/src/manager.rs index 73b1f14807..db19322acf 100644 --- a/codex-rs/core-skills/src/manager.rs +++ b/codex-rs/core-skills/src/manager.rs @@ -131,17 +131,6 @@ impl SkillsManager { input: &SkillsLoadInput, force_reload: bool, fs: Option>, - ) -> SkillLoadOutcome { - self.skills_for_cwd_with_extra_user_roots(input, force_reload, &[], fs) - .await - } - - pub async fn skills_for_cwd_with_extra_user_roots( - &self, - input: &SkillsLoadInput, - force_reload: bool, - extra_user_roots: &[AbsolutePathBuf], - fs: Option>, ) -> SkillLoadOutcome { let use_cwd_cache = fs.is_some(); if use_cwd_cache @@ -161,18 +150,6 @@ impl SkillsManager { if !bundled_skills_enabled_from_stack(&input.config_layer_stack) { roots.retain(|root| root.scope != SkillScope::System); } - if let Some(fs) = fs { - roots.extend( - normalize_extra_user_roots(extra_user_roots) - .into_iter() - .map(|path| SkillRoot { - path, - scope: SkillScope::User, - file_system: Arc::clone(&fs), - plugin_id: None, - }), - ); - } let skill_config_rules = skill_config_rules_from_stack(&input.config_layer_stack); let outcome = self.build_skill_outcome(roots, &skill_config_rules).await; if use_cwd_cache { @@ -300,16 +277,6 @@ fn finalize_skill_outcome( outcome } -fn normalize_extra_user_roots(extra_user_roots: &[AbsolutePathBuf]) -> Vec { - let mut normalized: Vec = extra_user_roots - .iter() - .map(|root| root.canonicalize().unwrap_or_else(|_| root.clone())) - .collect(); - normalized.sort_unstable(); - normalized.dedup(); - normalized -} - #[cfg(test)] #[path = "manager_tests.rs"] mod tests; diff --git a/codex-rs/core-skills/src/manager_tests.rs b/codex-rs/core-skills/src/manager_tests.rs index 532d6951ec..338da0c398 100644 --- a/codex-rs/core-skills/src/manager_tests.rs +++ b/codex-rs/core-skills/src/manager_tests.rs @@ -11,7 +11,6 @@ use codex_exec_server::LOCAL_FS; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_absolute_path::test_support::PathBufExt; use codex_utils_absolute_path::test_support::PathExt; -use codex_utils_absolute_path::test_support::test_path_buf; use codex_utils_plugins::PluginSkillRoot; use pretty_assertions::assert_eq; use std::collections::HashSet; @@ -263,75 +262,13 @@ async fn skills_for_config_disables_plugin_skills_by_name() { } #[tokio::test] -async fn skills_for_cwd_reuses_cached_entry_even_when_entry_has_extra_roots() { +async fn skills_for_cwd_loads_repo_and_user_roots_with_local_fs() { let codex_home = tempfile::tempdir().expect("tempdir"); let cwd = tempfile::tempdir().expect("tempdir"); - let extra_root = tempfile::tempdir().expect("tempdir"); - let config_layer_stack = config_stack(&codex_home, ""); - let skills_manager = SkillsManager::new( - codex_home.path().abs(), - /*bundled_skills_enabled*/ true, - ); - let _ = skills_for_config_with_stack(&skills_manager, &cwd, &config_layer_stack, &[]).await; - - write_user_skill(&extra_root, "x", "extra-skill", "from extra root"); - let extra_root_path = extra_root.path().abs(); - let base_input = SkillsLoadInput::new( - cwd.path().abs(), - Vec::new(), - config_layer_stack.clone(), - bundled_skills_enabled_from_stack(&config_layer_stack), - ); - let outcome_with_extra = skills_manager - .skills_for_cwd_with_extra_user_roots( - &base_input, - /*force_reload*/ true, - std::slice::from_ref(&extra_root_path), - Some(Arc::clone(&LOCAL_FS)), - ) - .await; - assert!( - outcome_with_extra - .skills - .iter() - .any(|skill| skill.name == "extra-skill") - ); - assert!( - outcome_with_extra - .skills - .iter() - .any(|skill| skill.scope == SkillScope::System) - ); - - // The cwd-only API returns the current cached entry for this cwd, even when that entry - // was produced with extra roots. - let base_input = SkillsLoadInput::new( - cwd.path().abs(), - Vec::new(), - config_layer_stack.clone(), - bundled_skills_enabled_from_stack(&config_layer_stack), - ); - let outcome_without_extra = skills_manager - .skills_for_cwd( - &base_input, - /*force_reload*/ false, - Some(Arc::clone(&LOCAL_FS)), - ) - .await; - assert_eq!(outcome_without_extra.skills, outcome_with_extra.skills); - assert_eq!(outcome_without_extra.errors, outcome_with_extra.errors); -} - -#[tokio::test] -async fn skills_for_cwd_loads_repo_user_and_extra_roots_with_local_fs() { - let codex_home = tempfile::tempdir().expect("tempdir"); - let cwd = tempfile::tempdir().expect("tempdir"); - let extra_root = tempfile::tempdir().expect("tempdir"); let repo_dot_codex = cwd.path().join(".codex"); fs::create_dir_all(&repo_dot_codex).expect("create repo config dir"); write_user_skill(&codex_home, "user", "user-skill", "from local user root"); - write_user_skill(&extra_root, "extra", "extra-skill", "from extra root"); let repo_skill_dir = repo_dot_codex.join("skills/repo"); fs::create_dir_all(&repo_skill_dir).expect("create repo skill dir"); fs::write( @@ -366,10 +303,9 @@ async fn skills_for_cwd_loads_repo_user_and_extra_roots_with_local_fs() { ); let outcome = skills_manager - .skills_for_cwd_with_extra_user_roots( + .skills_for_cwd( &skills_input, /*force_reload*/ true, - &[extra_root.path().abs()], Some(Arc::clone(&LOCAL_FS)), ) .await; @@ -386,19 +322,16 @@ async fn skills_for_cwd_loads_repo_user_and_extra_roots_with_local_fs() { .collect::>(); assert!(loaded_names.contains("user-skill")); assert!(loaded_names.contains("repo-skill")); - assert!(loaded_names.contains("extra-skill")); } #[tokio::test] -async fn skills_for_cwd_without_fs_skips_repo_and_extra_roots() { +async fn skills_for_cwd_without_fs_skips_repo_roots() { let codex_home = tempfile::tempdir().expect("tempdir"); let cwd = tempfile::tempdir().expect("tempdir"); - let extra_root = tempfile::tempdir().expect("tempdir"); let repo_dot_codex = cwd.path().join(".codex"); fs::create_dir_all(&repo_dot_codex).expect("create repo config dir"); write_user_skill(&codex_home, "user", "user-skill", "from local user root"); - write_user_skill(&extra_root, "extra", "extra-skill", "from extra root"); let repo_skill_dir = repo_dot_codex.join("skills/repo"); fs::create_dir_all(&repo_skill_dir).expect("create repo skill dir"); fs::write( @@ -433,12 +366,7 @@ async fn skills_for_cwd_without_fs_skips_repo_and_extra_roots() { ); let outcome = skills_manager - .skills_for_cwd_with_extra_user_roots( - &skills_input, - /*force_reload*/ true, - &[extra_root.path().abs()], - /*fs*/ None, - ) + .skills_for_cwd(&skills_input, /*force_reload*/ true, /*fs*/ None) .await; assert!( @@ -453,7 +381,6 @@ async fn skills_for_cwd_without_fs_skips_repo_and_extra_roots() { .collect::>(); assert!(loaded_names.contains("user-skill")); assert!(!loaded_names.contains("repo-skill")); - assert!(!loaded_names.contains("extra-skill")); } #[tokio::test] @@ -499,22 +426,15 @@ async fn skills_for_config_excludes_bundled_skills_when_disabled_in_config() { } #[tokio::test] -async fn skills_for_cwd_with_extra_roots_only_refreshes_on_force_reload() { +async fn skills_for_cwd_uses_cached_result_until_force_reload() { let codex_home = tempfile::tempdir().expect("tempdir"); let cwd = tempfile::tempdir().expect("tempdir"); - let extra_root_a = tempfile::tempdir().expect("tempdir"); - let extra_root_b = tempfile::tempdir().expect("tempdir"); let config_layer_stack = config_stack(&codex_home, ""); let skills_manager = SkillsManager::new( codex_home.path().abs(), /*bundled_skills_enabled*/ true, ); let _ = skills_for_config_with_stack(&skills_manager, &cwd, &config_layer_stack, &[]).await; - - write_user_skill(&extra_root_a, "x", "extra-skill-a", "from extra root a"); - write_user_skill(&extra_root_b, "x", "extra-skill-b", "from extra root b"); - - let extra_root_a_path = extra_root_a.path().abs(); let base_input = SkillsLoadInput::new( cwd.path().abs(), Vec::new(), @@ -522,32 +442,25 @@ async fn skills_for_cwd_with_extra_roots_only_refreshes_on_force_reload() { bundled_skills_enabled_from_stack(&config_layer_stack), ); let outcome_a = skills_manager - .skills_for_cwd_with_extra_user_roots( - &base_input, - /*force_reload*/ true, - std::slice::from_ref(&extra_root_a_path), - Some(Arc::clone(&LOCAL_FS)), - ) - .await; - assert!( - outcome_a - .skills - .iter() - .any(|skill| skill.name == "extra-skill-a") - ); - assert!( - outcome_a - .skills - .iter() - .all(|skill| skill.name != "extra-skill-b") - ); - - let extra_root_b_path = extra_root_b.path().abs(); - let outcome_b = skills_manager - .skills_for_cwd_with_extra_user_roots( + .skills_for_cwd( + &base_input, + /*force_reload*/ false, + Some(Arc::clone(&LOCAL_FS)), + ) + .await; + assert!( + outcome_a + .skills + .iter() + .all(|skill| skill.name != "late-skill") + ); + + write_user_skill(&codex_home, "late", "late-skill", "added after cache"); + + let outcome_b = skills_manager + .skills_for_cwd( &base_input, /*force_reload*/ false, - std::slice::from_ref(&extra_root_b_path), Some(Arc::clone(&LOCAL_FS)), ) .await; @@ -555,20 +468,13 @@ async fn skills_for_cwd_with_extra_roots_only_refreshes_on_force_reload() { outcome_b .skills .iter() - .any(|skill| skill.name == "extra-skill-a") - ); - assert!( - outcome_b - .skills - .iter() - .all(|skill| skill.name != "extra-skill-b") + .all(|skill| skill.name != "late-skill") ); let outcome_reloaded = skills_manager - .skills_for_cwd_with_extra_user_roots( + .skills_for_cwd( &base_input, /*force_reload*/ true, - std::slice::from_ref(&extra_root_b_path), Some(Arc::clone(&LOCAL_FS)), ) .await; @@ -576,25 +482,8 @@ async fn skills_for_cwd_with_extra_roots_only_refreshes_on_force_reload() { outcome_reloaded .skills .iter() - .any(|skill| skill.name == "extra-skill-b") + .any(|skill| skill.name == "late-skill") ); - assert!( - outcome_reloaded - .skills - .iter() - .all(|skill| skill.name != "extra-skill-a") - ); -} - -#[test] -fn normalize_extra_user_roots_is_stable_for_equivalent_inputs() { - let a = test_path_buf("/tmp/a").abs(); - let b = test_path_buf("/tmp/b").abs(); - - let first = normalize_extra_user_roots(&[a.clone(), b.clone(), a.clone()]); - let second = normalize_extra_user_roots(&[b, a]); - - assert_eq!(first, second); } #[cfg_attr(windows, ignore)] diff --git a/codex-rs/core/src/codex_delegate_tests.rs b/codex-rs/core/src/codex_delegate_tests.rs index 84224ea2d5..ecd392e3e7 100644 --- a/codex-rs/core/src/codex_delegate_tests.rs +++ b/codex-rs/core/src/codex_delegate_tests.rs @@ -225,6 +225,7 @@ async fn handle_request_permissions_uses_tool_call_id_for_round_trip() { RequestPermissionsEvent { call_id: request_call_id, turn_id: "child-turn-1".to_string(), + started_at_ms: 0, reason: Some("need access".to_string()), permissions: RequestPermissionProfile { network: Some(NetworkPermissions { @@ -313,6 +314,7 @@ async fn handle_exec_approval_uses_call_id_for_guardian_review_and_approval_id_f call_id: "command-item-1".to_string(), approval_id: Some("callback-approval-1".to_string()), turn_id: "child-turn-1".to_string(), + started_at_ms: 0, command: vec!["rm".to_string(), "-rf".to_string(), "tmp".to_string()], cwd: test_path_buf("/tmp").abs(), reason: Some("unsafe subcommand".to_string()), diff --git a/codex-rs/core/src/guardian/review.rs b/codex-rs/core/src/guardian/review.rs index 850d84dd2a..bba2167cef 100644 --- a/codex-rs/core/src/guardian/review.rs +++ b/codex-rs/core/src/guardian/review.rs @@ -23,6 +23,7 @@ use tokio_util::sync::CancellationToken; use crate::session::session::Session; use crate::session::turn_context::TurnContext; +use crate::turn_timing::now_unix_timestamp_ms; use super::GUARDIAN_REVIEW_TIMEOUT; use super::GUARDIAN_REVIEWER_NAME; @@ -251,6 +252,7 @@ async fn run_guardian_review( guardian_reviewed_action(&request), GUARDIAN_REVIEW_TIMEOUT.as_millis() as u64, ); + let started_at_ms = review_tracking.started_at_ms.try_into().unwrap_or_default(); session .send_event( turn.as_ref(), @@ -258,6 +260,8 @@ async fn run_guardian_review( id: review_id.clone(), target_item_id: target_item_id.clone(), turn_id: assessment_turn_id.clone(), + started_at_ms, + completed_at_ms: None, status: GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -289,6 +293,8 @@ async fn run_guardian_review( id: review_id, target_item_id, turn_id: assessment_turn_id.clone(), + started_at_ms, + completed_at_ms: Some(now_unix_timestamp_ms()), status: GuardianAssessmentStatus::Aborted, risk_level: None, user_authorization: None, @@ -372,6 +378,8 @@ async fn run_guardian_review( id: review_id, target_item_id, turn_id: assessment_turn_id.clone(), + started_at_ms, + completed_at_ms: Some(now_unix_timestamp_ms()), status: GuardianAssessmentStatus::TimedOut, risk_level: None, user_authorization: None, @@ -402,6 +410,8 @@ async fn run_guardian_review( id: review_id, target_item_id, turn_id: assessment_turn_id.clone(), + started_at_ms, + completed_at_ms: Some(now_unix_timestamp_ms()), status: GuardianAssessmentStatus::Aborted, risk_level: None, user_authorization: None, @@ -495,6 +505,8 @@ async fn run_guardian_review( id: review_id, target_item_id, turn_id: assessment_turn_id.clone(), + started_at_ms, + completed_at_ms: Some(now_unix_timestamp_ms()), status, risk_level: Some(assessment.risk_level), user_authorization: Some(assessment.user_authorization), diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs index 8950cdc03f..422ee87792 100644 --- a/codex-rs/core/src/session/mod.rs +++ b/codex-rs/core/src/session/mod.rs @@ -1934,6 +1934,7 @@ impl Session { call_id, approval_id, turn_id: turn_context.sub_id.clone(), + started_at_ms: now_unix_timestamp_ms(), command, cwd, reason, @@ -1980,6 +1981,7 @@ impl Session { let event = EventMsg::ApplyPatchApprovalRequest(ApplyPatchApprovalRequestEvent { call_id, turn_id: turn_context.sub_id.clone(), + started_at_ms: now_unix_timestamp_ms(), changes, reason, grant_root, @@ -2143,6 +2145,7 @@ impl Session { let event = EventMsg::RequestPermissions(RequestPermissionsEvent { call_id: call_id.clone(), turn_id: turn_context.sub_id.clone(), + started_at_ms: now_unix_timestamp_ms(), reason: args.reason, permissions: requested_permissions, cwd: Some(cwd), diff --git a/codex-rs/mcp-server/src/codex_tool_runner.rs b/codex-rs/mcp-server/src/codex_tool_runner.rs index 00611b3a8c..9e3ac1bae9 100644 --- a/codex-rs/mcp-server/src/codex_tool_runner.rs +++ b/codex-rs/mcp-server/src/codex_tool_runner.rs @@ -222,6 +222,7 @@ async fn run_codex_tool_session_inner( let approval_id = ev.effective_approval_id(); let ExecApprovalRequestEvent { turn_id: _, + started_at_ms: _, command, cwd, call_id, @@ -278,6 +279,7 @@ async fn run_codex_tool_session_inner( EventMsg::ApplyPatchApprovalRequest(ApplyPatchApprovalRequestEvent { call_id, turn_id: _, + started_at_ms: _, reason, grant_root, changes, diff --git a/codex-rs/model-provider/src/amazon_bedrock/auth.rs b/codex-rs/model-provider/src/amazon_bedrock/auth.rs index 96c233207f..f3101b0ae9 100644 --- a/codex-rs/model-provider/src/amazon_bedrock/auth.rs +++ b/codex-rs/model-provider/src/amazon_bedrock/auth.rs @@ -20,7 +20,6 @@ use super::mantle::aws_auth_config; use super::mantle::region_from_config; const AWS_BEARER_TOKEN_BEDROCK_ENV_VAR: &str = "AWS_BEARER_TOKEN_BEDROCK"; -const LEGACY_SESSION_ID_HEADER: &str = "session_id"; pub(super) enum BedrockAuthMethod { EnvBearerToken { token: String, region: String }, @@ -87,10 +86,18 @@ fn aws_auth_error_to_auth_error(error: AwsAuthError) -> AuthError { } fn remove_headers_not_preserved_by_bedrock_mantle(headers: &mut HeaderMap) { - // The Bedrock Mantle front door does not preserve this legacy OpenAI header - // for SigV4 verification. Signing it makes the richer Codex agent request - // fail even though raw Responses requests work. - headers.remove(LEGACY_SESSION_ID_HEADER); + // The Bedrock Mantle front door does not preserve legacy OpenAI + // compatibility headers that use snake_case, such as `session_id` and + // `thread_id`, before SigV4 verification. Signing that header class makes + // richer Codex agent requests fail even though raw Responses requests work. + let headers_to_remove = headers + .keys() + .filter(|name| name.as_str().contains('_')) + .cloned() + .collect::>(); + for name in headers_to_remove { + headers.remove(name); + } } /// AWS SigV4 auth provider for Bedrock Mantle OpenAI-compatible requests. @@ -182,10 +189,18 @@ mod tests { } #[test] - fn bedrock_mantle_sigv4_strips_legacy_session_id_header() { + fn bedrock_mantle_sigv4_strips_headers_not_preserved_by_mantle() { let mut headers = HeaderMap::new(); headers.insert( - LEGACY_SESSION_ID_HEADER, + "session_id", + HeaderValue::from_static("019dae79-15c3-70c3-8736-3219b8602b37"), + ); + headers.insert( + "thread_id", + HeaderValue::from_static("019dae79-15c3-70c3-8736-3219b8602b37"), + ); + headers.insert( + "future_identity_header", HeaderValue::from_static("019dae79-15c3-70c3-8736-3219b8602b37"), ); headers.insert( @@ -195,7 +210,9 @@ mod tests { remove_headers_not_preserved_by_bedrock_mantle(&mut headers); - assert!(!headers.contains_key(LEGACY_SESSION_ID_HEADER)); + assert!(!headers.contains_key("session_id")); + assert!(!headers.contains_key("thread_id")); + assert!(!headers.contains_key("future_identity_header")); assert_eq!( headers .get("x-client-request-id") diff --git a/codex-rs/protocol/src/approvals.rs b/codex-rs/protocol/src/approvals.rs index 73283e3eb6..ace096359c 100644 --- a/codex-rs/protocol/src/approvals.rs +++ b/codex-rs/protocol/src/approvals.rs @@ -187,6 +187,12 @@ pub struct GuardianAssessmentEvent { /// Uses `#[serde(default)]` for backwards compatibility. #[serde(default)] pub turn_id: String, + #[serde(default)] + #[ts(type = "number")] + pub started_at_ms: i64, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[ts(optional, type = "number")] + pub completed_at_ms: Option, pub status: GuardianAssessmentStatus, /// Coarse risk label. Omitted while the assessment is in progress. #[serde(default, skip_serializing_if = "Option::is_none")] @@ -223,6 +229,8 @@ pub struct ExecApprovalRequestEvent { /// Uses `#[serde(default)]` for backwards compatibility. #[serde(default)] pub turn_id: String, + #[ts(type = "number")] + pub started_at_ms: i64, /// The command to be executed. pub command: Vec, /// The command's working directory. @@ -370,6 +378,8 @@ pub struct ApplyPatchApprovalRequestEvent { /// Uses `#[serde(default)]` for backwards compatibility with older senders. #[serde(default)] pub turn_id: String, + #[ts(type = "number")] + pub started_at_ms: i64, pub changes: HashMap, /// Optional explanatory reason (e.g. request for extra write access). #[serde(skip_serializing_if = "Option::is_none")] diff --git a/codex-rs/protocol/src/request_permissions.rs b/codex-rs/protocol/src/request_permissions.rs index 6c7b699daf..be6b88ef52 100644 --- a/codex-rs/protocol/src/request_permissions.rs +++ b/codex-rs/protocol/src/request_permissions.rs @@ -71,6 +71,8 @@ pub struct RequestPermissionsEvent { /// Uses `#[serde(default)]` for backwards compatibility. #[serde(default)] pub turn_id: String, + #[ts(type = "number")] + pub started_at_ms: i64, #[serde(skip_serializing_if = "Option::is_none")] pub reason: Option, pub permissions: RequestPermissionProfile, diff --git a/codex-rs/rollout/src/recorder_tests.rs b/codex-rs/rollout/src/recorder_tests.rs index 505cd59929..bf51241f5b 100644 --- a/codex-rs/rollout/src/recorder_tests.rs +++ b/codex-rs/rollout/src/recorder_tests.rs @@ -216,6 +216,68 @@ async fn load_rollout_items_skips_legacy_ghost_snapshot_lines() -> std::io::Resu Ok(()) } +#[tokio::test] +async fn load_rollout_items_preserves_legacy_guardian_assessment_lines() -> std::io::Result<()> { + let home = TempDir::new().expect("temp dir"); + let rollout_path = home.path().join("rollout.jsonl"); + let mut file = File::create(&rollout_path)?; + let thread_id = ThreadId::new(); + let ts = "2025-01-03T12:00:00Z"; + + writeln!( + file, + "{}", + serde_json::json!({ + "timestamp": ts, + "type": "session_meta", + "payload": { + "id": thread_id, + "timestamp": ts, + "cwd": ".", + "originator": "test_originator", + "cli_version": "test_version", + "source": "cli", + "model_provider": "test-provider", + }, + }) + )?; + writeln!( + file, + "{}", + serde_json::json!({ + "timestamp": ts, + "type": "event_msg", + "payload": { + "type": "guardian_assessment", + "id": "guardian-1", + "turn_id": "turn-1", + "status": "in_progress", + "action": { + "type": "command", + "source": "shell", + "command": "rm -rf /tmp/guardian", + "cwd": if cfg!(windows) { r"C:\tmp" } else { "/tmp" }, + }, + }, + }) + )?; + + let (items, loaded_thread_id, parse_errors) = + RolloutRecorder::load_rollout_items(&rollout_path).await?; + + assert_eq!(loaded_thread_id, Some(thread_id)); + assert_eq!(parse_errors, 0); + assert_eq!(items.len(), 2); + let RolloutItem::EventMsg(EventMsg::GuardianAssessment(assessment)) = &items[1] else { + panic!("expected guardian assessment rollout item"); + }; + assert_eq!(assessment.id, "guardian-1"); + assert_eq!(assessment.turn_id, "turn-1"); + assert_eq!(assessment.started_at_ms, 0); + + Ok(()) +} + #[tokio::test] async fn load_rollout_items_filters_legacy_ghost_snapshots_from_compaction_history() -> std::io::Result<()> { diff --git a/codex-rs/tui/src/app/app_server_requests.rs b/codex-rs/tui/src/app/app_server_requests.rs index 4b587b0fc8..dce87f367e 100644 --- a/codex-rs/tui/src/app/app_server_requests.rs +++ b/codex-rs/tui/src/app/app_server_requests.rs @@ -429,6 +429,7 @@ mod tests { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), item_id: "call-1".to_string(), + started_at_ms: 0, approval_id: Some("approval-1".to_string()), reason: None, network_approval_context: None, @@ -481,6 +482,7 @@ mod tests { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), item_id: "perm-1".to_string(), + started_at_ms: 0, cwd: absolute_path(if cfg!(windows) { r"C:\tmp" } else { "/tmp" }), reason: None, permissions: serde_json::from_value(json!({ @@ -686,6 +688,7 @@ mod tests { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), item_id: "patch-1".to_string(), + started_at_ms: 0, reason: None, grant_root: None, }, @@ -715,6 +718,7 @@ mod tests { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), item_id: "call-1".to_string(), + started_at_ms: 0, approval_id: Some("approval-1".to_string()), reason: None, network_approval_context: None, diff --git a/codex-rs/tui/src/app/background_requests.rs b/codex-rs/tui/src/app/background_requests.rs index 82cbd9f301..83819349b4 100644 --- a/codex-rs/tui/src/app/background_requests.rs +++ b/codex-rs/tui/src/app/background_requests.rs @@ -648,7 +648,6 @@ pub(super) async fn fetch_skills_list( params: SkillsListParams { cwds: vec![cwd], force_reload: true, - per_cwd_extra_user_roots: None, }, }) .await diff --git a/codex-rs/tui/src/app/pending_interactive_replay.rs b/codex-rs/tui/src/app/pending_interactive_replay.rs index 671e41461c..1a21d4df50 100644 --- a/codex-rs/tui/src/app/pending_interactive_replay.rs +++ b/codex-rs/tui/src/app/pending_interactive_replay.rs @@ -612,6 +612,7 @@ mod tests { thread_id: "thread-1".to_string(), turn_id: turn_id.to_string(), item_id: call_id.to_string(), + started_at_ms: 0, approval_id: approval_id.map(str::to_string), reason: None, network_approval_context: None, @@ -633,6 +634,7 @@ mod tests { thread_id: "thread-1".to_string(), turn_id: turn_id.to_string(), item_id: call_id.to_string(), + started_at_ms: 0, reason: None, grant_root: None, }, diff --git a/codex-rs/tui/src/app/tests.rs b/codex-rs/tui/src/app/tests.rs index 5ab85887a7..eacb6d5053 100644 --- a/codex-rs/tui/src/app/tests.rs +++ b/codex-rs/tui/src/app/tests.rs @@ -2659,6 +2659,7 @@ async fn inactive_thread_file_change_approval_recovers_buffered_changes() { thread_id: thread_id.to_string(), turn_id: "turn-approval".to_string(), item_id: "patch-approval".to_string(), + started_at_ms: 0, reason: Some("command failed; retry without sandbox?".to_string()), grant_root: None, }, @@ -2709,6 +2710,7 @@ async fn inactive_thread_permissions_approval_preserves_file_system_permissions( thread_id: thread_id.to_string(), turn_id: "turn-approval".to_string(), item_id: "call-approval".to_string(), + started_at_ms: 0, cwd: test_absolute_path("/tmp"), reason: Some("Need access to .git".to_string()), permissions: codex_app_server_protocol::RequestPermissionProfile { @@ -4259,6 +4261,7 @@ fn exec_approval_request( thread_id: thread_id.to_string(), turn_id: turn_id.to_string(), item_id: item_id.to_string(), + started_at_ms: 0, approval_id: approval_id.map(str::to_string), reason: Some("needs approval".to_string()), network_approval_context: None, diff --git a/codex-rs/tui/src/app/thread_events.rs b/codex-rs/tui/src/app/thread_events.rs index 56477c18cf..431bf5f804 100644 --- a/codex-rs/tui/src/app/thread_events.rs +++ b/codex-rs/tui/src/app/thread_events.rs @@ -465,6 +465,7 @@ mod tests { thread_id: thread_id.to_string(), turn_id: turn_id.to_string(), item_id: item_id.to_string(), + started_at_ms: 0, approval_id: approval_id.map(str::to_string), reason: Some("needs approval".to_string()), network_approval_context: None, diff --git a/codex-rs/tui/src/app/thread_routing.rs b/codex-rs/tui/src/app/thread_routing.rs index 1a7986ad31..9a76b54168 100644 --- a/codex-rs/tui/src/app/thread_routing.rs +++ b/codex-rs/tui/src/app/thread_routing.rs @@ -621,7 +621,6 @@ impl App { .skills_list(codex_app_server_protocol::SkillsListParams { cwds: cwds.clone(), force_reload: *force_reload, - per_cwd_extra_user_roots: None, }) .await, "failed to refresh skills", diff --git a/codex-rs/tui/src/auto_review_denials.rs b/codex-rs/tui/src/auto_review_denials.rs index e51e071e21..149a60f049 100644 --- a/codex-rs/tui/src/auto_review_denials.rs +++ b/codex-rs/tui/src/auto_review_denials.rs @@ -88,6 +88,8 @@ mod tests { id: format!("review-{id}"), target_item_id: None, turn_id: "turn-1".to_string(), + started_at_ms: 0, + completed_at_ms: Some(1), status: GuardianAssessmentStatus::Denied, risk_level: None, user_authorization: None, diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index adaba76b24..35d523aa5b 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -1637,6 +1637,7 @@ fn request_permissions_from_params( RequestPermissionsEvent { turn_id: params.turn_id, call_id: params.item_id, + started_at_ms: params.started_at_ms, reason: params.reason, permissions: params.permissions.into(), cwd: Some(params.cwd), @@ -6374,8 +6375,9 @@ impl ChatWidget { self.on_guardian_review_notification( notification.review_id, notification.turn_id, + notification.started_at_ms, notification.review, - /*decision_source*/ None, + /*completion*/ None, notification.action, ); } @@ -6383,8 +6385,9 @@ impl ChatWidget { self.on_guardian_review_notification( notification.review_id, notification.turn_id, + notification.started_at_ms, notification.review, - Some(notification.decision_source), + Some((notification.completed_at_ms, notification.decision_source)), notification.action, ); } @@ -6567,14 +6570,24 @@ impl ChatWidget { &mut self, id: String, turn_id: String, + started_at_ms: i64, review: codex_app_server_protocol::GuardianApprovalReview, - decision_source: Option, + completion: Option<(i64, codex_app_server_protocol::AutoReviewDecisionSource)>, action: GuardianApprovalReviewAction, ) { + let (completed_at_ms, decision_source) = match completion { + Some((completed_at_ms, decision_source)) => { + (Some(completed_at_ms), Some(decision_source)) + } + None => (None, None), + }; + self.on_guardian_assessment(GuardianAssessmentEvent { id, target_item_id: None, turn_id, + started_at_ms, + completed_at_ms, status: match review.status { codex_app_server_protocol::GuardianApprovalReviewStatus::InProgress => { GuardianAssessmentStatus::InProgress diff --git a/codex-rs/tui/src/chatwidget/tests/approval_requests.rs b/codex-rs/tui/src/chatwidget/tests/approval_requests.rs index 93e2a38c13..85c8fc6c03 100644 --- a/codex-rs/tui/src/chatwidget/tests/approval_requests.rs +++ b/codex-rs/tui/src/chatwidget/tests/approval_requests.rs @@ -55,6 +55,7 @@ fn app_server_exec_approval_request_splits_shell_wrapped_command() { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), item_id: "item-1".to_string(), + started_at_ms: 0, approval_id: Some("approval-1".to_string()), reason: None, network_approval_context: None, @@ -93,6 +94,7 @@ fn app_server_exec_approval_request_preserves_permissions_context() { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), item_id: "item-1".to_string(), + started_at_ms: 0, approval_id: Some("approval-1".to_string()), reason: None, network_approval_context: Some(codex_app_server_protocol::NetworkApprovalContext { @@ -156,6 +158,7 @@ fn app_server_request_permissions_preserves_file_system_permissions() { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), item_id: "item-1".to_string(), + started_at_ms: 0, cwd: cwd.clone(), reason: Some("Select a workspace root".to_string()), permissions: codex_app_server_protocol::RequestPermissionProfile { diff --git a/codex-rs/tui/src/chatwidget/tests/exec_flow.rs b/codex-rs/tui/src/chatwidget/tests/exec_flow.rs index b1949d7809..0045e7d126 100644 --- a/codex-rs/tui/src/chatwidget/tests/exec_flow.rs +++ b/codex-rs/tui/src/chatwidget/tests/exec_flow.rs @@ -54,6 +54,7 @@ fn app_server_exec_approval_request_splits_shell_wrapped_command() { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), item_id: "item-1".to_string(), + started_at_ms: 0, approval_id: Some("approval-1".to_string()), reason: None, network_approval_context: None, diff --git a/codex-rs/tui/src/chatwidget/tests/guardian.rs b/codex-rs/tui/src/chatwidget/tests/guardian.rs index c51b3f6687..7cdc9f760b 100644 --- a/codex-rs/tui/src/chatwidget/tests/guardian.rs +++ b/codex-rs/tui/src/chatwidget/tests/guardian.rs @@ -6,6 +6,8 @@ fn auto_review_denial_event() -> GuardianAssessmentEvent { id: "auto-review-recent-1".into(), target_item_id: Some("target-auto-review-recent-1".into()), turn_id: "turn-recent-1".into(), + started_at_ms: 0, + completed_at_ms: Some(1), status: GuardianAssessmentStatus::Denied, risk_level: Some(GuardianRiskLevel::High), user_authorization: Some(GuardianUserAuthorization::Low), @@ -73,6 +75,8 @@ async fn guardian_denied_exec_renders_warning_and_denied_request() { id: "guardian-1".into(), target_item_id: Some("guardian-target-1".into()), turn_id: "turn-1".into(), + started_at_ms: 0, + completed_at_ms: None, status: GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -85,6 +89,8 @@ async fn guardian_denied_exec_renders_warning_and_denied_request() { id: "guardian-1".into(), target_item_id: Some("guardian-target-1".into()), turn_id: "turn-1".into(), + started_at_ms: 0, + completed_at_ms: Some(1), status: GuardianAssessmentStatus::Denied, risk_level: Some(GuardianRiskLevel::High), user_authorization: Some(GuardianUserAuthorization::Low), @@ -127,6 +133,8 @@ async fn guardian_approved_exec_renders_approved_request() { id: "thread:child-thread:guardian-1".into(), target_item_id: Some("guardian-approved-target".into()), turn_id: "turn-1".into(), + started_at_ms: 0, + completed_at_ms: Some(1), status: GuardianAssessmentStatus::Approved, risk_level: Some(GuardianRiskLevel::Low), user_authorization: Some(GuardianUserAuthorization::High), @@ -183,6 +191,8 @@ async fn guardian_approved_request_permissions_renders_request_summary() { id: "guardian-request-permissions".into(), target_item_id: None, turn_id: "turn-1".into(), + started_at_ms: 0, + completed_at_ms: None, status: GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -205,6 +215,8 @@ async fn guardian_approved_request_permissions_renders_request_summary() { id: "guardian-request-permissions".into(), target_item_id: None, turn_id: "turn-1".into(), + started_at_ms: 0, + completed_at_ms: Some(1), status: GuardianAssessmentStatus::Approved, risk_level: Some(GuardianRiskLevel::Low), user_authorization: Some(GuardianUserAuthorization::High), @@ -253,6 +265,8 @@ async fn guardian_timed_out_exec_renders_warning_and_timed_out_request() { id: "guardian-1".into(), target_item_id: Some("guardian-target-1".into()), turn_id: "turn-1".into(), + started_at_ms: 0, + completed_at_ms: None, status: GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -265,6 +279,8 @@ async fn guardian_timed_out_exec_renders_warning_and_timed_out_request() { id: "guardian-1".into(), target_item_id: Some("guardian-target-1".into()), turn_id: "turn-1".into(), + started_at_ms: 0, + completed_at_ms: Some(1), status: GuardianAssessmentStatus::TimedOut, risk_level: None, user_authorization: None, @@ -315,6 +331,7 @@ async fn app_server_guardian_review_started_sets_review_status() { ItemGuardianApprovalReviewStartedNotification { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), + started_at_ms: 0, review_id: "guardian-1".to_string(), target_item_id: Some("guardian-target-1".to_string()), review: GuardianApprovalReview { @@ -356,6 +373,7 @@ async fn app_server_guardian_review_denied_renders_denied_request_snapshot() { ItemGuardianApprovalReviewStartedNotification { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), + started_at_ms: 0, review_id: "guardian-1".to_string(), target_item_id: Some("guardian-target-1".to_string()), review: GuardianApprovalReview { @@ -375,6 +393,8 @@ async fn app_server_guardian_review_denied_renders_denied_request_snapshot() { ItemGuardianApprovalReviewCompletedNotification { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), + started_at_ms: 0, + completed_at_ms: 1, review_id: "guardian-1".to_string(), target_item_id: Some("guardian-target-1".to_string()), decision_source: AppServerGuardianApprovalReviewDecisionSource::Agent, @@ -431,6 +451,7 @@ async fn app_server_guardian_review_timed_out_renders_timed_out_request_snapshot ItemGuardianApprovalReviewStartedNotification { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), + started_at_ms: 0, review_id: "guardian-1".to_string(), target_item_id: Some("guardian-target-1".to_string()), review: GuardianApprovalReview { @@ -450,6 +471,8 @@ async fn app_server_guardian_review_timed_out_renders_timed_out_request_snapshot ItemGuardianApprovalReviewCompletedNotification { thread_id: "thread-1".to_string(), turn_id: "turn-1".to_string(), + started_at_ms: 0, + completed_at_ms: 1, review_id: "guardian-1".to_string(), target_item_id: Some("guardian-target-1".to_string()), decision_source: AppServerGuardianApprovalReviewDecisionSource::Agent, @@ -506,6 +529,8 @@ async fn guardian_parallel_reviews_render_aggregate_status_snapshot() { id: id.to_string(), target_item_id: Some(format!("{id}-target")), turn_id: "turn-1".to_string(), + started_at_ms: 0, + completed_at_ms: None, status: GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -535,6 +560,8 @@ async fn guardian_parallel_reviews_keep_remaining_review_visible_after_denial() id: "guardian-1".to_string(), target_item_id: Some("guardian-1-target".to_string()), turn_id: "turn-1".to_string(), + started_at_ms: 0, + completed_at_ms: None, status: GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -550,6 +577,8 @@ async fn guardian_parallel_reviews_keep_remaining_review_visible_after_denial() id: "guardian-2".to_string(), target_item_id: Some("guardian-2-target".to_string()), turn_id: "turn-1".to_string(), + started_at_ms: 0, + completed_at_ms: None, status: GuardianAssessmentStatus::InProgress, risk_level: None, user_authorization: None, @@ -565,6 +594,8 @@ async fn guardian_parallel_reviews_keep_remaining_review_visible_after_denial() id: "guardian-1".to_string(), target_item_id: Some("guardian-1-target".to_string()), turn_id: "turn-1".to_string(), + started_at_ms: 0, + completed_at_ms: Some(1), status: GuardianAssessmentStatus::Denied, risk_level: Some(GuardianRiskLevel::High), user_authorization: Some(GuardianUserAuthorization::Low),