ciris-server 0.1.2__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. ciris_server-0.2.0/.cargo/config.toml +14 -0
  2. ciris_server-0.2.0/.github/workflows/bench.yml +67 -0
  3. {ciris_server-0.1.2 → ciris_server-0.2.0}/.github/workflows/ci.yml +22 -2
  4. {ciris_server-0.1.2 → ciris_server-0.2.0}/.github/workflows/publish-pypi.yml +59 -1
  5. {ciris_server-0.1.2 → ciris_server-0.2.0}/CHANGELOG.md +31 -0
  6. {ciris_server-0.1.2 → ciris_server-0.2.0}/Cargo.lock +4 -1
  7. {ciris_server-0.1.2 → ciris_server-0.2.0}/Cargo.toml +33 -10
  8. {ciris_server-0.1.2 → ciris_server-0.2.0}/FSD/LENS_TO_SERVER_MIGRATION.md +8 -1
  9. {ciris_server-0.1.2 → ciris_server-0.2.0}/PKG-INFO +1 -1
  10. ciris_server-0.2.0/benches/replication_ingest.rs +181 -0
  11. {ciris_server-0.1.2 → ciris_server-0.2.0}/pyproject.toml +1 -1
  12. ciris_server-0.2.0/scripts/bench_report.py +234 -0
  13. {ciris_server-0.1.2 → ciris_server-0.2.0}/src/compose.rs +73 -19
  14. {ciris_server-0.1.2 → ciris_server-0.2.0}/.github/workflows/conformance.yml +0 -0
  15. {ciris_server-0.1.2 → ciris_server-0.2.0}/.github/workflows/release.yml +0 -0
  16. {ciris_server-0.1.2 → ciris_server-0.2.0}/.gitignore +0 -0
  17. {ciris_server-0.1.2 → ciris_server-0.2.0}/FSD/PQC_AV_STREAMING_BENCH.md +0 -0
  18. {ciris_server-0.1.2 → ciris_server-0.2.0}/FSD/REGISTRY_FOLD_DERISK.md +0 -0
  19. {ciris_server-0.1.2 → ciris_server-0.2.0}/FSD/SERVER_1.0_PLAN.md +0 -0
  20. {ciris_server-0.1.2 → ciris_server-0.2.0}/LICENSE +0 -0
  21. {ciris_server-0.1.2 → ciris_server-0.2.0}/MISSION.md +0 -0
  22. {ciris_server-0.1.2 → ciris_server-0.2.0}/README.md +0 -0
  23. {ciris_server-0.1.2 → ciris_server-0.2.0}/benches/pqc_av_streaming.rs +0 -0
  24. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/.github/workflows/bench.yml +0 -0
  25. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/.github/workflows/ci.yml +0 -0
  26. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/.gitignore +0 -0
  27. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/.pre-commit-config.yaml +0 -0
  28. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/Cargo.toml +0 -0
  29. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/FSD/CIRIS_LENS_CORE.md +0 -0
  30. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/FSD/LENS_CORE_V0_5.md +0 -0
  31. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/FSD/OPEN_QUESTIONS.md +0 -0
  32. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/LICENSE +0 -0
  33. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/MISSION.md +0 -0
  34. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/README.md +0 -0
  35. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/benches/aggregate.rs +0 -0
  36. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/benches/canonicalize.rs +0 -0
  37. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/benches/project.rs +0 -0
  38. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/deny.toml +0 -0
  39. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/docs/BENCHMARKS.md +0 -0
  40. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/docs/COHABITATION.md +0 -0
  41. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/docs/PRE_COMMIT.md +0 -0
  42. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/docs/PUBLIC_SCHEMA_CONTRACT.md +0 -0
  43. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/docs/PYPI_PUBLISH.md +0 -0
  44. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/docs/RELEASE_NOTES.md +0 -0
  45. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/docs/STANDARDS_COMPARISON.md +0 -0
  46. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/docs/THREAT_MODEL.md +0 -0
  47. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/extraction/json_path.rs +0 -0
  48. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/extraction/metadata.rs +0 -0
  49. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/extraction/mod.rs +0 -0
  50. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/distilbert_loader.rs +0 -0
  51. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/fields.rs +0 -0
  52. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/mod.rs +0 -0
  53. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/ner.rs +0 -0
  54. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/ort_loader.rs +0 -0
  55. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/proptests.rs +0 -0
  56. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/regex.rs +0 -0
  57. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/walker.rs +0 -0
  58. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/xlm_r_loader.rs +0 -0
  59. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/pyproject.toml +0 -0
  60. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/python/ciris_lens_core/__init__.py +0 -0
  61. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/audit/api.rs +0 -0
  62. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/audit/delegate.rs +0 -0
  63. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/audit/mod.rs +0 -0
  64. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/audit/pyo3.rs +0 -0
  65. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/canonical/ceg_egress.rs +0 -0
  66. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/canonical/mod.rs +0 -0
  67. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capacity/attestation.rs +0 -0
  68. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capacity/mod.rs +0 -0
  69. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capacity/score.rs +0 -0
  70. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capture/batch.rs +0 -0
  71. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capture/client.rs +0 -0
  72. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capture/consent.rs +0 -0
  73. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capture/correlation.rs +0 -0
  74. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capture/event.rs +0 -0
  75. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capture/mod.rs +0 -0
  76. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capture/partial.rs +0 -0
  77. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capture/py_engine.rs +0 -0
  78. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/capture/seal.rs +0 -0
  79. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/cohort/declared.rs +0 -0
  80. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/cohort/mod.rs +0 -0
  81. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/cohort/resourcing.rs +0 -0
  82. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/config/egress.rs +0 -0
  83. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/config/mod.rs +0 -0
  84. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/config/node.rs +0 -0
  85. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/config/retention.rs +0 -0
  86. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/config/upstream.rs +0 -0
  87. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/detector/axis_metrics.rs +0 -0
  88. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/detector/coherence_ratchet.rs +0 -0
  89. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/detector/correlated_action.rs +0 -0
  90. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/detector/distributive_access.rs +0 -0
  91. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/detector/manifold.rs +0 -0
  92. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/detector/mod.rs +0 -0
  93. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/extract/mod.rs +0 -0
  94. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/extract/projection.rs +0 -0
  95. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/ffi/mod.rs +0 -0
  96. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/ffi/pyo3.rs +0 -0
  97. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/lib.rs +0 -0
  98. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/observability/mod.rs +0 -0
  99. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/pipeline/lifecycle.rs +0 -0
  100. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/pipeline/mod.rs +0 -0
  101. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/retention/eviction.rs +0 -0
  102. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/retention/mod.rs +0 -0
  103. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/retention/summary.rs +0 -0
  104. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/role/handler.rs +0 -0
  105. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/role/mod.rs +0 -0
  106. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/role/node.rs +0 -0
  107. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/role/relay.rs +0 -0
  108. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/role/ret_relay.rs +0 -0
  109. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scores/aggregate.rs +0 -0
  110. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scores/mod.rs +0 -0
  111. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scores/oracle.rs +0 -0
  112. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scoring/assembly.rs +0 -0
  113. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scoring/axis_calibration.rs +0 -0
  114. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scoring/calibration.rs +0 -0
  115. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scoring/capacity.rs +0 -0
  116. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scoring/mod.rs +0 -0
  117. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scoring/n_eff.rs +0 -0
  118. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/scoring/result.rs +0 -0
  119. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/signing/event.rs +0 -0
  120. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/signing/mod.rs +0 -0
  121. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/wire/mod.rs +0 -0
  122. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/src/wire/signer.rs +0 -0
  123. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/tests/parity/README.md +0 -0
  124. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/tests/parity/canonical_fixtures.json +0 -0
  125. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/tests/parity/generate_canonical_fixtures.py +0 -0
  126. {ciris_server-0.1.2 → ciris_server-0.2.0}/crates/ciris-lens-core/tests/sovereign_rlib.rs +0 -0
  127. {ciris_server-0.1.2 → ciris_server-0.2.0}/rust-toolchain.toml +0 -0
  128. {ciris_server-0.1.2 → ciris_server-0.2.0}/src/config.rs +0 -0
  129. {ciris_server-0.1.2 → ciris_server-0.2.0}/src/lib.rs +0 -0
  130. {ciris_server-0.1.2 → ciris_server-0.2.0}/src/main.rs +0 -0
  131. {ciris_server-0.1.2 → ciris_server-0.2.0}/src/quorum.rs +0 -0
  132. {ciris_server-0.1.2 → ciris_server-0.2.0}/tests/replication.rs +0 -0
