ciris-server 0.5.76__tar.gz → 0.5.78__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 (262) hide show
  1. {ciris_server-0.5.76 → ciris_server-0.5.78}/Cargo.lock +5 -5
  2. {ciris_server-0.5.76 → ciris_server-0.5.78}/Cargo.toml +5 -5
  3. {ciris_server-0.5.76 → ciris_server-0.5.78}/PKG-INFO +1 -1
  4. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/Cargo.toml +2 -2
  5. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/accord_provision.rs +42 -4
  6. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/compose.rs +27 -3
  7. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/federation_peers.rs +6 -0
  8. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/holonomic.rs +4 -0
  9. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/replication_reconcile.rs +20 -6
  10. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/accord.rs +27 -9
  11. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/accord_admit_node.rs +106 -0
  12. ciris_server-0.5.78/tests/mesh_seed_keyplane_e2e.rs +225 -0
  13. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates/support.rs +2 -2
  14. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/replication_reconcile.rs +23 -0
  15. {ciris_server-0.5.76 → ciris_server-0.5.78}/.cargo/config.toml +0 -0
  16. {ciris_server-0.5.76 → ciris_server-0.5.78}/.claude/workflows/localize-ui.js +0 -0
  17. {ciris_server-0.5.76 → ciris_server-0.5.78}/.github/workflows/bench.yml +0 -0
  18. {ciris_server-0.5.76 → ciris_server-0.5.78}/.github/workflows/build-wheels.yml +0 -0
  19. {ciris_server-0.5.76 → ciris_server-0.5.78}/.github/workflows/ci.yml +0 -0
  20. {ciris_server-0.5.76 → ciris_server-0.5.78}/.github/workflows/client-artifacts.yml +0 -0
  21. {ciris_server-0.5.76 → ciris_server-0.5.78}/.github/workflows/conformance.yml +0 -0
  22. {ciris_server-0.5.76 → ciris_server-0.5.78}/.github/workflows/localization.yml +0 -0
  23. {ciris_server-0.5.76 → ciris_server-0.5.78}/.github/workflows/publish-pypi.yml +0 -0
  24. {ciris_server-0.5.76 → ciris_server-0.5.78}/.github/workflows/release.yml +0 -0
  25. {ciris_server-0.5.76 → ciris_server-0.5.78}/.gitignore +0 -0
  26. {ciris_server-0.5.76 → ciris_server-0.5.78}/CHANGELOG.md +0 -0
  27. {ciris_server-0.5.76 → ciris_server-0.5.78}/LICENSE +0 -0
  28. {ciris_server-0.5.76 → ciris_server-0.5.78}/MISSION.md +0 -0
  29. {ciris_server-0.5.76 → ciris_server-0.5.78}/README.md +0 -0
  30. {ciris_server-0.5.76 → ciris_server-0.5.78}/WIRE_VOCABULARY_KINDS.md +0 -0
  31. {ciris_server-0.5.76 → ciris_server-0.5.78}/bench-site/bench_results.json +0 -0
  32. {ciris_server-0.5.76 → ciris_server-0.5.78}/bench-site/index.html +0 -0
  33. {ciris_server-0.5.76 → ciris_server-0.5.78}/bench_results.json +0 -0
  34. {ciris_server-0.5.76 → ciris_server-0.5.78}/benches/alm_chain.rs +0 -0
  35. {ciris_server-0.5.76 → ciris_server-0.5.78}/benches/erasure_survival.rs +0 -0
  36. {ciris_server-0.5.76 → ciris_server-0.5.78}/benches/n_eff_scoring.rs +0 -0
  37. {ciris_server-0.5.76 → ciris_server-0.5.78}/benches/pqc_av_streaming.rs +0 -0
  38. {ciris_server-0.5.76 → ciris_server-0.5.78}/benches/replication_ingest.rs +0 -0
  39. {ciris_server-0.5.76 → ciris_server-0.5.78}/benches/sig_overhead.rs +0 -0
  40. {ciris_server-0.5.76 → ciris_server-0.5.78}/benches/stream_fanout.rs +0 -0
  41. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/.github/workflows/bench.yml +0 -0
  42. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/.github/workflows/ci.yml +0 -0
  43. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/.gitignore +0 -0
  44. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/.pre-commit-config.yaml +0 -0
  45. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/FSD/CIRIS_LENS_CORE.md +0 -0
  46. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/FSD/LENS_CORE_V0_5.md +0 -0
  47. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/FSD/OPEN_QUESTIONS.md +0 -0
  48. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/LICENSE +0 -0
  49. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/MISSION.md +0 -0
  50. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/README.md +0 -0
  51. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/benches/aggregate.rs +0 -0
  52. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/benches/canonicalize.rs +0 -0
  53. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/benches/project.rs +0 -0
  54. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/deny.toml +0 -0
  55. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/docs/BENCHMARKS.md +0 -0
  56. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/docs/COHABITATION.md +0 -0
  57. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/docs/PRE_COMMIT.md +0 -0
  58. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/docs/PUBLIC_SCHEMA_CONTRACT.md +0 -0
  59. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/docs/PYPI_PUBLISH.md +0 -0
  60. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/docs/RELEASE_NOTES.md +0 -0
  61. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/docs/STANDARDS_COMPARISON.md +0 -0
  62. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/docs/THREAT_MODEL.md +0 -0
  63. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/extraction/json_path.rs +0 -0
  64. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/extraction/metadata.rs +0 -0
  65. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/extraction/mod.rs +0 -0
  66. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/distilbert_loader.rs +0 -0
  67. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/fields.rs +0 -0
  68. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/mod.rs +0 -0
  69. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/ner.rs +0 -0
  70. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/ort_loader.rs +0 -0
  71. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/proptests.rs +0 -0
  72. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/regex.rs +0 -0
  73. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/walker.rs +0 -0
  74. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/xlm_r_loader.rs +0 -0
  75. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/pyproject.toml +0 -0
  76. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/python/ciris_lens_core/__init__.py +0 -0
  77. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/audit/api.rs +0 -0
  78. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/audit/delegate.rs +0 -0
  79. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/audit/mod.rs +0 -0
  80. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/audit/pyo3.rs +0 -0
  81. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/canonical/ceg_egress.rs +0 -0
  82. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/canonical/mod.rs +0 -0
  83. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capacity/attestation.rs +0 -0
  84. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capacity/mod.rs +0 -0
  85. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capacity/score.rs +0 -0
  86. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capture/batch.rs +0 -0
  87. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capture/client.rs +0 -0
  88. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capture/consent.rs +0 -0
  89. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capture/correlation.rs +0 -0
  90. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capture/event.rs +0 -0
  91. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capture/mod.rs +0 -0
  92. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capture/partial.rs +0 -0
  93. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capture/py_engine.rs +0 -0
  94. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/capture/seal.rs +0 -0
  95. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/cohort/declared.rs +0 -0
  96. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/cohort/mod.rs +0 -0
  97. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/cohort/resourcing.rs +0 -0
  98. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/config/egress.rs +0 -0
  99. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/config/mod.rs +0 -0
  100. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/config/node.rs +0 -0
  101. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/config/retention.rs +0 -0
  102. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/config/upstream.rs +0 -0
  103. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/detector/axis_metrics.rs +0 -0
  104. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/detector/coherence_ratchet.rs +0 -0
  105. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/detector/correlated_action.rs +0 -0
  106. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/detector/distributive_access.rs +0 -0
  107. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/detector/manifold.rs +0 -0
  108. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/detector/mod.rs +0 -0
  109. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/extract/mod.rs +0 -0
  110. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/extract/projection.rs +0 -0
  111. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/ffi/mod.rs +0 -0
  112. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/ffi/pyo3.rs +0 -0
  113. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/lib.rs +0 -0
  114. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/observability/mod.rs +0 -0
  115. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/pipeline/lifecycle.rs +0 -0
  116. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/pipeline/mod.rs +0 -0
  117. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/retention/eviction.rs +0 -0
  118. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/retention/mod.rs +0 -0
  119. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/retention/summary.rs +0 -0
  120. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/role/handler.rs +0 -0
  121. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/role/mod.rs +0 -0
  122. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/role/node.rs +0 -0
  123. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/role/relay.rs +0 -0
  124. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/role/ret_relay.rs +0 -0
  125. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scores/aggregate.rs +0 -0
  126. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scores/mod.rs +0 -0
  127. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scores/oracle.rs +0 -0
  128. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scoring/assembly.rs +0 -0
  129. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scoring/axis_calibration.rs +0 -0
  130. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scoring/calibration.rs +0 -0
  131. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scoring/capacity.rs +0 -0
  132. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scoring/mod.rs +0 -0
  133. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scoring/n_eff.rs +0 -0
  134. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/scoring/result.rs +0 -0
  135. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/signing/event.rs +0 -0
  136. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/signing/mod.rs +0 -0
  137. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/wire/mod.rs +0 -0
  138. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/src/wire/signer.rs +0 -0
  139. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/tests/parity/README.md +0 -0
  140. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/tests/parity/canonical_fixtures.json +0 -0
  141. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/tests/parity/generate_canonical_fixtures.py +0 -0
  142. {ciris_server-0.5.76 → ciris_server-0.5.78}/crates/ciris-lens-core/tests/sovereign_rlib.rs +0 -0
  143. {ciris_server-0.5.76 → ciris_server-0.5.78}/data/live_mesh_2026-06-22.json +0 -0
  144. {ciris_server-0.5.76 → ciris_server-0.5.78}/docs/SCOPE_PRIVACY.md +0 -0
  145. {ciris_server-0.5.76 → ciris_server-0.5.78}/examples/mesh_propagation/main.rs +0 -0
  146. {ciris_server-0.5.76 → ciris_server-0.5.78}/examples/qa_runner/accord.rs +0 -0
  147. {ciris_server-0.5.76 → ciris_server-0.5.78}/examples/qa_runner/common.rs +0 -0
  148. {ciris_server-0.5.76 → ciris_server-0.5.78}/examples/qa_runner/family.rs +0 -0
  149. {ciris_server-0.5.76 → ciris_server-0.5.78}/examples/qa_runner/main.rs +0 -0
  150. {ciris_server-0.5.76 → ciris_server-0.5.78}/examples/qa_runner/verify.rs +0 -0
  151. {ciris_server-0.5.76 → ciris_server-0.5.78}/installers/windows/README.md +0 -0
  152. {ciris_server-0.5.76 → ciris_server-0.5.78}/installers/windows/bundle-jre.ps1 +0 -0
  153. {ciris_server-0.5.76 → ciris_server-0.5.78}/installers/windows/ciris-server-entry.py +0 -0
  154. {ciris_server-0.5.76 → ciris_server-0.5.78}/installers/windows/ciris-server-installer.iss +0 -0
  155. {ciris_server-0.5.76 → ciris_server-0.5.78}/installers/windows/ciris-server.spec +0 -0
  156. {ciris_server-0.5.76 → ciris_server-0.5.78}/pyproject.toml +0 -0
  157. {ciris_server-0.5.76 → ciris_server-0.5.78}/python/ciris_server/__init__.py +0 -0
  158. {ciris_server-0.5.76 → ciris_server-0.5.78}/python/ciris_server/__main__.py +0 -0
  159. {ciris_server-0.5.76 → ciris_server-0.5.78}/python/ciris_server/cli.py +0 -0
  160. {ciris_server-0.5.76 → ciris_server-0.5.78}/python/ciris_server/desktop_launcher.py +0 -0
  161. {ciris_server-0.5.76 → ciris_server-0.5.78}/rust-toolchain.toml +0 -0
  162. {ciris_server-0.5.76 → ciris_server-0.5.78}/scripts/bench_report.py +0 -0
  163. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/accord.rs +0 -0
  164. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/accord_custody.rs +0 -0
  165. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/accord_halt.rs +0 -0
  166. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/accord_pki/yubico_attestation_root_1.der +0 -0
  167. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/accord_pki/yubico_attestation_root_1.pem +0 -0
  168. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/accord_reactivate.rs +0 -0
  169. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/adapter.rs +0 -0
  170. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/ABSORPTION.md +0 -0
  171. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/api_keys.rs +0 -0
  172. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/attestation.rs +0 -0
  173. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/bootstrap.rs +0 -0
  174. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/consent.rs +0 -0
  175. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/device_auth.rs +0 -0
  176. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/device_grant.rs +0 -0
  177. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/erasure.rs +0 -0
  178. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/gate.rs +0 -0
  179. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/loopback.rs +0 -0
  180. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/mod.rs +0 -0
  181. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/oauth.rs +0 -0
  182. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/occurrence.rs +0 -0
  183. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/ownership.rs +0 -0
  184. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/portable_occurrence.rs +0 -0
  185. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/roles.rs +0 -0
  186. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/self_login.rs +0 -0
  187. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/session.rs +0 -0
  188. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/store.rs +0 -0
  189. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/auth/verify.rs +0 -0
  190. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/benchmarks/bench_results.rs +0 -0
  191. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/benchmarks/mesh.rs +0 -0
  192. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/benchmarks/mod.rs +0 -0
  193. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/benchmarks/scoreboard.rs +0 -0
  194. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/claim_remote.rs +0 -0
  195. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/config.rs +0 -0
  196. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/config_api.rs +0 -0
  197. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/config_reconcile.rs +0 -0
  198. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/delegation_transparency.rs +0 -0
  199. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/family.rs +0 -0
  200. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/federation_admin.rs +0 -0
  201. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/federation_nodecode.rs +0 -0
  202. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/graph_config.rs +0 -0
  203. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/health.rs +0 -0
  204. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/http_log.rs +0 -0
  205. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/identity.rs +0 -0
  206. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/ids.rs +0 -0
  207. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/import.rs +0 -0
  208. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/ingest_http.rs +0 -0
  209. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/lib.rs +0 -0
  210. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/main.rs +0 -0
  211. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/memory_api.rs +0 -0
  212. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/mesh_relay.rs +0 -0
  213. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/nodecode.rs +0 -0
  214. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/peer.rs +0 -0
  215. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/proxy.rs +0 -0
  216. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/py_adapter.rs +0 -0
  217. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/quorum.rs +0 -0
  218. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/radio.rs +0 -0
  219. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/safety/age.rs +0 -0
  220. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/safety/mod.rs +0 -0
  221. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/safety/moderation.rs +0 -0
  222. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/safety/named.rs +0 -0
  223. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/safety/watchlist.rs +0 -0
  224. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/scorer/n_eff.rs +0 -0
  225. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/scorer.rs +0 -0
  226. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/system_data.rs +0 -0
  227. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/telemetry_logs.rs +0 -0
  228. {ciris_server-0.5.76 → ciris_server-0.5.78}/src/yubico_attestation_ca.pem +0 -0
  229. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/alm_chain.rs +0 -0
  230. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/audit_chain.rs +0 -0
  231. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/capacity_scorer.rs +0 -0
  232. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/chaos_mesh.rs +0 -0
  233. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/claim_remote.rs +0 -0
  234. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/config_reconcile.rs +0 -0
  235. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/device_grant.rs +0 -0
  236. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/federation_admin.rs +0 -0
  237. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/federation_session_kex.rs +0 -0
  238. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/graph_config.rs +0 -0
  239. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/ingest_http.rs +0 -0
  240. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/mesh_seed_e2e.rs +0 -0
  241. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/nat_traversal.rs +0 -0
  242. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/nodecode.rs +0 -0
  243. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/noise_floor.rs +0 -0
  244. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/occurrence.rs +0 -0
  245. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/ownership.rs +0 -0
  246. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/peer_replication.rs +0 -0
  247. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/portable_occurrence.rs +0 -0
  248. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates/stage1.rs +0 -0
  249. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates/stage2.rs +0 -0
  250. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates/stage3.rs +0 -0
  251. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates/stage4.rs +0 -0
  252. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates/stage5.rs +0 -0
  253. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates/stage6.rs +0 -0
  254. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates/stage7.rs +0 -0
  255. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates/stage8.rs +0 -0
  256. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/release_gates.rs +0 -0
  257. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/replication.rs +0 -0
  258. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/root_bootstrap.rs +0 -0
  259. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/safety.rs +0 -0
  260. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/stream_sth_consistency.rs +0 -0
  261. {ciris_server-0.5.76 → ciris_server-0.5.78}/tests/wire_vocabulary_gate.rs +0 -0
  262. {ciris_server-0.5.76 → ciris_server-0.5.78}/tools/audit_cohort_scope_callers.py +0 -0
