From ca18d54fa21189c2c7caf964ea0b8d689ccdafc5 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 10 Jul 2026 11:44:19 +0100 Subject: [PATCH] Serve Norn plugin ABI over CultNet --- Cargo.lock | 827 +++++++++++++++++++ README.md | 13 +- crates/norn-eve-plugin/Cargo.toml | 5 +- crates/norn-eve-plugin/src/lib.rs | 1 + crates/norn-eve-plugin/src/main.rs | 64 +- package-lock.json | 42 + package.json | 12 + plugins/norn-graph.plugin-advertisement.json | 5 +- plugins/norn-graph.plugin.json | 5 +- scripts/run-eve-cultnet-witness.mjs | 82 ++ scripts/run-eve-plugin-witness.ps1 | 30 +- 11 files changed, 1045 insertions(+), 41 deletions(-) create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 scripts/run-eve-cultnet-witness.mjs diff --git a/Cargo.lock b/Cargo.lock index 6188692..1a8863f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,379 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "cc" +version = "1.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d6cac793997bd970000024b2934968efe83b382de4fdcf4fcb46b6ee4ad996" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "cultcache-rs" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "cultcache-rs-derive", + "fs2", + "rmp-serde", + "serde", + "serde_bytes", + "serde_json", + "uuid", +] + +[[package]] +name = "cultcache-rs-derive" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cultnet-rs" +version = "0.1.0" +dependencies = [ + "aes-gcm", + "anyhow", + "base64", + "chrono", + "cultcache-rs", + "hmac", + "rand", + "rmp-serde", + "rmpv", + "serde", + "serde_bytes", + "serde_json", + "sha2", + "socket2", + "uuid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "itoa" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + [[package]] name = "memchr" version = "2.8.3" @@ -18,7 +385,11 @@ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" name = "norn-eve-plugin" version = "0.1.0" dependencies = [ + "anyhow", + "base64", + "cultnet-rs", "norn-rs", + "rmp-serde", "serde", "serde_json", ] @@ -27,6 +398,54 @@ dependencies = [ name = "norn-rs" version = "0.1.0" +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -45,6 +464,92 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rmp" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "rmp-serde" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" +dependencies = [ + "rmp", + "serde", +] + +[[package]] +name = "rmpv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a4e1d4b9b938a26d2996af33229f0ca0956c652c1375067f0b45291c1df8417" +dependencies = [ + "rmp", + "serde", + "serde_bytes", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + [[package]] name = "serde" version = "1.0.228" @@ -55,6 +560,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + [[package]] name = "serde_core" version = "1.0.228" @@ -88,6 +603,45 @@ dependencies = [ "zmij", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.118" @@ -99,12 +653,285 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "uuid" +version = "1.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" +dependencies = [ + "getrandom 0.4.3", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "zerocopy" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zmij" version = "1.0.21" diff --git a/README.md b/README.md index c08d3cd..e7d2da5 100644 --- a/README.md +++ b/README.md @@ -15,18 +15,17 @@ truths like this repo is a sad little trade show booth. ## Eve Plugin Sidecar -`crates/norn-eve-plugin` is Norn's runtime-independent Eve plugin boundary. It -accepts one `gamecult.eve.plugin_abi.request.v1` JSON document per UTF-8 stdin -line and emits one response line in request order. The sidecar owns graph -validation, semantic projection, and solver-backed measurement. It does not -own provider state or renderer projection. +`crates/norn-eve-plugin` is Norn's runtime-independent Eve plugin boundary. Its +default entry point advertises a CultNet RUDP operation endpoint carrying +MessagePack Eve ABI requests. The sidecar owns graph validation, semantic +projection, and solver-backed measurement. It does not own provider state or +renderer projection. Pass `--stdio` only for local NDJSON debugging. Owner-published discovery and conformance documents live under `plugins/` and the graph document/layout schemas live under `schemas/`. ```powershell -Get-Content .\crates\norn-eve-plugin\tests\fixtures\sai-nested-norn.ndjson | - cargo run -q -p norn-eve-plugin +npm run witness:eve-plugin ``` ## Rust Solver diff --git a/crates/norn-eve-plugin/Cargo.toml b/crates/norn-eve-plugin/Cargo.toml index ba705bf..cd3623b 100644 --- a/crates/norn-eve-plugin/Cargo.toml +++ b/crates/norn-eve-plugin/Cargo.toml @@ -7,7 +7,10 @@ license = "MIT OR Apache-2.0" repository = "https://github.com/GameCult/Norn" [dependencies] +anyhow = "1" +base64 = "0.22" +cultnet-rs = { path = "../../../CultLib/packages/cultnet-rs" } norn-rs = { path = "../norn-rs" } +rmp-serde = "1.3" serde = { version = "1", features = ["derive"] } serde_json = "1" - diff --git a/crates/norn-eve-plugin/src/lib.rs b/crates/norn-eve-plugin/src/lib.rs index ced621f..c4e1a0e 100644 --- a/crates/norn-eve-plugin/src/lib.rs +++ b/crates/norn-eve-plugin/src/lib.rs @@ -213,6 +213,7 @@ fn measure(request: &PluginRequest) -> PluginResponse { request, json!({ "measurementKind": "graph-layout-metrics", + "measurementOutputs": ["nodeBounds", "edgeRoutes", "viewportBounds"], "layoutSchema": "norn.graph.layout_result.v1", "nodeBounds": node_bounds, "edgeRoutes": edge_routes, diff --git a/crates/norn-eve-plugin/src/main.rs b/crates/norn-eve-plugin/src/main.rs index 860fd2f..e8075bf 100644 --- a/crates/norn-eve-plugin/src/main.rs +++ b/crates/norn-eve-plugin/src/main.rs @@ -1,9 +1,71 @@ use std::io::{self, BufRead, Write}; +use anyhow::{Result, anyhow}; +use base64::{Engine, engine::general_purpose::STANDARD as BASE64}; +use cultnet_rs::{CultNetMessage, CultNetOperationServer}; use norn_eve_plugin::{PLUGIN_ID, PluginRequest, PluginResponse, RESPONSE_SCHEMA, dispatch}; use serde_json::json; -fn main() -> io::Result<()> { +fn main() -> Result<()> { + if std::env::args().any(|argument| argument == "--stdio") { + return run_stdio().map_err(Into::into); + } + let host = std::env::var("EVE_PLUGIN_HOST").unwrap_or_else(|_| "127.0.0.1".into()); + let port = std::env::var("EVE_PLUGIN_PORT") + .ok() + .and_then(|value| value.parse().ok()) + .unwrap_or(0); + let mut server = CultNetOperationServer::bind("norn-graph-plugin", &host, port)?; + println!( + "{}", + json!({ "schema": "gamecult.eve.plugin_endpoint.v1", "pluginId": PLUGIN_ID, "endpoint": server.endpoint() }) + ); + loop { + server.serve_once(handle_operation)?; + } +} + +fn handle_operation(message: CultNetMessage) -> Result { + let CultNetMessage::OperationRequest { + message_id, + service_id, + operation, + payload_schema, + payload_encoding, + payload, + .. + } = message + else { + return Err(anyhow!("expected operation request")); + }; + if service_id != PLUGIN_ID + || payload_schema != "gamecult.eve.plugin_abi.request.v1" + || payload_encoding != "messagepack-base64" + { + return Err(anyhow!("unsupported Norn plugin operation envelope")); + } + let request: PluginRequest = rmp_serde::from_slice(&BASE64.decode(payload)?)?; + let response = dispatch(request); + let status = response.status.to_string(); + let diagnostics = response + .diagnostics + .iter() + .map(|item| item.message.clone()) + .collect(); + Ok(CultNetMessage::OperationResponse { + message_id, + service_id, + operation, + status, + payload_schema: RESPONSE_SCHEMA.into(), + payload_encoding: "messagepack-base64".into(), + payload: BASE64.encode(rmp_serde::to_vec_named(&response)?), + diagnostics, + source_runtime_id: Some("norn-graph-plugin".into()), + }) +} + +fn run_stdio() -> io::Result<()> { let stdin = io::stdin(); let mut stdout = io::stdout().lock(); for line in stdin.lock().lines() { diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9a68884 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,42 @@ +{ + "name": "@gamecult/norn-conformance", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@gamecult/norn-conformance", + "dependencies": { + "@msgpack/msgpack": "^3.1.3", + "cultnet-ts": "file:../CultLib/packages/cultnet-ts" + } + }, + "../CultLib/packages/cultnet-ts": { + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@msgpack/msgpack": "^3.1.3", + "ajv": "^8.17.1", + "cultcache-ts": "file:../cultcache-ts" + }, + "devDependencies": { + "@types/node": "^24.0.0", + "json-schema-to-typescript": "^15.0.4", + "typescript": "^5.9.0", + "zod": "^3.25.76" + } + }, + "node_modules/@msgpack/msgpack": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.3.tgz", + "integrity": "sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==", + "license": "ISC", + "engines": { + "node": ">= 18" + } + }, + "node_modules/cultnet-ts": { + "resolved": "../CultLib/packages/cultnet-ts", + "link": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6f26300 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "@gamecult/norn-conformance", + "private": true, + "type": "module", + "scripts": { + "witness:eve-plugin": "node scripts/run-eve-cultnet-witness.mjs" + }, + "dependencies": { + "@msgpack/msgpack": "^3.1.3", + "cultnet-ts": "file:../CultLib/packages/cultnet-ts" + } +} diff --git a/plugins/norn-graph.plugin-advertisement.json b/plugins/norn-graph.plugin-advertisement.json index 22db272..58bb1c6 100644 --- a/plugins/norn-graph.plugin-advertisement.json +++ b/plugins/norn-graph.plugin-advertisement.json @@ -7,11 +7,12 @@ "runtime": { "invocationModel": "executable-sidecar", "contract": "gamecult.eve.plugin_abi.v1", - "transports": ["stdio"], + "transports": ["cultnet-rudp", "stdio"], "authority": ["renderer-independent", "no-provider-state-mutation", "provider-accepts-or-denies-commands"], "sidecar": { "processKind": "long-running-daemon", - "protocol": "stdio-ndjson", + "protocol": "cultnet-operation-v0", + "debugProtocol": "stdio-ndjson", "requestSchema": "gamecult.eve.plugin_abi.request.v1", "responseSchema": "gamecult.eve.plugin_abi.response.v1", "operations": ["describe", "validate", "project", "measure"], diff --git a/plugins/norn-graph.plugin.json b/plugins/norn-graph.plugin.json index 60b25b9..41b1ad6 100644 --- a/plugins/norn-graph.plugin.json +++ b/plugins/norn-graph.plugin.json @@ -13,11 +13,12 @@ "runtime": { "invocationModel": "executable-sidecar", "contract": "gamecult.eve.plugin_abi.v1", - "transports": ["stdio"], + "transports": ["cultnet-rudp", "stdio"], "authority": ["renderer-independent", "no-provider-state-mutation", "provider-accepts-or-denies-commands"], "sidecar": { "processKind": "long-running-daemon", - "protocol": "stdio-ndjson", + "protocol": "cultnet-operation-v0", + "debugProtocol": "stdio-ndjson", "requestSchema": "gamecult.eve.plugin_abi.request.v1", "responseSchema": "gamecult.eve.plugin_abi.response.v1", "operations": ["describe", "validate", "project", "measure"], diff --git a/scripts/run-eve-cultnet-witness.mjs b/scripts/run-eve-cultnet-witness.mjs new file mode 100644 index 0000000..1453467 --- /dev/null +++ b/scripts/run-eve-cultnet-witness.mjs @@ -0,0 +1,82 @@ +import assert from "node:assert/strict"; +import { spawn, spawnSync } from "node:child_process"; +import fs from "node:fs"; +import path from "node:path"; +import readline from "node:readline"; +import os from "node:os"; +import { Buffer } from "node:buffer"; +import { decode, encode } from "@msgpack/msgpack"; +import { invokeCultNetOperation } from "cultnet-ts"; + +const root = path.resolve(import.meta.dirname, ".."); +const cargo = process.env.CARGO || (process.platform === "win32" ? path.join(os.homedir(), ".cargo/bin/cargo.exe") : "cargo"); +const build = spawnSync(cargo, ["build", "--quiet", "-p", "norn-eve-plugin"], { cwd: root, stdio: "inherit" }); +assert.equal(build.status, 0, "norn-eve-plugin build failed"); +const executable = path.join(root, "target", "debug", process.platform === "win32" ? "norn-eve-plugin.exe" : "norn-eve-plugin"); +const fixture = JSON.parse(fs.readFileSync(path.join(root, "plugins/norn-graph.plugin-abi-fixture.json"), "utf8")); +const child = spawn(executable, [], { cwd: root, stdio: ["ignore", "pipe", "inherit"] }); +const lines = readline.createInterface({ input: child.stdout })[Symbol.asyncIterator](); +const endpointLine = await lines.next(); +assert.equal(endpointLine.done, false); +const endpointAdvertisement = JSON.parse(endpointLine.value); +assert.equal(endpointAdvertisement.pluginId, fixture.pluginId); +const startedAt = performance.now(); +const operations = []; + +try { + for (let index = 0; index < fixture.operations.length; index += 1) { + const fixtureOperation = fixture.operations[index]; + const requestId = `norn-witness-${index}`; + const operationStartedAt = performance.now(); + const abiRequest = { schema: fixture.requestSchema, pluginId: fixture.pluginId, operation: fixtureOperation.operation, requestId, input: fixtureOperation.input }; + const envelope = await invokeCultNetOperation(endpointAdvertisement.endpoint, { + schemaVersion: "cultnet.operation_request.v0", + messageId: requestId, + serviceId: fixture.pluginId, + operation: fixtureOperation.operation, + payloadSchema: fixture.requestSchema, + payloadEncoding: "messagepack-base64", + payload: Buffer.from(encode(abiRequest)).toString("base64"), + sourceRuntimeId: "eve-conformance", + }, { runtimeId: "eve-conformance" }); + const response = decode(Buffer.from(envelope.payload, "base64")); + assert.equal(response.schema, fixture.responseSchema); + assert.equal(response.pluginId, fixture.pluginId); + assert.equal(response.operation, fixtureOperation.operation); + assert.equal(response.requestId, requestId); + assert.equal(response.status, "accepted"); + assertSubset(response.output, fixtureOperation.expect, fixtureOperation.operation); + operations.push({ operation: fixtureOperation.operation, requestId, status: response.status, durationMs: Number((performance.now() - operationStartedAt).toFixed(3)), expectationCount: Object.keys(fixtureOperation.expect).length }); + } +} finally { + child.kill(); +} + +const outputPath = path.join(root, "artifacts/eve-plugin/runtime-witness.json"); +fs.mkdirSync(path.dirname(outputPath), { recursive: true }); +fs.writeFileSync(outputPath, `${JSON.stringify({ + schema: "gamecult.eve.plugin_witness.v1", + witnessId: "norn.graph.owner-sidecar", + pluginId: fixture.pluginId, + ownerRepo: "Norn", + status: "pass", + transport: "cultnet-operation-v0+rudp", + generatedAtUtc: new Date().toISOString(), + durationMs: Number((performance.now() - startedAt).toFixed(3)), + operations, + advertisementPath: "plugins/norn-graph.plugin-advertisement.json", + fixturePath: "plugins/norn-graph.plugin-abi-fixture.json", + executable: { artifact: "target/debug/norn-eve-plugin", command: "cargo build -p norn-eve-plugin" }, + diagnostics: [], + authority: "norn-sidecar-owns-graph-semantics-provider-retains-command-acceptance", +}, null, 2)}\n`); +console.log(outputPath); + +function assertSubset(actual, expected, label) { + if (Array.isArray(expected)) return assert.deepEqual(actual, expected, label); + if (expected && typeof expected === "object") { + for (const [key, value] of Object.entries(expected)) assertSubset(actual?.[key], value, `${label}.${key}`); + return; + } + assert.equal(actual, expected, label); +} diff --git a/scripts/run-eve-plugin-witness.ps1 b/scripts/run-eve-plugin-witness.ps1 index 209bb6e..28fbd2b 100644 --- a/scripts/run-eve-plugin-witness.ps1 +++ b/scripts/run-eve-plugin-witness.ps1 @@ -1,31 +1,5 @@ -param( - [string] $EveRoot = "E:\Projects\Eve", - [string] $OutputPath = "artifacts\eve-plugin\runtime-witness.json" -) +param([string] $NodePath = "node") $ErrorActionPreference = "Stop" -$repoRoot = Split-Path -Parent $PSScriptRoot -$output = if ([IO.Path]::IsPathRooted($OutputPath)) { $OutputPath } else { Join-Path $repoRoot $OutputPath } -$launcher = Join-Path $EveRoot "tools\plugins\run-sidecar-witness.mjs" -$advertisement = Join-Path $repoRoot "plugins\norn-graph.plugin-advertisement.json" -$fixture = Join-Path $repoRoot "plugins\norn-graph.plugin-abi-fixture.json" - -foreach ($required in @($launcher, $advertisement, $fixture)) { - if (-not (Test-Path -LiteralPath $required)) { throw "Norn Eve plugin witness path not found: $required" } -} - -cargo build --quiet -p norn-eve-plugin -if ($LASTEXITCODE -ne 0) { throw "norn-eve-plugin build failed with exit code $LASTEXITCODE" } -$executable = Join-Path $repoRoot "target\debug\norn-eve-plugin.exe" -if (-not (Test-Path -LiteralPath $executable)) { throw "Norn sidecar executable was not produced: $executable" } - -node $launcher ` - --advertisement $advertisement ` - --fixture $fixture ` - --output $output ` - --witness-id "norn.graph.owner-sidecar" ` - --cwd $repoRoot ` - --command $executable +& $NodePath (Join-Path $PSScriptRoot "run-eve-cultnet-witness.mjs") if ($LASTEXITCODE -ne 0) { throw "Norn Eve plugin witness failed with exit code $LASTEXITCODE" } - -Write-Host "Norn Eve plugin witness: $output"