@@ -0,0 +1,14 @@
1
+ # Android cross-link targets (NDK API 24). The 16 KiB max-page-size arg is the
2
+ # Android-15+ compatibility flag the substrate crates use. Mirrors
3
+ # CIRISVerify/.cargo/config.toml so the android wheel lane links cleanly.
4
+ [target.armv7-linux-androideabi]
5
+ linker = "armv7a-linux-androideabi24-clang"
6
+ rustflags = ["-C", "link-arg=-Wl,-z,max-page-size=16384"]
7
+
8
+ [target.aarch64-linux-android]
9
+ linker = "aarch64-linux-android24-clang"
10
+ rustflags = ["-C", "link-arg=-Wl,-z,max-page-size=16384"]
11
+
12
+ [target.x86_64-linux-android]
13
+ linker = "x86_64-linux-android24-clang"
14
+ rustflags = ["-C", "link-arg=-Wl,-z,max-page-size=16384"]
@@ -0,0 +1,67 @@
1
+ name: bench
2
+
3
+ # Run the criterion benches, turn them into an INTERPRETED page (video
4
+ # throughput / replication speed / post-quantum overhead — what the numbers
5
+ # mean, not just ns), and publish to GitHub Pages. Mirrors the substrate
6
+ # sisters' publish-only bench discipline (not a pass/fail gate — shared runners
7
+ # are too noisy), but with an interpretation layer on top (scripts/bench_report.py).
8
+ #
9
+ # Published at: https://cirisai.github.io/CIRISServer/
10
+ # One-time: Settings → Pages → Source = "GitHub Actions" (the configure-pages
11
+ # step below sets enablement: true to do this automatically on first run).
12
+
13
+ on:
14
+ push:
15
+ branches: [main]
16
+ paths:
17
+ - "benches/**"
18
+ - "scripts/bench_report.py"
19
+ - ".github/workflows/bench.yml"
20
+ - "Cargo.toml"
21
+ workflow_dispatch:
22
+ schedule:
23
+ - cron: "0 7 * * 1" # Mondays 07:00 UTC
24
+
25
+ permissions:
26
+ contents: read
27
+ pages: write
28
+ id-token: write
29
+
30
+ # Never cancel an in-flight Pages deploy; let bench runs serialize.
31
+ concurrency:
32
+ group: bench-pages
33
+ cancel-in-progress: false
34
+
35
+ jobs:
36
+ bench-and-publish:
37
+ runs-on: ubuntu-latest
38
+ environment:
39
+ name: github-pages
40
+ url: ${{ steps.deploy.outputs.page_url }}
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+ - uses: dtolnay/rust-toolchain@stable
44
+ - name: Install build deps
45
+ run: sudo apt-get update && sudo apt-get install -y libtss2-dev libsqlite3-dev
46
+ - uses: Swatinem/rust-cache@v2
47
+ continue-on-error: true
48
+ with:
49
+ cache-bin: false
50
+ key: bench
51
+ - uses: actions/setup-python@v5
52
+ with:
53
+ python-version: "3.12"
54
+ - name: Run benches (criterion)
55
+ run: cargo bench --bench pqc_av_streaming --bench replication_ingest
56
+ - name: Generate interpreted page
57
+ run: |
58
+ BENCH_DATE="$(date -u +%Y-%m-%d)" \
59
+ python3 scripts/bench_report.py --out bench-site --commit "$GITHUB_SHA"
60
+ - uses: actions/configure-pages@v5
61
+ with:
62
+ enablement: true
63
+ - uses: actions/upload-pages-artifact@v3
64
+ with:
65
+ path: bench-site
66
+ - id: deploy
67
+ uses: actions/deploy-pages@v4
@@ -33,13 +33,23 @@ jobs:
33
33
  components: clippy
