anvilsign in

collin/anvil · 04186540

Run locally in Docker at https://anvil.localhost

Collin Richards · 2026-08-18 09:42 UTC · 04186540960d06c008741d226edddf2c7e127666 · parent 31844800 · browse files

modifiedCargo.lock+587 −87
⋯ 165 unchanged lines
166166 "argon2 0.5.3",
167167 "async-trait",
168168 "base64",
169- "curve25519-dalek",
169+ "curve25519-dalek 5.0.0-rc.0",
170170 "gix",
171171 "hmac 0.12.1",
172172 "pulldown-cmark",
⋯ 9 unchanged lines
182182 "tokio",
183183 "toml",
184184 "tracing",
185+ "webauthn_rp",
185186 ]
186187
187188 [[package]]
⋯ 18 unchanged lines
206207 dependencies = [
207208 "anvil-core",
208209 "anvil-git",
209- "rand",
210+ "rand 0.10.1",
210211 "russh",
211212 "tokio",
212213 "tracing",
⋯ 23 unchanged lines
236237 "tokio-util",
237238 "tower-http",
238239 "tracing",
240+ "webauthn_rp",
239241 ]
240242
241243 [[package]]
⋯ 141 unchanged lines
383385
384386 [[package]]
385387 name = "base16ct"
388+version = "0.2.0"
389+source = "registry+https://github.com/rust-lang/crates.io-index"
390+checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
391+
392+[[package]]
393+name = "base16ct"
386394 version = "1.0.0"
387395 source = "registry+https://github.com/rust-lang/crates.io-index"
388396 checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6"
⋯ 331 unchanged lines
720728
721729 [[package]]
722730 name = "const-oid"
731+version = "0.9.6"
732+source = "registry+https://github.com/rust-lang/crates.io-index"
733+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
734+
735+[[package]]
736+name = "const-oid"
723737 version = "0.10.2"
724738 source = "registry+https://github.com/rust-lang/crates.io-index"
725739 checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
⋯ 10 unchanged lines
736750 ]
737751
738752 [[package]]
753+name = "core-foundation"
754+version = "0.10.1"
755+source = "registry+https://github.com/rust-lang/crates.io-index"
756+checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
757+dependencies = [
758+ "core-foundation-sys",
759+ "libc",
760+]
761+
762+[[package]]
739763 name = "core-foundation-sys"
740764 version = "0.8.7"
741765 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 49 unchanged lines
791815
792816 [[package]]
793817 name = "crypto-bigint"
818+version = "0.5.5"
819+source = "registry+https://github.com/rust-lang/crates.io-index"
820+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
821+dependencies = [
822+ "generic-array 0.14.7",
823+ "rand_core 0.6.4",
824+ "subtle",
825+ "zeroize",
826+]
827+
828+[[package]]
829+name = "crypto-bigint"
794830 version = "0.7.3"
795831 source = "registry+https://github.com/rust-lang/crates.io-index"
796832 checksum = "42a0d26b245348befa0c121944541476763dcc46ede886c88f9d12e1697d27c3"
⋯ 36 unchanged lines
833869 source = "registry+https://github.com/rust-lang/crates.io-index"
834870 checksum = "21f41f23de7d24cdbda7f0c4d9c0351f99a4ceb258ef30e5c1927af8987ffe5a"
835871 dependencies = [
836- "crypto-bigint",
872+ "crypto-bigint 0.7.3",
837873 "libm",
838874 "rand_core 0.10.1",
839875 ]
⋯ 19 unchanged lines
859895
860896 [[package]]
861897 name = "curve25519-dalek"
898+version = "4.1.3"
899+source = "registry+https://github.com/rust-lang/crates.io-index"
900+checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
901+dependencies = [
902+ "cfg-if",
903+ "cpufeatures 0.2.17",
904+ "curve25519-dalek-derive",
905+ "digest 0.10.7",
906+ "fiat-crypto 0.2.9",
907+ "rustc_version",
908+ "subtle",
909+]
910+
911+[[package]]
912+name = "curve25519-dalek"
862913 version = "5.0.0-rc.0"
863914 source = "registry+https://github.com/rust-lang/crates.io-index"
864915 checksum = "4f359e08ca85e7bd759e1fd933ff2bccd81864c60a8fba0e259c7f822b0924bf"
⋯ 2 unchanged lines
867918 "cpufeatures 0.3.0",
868919 "curve25519-dalek-derive",
869920 "digest 0.11.3",
870- "fiat-crypto",
921+ "fiat-crypto 0.3.0",
871922 "rustc_version",
872923 "subtle",
873924 "zeroize",
⋯ 63 unchanged lines
937988
938989 [[package]]
939990 name = "der"
991+version = "0.7.10"
992+source = "registry+https://github.com/rust-lang/crates.io-index"
993+checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
994+dependencies = [
995+ "const-oid 0.9.6",
996+ "zeroize",
997+]
998+
999+[[package]]
1000+name = "der"
9401001 version = "0.8.0"
9411002 source = "registry+https://github.com/rust-lang/crates.io-index"
9421003 checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b"
9431004 dependencies = [
944- "const-oid",
1005+ "const-oid 0.10.2",
9451006 "pem-rfc7468",
9461007 "zeroize",
9471008 ]
⋯ 24 unchanged lines
9721033 checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
9731034 dependencies = [
9741035 "block-buffer 0.10.4",
1036+ "const-oid 0.9.6",
9751037 "crypto-common 0.1.7",
9761038 "subtle",
9771039 ]
⋯ 5 unchanged lines
9831045 checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
9841046 dependencies = [
9851047 "block-buffer 0.12.0",
986- "const-oid",
1048+ "const-oid 0.10.2",
9871049 "crypto-common 0.2.2",
9881050 "ctutils",
9891051 ]
⋯ 23 unchanged lines
10131075
10141076 [[package]]
10151077 name = "ecdsa"
1078+version = "0.16.9"
1079+source = "registry+https://github.com/rust-lang/crates.io-index"
1080+checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
1081+dependencies = [
1082+ "der 0.7.10",
1083+ "digest 0.10.7",
1084+ "elliptic-curve 0.13.8",
1085+ "rfc6979 0.4.0",
1086+ "signature 2.2.0",
1087+]
1088+
1089+[[package]]
1090+name = "ecdsa"
10161091 version = "0.17.0-rc.18"
10171092 source = "registry+https://github.com/rust-lang/crates.io-index"
10181093 checksum = "54fb064faabbee66e1fc8e5c5a9458d4269dc2d8b638fe86a425adb2510d1a96"
10191094 dependencies = [
1020- "der",
1095+ "der 0.8.0",
10211096 "digest 0.11.3",
1022- "elliptic-curve",
1023- "rfc6979",
1024- "signature",
1025- "spki",
1097+ "elliptic-curve 0.14.0-rc.33",
1098+ "rfc6979 0.5.0",
1099+ "signature 3.0.0",
1100+ "spki 0.8.0",
10261101 "zeroize",
10271102 ]
10281103
10291104 [[package]]
10301105 name = "ed25519"
1106+version = "2.2.3"
1107+source = "registry+https://github.com/rust-lang/crates.io-index"
1108+checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
1109+dependencies = [
1110+ "signature 2.2.0",
1111+]
1112+
1113+[[package]]
1114+name = "ed25519"
10311115 version = "3.0.0"
10321116 source = "registry+https://github.com/rust-lang/crates.io-index"
10331117 checksum = "29fcf32e6c73d1079f83ab4d782de2d81620346a5f38c6237a86a22f8368980a"
10341118 dependencies = [
1035- "pkcs8",
1036- "signature",
1119+ "pkcs8 0.11.0",
1120+ "signature 3.0.0",
1121+]
1122+
1123+[[package]]
1124+name = "ed25519-dalek"
1125+version = "2.2.0"
1126+source = "registry+https://github.com/rust-lang/crates.io-index"
1127+checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
1128+dependencies = [
1129+ "curve25519-dalek 4.1.3",
1130+ "ed25519 2.2.3",
1131+ "sha2 0.10.9",
1132+ "subtle",
10371133 ]
10381134
10391135 [[package]]
⋯ 2 unchanged lines
10421138 source = "registry+https://github.com/rust-lang/crates.io-index"
10431139 checksum = "b011170fe4f04665565b4110afef66774fe9ffff278f3eb5b81cc73d26e27d60"
10441140 dependencies = [
1045- "curve25519-dalek",
1046- "ed25519",
1141+ "curve25519-dalek 5.0.0-rc.0",
1142+ "ed25519 3.0.0",
10471143 "rand_core 0.10.1",
10481144 "serde",
10491145 "sha2 0.11.0",
1050- "signature",
1146+ "signature 3.0.0",
1147+ "subtle",
1148+ "zeroize",
1149+]
1150+
1151+[[package]]
1152+name = "elliptic-curve"
1153+version = "0.13.8"
1154+source = "registry+https://github.com/rust-lang/crates.io-index"
1155+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
1156+dependencies = [
1157+ "base16ct 0.2.0",
1158+ "crypto-bigint 0.5.5",
1159+ "digest 0.10.7",
1160+ "ff 0.13.1",
1161+ "generic-array 0.14.7",
1162+ "group 0.13.0",
1163+ "rand_core 0.6.4",
1164+ "sec1 0.7.3",
10511165 "subtle",
10521166 "zeroize",
10531167 ]
⋯ 4 unchanged lines
10581172 source = "registry+https://github.com/rust-lang/crates.io-index"
10591173 checksum = "102d3643d30dd8b559613c5cced68317199597fffb278cdc88daa2ef7fafc935"
10601174 dependencies = [
1061- "base16ct",
1062- "crypto-bigint",
1175+ "base16ct 1.0.0",
1176+ "crypto-bigint 0.7.3",
10631177 "crypto-common 0.2.2",
10641178 "digest 0.11.3",
1065- "ff",
1066- "group",
1179+ "ff 0.14.0",
1180+ "group 0.14.0",
10671181 "hkdf",
10681182 "hybrid-array",
10691183 "once_cell",
10701184 "pem-rfc7468",
1071- "pkcs8",
1185+ "pkcs8 0.11.0",
10721186 "rand_core 0.10.1",
1073- "sec1",
1187+ "sec1 0.8.1",
10741188 "subtle",
10751189 "zeroize",
10761190 ]
⋯ 65 unchanged lines
11421256
11431257 [[package]]
11441258 name = "ff"
1259+version = "0.13.1"
1260+source = "registry+https://github.com/rust-lang/crates.io-index"
1261+checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
1262+dependencies = [
1263+ "rand_core 0.6.4",
1264+ "subtle",
1265+]
1266+
1267+[[package]]
1268+name = "ff"
11451269 version = "0.14.0"
11461270 source = "registry+https://github.com/rust-lang/crates.io-index"
11471271 checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f"
⋯ 4 unchanged lines
11521276
11531277 [[package]]
11541278 name = "fiat-crypto"
1279+version = "0.2.9"
1280+source = "registry+https://github.com/rust-lang/crates.io-index"
1281+checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
1282+
1283+[[package]]
1284+name = "fiat-crypto"
11551285 version = "0.3.0"
11561286 source = "registry+https://github.com/rust-lang/crates.io-index"
11571287 checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24"
⋯ 147 unchanged lines
13051435 dependencies = [
13061436 "typenum",
13071437 "version_check",
1438+ "zeroize",
13081439 ]
13091440
13101441 [[package]]
⋯ 20 unchanged lines
13311462
13321463 [[package]]
13331464 name = "getrandom"
1465+version = "0.3.4"
1466+source = "registry+https://github.com/rust-lang/crates.io-index"
1467+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
1468+dependencies = [
1469+ "cfg-if",
1470+ "libc",
1471+ "r-efi 5.3.0",
1472+ "wasip2",
1473+]
1474+
1475+[[package]]
1476+name = "getrandom"
13341477 version = "0.4.2"
13351478 source = "registry+https://github.com/rust-lang/crates.io-index"
13361479 checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
⋯ 1 unchanged line
13381481 "cfg-if",
13391482 "js-sys",
13401483 "libc",
1341- "r-efi",
1484+ "r-efi 6.0.0",
13421485 "rand_core 0.10.1",
13431486 "wasip2",
13441487 "wasip3",
⋯ 756 unchanged lines
21012244
21022245 [[package]]
21032246 name = "group"
2247+version = "0.13.0"
2248+source = "registry+https://github.com/rust-lang/crates.io-index"
2249+checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
2250+dependencies = [
2251+ "ff 0.13.1",
2252+ "rand_core 0.6.4",
2253+ "subtle",
2254+]
2255+
2256+[[package]]
2257+name = "group"
21042258 version = "0.14.0"
21052259 source = "registry+https://github.com/rust-lang/crates.io-index"
21062260 checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4"
21072261 dependencies = [
2108- "ff",
2262+ "ff 0.14.0",
21092263 "rand_core 0.10.1",
21102264 "subtle",
21112265 ]
⋯ 231 unchanged lines
23432497 "hyper",
23442498 "hyper-util",
23452499 "rustls",
2500+ "rustls-native-certs",
23462501 "tokio",
23472502 "tokio-rustls",
23482503 "tower-service",
2349- "webpki-roots",
23502504 ]
23512505
23522506 [[package]]
⋯ 214 unchanged lines
25672721 dependencies = [
25682722 "num-integer",
25692723 "num-traits",
2570- "rand",
2724+ "rand 0.10.1",
25712725 "rand_core 0.10.1",
25722726 ]
25732727
⋯ 110 unchanged lines
26842838 version = "1.5.0"
26852839 source = "registry+https://github.com/rust-lang/crates.io-index"
26862840 checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
2841+dependencies = [
2842+ "spin",
2843+]
26872844
26882845 [[package]]
26892846 name = "leb128fmt"
⋯ 183 unchanged lines
28733030 "hybrid-array",
28743031 "kem",
28753032 "module-lattice",
2876- "pkcs8",
3033+ "pkcs8 0.11.0",
28773034 "rand_core 0.10.1",
28783035 "sha3",
28793036 ]
⋯ 47 unchanged lines
29273084 ]
29283085
29293086 [[package]]
3087+name = "num-bigint-dig"
3088+version = "0.8.6"
3089+source = "registry+https://github.com/rust-lang/crates.io-index"
3090+checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7"
3091+dependencies = [
3092+ "lazy_static",
3093+ "libm",
3094+ "num-integer",
3095+ "num-iter",
3096+ "num-traits",
3097+ "rand 0.8.7",
3098+ "smallvec",
3099+ "zeroize",
3100+]
3101+
3102+[[package]]
29303103 name = "num-conv"
29313104 version = "0.2.2"
29323105 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 9 unchanged lines
29423115 ]
29433116
29443117 [[package]]
3118+name = "num-iter"
3119+version = "0.1.46"
3120+source = "registry+https://github.com/rust-lang/crates.io-index"
3121+checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b"
3122+dependencies = [
3123+ "num-integer",
3124+ "num-traits",
3125+]
3126+
3127+[[package]]
29453128 name = "num-traits"
29463129 version = "0.2.19"
29473130 source = "registry+https://github.com/rust-lang/crates.io-index"
29483131 checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
29493132 dependencies = [
29503133 "autocfg",
3134+ "libm",
29513135 ]
29523136
29533137 [[package]]
⋯ 41 unchanged lines
29953179 ]
29963180
29973181 [[package]]
3182+name = "openssl-probe"
3183+version = "0.2.1"
3184+source = "registry+https://github.com/rust-lang/crates.io-index"
3185+checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
3186+
3187+[[package]]
3188+name = "p256"
3189+version = "0.13.2"
3190+source = "registry+https://github.com/rust-lang/crates.io-index"
3191+checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
3192+dependencies = [
3193+ "ecdsa 0.16.9",
3194+ "elliptic-curve 0.13.8",
3195+ "primeorder 0.13.6",
3196+ "sha2 0.10.9",
3197+]
3198+
3199+[[package]]
29983200 name = "p256"
29993201 version = "0.14.0-rc.10"
30003202 source = "registry+https://github.com/rust-lang/crates.io-index"
30013203 checksum = "41adc63effe99d48837a8cc0e6d7a77e32ae6a07f6000df466178dbc2193093e"
30023204 dependencies = [
3003- "ecdsa",
3004- "elliptic-curve",
3205+ "ecdsa 0.17.0-rc.18",
3206+ "elliptic-curve 0.14.0-rc.33",
30053207 "primefield",
3006- "primeorder",
3208+ "primeorder 0.14.0-rc.10",
30073209 "sha2 0.11.0",
30083210 ]
30093211
30103212 [[package]]
30113213 name = "p384"
3214+version = "0.13.1"
3215+source = "registry+https://github.com/rust-lang/crates.io-index"
3216+checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6"
3217+dependencies = [
3218+ "ecdsa 0.16.9",
3219+ "elliptic-curve 0.13.8",
3220+ "primeorder 0.13.6",
3221+ "sha2 0.10.9",
3222+]
3223+
3224+[[package]]
3225+name = "p384"
30123226 version = "0.14.0-rc.10"
30133227 source = "registry+https://github.com/rust-lang/crates.io-index"
30143228 checksum = "9bd5333afa5ae0347f39e6a0f2c9c155da431583fd71fe5555bd0521b4ccaf02"
30153229 dependencies = [
3016- "ecdsa",
3017- "elliptic-curve",
3018- "fiat-crypto",
3230+ "ecdsa 0.17.0-rc.18",
3231+ "elliptic-curve 0.14.0-rc.33",
3232+ "fiat-crypto 0.3.0",
30193233 "primefield",
3020- "primeorder",
3234+ "primeorder 0.14.0-rc.10",
30213235 "sha2 0.11.0",
30223236 ]
30233237
⋯ 3 unchanged lines
30273241 source = "registry+https://github.com/rust-lang/crates.io-index"
30283242 checksum = "a3a5297f53dc16d35909060ba3032cff7867e8809f01e273ff325579d5f0ceae"
30293243 dependencies = [
3030- "base16ct",
3031- "ecdsa",
3032- "elliptic-curve",
3244+ "base16ct 1.0.0",
3245+ "ecdsa 0.17.0-rc.18",
3246+ "elliptic-curve 0.14.0-rc.33",
30333247 "primefield",
3034- "primeorder",
3248+ "primeorder 0.14.0-rc.10",
30353249 "sha2 0.11.0",
30363250 ]
30373251
⋯ 3 unchanged lines
30413255 source = "registry+https://github.com/rust-lang/crates.io-index"
30423256 checksum = "4f3a5ae18f65a85c67a77d18d42d3606c07948e3c17c1e5f74852b26589e88a5"
30433257 dependencies = [
3044- "base16ct",
3258+ "base16ct 1.0.0",
30453259 "byteorder",
30463260 "bytes",
30473261 "delegate",
30483262 "futures",
30493263 "log",
3050- "rand",
3264+ "rand 0.10.1",
30513265 "sha2 0.11.0",
30523266 "thiserror",
30533267 "tokio",
⋯ 87 unchanged lines
31413355
31423356 [[package]]
31433357 name = "pkcs1"
3358+version = "0.7.5"
3359+source = "registry+https://github.com/rust-lang/crates.io-index"
3360+checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
3361+dependencies = [
3362+ "der 0.7.10",
3363+ "pkcs8 0.10.2",
3364+ "spki 0.7.3",
3365+]
3366+
3367+[[package]]
3368+name = "pkcs1"
31443369 version = "0.8.0-rc.4"
31453370 source = "registry+https://github.com/rust-lang/crates.io-index"
31463371 checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e"
31473372 dependencies = [
3148- "der",
3149- "spki",
3373+ "der 0.8.0",
3374+ "spki 0.8.0",
31503375 ]
31513376
31523377 [[package]]
⋯ 4 unchanged lines
31573382 dependencies = [
31583383 "aes",
31593384 "cbc",
3160- "der",
3385+ "der 0.8.0",
31613386 "pbkdf2",
31623387 "rand_core 0.10.1",
31633388 "scrypt",
31643389 "sha2 0.11.0",
3165- "spki",
3390+ "spki 0.8.0",
3391+]
3392+
3393+[[package]]
3394+name = "pkcs8"
3395+version = "0.10.2"
3396+source = "registry+https://github.com/rust-lang/crates.io-index"
3397+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
3398+dependencies = [
3399+ "der 0.7.10",
3400+ "spki 0.7.3",
31663401 ]
31673402
31683403 [[package]]
⋯ 2 unchanged lines
31713406 source = "registry+https://github.com/rust-lang/crates.io-index"
31723407 checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7"
31733408 dependencies = [
3174- "der",
3409+ "der 0.8.0",
31753410 "pkcs5",
31763411 "rand_core 0.10.1",
3177- "spki",
3412+ "spki 0.8.0",
31783413 ]
31793414
31803415 [[package]]
⋯ 78 unchanged lines
32593494 checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
32603495
32613496 [[package]]
3497+name = "ppv-lite86"
3498+version = "0.2.21"
3499+source = "registry+https://github.com/rust-lang/crates.io-index"
3500+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
3501+dependencies = [
3502+ "zerocopy",
3503+]
3504+
3505+[[package]]
3506+name = "precis-core"
3507+version = "0.1.11"
3508+source = "registry+https://github.com/rust-lang/crates.io-index"
3509+checksum = "9c2e7b31f132e0c6f8682cfb7bf4a5340dbe925b7986618d0826a56dfe0c8e56"
3510+dependencies = [
3511+ "precis-tools",
3512+ "ucd-parse",
3513+ "unicode-normalization",
3514+]
3515+
3516+[[package]]
3517+name = "precis-profiles"
3518+version = "0.1.13"
3519+source = "registry+https://github.com/rust-lang/crates.io-index"
3520+checksum = "31e2768890a47af73a032af9f0cedbddce3c9d06cf8de201d5b8f2436ded7674"
3521+dependencies = [
3522+ "lazy_static",
3523+ "precis-core",
3524+ "precis-tools",
3525+ "unicode-normalization",
3526+]
3527+
3528+[[package]]
3529+name = "precis-tools"
3530+version = "0.1.9"
3531+source = "registry+https://github.com/rust-lang/crates.io-index"
3532+checksum = "6cc1eb2d5887ac7bfd2c0b745764db89edb84b856e4214e204ef48ef96d10c4a"
3533+dependencies = [
3534+ "lazy_static",
3535+ "regex",
3536+ "ucd-parse",
3537+]
3538+
3539+[[package]]
32623540 name = "prettyplease"
32633541 version = "0.2.37"
32643542 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 9 unchanged lines
32743552 source = "registry+https://github.com/rust-lang/crates.io-index"
32753553 checksum = "f845ec3240cd5ed5e1e31cf3ff633a5bf47c698dc4092ba9e767415b3d393406"
32763554 dependencies = [
3277- "crypto-bigint",
3555+ "crypto-bigint 0.7.3",
32783556 "crypto-common 0.2.2",
3279- "ff",
3557+ "ff 0.14.0",
32803558 "rand_core 0.10.1",
32813559 "subtle",
32823560 "zeroize",
⋯ 1 unchanged line
32843562
32853563 [[package]]
32863564 name = "primeorder"
3565+version = "0.13.6"
3566+source = "registry+https://github.com/rust-lang/crates.io-index"
3567+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
3568+dependencies = [
3569+ "elliptic-curve 0.13.8",
3570+]
3571+
3572+[[package]]
3573+name = "primeorder"
32873574 version = "0.14.0-rc.10"
32883575 source = "registry+https://github.com/rust-lang/crates.io-index"
32893576 checksum = "7d2793f22b9b6fd11ef3ac1d59bf003c2573593e4968702341605c2748fd90bf"
32903577 dependencies = [
3291- "elliptic-curve",
3578+ "elliptic-curve 0.14.0-rc.33",
32923579 ]
32933580
32943581 [[package]]
⋯ 64 unchanged lines
33593646
33603647 [[package]]
33613648 name = "r-efi"
3649+version = "5.3.0"
3650+source = "registry+https://github.com/rust-lang/crates.io-index"
3651+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
3652+
3653+[[package]]
3654+name = "r-efi"
33623655 version = "6.0.0"
33633656 source = "registry+https://github.com/rust-lang/crates.io-index"
33643657 checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
33653658
33663659 [[package]]
33673660 name = "rand"
3661+version = "0.8.7"
3662+source = "registry+https://github.com/rust-lang/crates.io-index"
3663+checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
3664+dependencies = [
3665+ "rand_chacha 0.3.1",
3666+ "rand_core 0.6.4",
3667+]
3668+
3669+[[package]]
3670+name = "rand"
3671+version = "0.9.5"
3672+source = "registry+https://github.com/rust-lang/crates.io-index"
3673+checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
3674+dependencies = [
3675+ "rand_chacha 0.9.0",
3676+ "rand_core 0.9.5",
3677+]
3678+
3679+[[package]]
3680+name = "rand"
33683681 version = "0.10.1"
33693682 source = "registry+https://github.com/rust-lang/crates.io-index"
33703683 checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
⋯ 4 unchanged lines
33753688 ]
33763689
33773690 [[package]]
3691+name = "rand_chacha"
3692+version = "0.3.1"
3693+source = "registry+https://github.com/rust-lang/crates.io-index"
3694+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
3695+dependencies = [
3696+ "ppv-lite86",
3697+ "rand_core 0.6.4",
3698+]
3699+
3700+[[package]]
3701+name = "rand_chacha"
3702+version = "0.9.0"
3703+source = "registry+https://github.com/rust-lang/crates.io-index"
3704+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
3705+dependencies = [
3706+ "ppv-lite86",
3707+ "rand_core 0.9.5",
3708+]
3709+
3710+[[package]]
33783711 name = "rand_core"
33793712 version = "0.6.4"
33803713 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 4 unchanged lines
33853718
33863719 [[package]]
33873720 name = "rand_core"
3721+version = "0.9.5"
3722+source = "registry+https://github.com/rust-lang/crates.io-index"
3723+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
3724+dependencies = [
3725+ "getrandom 0.3.4",
3726+]
3727+
3728+[[package]]
3729+name = "rand_core"
33883730 version = "0.10.1"
33893731 source = "registry+https://github.com/rust-lang/crates.io-index"
33903732 checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
⋯ 51 unchanged lines
34423784 ]
34433785
34443786 [[package]]
3787+name = "regex-lite"
3788+version = "0.1.9"
3789+source = "registry+https://github.com/rust-lang/crates.io-index"
3790+checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973"
3791+
3792+[[package]]
34453793 name = "regex-syntax"
34463794 version = "0.8.11"
34473795 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 19 unchanged lines
34673815 "percent-encoding",
34683816 "pin-project-lite",
34693817 "rustls",
3818+ "rustls-native-certs",
34703819 "rustls-pki-types",
34713820 "serde",
34723821 "serde_json",
⋯ 8 unchanged lines
34813830 "wasm-bindgen",
34823831 "wasm-bindgen-futures",
34833832 "web-sys",
3484- "webpki-roots",
34853833 ]
34863834
34873835 [[package]]
34883836 name = "rfc6979"
3837+version = "0.4.0"
3838+source = "registry+https://github.com/rust-lang/crates.io-index"
3839+checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
3840+dependencies = [
3841+ "hmac 0.12.1",
3842+ "subtle",
3843+]
3844+
3845+[[package]]
3846+name = "rfc6979"
34893847 version = "0.5.0"
34903848 source = "registry+https://github.com/rust-lang/crates.io-index"
34913849 checksum = "5236ce872cac07e0fb3969b0cbf468c7d2f37d432f1b627dcb7b8d34563fb0c3"
⋯ 29 unchanged lines
35213879
35223880 [[package]]
35233881 name = "rsa"
3882+version = "0.9.10"
3883+source = "registry+https://github.com/rust-lang/crates.io-index"
3884+checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d"
3885+dependencies = [
3886+ "const-oid 0.9.6",
3887+ "digest 0.10.7",
3888+ "num-bigint-dig",
3889+ "num-integer",
3890+ "num-traits",
3891+ "pkcs1 0.7.5",
3892+ "pkcs8 0.10.2",
3893+ "rand_core 0.6.4",
3894+ "sha2 0.10.9",
3895+ "signature 2.2.0",
3896+ "spki 0.7.3",
3897+ "subtle",
3898+ "zeroize",
3899+]
3900+
3901+[[package]]
3902+name = "rsa"
35243903 version = "0.10.0-rc.18"
35253904 source = "registry+https://github.com/rust-lang/crates.io-index"
35263905 checksum = "30b2aa4ba0d89f73d1e332df05be0eeab8840351c36ca5654341dfdb57bb3caf"
35273906 dependencies = [
3528- "const-oid",
3529- "crypto-bigint",
3907+ "const-oid 0.10.2",
3908+ "crypto-bigint 0.7.3",
35303909 "crypto-primes",
35313910 "digest 0.11.3",
3532- "pkcs1",
3533- "pkcs8",
3911+ "pkcs1 0.8.0-rc.4",
3912+ "pkcs8 0.11.0",
35343913 "rand_core 0.10.1",
35353914 "sha2 0.11.0",
3536- "signature",
3537- "spki",
3915+ "signature 3.0.0",
3916+ "spki 0.8.0",
35383917 "zeroize",
35393918 ]
35403919
⋯ 45 unchanged lines
35863965 "bytes",
35873966 "cbc",
35883967 "cipher",
3589- "crypto-bigint",
3968+ "crypto-bigint 0.7.3",
35903969 "ctr",
3591- "curve25519-dalek",
3970+ "curve25519-dalek 5.0.0-rc.0",
35923971 "data-encoding",
35933972 "delegate",
3594- "der",
3973+ "der 0.8.0",
35953974 "digest 0.11.3",
3596- "ecdsa",
3597- "ed25519-dalek",
3598- "elliptic-curve",
3975+ "ecdsa 0.17.0-rc.18",
3976+ "ed25519-dalek 3.0.0-rc.0",
3977+ "elliptic-curve 0.14.0-rc.33",
35993978 "enum_dispatch",
36003979 "flate2",
36013980 "futures",
⋯ 10 unchanged lines
36123991 "ml-kem",
36133992 "module-lattice",
36143993 "num-bigint",
3615- "p256",
3616- "p384",
3994+ "p256 0.14.0-rc.10",
3995+ "p384 0.14.0-rc.10",
36173996 "p521",
36183997 "pageant",
36193998 "pbkdf2",
3620- "pkcs1",
3999+ "pkcs1 0.8.0-rc.4",
36214000 "pkcs5",
3622- "pkcs8",
4001+ "pkcs8 0.11.0",
36234002 "polyval",
3624- "rand",
4003+ "rand 0.10.1",
36254004 "rand_core 0.10.1",
36264005 "ring",
3627- "rsa",
4006+ "rsa 0.10.0-rc.18",
36284007 "russh-cryptovec",
36294008 "russh-util",
36304009 "salsa20",
36314010 "scrypt",
3632- "sec1",
4011+ "sec1 0.8.1",
36334012 "sha1 0.11.0",
36344013 "sha2 0.11.0",
36354014 "sha3",
3636- "signature",
3637- "spki",
4015+ "signature 3.0.0",
4016+ "spki 0.8.0",
36384017 "ssh-encoding",
36394018 "ssh-key",
36404019 "subtle",
⋯ 66 unchanged lines
37074086 ]
37084087
37094088 [[package]]
4089+name = "rustls-native-certs"
4090+version = "0.8.4"
4091+source = "registry+https://github.com/rust-lang/crates.io-index"
4092+checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d"
4093+dependencies = [
4094+ "openssl-probe",
4095+ "rustls-pki-types",
4096+ "schannel",
4097+ "security-framework",
4098+]
4099+
4100+[[package]]
37104101 name = "rustls-pki-types"
37114102 version = "1.14.1"
37124103 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 45 unchanged lines
37584149 ]
37594150
37604151 [[package]]
4152+name = "schannel"
4153+version = "0.1.29"
4154+source = "registry+https://github.com/rust-lang/crates.io-index"
4155+checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
4156+dependencies = [
4157+ "windows-sys 0.61.2",
4158+]
4159+
4160+[[package]]
37614161 name = "schemars"
37624162 version = "0.9.0"
37634163 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 37 unchanged lines
38014201
38024202 [[package]]
38034203 name = "sec1"
4204+version = "0.7.3"
4205+source = "registry+https://github.com/rust-lang/crates.io-index"
4206+checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
4207+dependencies = [
4208+ "base16ct 0.2.0",
4209+ "der 0.7.10",
4210+ "generic-array 0.14.7",
4211+ "subtle",
4212+ "zeroize",
4213+]
4214+
4215+[[package]]
4216+name = "sec1"
38044217 version = "0.8.1"
38054218 source = "registry+https://github.com/rust-lang/crates.io-index"
38064219 checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d"
38074220 dependencies = [
3808- "base16ct",
4221+ "base16ct 1.0.0",
38094222 "ctutils",
3810- "der",
4223+ "der 0.8.0",
38114224 "hybrid-array",
38124225 "subtle",
38134226 "zeroize",
38144227 ]
38154228
38164229 [[package]]
4230+name = "security-framework"
4231+version = "3.7.0"
4232+source = "registry+https://github.com/rust-lang/crates.io-index"
4233+checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
4234+dependencies = [
4235+ "bitflags",
4236+ "core-foundation",
4237+ "core-foundation-sys",
4238+ "libc",
4239+ "security-framework-sys",
4240+]
4241+
4242+[[package]]
4243+name = "security-framework-sys"
4244+version = "2.17.0"
4245+source = "registry+https://github.com/rust-lang/crates.io-index"
4246+checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
4247+dependencies = [
4248+ "core-foundation-sys",
4249+ "libc",
4250+]
4251+
4252+[[package]]
38174253 name = "semver"
38184254 version = "1.0.28"
38194255 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 123 unchanged lines
39434379 source = "registry+https://github.com/rust-lang/crates.io-index"
39444380 checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e"
39454381 dependencies = [
3946- "base16ct",
4382+ "base16ct 1.0.0",
39474383 "serde",
39484384 ]
39494385
⋯ 94 unchanged lines
40444480
40454481 [[package]]
40464482 name = "signature"
4483+version = "2.2.0"
4484+source = "registry+https://github.com/rust-lang/crates.io-index"
4485+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
4486+dependencies = [
4487+ "digest 0.10.7",
4488+ "rand_core 0.6.4",
4489+]
4490+
4491+[[package]]
4492+name = "signature"
40474493 version = "3.0.0"
40484494 source = "registry+https://github.com/rust-lang/crates.io-index"
40494495 checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5"
⋯ 37 unchanged lines
40874533 ]
40884534
40894535 [[package]]
4536+name = "spin"
4537+version = "0.9.9"
4538+source = "registry+https://github.com/rust-lang/crates.io-index"
4539+checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
4540+
4541+[[package]]
4542+name = "spki"
4543+version = "0.7.3"
4544+source = "registry+https://github.com/rust-lang/crates.io-index"
4545+checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
4546+dependencies = [
4547+ "base64ct",
4548+ "der 0.7.10",
4549+]
4550+
4551+[[package]]
40904552 name = "spki"
40914553 version = "0.8.0"
40924554 source = "registry+https://github.com/rust-lang/crates.io-index"
40934555 checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f"
40944556 dependencies = [
40954557 "base64ct",
4096- "der",
4558+ "der 0.8.0",
40974559 ]
40984560
40994561 [[package]]
⋯ 36 unchanged lines
41364598 dependencies = [
41374599 "base64ct",
41384600 "bytes",
4139- "crypto-bigint",
4601+ "crypto-bigint 0.7.3",
41404602 "ctutils",
41414603 "digest 0.11.3",
41424604 "pem-rfc7468",
⋯ 9 unchanged lines
41524614 "argon2 0.6.0-rc.8",
41534615 "bcrypt-pbkdf",
41544616 "ctutils",
4155- "ed25519-dalek",
4617+ "ed25519-dalek 3.0.0-rc.0",
41564618 "hex",
41574619 "hmac 0.13.0",
4158- "p256",
4159- "p384",
4620+ "p256 0.14.0-rc.10",
4621+ "p384 0.14.0-rc.10",
41604622 "p521",
41614623 "rand_core 0.10.1",
4162- "rsa",
4163- "sec1",
4624+ "rsa 0.10.0-rc.18",
4625+ "sec1 0.8.1",
41644626 "sha1 0.11.0",
41654627 "sha2 0.11.0",
4166- "signature",
4628+ "signature 3.0.0",
41674629 "ssh-cipher",
41684630 "ssh-encoding",
41694631 "zeroize",
⋯ 500 unchanged lines
46705132 checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
46715133
46725134 [[package]]
5135+name = "ucd-parse"
5136+version = "0.1.13"
5137+source = "registry+https://github.com/rust-lang/crates.io-index"
5138+checksum = "c06ff81122fcbf4df4c1660b15f7e3336058e7aec14437c9f85c6b31a0f279b9"
5139+dependencies = [
5140+ "regex-lite",
5141+]
5142+
5143+[[package]]
46735144 name = "uluru"
46745145 version = "3.1.0"
46755146 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 89 unchanged lines
47655236 dependencies = [
47665237 "getrandom 0.4.2",
47675238 "js-sys",
4768- "rand",
5239+ "rand 0.10.1",
47695240 "wasm-bindgen",
47705241 ]
47715242
⋯ 158 unchanged lines
49305401 ]
49315402
49325403 [[package]]
4933-name = "webpki-roots"
4934-version = "1.0.7"
5404+name = "webauthn_rp"
5405+version = "0.3.0"
49355406 source = "registry+https://github.com/rust-lang/crates.io-index"
4936-checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d"
5407+checksum = "a3a3b672b5e6ffc799106fb40c86d5787e331d5491452ffc3eb616b418e04e85"
49375408 dependencies = [
4938- "rustls-pki-types",
5409+ "data-encoding",
5410+ "ed25519-dalek 2.2.0",
5411+ "p256 0.13.2",
5412+ "p384 0.13.1",
5413+ "precis-profiles",
5414+ "rand 0.9.5",
5415+ "rsa 0.9.10",
5416+ "serde",
5417+ "serde_json",
5418+ "url",
49395419 ]
49405420
49415421 [[package]]
⋯ 380 unchanged lines
53225802 ]
53235803
53245804 [[package]]
5805+name = "zerocopy"
5806+version = "0.8.56"
5807+source = "registry+https://github.com/rust-lang/crates.io-index"
5808+checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
5809+dependencies = [
5810+ "zerocopy-derive",
5811+]
5812+
5813+[[package]]
5814+name = "zerocopy-derive"
5815+version = "0.8.56"
5816+source = "registry+https://github.com/rust-lang/crates.io-index"
5817+checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
5818+dependencies = [
5819+ "proc-macro2",
5820+ "quote",
5821+ "syn",
5822+]
5823+
5824+[[package]]
53255825 name = "zerofrom"
53265826 version = "0.1.8"
53275827 source = "registry+https://github.com/rust-lang/crates.io-index"
⋯ 67 unchanged lines
modifiedCargo.toml+9 −1
⋯ 56 unchanged lines
5757 # cross-compile, ring does not. anvil-git installs the provider at use time.
5858 # Used for the CD deploy webhook (anvil-ci) and HTTPS push mirroring
5959 # (anvil-git).
60-reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-webpki-roots-no-provider"] }
60+# Native (system) roots rather than the bundled webpki set: `anvild secret`
61+# talks to whatever anvil you self-host, including one behind a private or
62+# local CA — portless's `.localhost` certificates being the everyday case. The
63+# deploy image installs ca-certificates, so the server side is unaffected.
64+reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-native-roots-no-provider"] }
6165 rustls = { version = "0.23", default-features = false, features = ["ring", "logging", "std", "tls12"] }
6266 # Used directly only for idempotent schema shims on existing databases; the
6367 # version tracks what toasty-driver-sqlite already pulls in.
6468 rusqlite = "0.39"
6569 # `anvild secret` prompts for an ssh key passphrase / an account password.
6670 rpassword = "7"
71+# WebAuthn/passkey sign-in, relying-party side. Pure Rust on purpose: the
72+# better-known webauthn-rs pulls in OpenSSL, which the static-musl deploy build
73+# (deploy/build.sh) cannot link.
74+webauthn_rp = { version = "0.3", features = ["serde_relaxed"] }
6775 serde = { version = "1", features = ["derive"] }
6876 serde_json = "1"
6977 serde_yaml = "0.9"
⋯ 25 unchanged lines
modifiedDockerfile+5 −1
⋯ 18 unchanged lines
1919
2020 # Prebuilt static binary staged by deploy/build.sh.
2121 COPY deploy/anvild /usr/local/bin/anvild
22-COPY deploy/anvil.toml /etc/anvil/anvil.toml
2322
23+# Which baked config to ship: production's by default, the committed local one
24+# when deploy/dev.sh builds the image.
25+ARG CONFIG=deploy/anvil.toml
26+COPY ${CONFIG} /etc/anvil/anvil.toml
27+
2428 EXPOSE 3000 2222
2529 VOLUME /data
2630 USER anvil
⋯ 3 unchanged lines
modifiedcrates/anvil-cli/src/secret.rs+20 −3
⋯ 275 unchanged lines
276276 let key = ssh_key::PrivateKey::read_openssh_file(&path)
277277 .with_context(|| format!("reading ssh key {}", path.display()))?;
278278 let key = if key.is_encrypted() {
279- let passphrase =
280- rpassword::prompt_password(format!("passphrase for {}: ", path.display()))?;
279+ // ssh-agent is no help here: the agent protocol only signs, and opening
280+ // an envelope needs the scalar itself for key agreement. So the key file
281+ // has to be decrypted in this process.
282+ let passphrase = match std::env::var("ANVIL_KEY_PASSPHRASE") {
283+ Ok(passphrase) => passphrase,
284+ Err(_) => prompt_passphrase(&path)?,
285+ };
281286 key.decrypt(passphrase)
282- .with_context(|| format!("decrypting {}", path.display()))?
287+ .with_context(|| format!("decrypting {} (wrong passphrase?)", path.display()))?
283288 } else {
284289 key
285290 };
286291 Ok(Identity::from_private_key(&key)?)
287292 }
288293
294+/// Ask for the key's passphrase, explaining the way out when there is no
295+/// terminal to ask on (a cron job, a pipeline, an agent's shell).
296+fn prompt_passphrase(path: &std::path::Path) -> Result<String> {
297+ rpassword::prompt_password(format!("passphrase for {}: ", path.display())).map_err(|e| {
298+ anyhow!(
299+ "{} is passphrase-protected and there is no terminal to prompt on ({e}). \
300+ Set ANVIL_KEY_PASSPHRASE, or point --identity at an unencrypted key.",
301+ path.display()
302+ )
303+ })
304+}
305+
289306 // --- HTTP client -----------------------------------------------------------
290307
291308 struct Client {
⋯ 215 unchanged lines
modifiedcrates/anvil-core/src/config.rs+98 −4
⋯ 247 unchanged lines
248248 toml::from_str(&text).map_err(|e| Error::Config(format!("parsing {}: {e}", path.display())))
249249 }
250250
251- /// Load from `path` if it exists, otherwise return defaults.
251+ /// Load from `path` if it exists, otherwise return defaults. Environment
252+ /// overrides are applied either way — see [`Config::apply_env`].
252253 pub fn load_or_default(path: impl AsRef<Path>) -> Result<Self> {
253254 let path = path.as_ref();
254- if path.exists() {
255- Self::load(path)
255+ let mut config = if path.exists() {
256+ Self::load(path)?
256257 } else {
257- Ok(Self::default())
258+ Self::default()
259+ };
260+ config.apply_env(|key| std::env::var(key).ok());
261+ Ok(config)
262+ }
263+
264+ /// Overlay environment variables onto a loaded config, so a supervisor can
265+ /// place anvil wherever it likes without a config file.
266+ ///
267+ /// - `ANVIL_LISTEN`, or `HOST`/`PORT` — the bind address. `PORT` (with
268+ /// `HOST` defaulting to `127.0.0.1`) is the convention process managers
269+ /// and local proxies use; portless, for one, hands the app a free port in
270+ /// 4000-4999 and reverse-proxies a `.localhost` name to it.
271+ /// - `ANVIL_BASE_URL`, or `PORTLESS_URL` — the externally visible URL that
272+ /// clone commands and links are built from. Getting this right is what
273+ /// makes the UI usable behind a proxy: the bind port is an implementation
274+ /// detail, `https://anvil.localhost` is the address users see.
275+ ///
276+ /// Explicit `ANVIL_*` wins over the generic name, and both win over the
277+ /// file, on the usual "closest to the invocation" principle.
278+ pub fn apply_env(&mut self, env: impl Fn(&str) -> Option<String>) {
279+ if let Some(listen) = env("ANVIL_LISTEN") {
280+ self.http.listen = listen;
281+ } else if let Some(port) = env("PORT").filter(|p| p.parse::<u16>().is_ok()) {
282+ let host = env("HOST").unwrap_or_else(|| "127.0.0.1".to_string());
283+ self.http.listen = format!("{host}:{port}");
284+ }
285+ if let Some(base) = env("ANVIL_BASE_URL").or_else(|| env("PORTLESS_URL")) {
286+ self.http.base_url = base.trim_end_matches('/').to_string();
258287 }
288+ if let Some(dir) = env("ANVIL_DATA_DIR") {
289+ self.data_dir = dir.into();
290+ }
259291 }
260292
261293 /// Filesystem path to the SQLite database file.
⋯ 58 unchanged lines
320352 mod tests {
321353 use super::*;
322354
355+ /// Look up from a fixed list, standing in for the process environment.
356+ fn env_of<'a>(pairs: &'a [(&'a str, &'a str)]) -> impl Fn(&str) -> Option<String> + 'a {
357+ move |key| {
358+ pairs
359+ .iter()
360+ .find(|(k, _)| *k == key)
361+ .map(|(_, v)| v.to_string())
362+ }
363+ }
364+
365+ #[test]
366+ fn port_and_host_set_the_bind_address() {
367+ let mut config = Config::default();
368+ config.apply_env(env_of(&[("PORT", "4738")]));
369+ assert_eq!(config.http.listen, "127.0.0.1:4738");
370+
371+ let mut config = Config::default();
372+ config.apply_env(env_of(&[("PORT", "4738"), ("HOST", "0.0.0.0")]));
373+ assert_eq!(config.http.listen, "0.0.0.0:4738");
374+ }
375+
376+ #[test]
377+ fn anvil_listen_wins_over_port() {
378+ let mut config = Config::default();
379+ config.apply_env(env_of(&[
380+ ("PORT", "4738"),
381+ ("ANVIL_LISTEN", "0.0.0.0:9000"),
382+ ]));
383+ assert_eq!(config.http.listen, "0.0.0.0:9000");
384+ }
385+
386+ #[test]
387+ fn a_nonsense_port_leaves_the_configured_address_alone() {
388+ let mut config = Config::default();
389+ config.apply_env(env_of(&[("PORT", "not-a-port")]));
390+ assert_eq!(config.http.listen, "127.0.0.1:3000");
391+ }
392+
393+ #[test]
394+ fn proxy_url_becomes_the_base_url() {
395+ let mut config = Config::default();
396+ config.apply_env(env_of(&[("PORTLESS_URL", "https://anvil.localhost/")]));
397+ assert_eq!(config.http.base_url, "https://anvil.localhost");
398+ // …and drives the Secure cookie attribute, since it is https.
399+ assert!(config.secure_cookies());
400+
401+ let mut config = Config::default();
402+ config.apply_env(env_of(&[
403+ ("PORTLESS_URL", "https://anvil.localhost"),
404+ ("ANVIL_BASE_URL", "https://forge.example.com"),
405+ ]));
406+ assert_eq!(config.http.base_url, "https://forge.example.com");
407+ }
408+
409+ #[test]
410+ fn an_empty_environment_changes_nothing() {
411+ let mut config = Config::default();
412+ config.apply_env(env_of(&[]));
413+ assert_eq!(config.http.listen, HttpConfig::default().listen);
414+ assert_eq!(config.http.base_url, HttpConfig::default().base_url);
415+ }
416+
323417 #[test]
324418 fn image_allowlist_semantics() {
325419 let mut ci = CiConfig::default();
⋯ 18 unchanged lines
addeddeploy/anvil.dev.toml+36 −0
1+# Config for the local Docker instance started by deploy/dev.sh.
2+#
3+# Committed on purpose (unlike deploy/anvil.toml, which is gitignored because it
4+# holds production's deploy secret): nothing here is sensitive, and a working
5+# local instance should be one command away.
6+
7+data_dir = "/data"
8+
9+[http]
10+# Inside the container; deploy/dev.sh publishes it to 127.0.0.1 on the host.
11+listen = "0.0.0.0:3000"
12+# What the browser sees. dev.sh also passes ANVIL_BASE_URL, which wins — so a
13+# differently named instance (ANVIL_DEV_NAME=anvil2) still gets correct links.
14+base_url = "https://anvil.localhost"
15+
16+[ssh]
17+enabled = true
18+listen = "0.0.0.0:2222"
19+# The published host port, i.e. dev.sh's $SSH_PORT (default: web port + 1).
20+# portless proxies HTTP only, so SSH clone URLs point straight at localhost.
21+clone_host = "localhost"
22+clone_port = 20641
23+clone_user = "git"
24+
25+[ci]
26+# The job container is a sibling on the host's Docker daemon, as in production.
27+memory_mb = 2048
28+cpus = 2.0
29+timeout_secs = 600
30+
31+[periodic]
32+# Local instances are small; scanning every 10 minutes keeps language stats and
33+# preview images fresh while you poke at things.
34+language_detection_interval_secs = 600
35+preview_image_interval_secs = 600
36+disk_usage_interval_secs = 600
addeddeploy/dev.sh+114 −0
1+#!/usr/bin/env bash
2+# Run anvil locally in Docker, reachable at https://anvil.localhost.
3+#
4+# The same image shape as production (deploy/build.sh + run.sh), but built and
5+# run on this machine: a container publishing 3000 to a fixed host port, with
6+# portless reverse-proxying a stable `.localhost` name onto it. Running in
7+# Docker rather than `cargo run` is what makes CI testable — the runner drives
8+# the host's Docker socket, which is mounted in.
9+#
10+# Usage:
11+# ./deploy/dev.sh build + (re)start, then print the URL
12+# ./deploy/dev.sh --release optimized binary (slower build, faster server)
13+# ./deploy/dev.sh --stop stop and remove the container
14+# ./deploy/dev.sh --logs follow the container log
15+#
16+# State lives in the `anvil-dev-data` volume and survives restarts;
17+# `docker volume rm anvil-dev-data` starts over.
18+set -euo pipefail
19+
20+cd "$(dirname "$0")/.."
21+
22+NAME="${ANVIL_DEV_NAME:-anvil}"
23+IMAGE="anvil-dev:latest"
24+TARGET="x86_64-unknown-linux-musl"
25+VOLUME="anvil-dev-data"
26+# A stable, collision-resistant port for this project (see `devport -h`), so the
27+# published port does not wander between runs. portless maps a name onto it.
28+PORT="${ANVIL_DEV_PORT:-$(command -v devport >/dev/null && devport || echo 20640)}"
29+SSH_PORT="${ANVIL_DEV_SSH_PORT:-$((PORT + 1))}"
30+PROFILE=debug
31+CARGO_FLAGS=()
32+
33+for arg in "$@"; do
34+ case "$arg" in
35+ --release)
36+ PROFILE=release
37+ CARGO_FLAGS+=(--release)
38+ ;;
39+ --stop)
40+ docker rm -f "$NAME" >/dev/null 2>&1 || true
41+ portless alias --remove "$NAME" >/dev/null 2>&1 || true
42+ echo "stopped $NAME"
43+ exit 0
44+ ;;
45+ --logs)
46+ exec docker logs -f "$NAME"
47+ ;;
48+ *)
49+ echo "unknown flag: $arg" >&2
50+ exit 2
51+ ;;
52+ esac
53+done
54+
55+echo "==> building anvild ($PROFILE, static musl)"
56+# Static musl, exactly as in production: the runtime image is debian-slim and a
57+# binary linked against Fedora's glibc would not run there.
58+cargo zigbuild --target "$TARGET" --bin anvild "${CARGO_FLAGS[@]}"
59+cp "target/$TARGET/$PROFILE/anvild" deploy/anvild
60+trap 'rm -f deploy/anvild' EXIT
61+
62+echo "==> building $IMAGE"
63+docker build --quiet --platform linux/amd64 \
64+ --build-arg CONFIG=deploy/anvil.dev.toml -t "$IMAGE" . >/dev/null
65+
66+echo "==> (re)starting container $NAME"
67+docker rm -f "$NAME" >/dev/null 2>&1 || true
68+# The CI runner is a Docker client, so it needs the socket and the group that
69+# owns it. `label=disable` rather than a `:z` relabel: :z would rewrite the
70+# label on the *host's* socket, which every other container also uses.
71+docker run -d --name "$NAME" --restart unless-stopped \
72+ -p "127.0.0.1:$PORT:3000" \
73+ -p "127.0.0.1:$SSH_PORT:2222" \
74+ -v "$VOLUME:/data" \
75+ -v /var/run/docker.sock:/var/run/docker.sock \
76+ --security-opt label=disable \
77+ --group-add "$(stat -c '%g' /var/run/docker.sock)" \
78+ -e "ANVIL_BASE_URL=https://$NAME.localhost" \
79+ "$IMAGE" >/dev/null
80+
81+# Wait for the server to answer before handing over a URL that would 502.
82+for _ in $(seq 1 50); do
83+ if curl -fsS -o /dev/null "http://127.0.0.1:$PORT/-/healthz" 2>/dev/null; then
84+ break
85+ fi
86+ sleep 0.2
87+done
88+
89+if command -v portless >/dev/null; then
90+ echo "==> routing https://$NAME.localhost -> 127.0.0.1:$PORT"
91+ portless alias "$NAME" "$PORT" >/dev/null
92+ URL="https://$NAME.localhost"
93+else
94+ echo "==> portless not installed; skipping the .localhost route"
95+ URL="http://127.0.0.1:$PORT"
96+fi
97+
98+cat <<EOF
99+
100+anvil is up.
101+
102+ web $URL
103+ ssh ssh://git@localhost:$SSH_PORT/<owner>/<repo>.git
104+ direct http://127.0.0.1:$PORT
105+
106+First run? Create an account and a repo:
107+
108+ docker exec $NAME anvild -c /etc/anvil/anvil.toml \\
109+ user create <you> --password '<password>' --admin
110+ docker exec -i $NAME anvild -c /etc/anvil/anvil.toml \\
111+ user add-key <you> --title laptop --key "\$(cat ~/.ssh/id_ed25519.pub)"
112+
113+Logs: ./deploy/dev.sh --logs Stop: ./deploy/dev.sh --stop
114+EOF