@@ -821,8 +821,8 @@ dependencies = [
821
821
 
822
822
  [[package]]
823
823
  name = "ciris-edge"
824
- version = "8.4.1"
825
- source = "git+https://github.com/CIRISAI/CIRISEdge?tag=v8.4.1#a95680eb01ca27c034a75a6e44b0674f2e9681ca"
824
+ version = "8.6.1"
825
+ source = "git+https://github.com/CIRISAI/CIRISEdge?tag=v8.6.1#acf26ce7cfe01aee5400c7e01dbd9d5b2e797d9b"
826
826
  dependencies = [
827
827
  "async-trait",
828
828
  "axum",
@@ -943,8 +943,8 @@ dependencies = [
943
943
 
944
944
  [[package]]
945
945
  name = "ciris-persist"
946
- version = "12.0.1"
947
- source = "git+https://github.com/CIRISAI/CIRISPersist?tag=v12.0.1#6cf472a2be325210c9d5da122fac61fb092aad40"
946
+ version = "12.2.0"
947
+ source = "git+https://github.com/CIRISAI/CIRISPersist?tag=v12.2.0#766212c92b52f27f7bf35779bf99f692d6b6a8d0"
948
948
  dependencies = [
949
949
  "async-trait",
950
950
  "base64 0.22.1",
@@ -983,7 +983,7 @@ dependencies = [
983
983
 
984
984
  [[package]]
985
985
  name = "ciris-server"
986
- version = "0.5.76"
986
+ version = "0.5.78"
987
987
  dependencies = [
988
988
  "anyhow",
989
989
  "async-trait",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "ciris-server"
3
- version = "0.5.76" # 0.5.76 = v12.0 GENESIS-MESH adoption + the accord ADMIT-NODE card. Substrate co-bump: verify v8.3.0->v8.5.0 (CIRISVerify#162 produce_scrubbed_key_record) / persist v11.9.1->v12.0.1 (root_binding anchors to the HUMANITY_ACCORD holder keyset, #344/#345) / edge v8.3.0->v8.4.1 (lockstep). NEW: POST /v1/accord/admit-node (src/accord_provision.rs) an accord holder scrub-signs a node registration on their portable YubiKey+USB holder signer (reuses the ceremony cosign path) via produce_scrubbed_key_record + produce_self_key_record("steward,accord_holder"), saving the genesis SEED object to ceg_outbox()/accord_admit_node/{target}.json (predictable, persist-ingestable) for CIRISPersist v12.0.2 to bake. QA gate tests/accord_admit_node.rs (emulates the accord-genesis QA): the scrubbed record survives persist STRICT register_federation_key + ROOTS at the accord anchor (root_binding_anchored=Confirmed), wrong-anchor rejected. Matching CLIENT card: AdmitNodeResponse DTO + CIRISApiClient.admitNode() + AccordViewModel.admitNode() + AccordScreen "Admit node to trust root" section (testable tags). App holds no keys; the YubiKey touch is consent. NEXT (0.5.77): roster labels, rotation/lost-key wizard (server family/change+supersede exist), partial-consensus announce. 0.5.75 = RNS rooting + hybrid keys.
3
+ version = "0.5.78" # 0.5.78 = edge v8.6.1 / persist v12.2.0 adoption the COMPLETE admit-node mesh-seed loop. (1) #144 KEY-PLANE replication (KERI publish-own): the ReplicationRuntime converges an EnvelopeKind::Key coordinator per consent peer + a key_selector publishing the node's OWN key_id. (2) #150 PRODUCER: admit-node now calls persist v12.2.0 Engine::adopt_scrub_upgrade (CIRISPersist#351) to upgrade the node's own self-signed row to the accord-holder-scrubbed record so the Key plane publishes an ANCHORED, rootable record peers root it. Producer (server upgrades the row) + publish-own (edge advertises it) = the seed closes in place, no wipe. (3) #147 §Q B5: persist FountainHeldMeta.{content_bytes,cohort_scope} adopted (server has no fountain-content admit path; import.rs already sets cohort_scope). Verify unchanged v8.5.0. 0.5.77 = persist v12.0.2 anchor seed + accord-card UX.
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.
@@ -123,8 +123,8 @@ ciris-lens-core = { path = "crates/ciris-lens-core" } # ABSORBED in-tree (wo
123
123
  # `cirislens_wa_cert` + `cirislens_service_token_revocation` expose the auth
124
124
  # substrate the fabric absorbs (CIRISServer#9, src/auth): the agent's `wa_cert`
125
125
  # table (users/WA/OAuth/api-keys) + the `revoked_service_tokens` table.
126
- ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v12.0.1", features = ["sqlite", "cirisgraph", "cirislens_wa_cert", "cirislens_service_token_revocation", "cirisaudit", "cirislens_tasks", "cirislens_thoughts", "cirislens_tickets", "cirislens_correlations", "cirislens_deferral_reports", "cirislens_maintenance_locks", "cirislens_creation_ceremonies", "cirislens_legacy_migration", "cirisincident", "telemetry", "secrets"] }
127
- ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "v8.4.1", features = ["transport-reticulum", "transport-http", "transport-packet-radio"] }
126
+ ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v12.2.0", features = ["sqlite", "cirisgraph", "cirislens_wa_cert", "cirislens_service_token_revocation", "cirisaudit", "cirislens_tasks", "cirislens_thoughts", "cirislens_tickets", "cirislens_correlations", "cirislens_deferral_reports", "cirislens_maintenance_locks", "cirislens_creation_ceremonies", "cirislens_legacy_migration", "cirisincident", "telemetry", "secrets"] }
127
+ ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "v8.6.1", features = ["transport-reticulum", "transport-http", "transport-packet-radio"] }
128
128
  # Founder-quorum verification + key-id fingerprint at the composition root
129
129
  # (threshold:: module path — NOT re-exported at the crate root).
130
130
  # LOCKSTEP: persist v9.4.0 transitively pins verify-core v6.6.x — the whole
@@ -206,7 +206,7 @@ tracing-appender = "0.2"
206
206
  # - keyring `tpm` (tss-esapi / TPM 2.0) — the real hardware backend; needs
207
207
  # libtss2 (Linux build dep). Other targets keep the software keystore.
208
208
  [target.'cfg(target_os = "linux")'.dependencies]
209
- ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v12.0.1", features = ["postgres", "cirisgraph", "cirislens_wa_cert", "cirislens_service_token_revocation", "cirisaudit", "cirislens_tasks", "cirislens_thoughts", "cirislens_tickets", "cirislens_correlations", "cirislens_deferral_reports", "cirislens_maintenance_locks", "cirislens_creation_ceremonies", "cirislens_legacy_migration", "cirisincident", "telemetry", "secrets"] }
209
+ ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v12.2.0", features = ["postgres", "cirisgraph", "cirislens_wa_cert", "cirislens_service_token_revocation", "cirisaudit", "cirislens_tasks", "cirislens_thoughts", "cirislens_tickets", "cirislens_correlations", "cirislens_deferral_reports", "cirislens_maintenance_locks", "cirislens_creation_ceremonies", "cirislens_legacy_migration", "cirisincident", "telemetry", "secrets"] }
210
210
  # keyring `tpm` (TPM-at-rest, Linux-only via tss-esapi). `pkcs11` is no longer
211
211
  # per-target — it rides the global `pkcs11` feature now that cryptoki builds on all
212
212
  # targets (CIRISVerify v6.12.0).
@@ -259,7 +259,7 @@ ciris-crypto = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v8.5.0"
259
259
  # and never encodes/decodes). This lets tests/chaos_mesh.rs exercise the SUBSTRATE
260
260
  # codec (`fountain_encode`/`fountain_decode`) directly — a real MEASURED proof,
261
261
  # not a reference stand-in.
262
- ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "v8.4.1", features = ["codec-fountain"] }
262
+ ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "v8.6.1", features = ["codec-fountain"] }
263
263
 
264
264
  # PQC realtime-A/V streaming E2E benchmark (CIRISEdge#62 realtime_av profile).
265
265
  [[bench]]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ciris-server
3
- Version: 0.5.76
3
+ Version: 0.5.78
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>
@@ -26,8 +26,8 @@ crate-type = ["cdylib", "rlib"]
26
26
  #
27
27
  # OQ-01 closure 2026-05-03: rlib primary, PyO3 cdylib via `python`
28
28
  # feature for the deployed-lens cutover.
29
- ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v12.0.1", version = "12", features = ["extract", "sqlite"] }
30
- ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "v8.4.1", version = "8", features = ["transport-http", "transport-reticulum"] }
29
+ ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v12.2.0", version = "12", features = ["extract", "sqlite"] }
30
+ ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "v8.6.1", version = "8", features = ["transport-http", "transport-reticulum"] }
31
31
 