34
34
  - name: Install build deps (Linux)
35
35
  if: runner.os == 'Linux'
36
+ # libtss2-dev: the Linux-only keyring/tpm backend (cfg(target_os=linux)).
37
+ # libsqlite3-dev: persist's sqlite. macOS/Windows pull NEITHER tss-esapi
38
+ # nor openssl (postgres+tpm are Linux-only per Cargo.toml [target.linux]).
36
39
  run: sudo apt-get update && sudo apt-get install -y libtss2-dev libsqlite3-dev
37
40
  - uses: Swatinem/rust-cache@v2
38
41
  continue-on-error: true
39
42
  with:
40
43
  cache-bin: false
41
- - run: cargo clippy --all-targets --all-features -- -D warnings
42
- - run: cargo test --all-features
44
+ # Default features build everywhere (sqlite + the binary path); postgres +
45
+ # tpm are Linux-only (per-target). NOT --all-features: that drags
46
+ # `extension-module` (libpython-no-link) into the test binary.
47
+ - run: cargo clippy --all-targets -- -D warnings
48
+ - run: cargo test
49
+ # The PyO3 wheel surface (Linux only; libpython linked, no extension-module).
50
+ - name: clippy (python surface, Linux)
51
+ if: runner.os == 'Linux'
52
+ run: cargo clippy --all-targets --features python -- -D warnings
43
53
 
44
54
  # Win7-SP1 → Win11 build check (CIRISVerify#67 pattern, mirrored by every
45
55
  # upstream substrate crate). Rust 1.78 raised the windows-msvc std floor to
@@ -65,6 +75,16 @@ jobs:
65
75
  - name: Build (x86_64-win7-windows-msvc, build-std)
66
76
  shell: bash
67
77
  run: |
78
+ # LNK1181 workaround (persist's recipe): build-std relinks std, which
79
+ # needs the windows_x86_64_msvc import-lib dirs on LIB. openssl/tss2 are
80
+ # NOT pulled on this windows target (postgres+tpm are Linux-only), so no
81
+ # vcpkg/openssl-src build is needed here anymore.
82
+ cargo fetch
83
+ extra=""
84
+ while IFS= read -r d; do
85
+ extra="${extra};$(cygpath -w "$d")"
86
+ done < <(find "$HOME/.cargo/registry/src" -type d -path '*windows_x86_64_msvc-*/lib' 2>/dev/null | sort -u)
87
+ [ -n "$extra" ] && export LIB="${LIB:-}${extra}"
68
88
  cargo +nightly build --release \
69
89
  --target x86_64-win7-windows-msvc \
70
90
  -Z build-std=std,panic_abort \
