diff --git a/.github/workflows/sdk-ci.yaml b/.github/workflows/sdk-ci.yaml index 505bae8..64f9a3a 100644 --- a/.github/workflows/sdk-ci.yaml +++ b/.github/workflows/sdk-ci.yaml @@ -86,7 +86,6 @@ jobs: with: # there are no builds for arm linux at all, so we'll make do with the system ones python-version: | - 3.7 3.8 3.9 3.10 diff --git a/Cargo.lock b/Cargo.lock index 4a37d22..c7ae521 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,7 +175,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.41", + "syn", ] [[package]] @@ -220,7 +220,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn", ] [[package]] @@ -470,7 +470,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.41", + "syn", ] [[package]] @@ -757,7 +757,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn", ] [[package]] @@ -790,19 +790,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generator" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "windows", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -813,15 +800,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - [[package]] name = "getrandom" version = "0.2.11" @@ -1204,29 +1182,6 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "loom" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" -dependencies = [ - "cfg-if", - "generator", - "pin-utils", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - [[package]] name = "matrixmultiply" version = "0.3.8" @@ -1328,16 +1283,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - [[package]] name = "num-complex" version = "0.4.4" @@ -1393,13 +1338,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] -name = "oneshot" +name = "oneshot-uniffi" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f6640c6bda7731b1fdbab747981a0f896dd1fedaf9f4a53fa237a04a84431f4" -dependencies = [ - "loom", -] +checksum = "6c548d5c78976f6955d72d0ced18c48ca07030f7a1d4024529fedd7c1c01b29c" [[package]] name = "oorandom" @@ -1413,12 +1355,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "paste" version = "1.0.14" @@ -1518,7 +1454,7 @@ dependencies = [ "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.8.2", + "regex-syntax", "rusty-fork", "tempfile", "unarray", @@ -1576,18 +1512,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "pulldown-cmark" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" -dependencies = [ - "bitflags 1.3.2", - "getopts", - "memchr", - "unicase", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -1695,17 +1619,8 @@ checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[package]] @@ -1716,15 +1631,9 @@ checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax", ] -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "regex-syntax" version = "0.8.2" @@ -1850,12 +1759,6 @@ dependencies = [ "untrusted 0.9.0", ] -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - [[package]] name = "rusty-fork" version = "0.3.0" @@ -1883,12 +1786,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scroll" version = "0.11.0" @@ -1906,7 +1803,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn", ] [[package]] @@ -1945,7 +1842,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn", ] [[package]] @@ -1982,15 +1879,6 @@ dependencies = [ "digest", ] -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - [[package]] name = "siphasher" version = "0.3.11" @@ -2007,10 +1895,10 @@ dependencies = [ ] [[package]] -name = "smallvec" -version = "1.11.2" +name = "smawk" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" @@ -2062,17 +1950,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.41" @@ -2118,6 +1995,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.50" @@ -2135,17 +2023,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", -] - -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", + "syn", ] [[package]] @@ -2198,7 +2076,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn", ] [[package]] @@ -2247,21 +2125,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.41", -] - [[package]] name = "tracing-core" version = "0.1.32" @@ -2269,36 +2135,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", ] [[package]] @@ -2340,6 +2176,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.22" @@ -2363,8 +2205,8 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +version = "0.25.3" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "anyhow", "camino", @@ -2376,8 +2218,8 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +version = "0.25.3" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "anyhow", "askama", @@ -2391,8 +2233,8 @@ dependencies = [ "once_cell", "paste", "serde", + "textwrap", "toml", - "uniffi_docs", "uniffi_meta", "uniffi_testing", "uniffi_udl", @@ -2400,8 +2242,8 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +version = "0.25.3" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "anyhow", "camino", @@ -2410,17 +2252,17 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +version = "0.25.3" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "quote", - "syn 2.0.41", + "syn", ] [[package]] name = "uniffi_core" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +version = "0.25.3" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "anyhow", "async-compat", @@ -2428,26 +2270,15 @@ dependencies = [ "camino", "log", "once_cell", - "oneshot", + "oneshot-uniffi", "paste", "static_assertions", ] -[[package]] -name = "uniffi_docs" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" -dependencies = [ - "anyhow", - "pulldown-cmark", - "syn 1.0.109", - "uniffi_meta", -] - [[package]] name = "uniffi_macros" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +version = "0.25.3" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "bincode", "camino", @@ -2456,7 +2287,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.41", + "syn", "toml", "uniffi_build", "uniffi_meta", @@ -2464,8 +2295,8 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +version = "0.25.3" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "anyhow", "bytes", @@ -2475,8 +2306,8 @@ dependencies = [ [[package]] name = "uniffi_testing" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +version = "0.25.3" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "anyhow", "camino", @@ -2487,10 +2318,11 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.24.3" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +version = "0.25.3" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "anyhow", + "textwrap", "uniffi_meta", "uniffi_testing", "weedle2", @@ -2535,12 +2367,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - [[package]] name = "version_check" version = "0.9.4" @@ -2602,7 +2428,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.41", + "syn", "wasm-bindgen-shared", ] @@ -2636,7 +2462,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2666,7 +2492,7 @@ checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/skeet70/uniffi-rs.git?rev=5c3aa4a9f7c603437c42c500833347e3d7dfe0c2#5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" +source = "git+https://github.com/bendk/uniffi-rs.git?branch=foreign-trait-interfaces-opt-in#5588e5b2fe478f87cadc339aea5affd08f73576d" dependencies = [ "nom", ] @@ -2714,15 +2540,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 94e2735..936f05f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,16 +48,17 @@ ring = "0.16.20" serde = { version = "1.0.163", features = ["derive"] } serde_json = { version = "1.0.96", features = ["float_roundtrip"] } thiserror = "1.0.50" -uniffi = { git = "https://github.com/skeet70/uniffi-rs.git", features = [ +# update when 0.26 (https://github.com/mozilla/uniffi-rs/issues/1911) releases +uniffi = { git = "https://github.com/bendk/uniffi-rs.git", features = [ "cli", "tokio", -], rev = "5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" } +], branch = "foreign-trait-interfaces-opt-in" } z85 = "3.0.5" [dev-dependencies] approx = "0.5.1" ascii85 = "0.2.1" -assertables = "7.0.1" +assertables = "7.0.1" base64 = "0.21.5" base85 = "2.0.0" camino = "1.1" @@ -67,10 +68,10 @@ hex-literal = "0.4.1" lazy_static = "1.4" proptest = "1.2.0" tokio = { version = "1.33", features = ["macros", "rt-multi-thread"] } -uniffi = { git = "https://github.com/skeet70/uniffi-rs.git", features = [ +uniffi = { git = "https://github.com/bendk/uniffi-rs.git", features = [ "bindgen-tests", -], rev = "5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" } -uniffi_bindgen = { git = "https://github.com/skeet70/uniffi-rs.git", rev = "5c3aa4a9f7c603437c42c500833347e3d7dfe0c2" } +], branch = "foreign-trait-interfaces-opt-in" } +uniffi_bindgen = { git = "https://github.com/bendk/uniffi-rs.git", branch = "foreign-trait-interfaces-opt-in" } z85 = "3.0.5" [features] diff --git a/examples/python/pyproject.toml b/examples/python/pyproject.toml index 94b9f4f..f42d523 100644 --- a/examples/python/pyproject.toml +++ b/examples/python/pyproject.toml @@ -3,6 +3,6 @@ [project] name = "ironcore-alloy-examples" authors = [{ name = "IronCore Labs", email = "info@ironcorelabs.com" }] -requires-python = ">=3.7" +requires-python = ">=3.8" dependencies = ["ironcore-alloy"] dynamic = ["version"] diff --git a/python/ironcore-alloy/hatch_build.py b/python/ironcore-alloy/hatch_build.py index 8615c28..9c45c69 100644 --- a/python/ironcore-alloy/hatch_build.py +++ b/python/ironcore-alloy/hatch_build.py @@ -8,7 +8,7 @@ # See https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/ for info on each tag. def get_cdylib_specific_tag(cdylib_platform: str) -> str: print(cdylib_platform) - # our generated python code uses python 3.7 features, so we don't actually support all py3. We're depending + # our generated python code uses python 3.8 features, so we don't actually support all py3. We're depending # on the `requires-python` value in our `pyproject.toml` to make sure earlier incompatible interpreters don't # install us. python_tag = "py3" diff --git a/python/ironcore-alloy/pyproject.toml b/python/ironcore-alloy/pyproject.toml index 568036c..49f0518 100644 --- a/python/ironcore-alloy/pyproject.toml +++ b/python/ironcore-alloy/pyproject.toml @@ -12,7 +12,7 @@ name = "ironcore-alloy" authors = [{ name = "IronCore Labs", email = "info@ironcorelabs.com" }] description = "Python bindings to the IronCore Labs Alloy SDK. Used for encrypting and decrypting embeddings and their related metadata." readme = "README.md" -requires-python = ">=3.7" +requires-python = ">=3.8" classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)", @@ -48,10 +48,10 @@ serve = "mkdocs serve --dev-addr localhost:8000 {args}" [tool.hatch.envs.test] dependencies = [ - "pytest==7.4.2", - "pytest-cov==4.1.0", - "pytest-metadata==3.0.0", - "pytest-asyncio==0.21.1", + "pytest==7.4.2", + "pytest-cov==4.1.0", + "pytest-metadata==3.0.0", + "pytest-asyncio==0.21.1", ] [tool.hatch.envs.test.scripts] @@ -59,12 +59,10 @@ coverage = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=i test = "coverage --no-cov {args}" [[tool.hatch.envs.test.matrix]] -python = ["37", "38", "39", "310", "311"] +python = ["38", "39", "310", "311"] [tool.hatch.envs.bench] -dependencies = [ - "pyperf==2.6.2" -] +dependencies = ["pyperf==2.6.2"] [tool.hatch.envs.bench.scripts] bench = "rm bench.json; python bench.py -o bench.json" diff --git a/src/saas_shield/deterministic.rs b/src/saas_shield/deterministic.rs index 2193020..1b99acc 100644 --- a/src/saas_shield/deterministic.rs +++ b/src/saas_shield/deterministic.rs @@ -40,6 +40,10 @@ impl AlloyClient for SaasShieldDeterministicClient { #[uniffi::export(async_runtime = "tokio")] impl DeterministicFieldOps for SaasShieldDeterministicClient { + /// Encrypt a field with the provided metadata. + /// Because the field is encrypted deterministically with each call, the result will be the same for repeated calls. + /// This allows for exact matches and indexing of the encrypted field, but comes with some security considerations. + /// If you don't need to support these use cases, we recommend using `standard` encryption instead. async fn encrypt( &self, plaintext_field: PlaintextField, @@ -72,6 +76,7 @@ impl DeterministicFieldOps for SaasShieldDeterministicClient { ) } + /// Decrypt a field that was deterministically encrypted with the provided metadata. async fn decrypt( &self, encrypted_field: EncryptedField, @@ -113,6 +118,8 @@ impl DeterministicFieldOps for SaasShieldDeterministicClient { } } + /// Encrypt each plaintext field with any Current and InRotation keys for the provided secret path. + /// The resulting encrypted fields should be used in tandem when querying the data store. async fn generate_query_field_values( &self, fields_to_query: PlaintextFields, @@ -155,6 +162,9 @@ impl DeterministicFieldOps for SaasShieldDeterministicClient { .collect() } + /// Re-encrypt already encrypted fields with the Current key for the provided tenant. The `metadata` passed + /// must contain the tenant ID that the fields were originally encrypted to. If `new_tenant_id` is empty, + /// the fields will simply be encrypted with the same tenant's current secret. async fn rotate_fields( &self, encrypted_fields: EncryptedFields, @@ -221,6 +231,11 @@ impl DeterministicFieldOps for SaasShieldDeterministicClient { Ok(collection_to_batch_result(encrypted_fields, reencrypt_field).into()) } + /// Generate a prefix that could used to search a data store for fields encrypted using an identifier (KMS + /// config id for SaaS Shield, secret id for Standalone). These bytes should be encoded into + /// a format matching the encoding in the data store. z85/ascii85 users should first pass these bytes through + /// `encode_prefix_z85` or `base85_prefix_padding`. Make sure you've read the documentation of those functions to + /// avoid pitfalls when encoding across byte boundaries. async fn get_in_rotation_prefix( &self, secret_path: SecretPath, diff --git a/src/saas_shield/standard.rs b/src/saas_shield/standard.rs index e0eedef..028f454 100644 --- a/src/saas_shield/standard.rs +++ b/src/saas_shield/standard.rs @@ -184,6 +184,15 @@ impl AlloyClient for SaasShieldStandardClient { #[uniffi::export(async_runtime = "tokio")] impl StandardDocumentOps for SaasShieldStandardClient { + /// Encrypt a document with the provided metadata. The document must be a map from field identifiers to plaintext + /// bytes, and the same metadata must be provided when decrypting the document. + /// A DEK (document encryption key) will be generated and encrypted using a derived key, then each field of the + /// document will be encrypted separately using a random IV and this single generated DEK. + /// The result contains a map from field identifiers to encrypted bytes as well as the EDEK (encrypted document + /// encryption key) used for encryption. + /// The document is encrypted differently with each call, so the result is not suited for exact matches or indexing. + /// For the same reason however the strongest protection of the document is provided by this method. + /// To support these uses, see the `DeterministicFieldOps.encrypt` function. async fn encrypt( &self, plaintext_document: PlaintextDocument, @@ -207,6 +216,9 @@ impl StandardDocumentOps for SaasShieldStandardClient { ) } + /// Decrypt a document that was encrypted with the provided metadata. The document must have been encrypted with one + /// of the `StandardDocumentOps.encrypt` functions. The result contains a map from field identifiers to decrypted + /// bytes. async fn decrypt( &self, encrypted_document: EncryptedDocument, @@ -224,6 +236,9 @@ impl StandardDocumentOps for SaasShieldStandardClient { decrypt_document_core(encrypted_document.document, enc_key) } + /// Decrypt the provided EDEKs and re-encrypt them using the tenant's current key. If `new_tenant_id` is `None`, + /// the EDEK will be encrypted to the original tenant. Because the underlying DEK does not change, a document + /// associated with the old EDEK can be decrypted with the new EDEK without changing its document data. async fn rekey_edeks( &self, edeks: HashMap, @@ -240,6 +255,10 @@ impl StandardDocumentOps for SaasShieldStandardClient { Ok(collection_to_batch_result(tsp_responses, identity).into()) } + /// Encrypt a document with the provided metadata. The document must be a map from field identifiers to plaintext + /// bytes, and the same metadata must be provided when decrypting the document. + /// The provided EDEK will be decrypted and used to encrypt each field. This is useful when updating some fields + /// of the document. async fn encrypt_with_existing_edek( &self, plaintext_document: PlaintextDocumentWithEdek, diff --git a/src/saas_shield/standard_attached.rs b/src/saas_shield/standard_attached.rs index 8168672..79a3bed 100644 --- a/src/saas_shield/standard_attached.rs +++ b/src/saas_shield/standard_attached.rs @@ -15,6 +15,9 @@ pub struct SaasShieldStandardAttachedClient { } impl StandardAttachedDocumentOps for SaasShieldStandardAttachedClient { + /// Encrypt a field with the provided metadata. + /// A DEK (document encryption key) will be generated and encrypted using a derived key. + /// The result is a single blob of bytes with the edek put on the front of it. async fn encrypt( &self, plaintext_field: PlaintextBytes, @@ -23,6 +26,8 @@ impl StandardAttachedDocumentOps for SaasShieldStandardAttachedClient { encrypt_core(&self.standard_client, plaintext_field, metadata).await } + /// Decrypt a field that was encrypted with the provided metadata. + /// The document must have been encrypted using attached encryption and not deterministic or standard encryption. async fn decrypt( &self, attached_field: EncryptedAttachedDocument, @@ -31,6 +36,12 @@ impl StandardAttachedDocumentOps for SaasShieldStandardAttachedClient { decrypt_core(&self.standard_client, attached_field, metadata).await } + /// Generate a prefix that could used to search a data store for documents encrypted using an identifier (KMS + /// config id for SaaS Shield, secret id for Standalone). These bytes should be encoded into + /// a format matching the encoding in the data store. z85/ascii85 users should first pass these bytes through + /// `encode_prefix_z85` or `base85_prefix_padding`. Make sure you've read the documentation of those functions to + /// avoid pitfalls when encoding across byte boundaries. + /// Note that this will not work for matching values that don't use our key_id_header format, such as cloaked search. async fn get_searchable_edek_prefix(&self, id: i32) -> Vec { self.standard_client.get_searchable_edek_prefix(id) } diff --git a/src/saas_shield/vector.rs b/src/saas_shield/vector.rs index d7e076f..e8988d3 100644 --- a/src/saas_shield/vector.rs +++ b/src/saas_shield/vector.rs @@ -87,6 +87,9 @@ impl AlloyClient for SaasShieldVectorClient { #[uniffi::export(async_runtime = "tokio")] impl VectorOps for SaasShieldVectorClient { + /// Encrypt a vector embedding with the provided metadata. The provided embedding is assumed to be normalized + /// and its values will be shuffled as part of the encryption. + /// The same tenant ID must be provided in the metadata when decrypting the embedding. async fn encrypt( &self, plaintext_vector: PlaintextVector, @@ -115,6 +118,8 @@ impl VectorOps for SaasShieldVectorClient { self.encrypt_core(&key, key_id, plaintext_vector) } + /// Decrypt a vector embedding that was encrypted with the provided metadata. The values of the embedding will + /// be unshuffled to their original positions during decryption. async fn decrypt( &self, encrypted_vector: EncryptedVector, @@ -163,6 +168,8 @@ impl VectorOps for SaasShieldVectorClient { } } + /// Encrypt each plaintext vector with any Current and InRotation keys for the provided secret path. + /// The resulting encrypted vectors should be used in tandem when querying the vector database. async fn generate_query_vectors( &self, vectors_to_query: PlaintextVectors, diff --git a/src/standalone/deterministic.rs b/src/standalone/deterministic.rs index c147bbc..5864461 100644 --- a/src/standalone/deterministic.rs +++ b/src/standalone/deterministic.rs @@ -104,6 +104,10 @@ impl AlloyClient for StandaloneDeterministicClient { #[uniffi::export] impl DeterministicFieldOps for StandaloneDeterministicClient { + /// Encrypt a field with the provided metadata. + /// Because the field is encrypted deterministically with each call, the result will be the same for repeated calls. + /// This allows for exact matches and indexing of the encrypted field, but comes with some security considerations. + /// If you don't need to support these use cases, we recommend using `standard` encryption instead. async fn encrypt( &self, plaintext_field: PlaintextField, @@ -112,6 +116,7 @@ impl DeterministicFieldOps for StandaloneDeterministicClient { self.encrypt_sync(plaintext_field, &metadata.tenant_id) } + /// Decrypt a field that was deterministically encrypted with the provided metadata. async fn decrypt( &self, encrypted_field: EncryptedField, @@ -120,6 +125,8 @@ impl DeterministicFieldOps for StandaloneDeterministicClient { self.decrypt_sync(encrypted_field, &metadata.tenant_id) } + /// Encrypt each plaintext field with any Current and InRotation keys for the provided secret path. + /// The resulting encrypted fields should be used in tandem when querying the data store. async fn generate_query_field_values( &self, fields_to_query: PlaintextFields, @@ -169,6 +176,9 @@ impl DeterministicFieldOps for StandaloneDeterministicClient { .try_collect() } + /// Re-encrypt already encrypted fields with the Current key for the provided tenant. The `metadata` passed + /// must contain the tenant ID that the fields were originally encrypted to. If `new_tenant_id` is empty, + /// the fields will simply be encrypted with the same tenant's current secret. async fn rotate_fields( &self, encrypted_fields: EncryptedFields, @@ -205,6 +215,11 @@ impl DeterministicFieldOps for StandaloneDeterministicClient { Ok(collection_to_batch_result(encrypted_fields, reencrypt_field).into()) } + /// Generate a prefix that could used to search a data store for fields encrypted using an identifier (KMS + /// config id for SaaS Shield, secret id for Standalone). These bytes should be encoded into + /// a format matching the encoding in the data store. z85/ascii85 users should first pass these bytes through + /// `encode_prefix_z85` or `base85_prefix_padding`. Make sure you've read the documentation of those functions to + /// avoid pitfalls when encoding across byte boundaries. async fn get_in_rotation_prefix( &self, secret_path: SecretPath, diff --git a/src/standalone/standard.rs b/src/standalone/standard.rs index 300e170..8b8593c 100644 --- a/src/standalone/standard.rs +++ b/src/standalone/standard.rs @@ -135,6 +135,15 @@ impl AlloyClient for StandaloneStandardClient { #[uniffi::export] impl StandardDocumentOps for StandaloneStandardClient { + /// Encrypt a document with the provided metadata. The document must be a map from field identifiers to plaintext + /// bytes, and the same metadata must be provided when decrypting the document. + /// A DEK (document encryption key) will be generated and encrypted using a derived key, then each field of the + /// document will be encrypted separately using a random IV and this single generated DEK. + /// The result contains a map from field identifiers to encrypted bytes as well as the EDEK (encrypted document + /// encryption key) used for encryption. + /// The document is encrypted differently with each call, so the result is not suited for exact matches or indexing. + /// For the same reason however the strongest protection of the document is provided by this method. + /// To support these uses, see the `DeterministicFieldOps.encrypt` function. async fn encrypt( &self, plaintext_document: PlaintextDocument, @@ -151,6 +160,9 @@ impl StandardDocumentOps for StandaloneStandardClient { Ok(encrypted_doc) } + /// Decrypt a document that was encrypted with the provided metadata. The document must have been encrypted with one + /// of the `StandardDocumentOps.encrypt` functions. The result contains a map from field identifiers to decrypted + /// bytes. async fn decrypt( &self, encrypted_document: EncryptedDocument, @@ -164,6 +176,9 @@ impl StandardDocumentOps for StandaloneStandardClient { decrypt_document_core(encrypted_document.document, dek) } + /// Decrypt the provided EDEKs and re-encrypt them using the tenant's current key. If `new_tenant_id` is `None`, + /// the EDEK will be encrypted to the original tenant. Because the underlying DEK does not change, a document + /// associated with the old EDEK can be decrypted with the new EDEK without changing its document data. async fn rekey_edeks( &self, edeks: HashMap, @@ -190,6 +205,10 @@ impl StandardDocumentOps for StandaloneStandardClient { Ok(collection_to_batch_result(edeks, rekey_edek).into()) } + /// Encrypt a document with the provided metadata. The document must be a map from field identifiers to plaintext + /// bytes, and the same metadata must be provided when decrypting the document. + /// The provided EDEK will be decrypted and used to encrypt each field. This is useful when updating some fields + /// of the document. async fn encrypt_with_existing_edek( &self, plaintext_document: PlaintextDocumentWithEdek, diff --git a/src/standalone/standard_attached.rs b/src/standalone/standard_attached.rs index d758ba9..bba22ea 100644 --- a/src/standalone/standard_attached.rs +++ b/src/standalone/standard_attached.rs @@ -22,6 +22,9 @@ impl StandaloneAttachedStandardClient { } impl StandardAttachedDocumentOps for StandaloneAttachedStandardClient { + /// Encrypt a field with the provided metadata. + /// A DEK (document encryption key) will be generated and encrypted using a derived key. + /// The result is a single blob of bytes with the edek put on the front of it. async fn encrypt( &self, plaintext_field: PlaintextBytes, @@ -30,6 +33,8 @@ impl StandardAttachedDocumentOps for StandaloneAttachedStandardClient { encrypt_core(&self.standard_client, plaintext_field, metadata).await } + /// Decrypt a field that was encrypted with the provided metadata. + /// The document must have been encrypted using attached encryption and not deterministic or standard encryption. async fn decrypt( &self, encrypted_field: crate::standard_attached::EncryptedAttachedDocument, @@ -38,6 +43,12 @@ impl StandardAttachedDocumentOps for StandaloneAttachedStandardClient { decrypt_core(&self.standard_client, encrypted_field, metadata).await } + /// Generate a prefix that could used to search a data store for documents encrypted using an identifier (KMS + /// config id for SaaS Shield, secret id for Standalone). These bytes should be encoded into + /// a format matching the encoding in the data store. z85/ascii85 users should first pass these bytes through + /// `encode_prefix_z85` or `base85_prefix_padding`. Make sure you've read the documentation of those functions to + /// avoid pitfalls when encoding across byte boundaries. + /// Note that this will not work for matching values that don't use our key_id_header format, such as cloaked search. async fn get_searchable_edek_prefix(&self, id: i32) -> Vec { self.standard_client.get_searchable_edek_prefix(id) } diff --git a/src/standalone/vector.rs b/src/standalone/vector.rs index 1b04b53..4f88d52 100644 --- a/src/standalone/vector.rs +++ b/src/standalone/vector.rs @@ -84,6 +84,9 @@ impl AlloyClient for StandaloneVectorClient { #[uniffi::export] impl VectorOps for StandaloneVectorClient { + /// Encrypt a vector embedding with the provided metadata. The provided embedding is assumed to be normalized + /// and its values will be shuffled as part of the encryption. + /// The same tenant ID must be provided in the metadata when decrypting the embedding. async fn encrypt( &self, plaintext_vector: PlaintextVector, @@ -122,6 +125,8 @@ impl VectorOps for StandaloneVectorClient { ) } + /// Decrypt a vector embedding that was encrypted with the provided metadata. The values of the embedding will + /// be unshuffled to their original positions during decryption. async fn decrypt( &self, encrypted_vector: EncryptedVector, @@ -160,6 +165,8 @@ impl VectorOps for StandaloneVectorClient { ) } + /// Encrypt each plaintext vector with any Current and InRotation keys for the provided secret path. + /// The resulting encrypted vectors should be used in tandem when querying the vector database. async fn generate_query_vectors( &self, vectors_to_query: PlaintextVectors, @@ -244,6 +251,16 @@ impl VectorOps for StandaloneVectorClient { ) } + /// Rotates vectors from the in-rotation secret for their secret path to the current secret. + /// This can also be used to rotate data from one tenant ID to a new one, which most useful when a tenant is + /// internally migrated. + /// + /// WARNINGS: + /// * this involves decrypting then encrypting vectors. Since the vectors are full of floating point numbers, + /// this process is lossy, which will cause some drift over time. If you need perfectly preserved accuracy + /// store the source vector encrypted with `standard` next to the encrypted vector. `standard` decrypt + /// that, `vector` encrypt it again, and replace the encrypted vector with the result. + /// * only one metadata and new tenant ID argument means each call to this needs to have one tenant's vectors. async fn rotate_vectors( &self, encrypted_vectors: EncryptedVectors, diff --git a/tests/common/mod.rs b/tests/common/mod.rs index f02ed51..531365a 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -82,6 +82,7 @@ pub(crate) fn generate_bindings( &camino_lib_path, None, &[language], + None, &camino_out_dir, true, )?;