32
32
  # Keyring — relay mode (CIRISLensCore#10) loads its Edge transport-
33
33
  # signing identity via `ciris_keyring::load_local_seed`. Edge's
@@ -1048,7 +1048,7 @@ fn default_admit_identity_type() -> String {
1048
1048
  /// (the predictable, persist-ingestable path the operator hands to CIRISPersist
1049
1049
  /// v12.0.2 to bake) and returned. **1-of-N bootstrap:** a single holder suffices —
1050
1050
  /// this is a trust EXTENSION, not the 2/3 kill-switch. Loopback + `pkcs11`-gated.
1051
- async fn admit_node(State(_st): State<ProvisionState>, body: axum::body::Bytes) -> Response {
1051
+ async fn admit_node(State(st): State<ProvisionState>, body: axum::body::Bytes) -> Response {
1052
1052
  let req: AdmitNodeRequest = match serde_json::from_slice(&body) {
1053
1053
  Ok(r) => r,
1054
1054
  Err(e) => return err(StatusCode::BAD_REQUEST, &format!("bad request: {e}")),
@@ -1082,11 +1082,11 @@ async fn admit_node(State(_st): State<ProvisionState>, body: axum::body::Bytes)
1082
1082
  "target key_id contains path separators — refusing to write it",
1083
1083
  );
1084
1084
  }
1085
- admit_node_impl(req).await
1085
+ admit_node_impl(st.engine, req).await
1086
1086
  }
1087
1087
 
1088
1088
  #[cfg(not(feature = "pkcs11"))]
1089
- async fn admit_node_impl(_req: AdmitNodeRequest) -> Response {
1089
+ async fn admit_node_impl(_engine: Arc<Engine>, _req: AdmitNodeRequest) -> Response {
1090
1090
  err(
1091
1091
  StatusCode::NOT_IMPLEMENTED,
1092
1092
  "admit-node needs the `pkcs11` feature (the holder's YubiKey + USB-wrapped ML-DSA signer)",
@@ -1094,7 +1094,7 @@ async fn admit_node_impl(_req: AdmitNodeRequest) -> Response {
1094
1094
  }
1095
1095
 
1096
1096
  #[cfg(feature = "pkcs11")]
1097
- async fn admit_node_impl(req: AdmitNodeRequest) -> Response {
1097
+ async fn admit_node_impl(engine: Arc<Engine>, req: AdmitNodeRequest) -> Response {
1098
1098
  use std::path::PathBuf;
1099
1099
  use std::sync::Arc;
1100
1100
 
@@ -1253,10 +1253,48 @@ async fn admit_node_impl(req: AdmitNodeRequest) -> Response {
1253
1253
  );
1254
1254
  }
1255
1255
 
1256
+ // #150 — PRODUCER: adopt the scrubbed record onto this node's OWN directory row
1257
+ // (persist v12.2.0 `Engine::adopt_scrub_upgrade`, CIRISPersist#351). When the
1258
+ // target IS this node, its boot-time self-signed own-key row is upgraded to the
1259
+ // accord-holder-scrubbed record, so the Key plane (edge publish-own) advertises
1260
+ // an ANCHORED, rootable record and consent peers root it. The primitive is
1261
+ // self-gating (verifies the scrub sig + only upgrades a self-signed → scrubbed
1262
+ // row for the SAME key_id/pubkey), so we call it unconditionally: a target whose
1263
+ // row isn't a valid local upgrade returns Err and we report it without failing
1264
+ // the outbox write (the JSON is still the transport for a remote target / bake).
1265
+ let applied: serde_json::Value = match serde_json::to_value(&scrubbed)
1266
+ .and_then(serde_json::from_value::<ciris_persist::federation::SignedKeyRecord>)
1267
+ {
1268
+ Ok(persist_rec) => match engine.adopt_scrub_upgrade(persist_rec).await {
1269
+ Ok(outcome) => {
1270
+ tracing::info!(
1271
+ target_key_id = %req.target.key_id.trim(),
1272
+ ?outcome,
1273
+ "admit-node: adopted the scrubbed record onto the local directory row"
1274
+ );
1275
+ serde_json::json!({ "adopted": true, "outcome": format!("{outcome:?}") })
1276
+ }
1277
+ Err(e) => {
1278
+ tracing::warn!(
1279
+ target_key_id = %req.target.key_id.trim(),
1280
+ error = %e,
1281
+ "admit-node: scrubbed record NOT adopted locally (not this node's own \
1282
+ self-signed row?) — seed JSON saved for transport/bake"
1283
+ );
1284
+ serde_json::json!({ "adopted": false, "reason": e.to_string() })
1285
+ }
1286
+ },
1287
+ Err(e) => {
1288
+ tracing::warn!(error = %e, "admit-node: scrubbed record convert for local adoption");
1289
+ serde_json::json!({ "adopted": false, "reason": format!("record convert: {e}") })
1290
+ }
1291
+ };
1292
+
1256
1293
  (
1257
1294
  StatusCode::OK,
1258
1295
  Json(serde_json::json!({
1259
1296
  "saved_to": out_path.display().to_string(),
1297
+ "applied": applied,
1260
1298
  "seed": seed,
1261
1299
  })),
1262
1300
  )
@@ -1352,18 +1352,42 @@ async fn setup_peer_replication(
1352
1352
  // health:liveness in. v5.1.0 `start` installs the scheduler control channel
1353
1353
  // unconditionally, so the runtime accepts `set_peers` mutation with no
1354
1354
  // extra opt-in (CIRISEdge#173 resolved).
1355
+ // Two coordinators per consent peer: Attestation (capacity:* / health:liveness)
1356
+ // AND Key (#144, CIRISEdge#257 — the KERI publish-own key plane). The reconciler
1357
+ // (replication_reconcile.rs) converges the same pair set at runtime.
1355
1358
  let peers: Vec<ReplicationPeer> = desired
1356
1359
  .iter()
1357
- .map(|p| ReplicationPeer {
1358
- peer_key_id: p.clone(),
1359
- kind: EnvelopeKind::Attestation,
1360
+ .flat_map(|p| {
1361
+ [
1362
+ ReplicationPeer {
1363
+ peer_key_id: p.clone(),
1364
+ kind: EnvelopeKind::Attestation,
1365
+ },
1366
+ ReplicationPeer {
1367
+ peer_key_id: p.clone(),
1368
+ kind: EnvelopeKind::Key,
1369
+ },
1370
+ ]
1360
1371
  })
1361
1372
  .collect();
1373
+
1374
+ // Key-plane publish selector (CIRISEdge#257 / edge v8.6.0): the Key plane's
1375
+ // `list_keys` advertises the key_ids THIS selector yields — the node's OWN
1376
+ // record — instead of the cohort's-own-keys projection. `list_keys` re-reads
1377
+ // the record live each tick, so once admit-node scrub-signs this node's own
1378
+ // record (scrub_key_id = an accord holder), the NEXT anti-entropy round
1379
+ // publishes the scrubbed, ANCHORED record to consent peers → they root it.
1380
+ // (KERI publish-own: the controller publishes its own establishment record.)
1381
+ let own_key_id = cfg.key_id.clone();
1382
+ let key_selector: ciris_edge::replication::CohortProvider =
1383
+ Arc::new(move || vec![own_key_id.clone()]);
1384
+
1362
1385
  let runtime = ReplicationRuntime::start(
1363
1386
  directory,
1364
1387
  transport as Arc<dyn ciris_edge::transport::Transport>,
1365
1388
  peers,
1366
1389
  ReplicationRuntimeConfig::default(),
1390
+ Some(key_selector),
1367
1391
  )
1368
1392
  .await;
1369
1393
 
@@ -80,6 +80,11 @@ fn err(code: StatusCode, error: &str) -> Response {
80
80
  struct LocalPeerState {
81
81
  key_id: String,
82
82
  pubkey_ed25519_base64: String,
83
+ /// The ML-DSA-65 half (present on a hybrid-complete row; `None` on a legacy
84
+ /// bookmark). Projected so the accord admit-node card can auto-fill BOTH of a
85
+ /// selected owned node's pubkeys from the local directory — no manual paste.
86
+ #[serde(skip_serializing_if = "Option::is_none")]
87
+ pubkey_ml_dsa_65_base64: Option<String>,
83
88
  canonical: bool,
84
89
  /// One of "trusted"|"untrusted"|"blocked"|"unknown". A directory row is an
85
90
  /// admitted key ⇒ "trusted".
@@ -104,6 +109,7 @@ fn to_peer(rec: KeyRecord) -> LocalPeerState {
104
109
  LocalPeerState {
105
110
  key_id: rec.key_id,
106
111
  pubkey_ed25519_base64: rec.pubkey_ed25519_base64,
112
+ pubkey_ml_dsa_65_base64: rec.pubkey_ml_dsa_65_base64,
107
113
  canonical,
108
114
  trust: "trusted",
109
115
  first_seen: rec.valid_from.to_rfc3339(),
@@ -185,6 +185,8 @@ mod tests {
185
185
  min_viable_symbols: 6,
186
186
  symbol_size: 256,
187
187
  held_symbols: 5,
188
+ content_bytes: 1280,
189
+ cohort_scope: Some("federation".to_string()),
188
190
  recoverable: false,
189
191
  admitted_at: "2026-06-21T00:00:00Z".to_string(),
190
192
  };
@@ -207,6 +209,8 @@ mod tests {
207
209
  min_viable_symbols: 1,
208
210
  symbol_size: 1,
209
211
  held_symbols: 0,
212
+ content_bytes: 0,
213
+ cohort_scope: None,
210
214
  recoverable: false,
211
215
  admitted_at: "2026-06-21T00:00:00Z".to_string(),
212
216
  };
@@ -68,13 +68,25 @@ pub async fn reconcile_once(
68
68
  // EnvelopeKind::Attestation carries BOTH directions (capacity:* out,
69
69
  // health:liveness in).
70
70
  let directory = engine.federation_directory();
71
- let mut desired: Vec<ReplicationPeer> = Vec::with_capacity(consented.len());
71
+ let mut desired: Vec<ReplicationPeer> = Vec::with_capacity(consented.len() * 2);
72
72
  for peer in consented {
73
73
  match directory.lookup_public_key(&peer).await {
74
- Ok(Some(_)) => desired.push(ReplicationPeer {
75
- peer_key_id: peer,
76
- kind: EnvelopeKind::Attestation,
77
- }),
74
+ Ok(Some(_)) => {
75
+ // BOTH planes per admitted peer:
76
+ // - Attestation: capacity:* out, health:liveness in (as before).
77
+ // - Key (#144, CIRISEdge#257): the KEY-PLANE anti-entropy. Paired
78
+ // with the runtime's `key_selector` (publishes the node's OWN
79
+ // record — KERI publish-own), this converges a node's scrub-signed
80
+ // accord-anchored record to its consent peers so they can ROOT it.
81
+ desired.push(ReplicationPeer {
82
+ peer_key_id: peer.clone(),
83
+ kind: EnvelopeKind::Attestation,
84
+ });
85
+ desired.push(ReplicationPeer {
86
+ peer_key_id: peer,
87
+ kind: EnvelopeKind::Key,
88
+ });
89
+ }
78
90
  Ok(None) => tracing::warn!(
79
91
  peer_key_id = %peer,
80
92
  "consent:replication observed for an UNADMITTED peer key — skipping reconcile for \
@@ -91,7 +103,9 @@ pub async fn reconcile_once(
91
103
  // Diff-converge the live Initiator set to the desired consent peers. Adds
92
104
  // become active Initiators (scheduler-driven pull) at runtime; removals stop
93
105
  // their rounds + drop inbound routing — all without a restart.
94
- let count = desired.len();
106
+ // `desired` holds TWO coordinators per peer (Attestation + Key); the reported
107
+ // count is distinct consent peers.
108
+ let count = desired.len() / 2;
95
109
  if let Err(e) = runtime.set_peers(desired).await {
96
110
  // The runtime's scheduler has stopped (shutdown) — surface so the caller
97
111
  // logs + skips; the controller never panics.
@@ -859,7 +859,11 @@ async fn genesis_refuses_a_member_that_is_not_a_custody_verified_accord_holder()
859
859
  "rejection must name the non-holder member; got {body}"
860
860
  );
861
861
 
862
- // No family was entrenched.
862
+ // The rejected genesis must not entrench THIS test's family. (Every node now
863
+ // seeds + bakes the canonical HUMANITY_ACCORD genesis A1/B1/C1 — persist
864
+ // v12.0.2 / verify v8.5.0 — so `family_established` is baseline-true and the
865
+ // seats are the baked A1/B1/C1; that is orthogonal to this test. What must
866
+ // hold is that NONE of the proposed test members became a seat.)
863
867
  let roster: serde_json::Value = client
864
868
  .get(format!("{base}/v1/accord-holders"))
865
869
  .send()
@@ -868,10 +872,13 @@ async fn genesis_refuses_a_member_that_is_not_a_custody_verified_accord_holder()
868
872
  .json()
869
873
  .await
870
874
  .unwrap();
871
- assert_eq!(
872
- roster["family_established"], false,
873
- "a rejected genesis must not entrench a family"
874
- );
875
+ let seats = roster["holders"].as_array().expect("holders array");
876
+ for member in ["seat-a", "seat-b", "outsider-not-a-holder"] {
877
+ assert!(
878
+ !seats.iter().any(|h| h["key_id"] == member),
879
+ "a rejected genesis must not entrench member {member}; got {roster}"
880
+ );
881
+ }
875
882
  }
876
883
 
877
884
  // ─── Operational halt (CC 4.2.1 / 4.2.3 / §9.2.1) — the enforceable kill-switch ─
@@ -1116,10 +1123,21 @@ async fn registered_spare_is_not_a_seat_and_cannot_help_reach_quorum() {
1116
1123
  .await
1117
1124
  .unwrap();
1118
1125
  assert_eq!(roster["seat_count"], 3, "exactly 3 seats; got {roster}");
1119
- assert_eq!(
1120
- roster["registered_total"], 4,
1121
- "3 seats + 1 spare registered"
1122
- );
1126
+ // This test's 3 seats + 1 spare are ALL registered accord_holders. (Every node
1127
+ // also seeds the baked A1/B1/C1 canonical genesis — persist v12.0.2 — so assert
1128
+ // membership rather than an exact `registered_total`, which now baselines +3.)
1129
+ let registered = roster["registered"].as_array().expect("registered array");
1130
+ for kid in [
1131
+ "accord-holder-a",
1132
+ "accord-holder-b",
1133
+ "accord-holder-c",
1134
+ "accord-holder-a-spare",
1135
+ ] {
1136
+ assert!(
1137
+ registered.iter().any(|h| h["key_id"] == kid),
1138
+ "the 3 seats + spare must all be registered; missing {kid}; got {roster}"
1139
+ );
1140
+ }
1123
1141
  assert!(
1124
1142
  !roster["holders"]
1125
1143
  .as_array()
@@ -159,3 +159,109 @@ async fn admit_node_scrubbed_record_roots_at_accord_anchor() {
159
159
  "must NOT root when A1 is not a pinned anchor, got {verdict_wrong:?}"
160
160
  );
161
161
  }
162
+
163
+ /// The PRODUCER path (CIRISServer#150 / CIRISPersist#351): a node that already
164
+ /// holds its boot-time **self-signed** own-key row upgrades that row IN PLACE to
165
+ /// the accord-holder-scrubbed record via `Engine::adopt_scrub_upgrade` (the old
166
+ /// `register_federation_key` is `ON CONFLICT DO NOTHING` and would have left the
167
+ /// self-signed row). After the upgrade the row ROOTS at the anchor, and a second
168
+ /// apply is idempotent — exactly what admit-node relies on to publish an anchored
169
+ /// record over the Key plane.
170
+ #[tokio::test]
171
+ async fn adopt_scrub_upgrade_promotes_self_signed_own_row_and_roots() {
172
+ use ciris_persist::federation::register::AdoptScrubOutcome;
173
+
174
+ let engine = node().await;
175
+ let now = chrono::Utc::now().to_rfc3339();
176
+
177
+ let a1 = HybridSigningIdentity::generate("humanity-accord-a1-test").expect("gen A1");
178
+ let anchor = produce_self_key_record(&a1, "steward,accord_holder", &now)
179
+ .await
180
+ .expect("A1 anchor");
181
+ let a1_ed_b64 = anchor.record.pubkey_ed25519_base64.clone();
182
+ engine
183
+ .register_federation_key(to_persist(&anchor))
184
+ .await
185
+ .expect("register A1 anchor");
186
+
187
+ // The node's boot-time state: its OWN row, SELF-signed.
188
+ let target = HybridSigningIdentity::generate("canonical-server-1-test").expect("gen target");
189
+ let target_self = produce_self_key_record(&target, "node", &now)
190
+ .await
191
+ .expect("target self record");
192
+ let target_ed_b64 = target_self.record.pubkey_ed25519_base64.clone();
193
+ let target_mldsa_b64 = target_self
194
+ .record
195
+ .pubkey_ml_dsa_65_base64
196
+ .clone()
197
+ .expect("target ml_dsa");
198
+ engine
199
+ .register_federation_key(to_persist(&target_self))
200
+ .await
201
+ .expect("register target SELF-signed own row");
202
+
203
+ // Precondition: a self-signed row does NOT root.
204
+ let backend = engine.sqlite_backend().expect("sqlite backend");
205
+ let anchor_set = [ed32(&a1_ed_b64)];
206
+ assert!(
207
+ !matches!(
208
+ root_binding_anchored(
209
+ backend.as_ref(),
210
+ "canonical-server-1-test",
211
+ &target_ed_b64,
212
+ &anchor_set
213
+ )
214
+ .await,
215
+ RootingVerdict::Confirmed { .. }
216
+ ),
217
+ "precondition: the self-signed own row must NOT root yet"
218
+ );
219
+
220
+ // A1 scrub-signs the target, and the node ADOPTS the upgrade onto its own row.
221
+ let scrubbed = produce_scrubbed_key_record(
222
+ &a1,
223
+ ScrubTarget {
224
+ key_id: "canonical-server-1-test".to_string(),
225
+ pubkey_ed25519_base64: target_ed_b64.clone(),
226
+ pubkey_ml_dsa_65_base64: target_mldsa_b64,
227
+ identity_type: "node".to_string(),
228
+ },
229
+ &now,
230
+ )
231
+ .await
232
+ .expect("A1 scrub-signs target");
233
+
234
+ let outcome = engine
235
+ .adopt_scrub_upgrade(to_persist(&scrubbed))
236
+ .await
237
+ .expect("adopt_scrub_upgrade must succeed on a self-signed own row");
238
+ assert!(
239
+ matches!(outcome, AdoptScrubOutcome::Upgraded),
240
+ "first adopt upgrades the self-signed row, got {outcome:?}"
241
+ );
242
+
243
+ // Now the SAME key_id ROOTS — the Key plane would publish an anchored record.
244
+ assert!(
245
+ matches!(
246
+ root_binding_anchored(
247
+ backend.as_ref(),
248
+ "canonical-server-1-test",
249
+ &target_ed_b64,
250
+ &anchor_set
251
+ )
252
+ .await,
253
+ RootingVerdict::Confirmed { .. }
254
+ ),
255
+ "after adopt the own row must ROOT at the accord anchor"
256
+ );
257
+
258
+ // Idempotent: re-applying the same outbox record is a no-op (second boot).
259
+ let again = engine
260
+ .adopt_scrub_upgrade(to_persist(&scrubbed))
261
+ .await
262
+ .expect("re-adopt must not error");
263
+ assert!(
264
+ matches!(again, AdoptScrubOutcome::AlreadyAdopted),
265
+ "second adopt is idempotent, got {again:?}"
266
+ );
267
+ }