@@ -108,6 +108,64 @@ jobs:
108
108
  path: dist/*.whl
109
109
  if-no-files-found: warn
110
110
 
111
+ # Android abi3 wheels (incl. arm32 armeabi-v7a) — the CIRISAgent KMP client's
112
+ # mobile targets. NDK cross-compile + libpython stub, the substrate recipe
113
+ # (CIRISVerify/Persist/Edge). continue-on-error while the cross lane iterates
114
+ # to green — it must not block the desktop/server publish.
115
+ android:
116
+ name: wheel android-${{ matrix.abi }}
117
+ runs-on: ubuntu-latest
118
+ continue-on-error: true
119
+ strategy:
120
+ fail-fast: false
121
+ matrix:
122
+ include:
123
+ - { abi: armeabi-v7a, target: armv7-linux-androideabi, clang: armv7a-linux-androideabi24, pw: 32 }
124
+ - { abi: arm64-v8a, target: aarch64-linux-android, clang: aarch64-linux-android24, pw: 64 }
125
+ steps:
126
+ - uses: actions/checkout@v4
127
+ - uses: dtolnay/rust-toolchain@stable
128
+ with:
129
+ targets: ${{ matrix.target }}
130
+ - uses: actions/setup-python@v5
131
+ with:
132
+ python-version: "3.12"
133
+ - uses: nttld/setup-ndk@v1
134
+ id: ndk
135
+ with:
136
+ ndk-version: r26b
137
+ add-to-path: true
138
+ - name: PyO3 cross config + libpython stub
139
+ env:
140
+ ANDROID_NDK_HOME: ${{ steps.ndk.outputs.ndk-path }}
141
+ run: |
142
+ CFG="${RUNNER_TEMP}/pyo3-android.config"
143
+ {
144
+ echo "implementation=CPython"; echo "version=3.10"; echo "shared=false"
145
+ echo "abi3=true"; echo "lib_name=python3.10"; echo "lib_dir="
146
+ echo "executable="; echo "pointer_width=${{ matrix.pw }}"; echo "build_flags="
147
+ echo "suppress_build_script_link_lines=true"
148
+ } > "$CFG"
149
+ echo "PYO3_CONFIG_FILE=${CFG}" >> "$GITHUB_ENV"
150
+ STUB="${RUNNER_TEMP}/python-stub"; mkdir -p "$STUB"
151
+ TC="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64"
152
+ echo 'void __pystub(void){}' | \
153
+ "${TC}/bin/${{ matrix.clang }}-clang" -shared -nostdlib \
154
+ -Wl,-soname,libpython3.10.so -o "${STUB}/libpython3.10.so" -x c -
155
+ - name: Build wheel (maturin, Android NDK)
156
+ env:
157
+ ANDROID_NDK_HOME: ${{ steps.ndk.outputs.ndk-path }}
158
+ RUSTFLAGS: "-L ${{ runner.temp }}/python-stub -C link-arg=-Wl,--no-as-needed -C link-arg=-lpython3.10"
159
+ run: |
160
+ python -m pip install --upgrade pip
161
+ pip install "maturin>=1.7,<2"
162
+ maturin build --release --out dist --target ${{ matrix.target }}
163
+ - uses: actions/upload-artifact@v4
164
+ with:
165
+ name: wheels-android-${{ matrix.abi }}
166
+ path: dist/*.whl
167
+ if-no-files-found: warn
168
+
111
169
  sdist:
112
170
  name: sdist
113
171
  runs-on: ubuntu-latest
@@ -145,7 +203,7 @@ jobs:
145
203
  # ── Publish to PyPI via Trusted Publishing (OIDC) ──────────────────────────
146
204
  publish:
147
205
  name: publish to PyPI
148
- needs: [linux, macos, windows, sdist, conformance-gate]
206
+ needs: [linux, macos, windows, android, sdist, conformance-gate]
149
207
  runs-on: ubuntu-latest
150
208
  if: startsWith(github.ref, 'refs/tags/') || inputs.publish
151
209
  environment: pypi
@@ -4,6 +4,37 @@ All notable changes to CIRISServer. Format follows [Keep a Changelog](https://ke
4
4
  this project uses [Semantic Versioning](https://semver.org/). The minor line tracks
5
5
  the fabric-node scope (0.1 lens · 0.5 +registry · 1.0 +node), paced by the CIRISAgent train.
6
6
 
7
+ ## [0.2.0] — 2026-06-15
8
+
9
+ All-platforms-green CI, **full hybrid post-quantum federation signatures**, and a
10
+ published interpreted benchmark page.
11
+
12
+ ### Added
13
+ - **Full hybrid PQC federation signature (Ed25519 + ML-DSA-65).** The node mints
14
+ (or **adopts**, on takeover) an `ml_dsa_65.seed` and signs every federation
15
+ envelope with both halves (edge `LocalSigner` classical + pqc). `/v1/identity`
16
+ now carries `ml_dsa_65_pubkey_b64` + `pqc_key_id`. Classical stays
17
+ hardware-sealed; the ML-DSA half is a software seed (no sealed-ML-DSA backend
18
+ exists — a TPM can't do ML-DSA).
19
+ - **One remaining classical path**, filed upstream: persist's storage-tier
20
+ scrub signature is Ed25519-only — `with_hardware_signer` is classical-only and
21
+ `with_signer_arcs` (hybrid) needs a plaintext key. **CIRISPersist#224** adds a
22
+ hybrid-hardware ctor to close it without un-sealing.
23
+ - **Interpreted benchmark page** → `https://cirisai.github.io/CIRISServer/`
24
+ (`.github/workflows/bench.yml` + `scripts/bench_report.py`): video throughput
25
+ (fps ceiling, sustainable mesh participants @30 fps), post-quantum handshake
26
+ overhead, mesh fan-out, and **replication speed** (new `replication_ingest`
27
+ bench, ~13K traces/s/core).
28
+ - Android arm32 (armeabi-v7a) + arm64 wheel lane (NDK cross-compile;
29
+ `continue-on-error` while it iterates to green).
30
+
31
+ ### Changed / Fixed
32
+ - **All CI platforms green** (was red on macOS/Windows/Win7). Root cause was our
33
+ own feature wiring: a top-level `tpm` feature + unconditional `postgres`
34
+ dragged `tss-esapi`/`openssl` onto platforms that can't build them. Fixed with
35
+ per-target deps (`postgres` + `tpm` Linux-only; `android` keyring backend) and
36
+ dropping `--all-features`.
37
+
7
38
  ## [0.1.2] — 2026-06-15
8
39
 
9
40
  Substrate floor bump + the `/v1/identity` endpoint the migration runbook requires.
@@ -982,7 +982,7 @@ dependencies = [
982
982
 
983
983
  [[package]]
984
984
  name = "ciris-server"
985
- version = "0.1.2"
985
+ version = "0.2.0"
986
986
  dependencies = [
987
987
  "anyhow",
988
988
  "axum",
@@ -997,6 +997,7 @@ dependencies = [
997
997
  "criterion",
998
998
  "ed25519-dalek",
999
999
  "fs2",
1000
+ "getrandom 0.3.4",
1000
1001
  "pyo3",
1001
1002
  "pyo3-async-runtimes",
1002
1003
  "serde_json",
@@ -1206,6 +1207,7 @@ dependencies = [
1206
1207
  "ciborium",
1207
1208
  "clap",
1208
1209
  "criterion-plot",
1210
+ "futures",
1209
1211
  "is-terminal",
1210
1212
  "itertools 0.10.5",
1211
1213
  "num-traits",
@@ -1218,6 +1220,7 @@ dependencies = [
1218
1220
  "serde_derive",
1219
1221
  "serde_json",
1220
1222
  "tinytemplate",
1223
+ "tokio",
1221
1224
  "walkdir",
1222
1225
  ]
1223
1226
 
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "ciris-server"
3
- version = "0.1.2" # 0.1 = lens-only (agent ~2.9.7); 0.5 = +registry (~2.9.8); 1.0 = +node (~2.9.10). Patch forward (0.1.1) on breakage.
3
+ version = "0.2.0" # 0.1 = lens-only (agent ~2.9.7); 0.5 = +registry (~2.9.8); 1.0 = +node (~2.9.10). Patch forward (0.1.1) on breakage.
4
4
  edition = "2021"
5
5
  # MSRV floor is set by the substrate: ciris-verify v5.2.0 requires 1.86
6
6
  # (persist v6.0.1 is 1.83). Build with the higher of the two.
@@ -41,13 +41,13 @@ python = ["dep:pyo3", "dep:pyo3-async-runtimes", "ciris-lens-core/python"]
41
41
  # `extension-module` is what maturin builds the wheel with (tells PyO3 not to
42
42
  # link libpython). The bin must NOT enable it. See pyproject.toml [tool.maturin].
43
43
  extension-module = ["python", "pyo3/extension-module"]
44
- # Real TPM-2.0 / Secure-Enclave / StrongBox hardware backing for the node's RNS
45
- # transport identity. The CIRIS family already pulls `ciris-keyring/tpm`
46
- # transitively on Linux (so libtss2-dev is a Linux build dep regardless — CI must
47
- # install it); this is the explicit handle for CIRISServer's own intent and for
48
- # non-Linux targets. Runtime auto-detects hardware and degrades to encrypted
49
- # software when absent (`is_hardware_backed()` reports the posture).
50
- tpm = ["ciris-keyring/tpm"]
44
+ # NOTE: hardware key custody (TPM/SE/StrongBox) is wired per-TARGET below, not as
45
+ # a cargo feature — TPM (tss-esapi) is Linux-only, so a top-level `tpm` feature
46
+ # made `--all-features` drag tss-esapi onto Windows/macOS (where it can't build).
47
+ # The `[target.'cfg(target_os = "linux")']` table enables keyring/tpm + persist
48
+ # postgres on Linux only; runtime auto-detects hardware and degrades to encrypted
49
+ # software when absent (`is_hardware_backed()` reports the posture). This mirrors
50
+ # the substrate crates' per-target keyring/postgres gating.
51
51
 
52
52
  # ----------------------------------------------------------------------------
53
53
  # Dependencies — CIRISServer AUTHORS NO PRIMITIVES. It composes the core
@@ -82,7 +82,10 @@ ciris-lens-core = { path = "crates/ciris-lens-core" } # ABSORBED in-tree (wo
82
82
 
83
83
  # The substrate trio (also pulled transitively by the cores; pinned here so the
84
84
  # composition root owns the singleton construction).
85
- ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v7.0.0", features = ["postgres", "sqlite"] }
85
+ # sqlite on all platforms; postgres is Linux-only (libpq/openssl don't link
86
+ # cleanly on the macOS/Windows runners — same posture as persist's own CI). The
87
+ # `[target.linux]` table below adds postgres.
88
+ ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v7.0.0", features = ["sqlite"] }
86
89
  ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "v3.6.0", features = ["transport-reticulum", "transport-http"] }
87
90
  # Founder-quorum verification + key-id fingerprint at the composition root
88
91
  # (threshold:: module path — NOT re-exported at the crate root).
@@ -106,9 +109,24 @@ fs2 = "0.4" # available-disk check for realistic-minimum feature gating
106
109
  axum = "0.8"
107
110
  base64 = "0.22"
108
111
  serde_json = "1"
112
+ getrandom = "0.3" # mint the ML-DSA-65 federation seed on first boot (hybrid PQC)
109
113
  tracing = "0.1"
110
114
  tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
111
115
 
116
+ # Linux-only hardware + Postgres: cargo UNIONS these onto the base deps above.
117
+ # - persist `postgres` (libpq/openssl) — Linux deployment + the postgres
118
+ # conformance lane; macOS/Windows stay sqlite-only.
119
+ # - keyring `tpm` (tss-esapi / TPM 2.0) — the real hardware backend; needs
120
+ # libtss2 (Linux build dep). Other targets keep the software keystore.
121
+ [target.'cfg(target_os = "linux")'.dependencies]
122
+ ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v7.0.0", features = ["postgres"] }
123
+ ciris-keyring = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v5.6.0", version = "5", features = ["tpm"] }
124
+
125
+ # Android (arm64/arm32/x86_64): the keyring `android` backend (JNI → Android
126
+ # Keystore/StrongBox); sqlite bundles, no postgres/tpm. Mirrors persist/edge.
127
+ [target.'cfg(target_os = "android")'.dependencies]
128
+ ciris-keyring = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v5.6.0", version = "5", features = ["android"] }
129
+
112
130
  # Test-only — the two-node replication integration test (tests/replication.rs)
113
131
  # builds + signs CEG batches with the same primitives persist verifies against.
114
132
  # ed25519-dalek MUST match persist's locked 2.x (the SigningKey type crosses the
@@ -118,7 +136,7 @@ ed25519-dalek = "2"
118
136
  base64 = "0.22"
119
137
  chrono = { version = "0.4", features = ["serde"] }
120
138
  serde_json = "1"
121
- criterion = "0.5"
139
+ criterion = { version = "0.5", features = ["async_tokio"] }
122
140
  # The PQC primitives the realtime-A/V E2E bench drives directly: hybrid KEX
123
141
  # (X25519 + ML-KEM-768) for the per-Link transit key, AES-256-GCM for the
124
142
  # two-layer chunk seal. Same pin/features edge composes (tag parity).
@@ -129,6 +147,11 @@ ciris-crypto = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v5.6.0"
129
147
  name = "pqc_av_streaming"
130
148
  harness = false
131
149
 
150
+ # Replication / corpus-ingest throughput (the CEG-RC5 receive spine).
151
+ [[bench]]
152
+ name = "replication_ingest"
153
+ harness = false
154
+
132
155
  [profile.release]
133
156
  # panic strategy stays "unwind" (the Win7 build-std lane relies on this being
134
157
  # pinned here, not on the build-std crate list — see release.yml win7 lane).
@@ -72,8 +72,13 @@ pip install ciris-server # the abi3 wheel (live on PyPI; self-contained,
72
72
  ```
73
73
  export CIRIS_HOME=/var/lib/ciris-server # data + identity root
74
74
  mkdir -p "$CIRIS_HOME/identity"
75
- # Federation signing seed → adopted + TPM-sealed on first boot, byte-identical
75
+ # Federation signing seed (Ed25519) → adopted + TPM-sealed on first boot, byte-identical
76
76
  cp /var/lib/cirislens/keyring/ed25519.seed "$CIRIS_HOME/identity/ed25519.seed"
77
+ # PQC signing seed (ML-DSA-65) → adopted as the hybrid half, IF the deployment had one.
78
+ # The federation signature is a FULL HYBRID (Ed25519 + ML-DSA-65); if no ml_dsa_65.seed
79
+ # is carried over, the node MINTS a fresh PQC half on first boot — a NEW PQC pubkey, so
80
+ # coordinate enrollment (the Ed25519 key_id is still continuous).
81
+ cp /var/lib/cirislens/keyring/ml_dsa_65.seed "$CIRIS_HOME/identity/ml_dsa_65.seed" # if present
77
82
  # RNS transport identity → adopted into the keystore byte-identically (dest hash preserved)
78
83
  export CIRIS_SERVER_RET_IDENTITY_PATH=/var/lib/cirislens/keyring/lens-edge.identity
79
84
  ```
@@ -81,6 +86,8 @@ On first boot the node:
81
86
  - **adopts** `ed25519.seed` (`SealedEd25519Signer::adopt`) → the **same** 32-byte
82
87
  Ed25519 pubkey ⇒ the **same `key_id`**, now TPM-sealed; the plaintext is archived
83
88
  to `ed25519.seed.migrated` (the sealed copy is load-bearing);
89
+ - **adopts** `ml_dsa_65.seed` (if present) → the **same** ML-DSA-65 pubkey (the PQC
90
+ half of the hybrid signature); software-at-rest (no sealed-ML-DSA backend);
84
91
  - **adopts** the `.rid` into `BlobTransportKeystore` → the **same Reticulum
85
92
  destination hash**, now TPM-sealed; the original is archived to
86
93
  `*.migrated-<ts>`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ciris-server
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  License-File: LICENSE
5
5
  Summary: The fabric node — the federation's headless cohabitation runtime (registry + lens [+ node] over one shared substrate), as the abi3 wheel CIRISAgent consumes. agent = fabric node + brain.
6
6
  Author-email: Eric Moore <eric@ciris.ai>
@@ -0,0 +1,181 @@
1
+ //! Replication / corpus-ingest throughput — the receive side of CEG-RC5
2
+ //! replication (the spine `tests/replication.rs` proves correct). Measures
3
+ //! `Engine::receive_and_persist`: verify (Ed25519) + persist + content-addressed
4
+ //! dedup — the cost a node pays per replicated trace. Run:
5
+ //! `cargo bench --bench replication_ingest`.
6
+ //!
7
+ //! Two numbers:
8
+ //! - `ingest_new` — a fresh signed trace each iteration (insert path = a new
9
+ //! envelope arriving from a peer). This is "replication speed" — traces/sec a
10
+ //! node absorbs.
11
+ //! - `ingest_dedup` — re-delivering an already-seen trace (the anti gossip-loop
12
+ //! path: verify + dedup-reject, no insert). The steady-state of anti-entropy.
13
+
14
+ use std::sync::Arc;
15
+ use std::time::SystemTime;
16
+
17
+ use base64::engine::general_purpose::STANDARD as BASE64;
18
+ use base64::Engine as _;
19
+ use criterion::{criterion_group, criterion_main, BatchSize, Criterion, Throughput};
20
+ use ed25519_dalek::{Signer as _, SigningKey};
21
+
22
+ use ciris_persist::federation::types::{algorithm, identity_type};
23
+ use ciris_persist::federation::{FederationDirectory as _, KeyRecord, SignedKeyRecord};
24
+ use ciris_persist::prelude::{Engine, LocalSigner};
25
+ use ciris_persist::schema::{
26
+ CompleteTrace, ComponentType, ReasoningEventType, SchemaVersion, TraceComponent, TraceLevel,
27
+ };
28
+ use ciris_persist::scrub::NullScrubber;
29
+
30
+ const KEY_ID: &str = "bench-agent";
31
+
32
+ fn rt() -> tokio::runtime::Runtime {
33
+ tokio::runtime::Builder::new_current_thread()
34
+ .enable_all()
35
+ .build()
36
+ .unwrap()
37
+ }
38
+
39
+ async fn engine_with_key(agent_sk: &SigningKey) -> Arc<Engine> {
40
+ let node = Arc::new(LocalSigner::from_parts(
41
+ SigningKey::from_bytes(&[0xA0; 32]),
42
+ "bench-node".to_string(),
43
+ None,
44
+ None,
45
+ ));
46
+ let engine = Arc::new(
47
+ Engine::with_signer(node, "sqlite::memory:")
48
+ .await
49
+ .expect("engine"),
50
+ );
51
+ // Register the agent key so VerifyMode::Full resolves the trace signature.
52
+ let pubkey_b64 = BASE64.encode(agent_sk.verifying_key().to_bytes());
53
+ let now = chrono::Utc::now();
54
+ let record = KeyRecord {
55
+ key_id: KEY_ID.into(),
56
+ pubkey_ed25519_base64: pubkey_b64.clone(),
57
+ pubkey_ml_dsa_65_base64: None,
58
+ algorithm: algorithm::HYBRID.into(),
59
+ identity_type: identity_type::AGENT.into(),
60
+ identity_ref: KEY_ID.into(),
61
+ valid_from: now,
62
+ valid_until: None,
63
+ registration_envelope: serde_json::json!({ "key_id": KEY_ID }),
64
+ original_content_hash: "deadbeef".into(),
65
+ scrub_signature_classical: pubkey_b64,
66
+ scrub_signature_pqc: None,
67
+ scrub_key_id: KEY_ID.into(),
68
+ scrub_timestamp: now,
69
+ pqc_completed_at: None,
70
+ persist_row_hash: String::new(),
71
+ roles: Vec::new(),
72
+ attestation_evidence: None,
73
+ };
74
+ engine
75
+ .sqlite_backend()
76
+ .expect("sqlite")
77
+ .put_public_key(SignedKeyRecord { record })
78
+ .await
79
+ .expect("register key");
80
+ engine
81
+ }
82
+
83
+ fn batch_bytes(agent_sk: &SigningKey, trace_id: &str) -> Vec<u8> {
84
+ use ciris_persist::verify::canonical::Canonicalizer;
85
+ use ciris_persist::verify::{ed25519::canonical_payload_value, PythonJsonDumpsCanonicalizer};
86
+ let mut data = serde_json::Map::new();
87
+ data.insert("seq".into(), serde_json::json!(0));
88
+ let mut trace = CompleteTrace {
89
+ trace_id: trace_id.into(),
90
+ thought_id: trace_id.into(),
91
+ task_id: Some("bench".into()),
92
+ agent_id_hash: "cafebabe".into(),
93
+ started_at: "2026-06-15T00:00:00Z".parse().unwrap(),
94
+ completed_at: "2026-06-15T00:01:00Z".parse().unwrap(),
95
+ trace_level: TraceLevel::Generic,
96
+ trace_schema_version: SchemaVersion::parse("2.7.0").unwrap(),
97
+ components: vec![TraceComponent {
98
+ component_type: ComponentType::Conscience,
99
+ event_type: ReasoningEventType::ConscienceResult,
100
+ timestamp: "2026-06-15T00:00:00Z".parse().unwrap(),
101
+ data,
102
+ agent_id_hash: None,
103
+ }],
104
+ deployment_profile: None,
105
+ cohort_scope: "federation".into(),
106
+ cohort_target_id: None,
107
+ signature: String::new(),
108
+ signature_key_id: KEY_ID.into(),
109
+ };
110
+ let canon = PythonJsonDumpsCanonicalizer
111
+ .canonicalize_value(&canonical_payload_value(&trace))
112
+ .unwrap();
113
+ trace.signature = BASE64.encode(agent_sk.sign(&canon).to_bytes());
114
+ serde_json::json!({
115
+ "events": [{ "event_type": "complete_trace", "trace_level": "generic",
116
+ "trace": serde_json::to_value(&trace).unwrap() }],
117
+ "batch_timestamp": "2026-06-15T00:00:00Z",
118
+ "consent_timestamp": "2025-01-01T00:00:00Z",
119
+ "trace_level": "generic",
120
+ "trace_schema_version": "2.7.0",
121
+ })
122
+ .to_string()
123
+ .into_bytes()
124
+ }
125
+
126
+ fn bench_ingest(c: &mut Criterion) {
127
+ let _ = SystemTime::now(); // (no-op; keeps import honest if trimmed)
128
+ let agent_sk = SigningKey::from_bytes(&[0x11; 32]);
129
+ let runtime = rt();
130
+ let engine = runtime.block_on(engine_with_key(&agent_sk));
131
+
132
+ let mut g = c.benchmark_group("replication_ingest");
133
+ g.throughput(Throughput::Elements(1)); // one trace per iteration
134
+
135
+ // New-trace insert path (a fresh envelope from a peer) = replication speed.
136
+ g.bench_function("ingest_new", |b| {
137
+ let mut n = 0u64;
138
+ b.to_async(&runtime).iter_batched(
139
+ || {
140
+ n += 1;
141
+ batch_bytes(&agent_sk, &format!("repl-{n:08}"))
142
+ },
143
+ |bytes| {
144
+ let engine = Arc::clone(&engine);
145
+ async move {
146
+ engine
147
+ .receive_and_persist(&bytes, &NullScrubber)
148
+ .await
149
+ .expect("ingest")
150
+ }
151
+ },
152
+ BatchSize::SmallInput,
153
+ );
154
+ });
155
+
156
+ // Re-delivery of an already-seen trace (anti gossip-loop dedup path).
157
+ let dup = batch_bytes(&agent_sk, "repl-dup-fixed");
158
+ runtime.block_on(async {
159
+ engine
160
+ .receive_and_persist(&dup, &NullScrubber)
161
+ .await
162
+ .expect("seed dup");
163
+ });
164
+ g.bench_function("ingest_dedup", |b| {
165
+ b.to_async(&runtime).iter(|| {
166
+ let engine = Arc::clone(&engine);
167
+ let bytes = dup.clone();
168
+ async move {
169
+ engine
170
+ .receive_and_persist(&bytes, &NullScrubber)
171
+ .await
172
+ .expect("dedup")
173
+ }
174
+ });
175
+ });
176
+
177
+ g.finish();
178
+ }
179
+
180
+ criterion_group!(benches, bench_ingest);
181
+ criterion_main!(benches);
@@ -12,7 +12,7 @@ build-backend = "maturin"
12
12
  [project]
13
13
  name = "ciris-server"
14
14
  # Mirrors Cargo.toml; bump in lockstep.
15
- version = "0.1.2" # matches the Cargo crate. 0.1 = lens-only; patch forward (0.1.1) on breakage
15
+ version = "0.2.0" # matches the Cargo crate. 0.1 = lens-only; patch forward (0.1.1) on breakage
16
16
  description = "The fabric node — the federation's headless cohabitation runtime (registry + lens [+ node] over one shared substrate), as the abi3 wheel CIRISAgent consumes. agent = fabric node + brain."
17
17
  authors = [{ name = "Eric Moore", email = "eric@ciris.ai" }]
18
18
  license = { text = "AGPL-3.0-or-later" }