mirror of
https://github.com/openai/codex.git
synced 2026-10-27 18:48:37 +00:00
Remove age dependency from secrets storage
This commit is contained in:
Generated
-32
File diff suppressed because one or more lines are too long
Generated
+20
-376
@@ -196,49 +196,6 @@ dependencies = [
|
||||
"cpufeatures 0.2.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "age"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf640be7658959746f1f0f2faab798f6098a9436a8e18e148d18bc9875e13c4b"
|
||||
dependencies = [
|
||||
"age-core",
|
||||
"base64 0.21.7",
|
||||
"bech32",
|
||||
"chacha20poly1305",
|
||||
"cookie-factory",
|
||||
"hmac 0.12.1",
|
||||
"i18n-embed",
|
||||
"i18n-embed-fl",
|
||||
"lazy_static",
|
||||
"nom 7.1.3",
|
||||
"pin-project",
|
||||
"rand 0.8.5",
|
||||
"rust-embed",
|
||||
"scrypt",
|
||||
"sha2 0.10.9",
|
||||
"subtle",
|
||||
"x25519-dalek",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "age-core"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2bf6a89c984ca9d850913ece2da39e1d200563b0a94b002b253beee4c5acf99"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"chacha20poly1305",
|
||||
"cookie-factory",
|
||||
"hkdf 0.12.4",
|
||||
"io_tee",
|
||||
"nom 7.1.3",
|
||||
"rand 0.8.5",
|
||||
"secrecy",
|
||||
"sha2 0.10.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.12"
|
||||
@@ -1250,21 +1207,6 @@ version = "1.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
|
||||
|
||||
[[package]]
|
||||
name = "basic-toml"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bech32"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
|
||||
|
||||
[[package]]
|
||||
name = "beef"
|
||||
version = "0.5.2"
|
||||
@@ -1295,7 +1237,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
@@ -2025,7 +1967,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"toml_edit 0.24.0+spec-1.1.0",
|
||||
"tracing",
|
||||
"tracing-opentelemetry",
|
||||
@@ -2057,7 +1999,7 @@ dependencies = [
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
@@ -2355,7 +2297,7 @@ dependencies = [
|
||||
"sys-locale",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
"tracing-subscriber",
|
||||
@@ -2532,7 +2474,7 @@ dependencies = [
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"toml_edit 0.24.0+spec-1.1.0",
|
||||
"tonic",
|
||||
"tonic-prost",
|
||||
@@ -2674,7 +2616,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"toml_edit 0.24.0+spec-1.1.0",
|
||||
"tracing",
|
||||
"tracing-opentelemetry",
|
||||
@@ -2741,7 +2683,7 @@ dependencies = [
|
||||
"tempfile",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"tracing",
|
||||
"url",
|
||||
"wiremock",
|
||||
@@ -2775,7 +2717,7 @@ dependencies = [
|
||||
"shlex",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"tracing",
|
||||
"zip 2.4.2",
|
||||
]
|
||||
@@ -2862,7 +2804,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"tracing",
|
||||
"uuid",
|
||||
"wiremock",
|
||||
@@ -2933,7 +2875,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"tempfile",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2959,7 +2901,7 @@ dependencies = [
|
||||
"pretty_assertions",
|
||||
"schemars 0.8.22",
|
||||
"serde",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -3394,7 +3336,7 @@ dependencies = [
|
||||
"schemars 0.8.22",
|
||||
"serde",
|
||||
"tempfile",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3720,9 +3662,9 @@ dependencies = [
|
||||
name = "codex-secrets"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"age",
|
||||
"anyhow",
|
||||
"base64 0.22.1",
|
||||
"chacha20poly1305",
|
||||
"codex-git-utils",
|
||||
"codex-keyring-store",
|
||||
"keyring",
|
||||
@@ -3735,6 +3677,7 @@ dependencies = [
|
||||
"sha2 0.10.9",
|
||||
"tempfile",
|
||||
"tracing",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4001,7 +3944,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
"tracing-subscriber",
|
||||
@@ -4079,7 +4022,7 @@ dependencies = [
|
||||
"codex-shell-command",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4119,7 +4062,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"pretty_assertions",
|
||||
"serde_json",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4466,15 +4409,6 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie-factory"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2"
|
||||
dependencies = [
|
||||
"futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie_store"
|
||||
version = "0.22.1"
|
||||
@@ -5890,15 +5824,6 @@ dependencies = [
|
||||
"libredox",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-crate"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2"
|
||||
dependencies = [
|
||||
"toml 0.5.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
@@ -5960,50 +5885,6 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb74634707bebd0ce645a981148e8fb8c7bccd4c33c652aeffd28bf2f96d555a"
|
||||
dependencies = [
|
||||
"fluent-bundle",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-bundle"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493"
|
||||
dependencies = [
|
||||
"fluent-langneg",
|
||||
"fluent-syntax",
|
||||
"intl-memoizer",
|
||||
"intl_pluralrules",
|
||||
"rustc-hash 1.1.0",
|
||||
"self_cell 0.10.3",
|
||||
"smallvec",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-langneg"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eebbe59450baee8282d71676f3bfed5689aeab00b27545e83e5f14b1195e8b0"
|
||||
dependencies = [
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-syntax"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d"
|
||||
dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-uri"
|
||||
version = "0.1.4"
|
||||
@@ -7735,72 +7616,6 @@ dependencies = [
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "i18n-config"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e06b90c8a0d252e203c94344b21e35a30f3a3a85dc7db5af8f8df9f3e0c63ef"
|
||||
dependencies = [
|
||||
"basic-toml",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"thiserror 1.0.69",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "i18n-embed"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "669ffc2c93f97e6ddf06ddbe999fcd6782e3342978bb85f7d3c087c7978404c4"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"fluent",
|
||||
"fluent-langneg",
|
||||
"fluent-syntax",
|
||||
"i18n-embed-impl",
|
||||
"intl-memoizer",
|
||||
"log",
|
||||
"parking_lot",
|
||||
"rust-embed",
|
||||
"thiserror 1.0.69",
|
||||
"unic-langid",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "i18n-embed-fl"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04b2969d0b3fc6143776c535184c19722032b43e6a642d710fa3f88faec53c2d"
|
||||
dependencies = [
|
||||
"find-crate",
|
||||
"fluent",
|
||||
"fluent-syntax",
|
||||
"i18n-config",
|
||||
"i18n-embed",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim 0.11.1",
|
||||
"syn 2.0.117",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "i18n-embed-impl"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f2cc0e0523d1fe6fc2c6f66e5038624ea8091b3e7748b5e8e0c84b1698db6c2"
|
||||
dependencies = [
|
||||
"find-crate",
|
||||
"i18n-config",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.65"
|
||||
@@ -8210,25 +8025,6 @@ dependencies = [
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "intl-memoizer"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f"
|
||||
dependencies = [
|
||||
"type-map",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "intl_pluralrules"
|
||||
version = "7.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972"
|
||||
dependencies = [
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.24"
|
||||
@@ -8248,12 +8044,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io_tee"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b3f7cef34251886990511df1c61443aa928499d598a9473929ab5a90a527304"
|
||||
|
||||
[[package]]
|
||||
name = "ipconfig"
|
||||
version = "0.3.2"
|
||||
@@ -10371,28 +10161,6 @@ dependencies = [
|
||||
"toml_edit 0.23.10+spec-1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
@@ -10635,7 +10403,7 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
"quinn-proto",
|
||||
"quinn-udp",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
"socket2 0.6.3",
|
||||
"thiserror 2.0.18",
|
||||
@@ -10656,7 +10424,7 @@ dependencies = [
|
||||
"lru-slab",
|
||||
"rand 0.9.3",
|
||||
"ring",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"slab",
|
||||
@@ -11464,40 +11232,6 @@ name = "runfiles"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/dzbarsky/rules_rust?rev=b56cbaa8465e74127f1ea216f813cd377295ad81#b56cbaa8465e74127f1ea216f813cd377295ad81"
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed"
|
||||
version = "8.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04113cb9355a377d83f06ef1f0a45b8ab8cd7d8b1288160717d66df5c7988d27"
|
||||
dependencies = [
|
||||
"rust-embed-impl",
|
||||
"rust-embed-utils",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-impl"
|
||||
version = "8.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0902e4c7c8e997159ab384e6d0fc91c221375f6894346ae107f47dd0f3ccaa"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"syn 2.0.117",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-utils"
|
||||
version = "8.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bcdef0be6fe7f6fa333b1073c949729274b05f123a0ad7efcb8efd878e5c3b1"
|
||||
dependencies = [
|
||||
"sha2 0.10.9",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-stemmers"
|
||||
version = "1.2.0"
|
||||
@@ -11514,12 +11248,6 @@ version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
@@ -11839,17 +11567,6 @@ version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2"
|
||||
|
||||
[[package]]
|
||||
name = "scrypt"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
|
||||
dependencies = [
|
||||
"pbkdf2 0.12.2",
|
||||
"salsa20",
|
||||
"sha2 0.10.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sdd"
|
||||
version = "3.0.10"
|
||||
@@ -11879,15 +11596,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secrecy"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a"
|
||||
dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secret-service"
|
||||
version = "4.0.0"
|
||||
@@ -11943,21 +11651,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d"
|
||||
dependencies = [
|
||||
"self_cell 1.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.27"
|
||||
@@ -13110,7 +12803,7 @@ dependencies = [
|
||||
"cfg-expr",
|
||||
"heck 0.5.0",
|
||||
"pkg-config",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"toml",
|
||||
"version-compare",
|
||||
]
|
||||
|
||||
@@ -13550,15 +13243,6 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.11+spec-1.1.0"
|
||||
@@ -13988,15 +13672,6 @@ dependencies = [
|
||||
"syntect",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "type-map"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90"
|
||||
dependencies = [
|
||||
"rustc-hash 2.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.3"
|
||||
@@ -14035,25 +13710,6 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
|
||||
|
||||
[[package]]
|
||||
name = "unic-langid"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05"
|
||||
dependencies = [
|
||||
"unic-langid-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-langid-impl"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tinystr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
@@ -15439,18 +15095,6 @@ version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
|
||||
|
||||
[[package]]
|
||||
name = "x25519-dalek"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"rand_core 0.6.4",
|
||||
"serde",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x509-parser"
|
||||
version = "0.18.1"
|
||||
|
||||
+1
-1
@@ -247,7 +247,6 @@ core_test_support = { path = "core/tests/common" }
|
||||
mcp_test_support = { path = "mcp-server/tests/common" }
|
||||
|
||||
# External
|
||||
age = "0.11.1"
|
||||
allocative = "0.3.3"
|
||||
ansi-to-tui = "7.0.0"
|
||||
anyhow = "1"
|
||||
@@ -268,6 +267,7 @@ base64 = "0.22.1"
|
||||
bm25 = "2.3.2"
|
||||
bytes = "1.10.1"
|
||||
chardetng = "0.1.17"
|
||||
chacha20poly1305 = "0.10.1"
|
||||
chrono = "0.4.43"
|
||||
clap = "4"
|
||||
clap_complete = "4"
|
||||
|
||||
@@ -8,9 +8,9 @@ license.workspace = true
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
age = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
base64 = { workspace = true }
|
||||
chacha20poly1305 = { workspace = true }
|
||||
codex-git-utils = { workspace = true }
|
||||
codex-keyring-store = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
@@ -20,6 +20,7 @@ serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
keyring = { workspace = true }
|
||||
|
||||
+170
-38
@@ -4,27 +4,25 @@ use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::atomic::compiler_fence;
|
||||
use std::time::SystemTime;
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
||||
use age::decrypt;
|
||||
use age::encrypt;
|
||||
use age::scrypt::Identity as ScryptIdentity;
|
||||
use age::scrypt::Recipient as ScryptRecipient;
|
||||
use age::secrecy::ExposeSecret;
|
||||
use age::secrecy::SecretString;
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use base64::Engine as _;
|
||||
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
|
||||
use chacha20poly1305::XChaCha20Poly1305;
|
||||
use chacha20poly1305::XNonce;
|
||||
use chacha20poly1305::aead::Aead;
|
||||
use chacha20poly1305::aead::KeyInit;
|
||||
use chacha20poly1305::aead::Payload;
|
||||
use codex_keyring_store::KeyringStore;
|
||||
use rand::TryRngCore;
|
||||
use rand::rngs::OsRng;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use tracing::warn;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use super::SecretListEntry;
|
||||
use super::SecretName;
|
||||
@@ -34,7 +32,12 @@ use super::compute_keyring_account;
|
||||
use super::keyring_service;
|
||||
|
||||
const SECRETS_VERSION: u8 = 1;
|
||||
const LOCAL_SECRETS_FILENAME: &str = "local.age";
|
||||
const LOCAL_SECRETS_FILENAME: &str = "local.secrets";
|
||||
const LEGACY_LOCAL_SECRETS_FILENAME: &str = "local.age";
|
||||
const LOCAL_SECRETS_MAGIC: &[u8] = b"codex-local-secrets-v2\n";
|
||||
const LOCAL_SECRETS_AAD: &[u8] = b"codex-local-secrets-v2";
|
||||
const LOCAL_SECRETS_KEY_BYTES: usize = 32;
|
||||
const LOCAL_SECRETS_NONCE_BYTES: usize = 24;
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
struct SecretsFile {
|
||||
@@ -115,16 +118,26 @@ impl LocalSecretsBackend {
|
||||
self.secrets_dir().join(LOCAL_SECRETS_FILENAME)
|
||||
}
|
||||
|
||||
fn legacy_secrets_path(&self) -> PathBuf {
|
||||
self.secrets_dir().join(LEGACY_LOCAL_SECRETS_FILENAME)
|
||||
}
|
||||
|
||||
fn load_file(&self) -> Result<SecretsFile> {
|
||||
let path = self.secrets_path();
|
||||
if !path.exists() {
|
||||
let legacy_path = self.legacy_secrets_path();
|
||||
anyhow::ensure!(
|
||||
!legacy_path.exists(),
|
||||
"found legacy age-encrypted secrets file at {}; this version cannot read it",
|
||||
legacy_path.display()
|
||||
);
|
||||
return Ok(SecretsFile::new_empty());
|
||||
}
|
||||
|
||||
let ciphertext = fs::read(&path)
|
||||
.with_context(|| format!("failed to read secrets file at {}", path.display()))?;
|
||||
let passphrase = self.load_or_create_passphrase()?;
|
||||
let plaintext = decrypt_with_passphrase(&ciphertext, &passphrase)?;
|
||||
let key = self.load_or_create_key()?;
|
||||
let plaintext = decrypt_with_key(&ciphertext, &key)?;
|
||||
let mut parsed: SecretsFile = serde_json::from_slice(&plaintext).with_context(|| {
|
||||
format!(
|
||||
"failed to deserialize decrypted secrets file at {}",
|
||||
@@ -148,15 +161,16 @@ impl LocalSecretsBackend {
|
||||
fs::create_dir_all(&dir)
|
||||
.with_context(|| format!("failed to create secrets dir {}", dir.display()))?;
|
||||
|
||||
let passphrase = self.load_or_create_passphrase()?;
|
||||
let plaintext = serde_json::to_vec(file).context("failed to serialize secrets file")?;
|
||||
let ciphertext = encrypt_with_passphrase(&plaintext, &passphrase)?;
|
||||
let key = self.load_or_create_key()?;
|
||||
let plaintext =
|
||||
Zeroizing::new(serde_json::to_vec(file).context("failed to serialize secrets file")?);
|
||||
let ciphertext = encrypt_with_key(&plaintext, &key)?;
|
||||
let path = self.secrets_path();
|
||||
write_file_atomically(&path, &ciphertext)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_or_create_passphrase(&self) -> Result<SecretString> {
|
||||
fn load_or_create_key(&self) -> Result<Zeroizing<[u8; LOCAL_SECRETS_KEY_BYTES]>> {
|
||||
let account = compute_keyring_account(&self.codex_home);
|
||||
let loaded = self
|
||||
.keyring_store
|
||||
@@ -164,14 +178,17 @@ impl LocalSecretsBackend {
|
||||
.map_err(|err| anyhow::anyhow!(err.message()))
|
||||
.with_context(|| format!("failed to load secrets key from keyring for {account}"))?;
|
||||
match loaded {
|
||||
Some(existing) => Ok(SecretString::from(existing)),
|
||||
Some(existing) => decode_key(&existing).with_context(|| {
|
||||
format!("failed to decode secrets key from keyring for {account}")
|
||||
}),
|
||||
None => {
|
||||
// Generate a high-entropy key and persist it in the OS keyring.
|
||||
// This keeps secrets out of plaintext config while remaining
|
||||
// fully local/offline for the MVP.
|
||||
let generated = generate_passphrase()?;
|
||||
let generated = generate_key()?;
|
||||
let encoded = Zeroizing::new(BASE64_STANDARD.encode(generated.as_slice()));
|
||||
self.keyring_store
|
||||
.save(keyring_service(), &account, generated.expose_secret())
|
||||
.save(keyring_service(), &account, encoded.as_str())
|
||||
.map_err(|err| anyhow::anyhow!(err.message()))
|
||||
.context("failed to persist secrets key in keyring")?;
|
||||
Ok(generated)
|
||||
@@ -270,34 +287,84 @@ fn write_file_atomically(path: &Path, contents: &[u8]) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_passphrase() -> Result<SecretString> {
|
||||
let mut bytes = [0_u8; 32];
|
||||
fn generate_key() -> Result<Zeroizing<[u8; LOCAL_SECRETS_KEY_BYTES]>> {
|
||||
let mut bytes = Zeroizing::new([0_u8; LOCAL_SECRETS_KEY_BYTES]);
|
||||
let mut rng = OsRng;
|
||||
rng.try_fill_bytes(&mut bytes)
|
||||
rng.try_fill_bytes(&mut *bytes)
|
||||
.context("failed to generate random secrets key")?;
|
||||
// Base64 keeps the keyring payload ASCII-safe without reducing entropy.
|
||||
let encoded = BASE64_STANDARD.encode(bytes);
|
||||
wipe_bytes(&mut bytes);
|
||||
Ok(SecretString::from(encoded))
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
fn wipe_bytes(bytes: &mut [u8]) {
|
||||
for byte in bytes {
|
||||
// Volatile writes make it much harder for the compiler to elide the wipe.
|
||||
// SAFETY: `byte` is a valid mutable reference into `bytes`.
|
||||
unsafe { std::ptr::write_volatile(byte, 0) };
|
||||
}
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
fn decode_key(encoded: &str) -> Result<Zeroizing<[u8; LOCAL_SECRETS_KEY_BYTES]>> {
|
||||
let decoded = Zeroizing::new(
|
||||
BASE64_STANDARD
|
||||
.decode(encoded)
|
||||
.context("secrets key is not valid base64")?,
|
||||
);
|
||||
anyhow::ensure!(
|
||||
decoded.len() == LOCAL_SECRETS_KEY_BYTES,
|
||||
"secrets key must be {LOCAL_SECRETS_KEY_BYTES} bytes"
|
||||
);
|
||||
let mut key = Zeroizing::new([0_u8; LOCAL_SECRETS_KEY_BYTES]);
|
||||
key.copy_from_slice(decoded.as_slice());
|
||||
Ok(key)
|
||||
}
|
||||
|
||||
fn encrypt_with_passphrase(plaintext: &[u8], passphrase: &SecretString) -> Result<Vec<u8>> {
|
||||
let recipient = ScryptRecipient::new(passphrase.clone());
|
||||
encrypt(&recipient, plaintext).context("failed to encrypt secrets file")
|
||||
fn encrypt_with_key(plaintext: &[u8], key: &[u8; LOCAL_SECRETS_KEY_BYTES]) -> Result<Vec<u8>> {
|
||||
let mut nonce_bytes = [0_u8; LOCAL_SECRETS_NONCE_BYTES];
|
||||
let mut rng = OsRng;
|
||||
rng.try_fill_bytes(&mut nonce_bytes)
|
||||
.context("failed to generate secrets file nonce")?;
|
||||
let nonce = XNonce::from_slice(&nonce_bytes);
|
||||
let cipher = XChaCha20Poly1305::new_from_slice(key)
|
||||
.map_err(|_| anyhow::anyhow!("invalid secrets key length"))?;
|
||||
let encrypted = cipher
|
||||
.encrypt(
|
||||
nonce,
|
||||
Payload {
|
||||
msg: plaintext,
|
||||
aad: LOCAL_SECRETS_AAD,
|
||||
},
|
||||
)
|
||||
.map_err(|_| anyhow::anyhow!("failed to encrypt secrets file"))?;
|
||||
|
||||
let mut envelope =
|
||||
Vec::with_capacity(LOCAL_SECRETS_MAGIC.len() + nonce_bytes.len() + encrypted.len());
|
||||
envelope.extend_from_slice(LOCAL_SECRETS_MAGIC);
|
||||
envelope.extend_from_slice(&nonce_bytes);
|
||||
envelope.extend_from_slice(&encrypted);
|
||||
Ok(envelope)
|
||||
}
|
||||
|
||||
fn decrypt_with_passphrase(ciphertext: &[u8], passphrase: &SecretString) -> Result<Vec<u8>> {
|
||||
let identity = ScryptIdentity::new(passphrase.clone());
|
||||
decrypt(&identity, ciphertext).context("failed to decrypt secrets file")
|
||||
fn decrypt_with_key(
|
||||
envelope: &[u8],
|
||||
key: &[u8; LOCAL_SECRETS_KEY_BYTES],
|
||||
) -> Result<Zeroizing<Vec<u8>>> {
|
||||
anyhow::ensure!(
|
||||
envelope.starts_with(LOCAL_SECRETS_MAGIC),
|
||||
"unsupported local secrets file format"
|
||||
);
|
||||
let encrypted_offset = LOCAL_SECRETS_MAGIC.len() + LOCAL_SECRETS_NONCE_BYTES;
|
||||
anyhow::ensure!(
|
||||
envelope.len() >= encrypted_offset,
|
||||
"local secrets file is truncated"
|
||||
);
|
||||
let nonce = XNonce::from_slice(
|
||||
&envelope[LOCAL_SECRETS_MAGIC.len()..LOCAL_SECRETS_MAGIC.len() + LOCAL_SECRETS_NONCE_BYTES],
|
||||
);
|
||||
let encrypted = &envelope[encrypted_offset..];
|
||||
let cipher = XChaCha20Poly1305::new_from_slice(key)
|
||||
.map_err(|_| anyhow::anyhow!("invalid secrets key length"))?;
|
||||
let plaintext = cipher
|
||||
.decrypt(
|
||||
nonce,
|
||||
Payload {
|
||||
msg: encrypted,
|
||||
aad: LOCAL_SECRETS_AAD,
|
||||
},
|
||||
)
|
||||
.map_err(|_| anyhow::anyhow!("failed to decrypt secrets file"))?;
|
||||
Ok(Zeroizing::new(plaintext))
|
||||
}
|
||||
|
||||
fn parse_canonical_key(canonical_key: &str) -> Option<SecretListEntry> {
|
||||
@@ -358,6 +425,71 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn save_file_writes_versioned_encrypted_envelope() -> Result<()> {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let keyring = Arc::new(MockKeyringStore::default());
|
||||
let backend = LocalSecretsBackend::new(codex_home.path().to_path_buf(), keyring);
|
||||
let file = SecretsFile {
|
||||
version: SECRETS_VERSION,
|
||||
secrets: BTreeMap::from([(
|
||||
"global/GITHUB_TOKEN".to_string(),
|
||||
"secret-value".to_string(),
|
||||
)]),
|
||||
};
|
||||
|
||||
backend.save_file(&file)?;
|
||||
|
||||
let ciphertext = fs::read(backend.secrets_path())?;
|
||||
assert!(ciphertext.starts_with(LOCAL_SECRETS_MAGIC));
|
||||
assert!(
|
||||
!String::from_utf8_lossy(&ciphertext).contains("secret-value"),
|
||||
"secrets file must not store plaintext secret values"
|
||||
);
|
||||
assert_eq!(backend.load_file()?, file);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_file_rejects_unknown_envelope_format() -> Result<()> {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let keyring = Arc::new(MockKeyringStore::default());
|
||||
let backend = LocalSecretsBackend::new(codex_home.path().to_path_buf(), keyring);
|
||||
fs::create_dir_all(backend.secrets_dir())?;
|
||||
fs::write(backend.secrets_path(), b"age-encryption.org/v1")?;
|
||||
|
||||
let error = backend
|
||||
.load_file()
|
||||
.expect_err("unknown envelope format should be rejected");
|
||||
assert!(
|
||||
error
|
||||
.to_string()
|
||||
.contains("unsupported local secrets file format"),
|
||||
"unexpected error: {error:#}"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_file_rejects_legacy_age_file() -> Result<()> {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
let keyring = Arc::new(MockKeyringStore::default());
|
||||
let backend = LocalSecretsBackend::new(codex_home.path().to_path_buf(), keyring);
|
||||
fs::create_dir_all(backend.secrets_dir())?;
|
||||
fs::write(backend.legacy_secrets_path(), b"age-encryption.org/v1")?;
|
||||
|
||||
let error = backend
|
||||
.load_file()
|
||||
.expect_err("legacy age format should be rejected");
|
||||
assert!(
|
||||
error
|
||||
.to_string()
|
||||
.contains("found legacy age-encrypted secrets file"),
|
||||
"unexpected error: {error:#}"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_fails_when_keyring_is_unavailable() -> Result<()> {
|
||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||
|
||||
Reference in New Issue
Block a user