ciris-server 0.5.71__tar.gz → 0.5.72__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.
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.gitignore +3 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/Cargo.lock +5 -32
- ciris_server-0.5.72/Cargo.toml +327 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/PKG-INFO +1 -1
- ciris_server-0.5.72/WIRE_VOCABULARY_KINDS.md +21 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/Cargo.toml +2 -2
- ciris_server-0.5.72/crates/ciris-lens-core/src/role/handler.rs +119 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/role/relay.rs +7 -6
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/role/ret_relay.rs +4 -3
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/device_grant.rs +100 -26
- ciris_server-0.5.72/src/auth/gate.rs +349 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/ownership.rs +7 -1
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/session.rs +153 -2
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/claim_remote.rs +29 -5
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/compose.rs +73 -4
- ciris_server-0.5.72/src/delegation_transparency.rs +58 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/federation_admin.rs +9 -2
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/lib.rs +11 -0
- ciris_server-0.5.72/src/mesh_relay.rs +1064 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/safety/age.rs +1 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/claim_remote.rs +31 -34
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/device_grant.rs +286 -1
- ciris_server-0.5.72/tests/mesh_seed_e2e.rs +1062 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/ownership.rs +19 -19
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates/support.rs +6 -2
- ciris_server-0.5.72/tests/wire_vocabulary_gate.rs +26 -0
- ciris_server-0.5.71/Cargo.toml +0 -321
- ciris_server-0.5.71/crates/ciris-lens-core/src/role/handler.rs +0 -97
- ciris_server-0.5.71/src/auth/gate.rs +0 -79
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.cargo/config.toml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.claude/workflows/localize-ui.js +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.github/workflows/bench.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.github/workflows/build-wheels.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.github/workflows/ci.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.github/workflows/client-artifacts.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.github/workflows/conformance.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.github/workflows/localization.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.github/workflows/publish-pypi.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/.github/workflows/release.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/CHANGELOG.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/LICENSE +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/MISSION.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/README.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/bench-site/bench_results.json +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/bench-site/index.html +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/bench_results.json +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/benches/alm_chain.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/benches/erasure_survival.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/benches/n_eff_scoring.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/benches/pqc_av_streaming.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/benches/replication_ingest.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/benches/sig_overhead.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/benches/stream_fanout.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/.github/workflows/bench.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/.github/workflows/ci.yml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/.gitignore +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/.pre-commit-config.yaml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/FSD/CIRIS_LENS_CORE.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/FSD/LENS_CORE_V0_5.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/FSD/OPEN_QUESTIONS.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/LICENSE +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/MISSION.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/README.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/benches/aggregate.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/benches/canonicalize.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/benches/project.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/deny.toml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/docs/BENCHMARKS.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/docs/COHABITATION.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/docs/PRE_COMMIT.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/docs/PUBLIC_SCHEMA_CONTRACT.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/docs/PYPI_PUBLISH.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/docs/RELEASE_NOTES.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/docs/STANDARDS_COMPARISON.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/docs/THREAT_MODEL.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/extraction/json_path.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/extraction/metadata.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/extraction/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/distilbert_loader.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/fields.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/ner.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/ort_loader.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/proptests.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/regex.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/walker.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/patterns_from_cirislens_core/scrubber/xlm_r_loader.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/pyproject.toml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/python/ciris_lens_core/__init__.py +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/audit/api.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/audit/delegate.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/audit/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/audit/pyo3.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/canonical/ceg_egress.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/canonical/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capacity/attestation.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capacity/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capacity/score.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capture/batch.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capture/client.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capture/consent.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capture/correlation.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capture/event.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capture/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capture/partial.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capture/py_engine.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/capture/seal.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/cohort/declared.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/cohort/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/cohort/resourcing.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/config/egress.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/config/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/config/node.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/config/retention.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/config/upstream.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/detector/axis_metrics.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/detector/coherence_ratchet.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/detector/correlated_action.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/detector/distributive_access.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/detector/manifold.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/detector/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/extract/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/extract/projection.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/ffi/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/ffi/pyo3.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/lib.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/observability/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/pipeline/lifecycle.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/pipeline/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/retention/eviction.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/retention/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/retention/summary.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/role/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/role/node.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scores/aggregate.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scores/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scores/oracle.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scoring/assembly.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scoring/axis_calibration.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scoring/calibration.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scoring/capacity.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scoring/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scoring/n_eff.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/scoring/result.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/signing/event.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/signing/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/wire/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/src/wire/signer.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/tests/parity/README.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/tests/parity/canonical_fixtures.json +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/tests/parity/generate_canonical_fixtures.py +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/crates/ciris-lens-core/tests/sovereign_rlib.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/data/live_mesh_2026-06-22.json +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/docs/SCOPE_PRIVACY.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/examples/mesh_propagation/main.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/examples/qa_runner/accord.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/examples/qa_runner/common.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/examples/qa_runner/family.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/examples/qa_runner/main.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/examples/qa_runner/verify.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/installers/windows/README.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/installers/windows/bundle-jre.ps1 +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/installers/windows/ciris-server-entry.py +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/installers/windows/ciris-server-installer.iss +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/installers/windows/ciris-server.spec +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/pyproject.toml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/python/ciris_server/__init__.py +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/python/ciris_server/__main__.py +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/python/ciris_server/cli.py +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/python/ciris_server/desktop_launcher.py +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/rust-toolchain.toml +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/scripts/bench_report.py +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/accord.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/accord_custody.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/accord_halt.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/accord_pki/yubico_attestation_root_1.der +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/accord_pki/yubico_attestation_root_1.pem +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/accord_provision.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/accord_reactivate.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/adapter.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/ABSORPTION.md +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/api_keys.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/attestation.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/bootstrap.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/consent.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/device_auth.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/erasure.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/loopback.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/oauth.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/occurrence.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/portable_occurrence.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/roles.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/self_login.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/store.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/auth/verify.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/benchmarks/bench_results.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/benchmarks/mesh.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/benchmarks/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/benchmarks/scoreboard.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/config.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/config_api.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/config_reconcile.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/family.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/federation_nodecode.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/federation_peers.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/graph_config.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/health.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/holonomic.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/http_log.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/identity.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/ids.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/import.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/ingest_http.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/main.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/memory_api.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/nodecode.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/peer.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/proxy.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/py_adapter.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/quorum.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/radio.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/replication_reconcile.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/safety/mod.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/safety/moderation.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/safety/named.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/safety/watchlist.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/scorer/n_eff.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/scorer.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/system_data.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/telemetry_logs.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/src/yubico_attestation_ca.pem +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/accord.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/alm_chain.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/audit_chain.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/capacity_scorer.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/chaos_mesh.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/config_reconcile.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/federation_admin.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/federation_session_kex.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/graph_config.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/ingest_http.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/nat_traversal.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/nodecode.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/noise_floor.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/occurrence.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/peer_replication.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/portable_occurrence.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates/stage1.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates/stage2.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates/stage3.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates/stage4.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates/stage5.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates/stage6.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates/stage7.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates/stage8.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/release_gates.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/replication.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/replication_reconcile.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/root_bootstrap.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/safety.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/tests/stream_sth_consistency.rs +0 -0
- {ciris_server-0.5.71 → ciris_server-0.5.72}/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 = "
|
|
825
|
-
source = "git+https://github.com/CIRISAI/CIRISEdge?tag=
|
|
824
|
+
version = "8.3.0"
|
|
825
|
+
source = "git+https://github.com/CIRISAI/CIRISEdge?tag=v8.3.0#6673692c7b73c351c76580bc767148c440dc8897"
|
|
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 = "11.
|
|
947
|
-
source = "git+https://github.com/CIRISAI/CIRISPersist?tag=v11.
|
|
946
|
+
version = "11.9.1"
|
|
947
|
+
source = "git+https://github.com/CIRISAI/CIRISPersist?tag=v11.9.1#e6748c4407e9c105e832ca3395571d59cb7c75b3"
|
|
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.
|
|
986
|
+
version = "0.5.72"
|
|
987
987
|
dependencies = [
|
|
988
988
|
"anyhow",
|
|
989
989
|
"async-trait",
|
|
@@ -1499,7 +1499,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
1499
1499
|
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
|
|
1500
1500
|
dependencies = [
|
|
1501
1501
|
"powerfmt",
|
|
1502
|
-
"serde_core",
|
|
1503
1502
|
]
|
|
1504
1503
|
|
|
1505
1504
|
[[package]]
|
|
@@ -4784,13 +4783,11 @@ dependencies = [
|
|
|
4784
4783
|
"log",
|
|
4785
4784
|
"regex",
|
|
4786
4785
|
"rusqlite",
|
|
4787
|
-
"serde",
|
|
4788
4786
|
"siphasher",
|
|
4789
4787
|
"thiserror 2.0.18",
|
|
4790
4788
|
"time",
|
|
4791
4789
|
"tokio",
|
|
4792
4790
|
"tokio-postgres",
|
|
4793
|
-
"toml 1.1.2+spec-1.1.0",
|
|
4794
4791
|
"url",
|
|
4795
4792
|
"walkdir",
|
|
4796
4793
|
]
|
|
@@ -6088,21 +6085,6 @@ dependencies = [
|
|
|
6088
6085
|
"winnow 0.7.15",
|
|
6089
6086
|
]
|
|
6090
6087
|
|
|
6091
|
-
[[package]]
|
|
6092
|
-
name = "toml"
|
|
6093
|
-
version = "1.1.2+spec-1.1.0"
|
|
6094
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
6095
|
-
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
|
|
6096
|
-
dependencies = [
|
|
6097
|
-
"indexmap",
|
|
6098
|
-
"serde_core",
|
|
6099
|
-
"serde_spanned 1.1.1",
|
|
6100
|
-
"toml_datetime 1.1.1+spec-1.1.0",
|
|
6101
|
-
"toml_parser",
|
|
6102
|
-
"toml_writer",
|
|
6103
|
-
"winnow 1.0.3",
|
|
6104
|
-
]
|
|
6105
|
-
|
|
6106
6088
|
[[package]]
|
|
6107
6089
|
name = "toml_datetime"
|
|
6108
6090
|
version = "0.6.11"
|
|
@@ -6121,15 +6103,6 @@ dependencies = [
|
|
|
6121
6103
|
"serde_core",
|
|
6122
6104
|
]
|
|
6123
6105
|
|
|
6124
|
-
[[package]]
|
|
6125
|
-
name = "toml_datetime"
|
|
6126
|
-
version = "1.1.1+spec-1.1.0"
|
|
6127
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
6128
|
-
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
|
|
6129
|
-
dependencies = [
|
|
6130
|
-
"serde_core",
|
|
6131
|
-
]
|
|
6132
|
-
|
|
6133
6106
|
[[package]]
|
|
6134
6107
|
name = "toml_edit"
|
|
6135
6108
|
version = "0.19.15"
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "ciris-server"
|
|
3
|
+
version = "0.5.72" # 0.5.72 = THE MESH-SEED RELEASE (delegation constraints + edge-8.0 opaque relay, both needed to seed A/B). SUBSTRATE: edge v7.4.4->v8.0.0 (CC 0.7 opaque wire vocabulary, WIRE_VOCABULARY.md v1.0.1 hash-pinned) + persist v11.5.0->v11.6.0; AccordEventsBatch retired -> OpaqueEvent (lens-core register_opaque_subscriber, provisional kind 0x0005_0001, ratify via CIRISPersist#337). MESH RELAY (CIRISServer#128 Phase D): src/mesh_relay.rs — local POST /v1/mesh/relay (dgrant + MeshRelay verb -> resolve_user_signer -> hybrid-sign -> Edge::send_opaque_request kind 0x0000_0001) + remote MeshControlHandler (verify_request/signer_acts_for -> is_steward_bound owner-authz -> nonce+ts replay-guard -> closed RELAYABLE allow-list [announce/peering/self-key-record/owned-nodes] -> tower::oneshot into the node OWN v1 router via a synthetic loopback owner session); reaches owned remotes by key_id over RNS, NO password on A/B. WIRE_VOCABULARY_KINDS.md = our CC-0.7 0x0000_* steward doc. tests/wire_vocabulary_gate.rs pins the edge vocab hash; tests/mesh_seed_e2e.rs = the runbook TDD gate (GREEN). GATED: seeding needs a fleet-wide 0.5.72 roll (relay is bilateral -> A/B need edge 8.0 + MeshControlHandler). INITIATOR leg NOW LIVE (edge#249 landed): substrate advanced edge v8.0.0->v8.3.0 + persist v11.6.0->v11.9.1 (verify stays v8.3.0); edge v8.2.0 ships Edge::run(self: Arc<Self>) so compose retains a live Arc<Edge> ACROSS run() and wires mesh_relay::edge_mesh_requester_with_loopback (target==self short-circuits to the in-process responder, every OTHER owned target sends for real over RNS via Edge::send_opaque_request) — the v8.0.0 local_only_requester stub (502'd cross-node) retired. The lens-core trace opaque kind is now the RATIFIED ciris_persist::TRACE_BATCH_KIND (CIRISPersist#337, shipped persist v11.9.0; wire value unchanged from the provisional 0x0005_0001). DELEGATION: DELEGATION CONSTRAINTS + transparency. Owner may bound a delegation grant along action allow/deny + goal (CC 2.4.1.2 delegated_scope/delegation_purpose); a single authorize_delegated(caller,verb) guard (CapabilityVerb enum + server never-list: delegate/wipe/accord_halt) wired into claim-remote/announce/peering/set-age; /delegate carries constraints, /approve tightens-only (never widens); constraints ride INSIDE the signed delegates_to envelope (durable/auditable, CC 2.1.1 forward-compat) AND self-expire via delegation_valid_until (emit_signed_attestation gained expires_at). TRANSPARENCY: full grant characteristics shown on EVERY use — x-ciris-delegation response header (global middleware) + a delegation object in /claim+/token issuance bodies. Client UX: DelegationsScreen constraints editor + "what this permits" display, 28-lang localized. Substrate floor UNCHANGED (edge v7.4.4/persist v11.5.0/verify v8.3.0). FSDs: DELEGATION_CONSTRAINTS/RNS_CONTROL_RELAY/MESH_SEED_RUNBOOK. 0.5.69 = #125 client-stateless + self-scoped ownership. Owner-binding now FOLLOWS the claim cohort (default SELF, was hardcoded FEDERATION) -> self-replicates to the owner's occurrences (owned-nodes cross-device, PRIVATE; CEG 10.1.4) + full self/family use. Community/federation participation is OPT-IN: POST /v1/federation/announce promotes self->FEDERATION (re-persists the already-user-signed envelope at the wider cohort; no substrate cohort-widen primitive) + sets config net.announce_ownership=true, which gates the AV-42 federation-IDENTITY announce via ReticulumAuth.signer (None when off -> empty app-data, peers drop; raw transport unaffected; boot-structural). Default OFF -> self-balances (no public owner => no community participation, but full private self/family use). CLIENT made stateless: NodeProfileStore (the Java-prefs ~/.java/.userPrefs side store -- root cause of wipe-leaves-stale-nodes + identity-name-only-after-restart + empty-memory-graph) DELETED; switcher/identity/memory read LIVE owned-nodes; token no longer persisted (re-login each launch). Wizard "announce yourself" toggle (default OFF) + Nodes-screen USB save/restore of the node list (ciris-nodes.json) for private users. Also: canonical config by-key surface (PUT/DELETE /v1/config/{key} + ConfigValue::Null tombstone -- the common impl the agent will adopt) + delegations offer copy/select. Substrate floor UNCHANGED (edge v7.4.4/persist v11.5.0/verify v8.3.0). FOLLOW-ON: mesh-addressing (reach owned remotes by key_id; listed-but-not-switchable until then) + canonical A/B must set net.announce_ownership=true + reboot to be federation-discoverable. 0.5.68 = edge v7.4.3->v7.4.4 (CIRISEdge#238 fix: edge now saves a LEAN release cache blob, was ~7.5GB debug+matrix target/ -> so downstream edge-layer restores, esp. Windows, drop from minutes to seconds; same floor persist v11.5.0/verify v8.3.0) + dropped the ci.yml debug -s SAVE (measured 586s/10min on main to spare a ~30s debug recompile, and it collided with conformance's release -s; CI now only RESTORES). 0.5.67 = CIRISCache restore@v2 -s* prefix fallback wired in + save -s on tags. Each consumer's restore now tries: exact -s<thisversion> -> most-recent -s<any> (lean ~1GB server blob, complete) -> edge -> persist -> verify, first-hit-wins. So a NEW version restores the latest lean -s and incremental-compiles only ciris-server, instead of pulling the 7.5GB edge layer (CIRISEdge#238). build-wheels now saves the -s blob on v* tags too (warm-release-cache is retired), so each release populates the -s for the next. CI-yaml only. 0.5.66 = edge v7.4.1->v7.4.3 (stable Windows wheel, CIRISEdge#236 — windows substrate cache keys now align so the cross-repo centipede hits on Windows; same floor persist v11.5.0 / verify v8.3.0) + CIRISCache restore@v2 wiring: the 4 per-layer restore steps collapse to ONE keys-list (server->edge->persist->verify, first-hit-wins) so a single deepest blob extracts instead of cumulative re-extraction of the substrate target/ (the edge layer measured 452s/7.5min on v1). 0.5.65 = drop the Tier-3 Win7 build-std lane (CI cycle-time + simplification): removed the ci.yml win7-build-std job (nightly + -Zbuild-std + rust-src), the release.yml win7 matrix entry (now stable + standard x86_64-pc-windows-msvc), the windows7-installer.yml workflow, and the client-artifacts UCRT-redist fetch. Windows floor is now Win10+/Server 2016+ (Win7 SP1 EOL 2020), matching persist + verify + edge v7.4.3 (CIRISEdge#236) so the cross-repo cache keys align. edge bump to v7.4.3 follows when it tags. 0.5.64 = ships the lean CI pipeline (no code change vs 0.5.63): deleted warm-release-cache (its only job, pre-warming the per-version -s server cache layer, was a wash — publish-pypi rebuilt it on the tag minutes later; the verify/persist/edge SUBSTRATE layers restore warm from upstream regardless, so the tag only recompiles the ciris-server/lens-core crates on top), dropped Cargo.toml from bench paths (no bench on version bumps), paths-ignore docs on CI + conformance, concurrency cancel-in-progress per ref. Per release: 6 commit-workflows + wheels x2 -> 3 commit-gates + wheels x1. 0.5.63 = IMPORT an existing fed-ID at first-run (one device = one person; import REPLACES, never coexists — families are the multi-person construct). Server: POST /v1/self/associate is now first-run-capable (was owner-gated, could not run at setup) + writes active_user_alias = imported alias so claim-remote/upgrade-owner/set-age re-own + operate under the IMPORTED fed-ID, not the throwaway <node>-user. Client: first-run wizard gains "Import existing Fed ID from USB" (DirectoryPickerDialog -> importPortableFromUsb -> associate -> self-claim owns the node as the imported ID). Replace-in-place on already-owned nodes too (owner-gated self-service re-home). 0.5.62 = post-provision polish + substrate bump (edge v7.4.1, persist v11.5.0; verify v8.3.0). Identity surfaces now show the OWNER fed-ID (eric-moore-v1) not the node key (ciris-client): IdentityManagementViewModel resolves getOwnedNodes().owner first; NodeGraphView centre vertex labeled with the owner fed-ID. set-age now resolves active_user_alias (was 409 post-claim — looked at <node>-user). 0.5.61 = custody ladder fix: the wizard defaulted "secure with 2FA" ON and hard-mapped it to pkcs11, so the fed-ID mint demanded an external YubiKey and 500d on any machine without one (libykcs11 missing; even a Linux .so path on macOS). Now: client defaults 2FA OFF (YubiKey opt-in), and the server mint walks a custody LADDER — YubiKey (if available AND selected) -> platform-sealed (TPM/SE, keychain fallback) -> software (last resort) — falling DOWN a rung when hardware cant be opened instead of failing. Unblocks the macOS software fed-ID mint (eric-moore-v1). 0.5.60 = mac re-provision fixes (wizard auto-mints fed-ID from typed name on Next + mint-if-absent backstop at self-claim; post-wipe process exit so the node restarts clean into first-run instead of disk-IO death-spiral) + edge v7.4.0 (dual-destination announce, closes CIRISEdge#231 — kills the "Explicit-hash destinations cannot be announced" warning; same triple floor v8.3.0/v11.2.0). 0.5.59 = serialport target-gate fix + CIRISCache 4-layer centipede (carries 0.5.58 unbrick + radio + UI). FIX: serialport/libudev-sys cannot cross-compile for armv7/musl (no cross libudev) — narrowed the radio cfg gate (Cargo.toml dep + mod radio + edge attach) from not(android/ios) to ONLY serial-capable targets: macos, windows, linux-gnu x86_64/aarch64. CIRISCache (CIRISServer#99): rewired ALL cache-using CI legs (build-wheels x4, conformance, ci.yml x3-os, release.yml) from a single key to the 4-layer centipede — restore verify->persist->edge->server (widest->narrowest, each continue-on-error), SAVE under the server-specific -s<version> key (was colliding with edge's key, polluting it with server's 1.3G target/). Eyeball ::notice:: per key surfaces NONE regressions. 0.5.58 = node-recovery + transport radio + nodes/trust UI (substrate UNCHANGED v8.3.0/v11.2.0/v7.3.1). CRITICAL: federation_signer was open-ONLY (get_platform_ed25519_signer) so a wiped/fresh home bricked with "Key not found: ed25519.seed"; now open_or_create (mint-if-absent), mirroring federation_pqc_signer — a node post wipe-signing-key comes back to FIRST-RUN. NEW: serial LoRa/RNode transport — src/radio.rs SerialRNodeDriver (serialport + RNode KISS, desktop-only cfg(not(android/ios))) wired into build_edge via EdgeBuilder.transport() when net.radio.* config:* enabled (KISS wire-correct vs Leviculum ref, HARDWARE-UNVALIDATED); client Transport card writes net.radio.* via /v1/config. libudev-dev added to Linux build legs (serialport). Client: neuralviz rings removed from nodes card, graph legend collapsed, trust page node-mode-clean. 0.5.57 = node Data/Logs/Graph endpoints + drop Win7 (substrate UNCHANGED — edge v7.3.1 / persist v11.2.0 / verify v8.3.0, so the warm-release-cache from 0.5.56 is reused, no substrate recompile). Adds GET /v1/telemetry/logs (tails <home>/logs/ciris-server.log), POST /v1/system/data/reset-account (data-only wipe, preserves keys) + /wipe-signing-key (data+keys, double-confirmed) + GET /v1/my-data/lens-identifier, and seeds the node identity into the graph at boot so the client Graph page is not empty (mirrors the agent agent/identity seed). Client: nodes-page key collapsed behind a "?" expander; Logs screen node/agent source dropdown (agent grayed in node mode). CI: dropped the Tier-3 Windows 7 build-std lane (kept standard Win10+ msvc); will re-add later. 0.5.56 = SELF-DEK end-to-end: adopt edge v7.3.1 / persist v11.2.0 / verify family v8.3.0 (CIRISVerify#151 self_enc derive + CIRISPersist#304 wrap-once dedup). The portable user fed-ID now DERIVES its content-encryption keypair (x25519 + ML-KEM-768) from the Ed25519 base seed via ciris_crypto::self_enc (HKDF-domain-separated, mirrors derive_wallet_keypair) and attaches the enc pubkeys to the occurrence at portable-mint bind. 0.5.55 = edge v7.3.0 / persist v11.0.0 / verify v8.0.0 (BREAKING): owner->steward rename + Engine::nodes_stewarded_by (#299), verify 8 tpm-plugin, CC-0.5.1 client round. 0.5.54 = adopt edge v7.2.1 / persist v10.6.0 / verify v7.6.0 substrate floor; lens seal signs HYBRID (Ed25519 + ML-DSA-65) — persist v10 hybrid-strict rejected the Ed25519-only seal with verify_hybrid_required (CIRISServer#121, blocks CIRISAgent#896); the FFI capture seal now mirrors the detection-event hybrid path (local_pqc_sign over canonical‖ed25519_sig) + seal::apply_hybrid_signature. # 0.5.53 = adopt the edge v7.2.0 substrate triple (persist v10.2.2->v10.5.0 / edge v7.0.12->v7.2.0 / verify family v7.5.0 unchanged / leviculum ->v0.8.1+ciris.1 — the RNS phone-radio floor) + #118 lens seal derived key_id + #120 reliable node file logging + client delegations test-input wiring. # 0.5.52 = adopt the edge v7.0.12 substrate triple — the AGENT-SWAP candidate (connection-bug fix in edge). persist v10.2.1->v10.2.2 / edge v7.0.11->v7.0.12 / verify family v7.4.0->v7.5.0 (verify-core + ciris-crypto + ciris-keyring co-bumped; MINOR, additive) / leviculum v0.7.0 unchanged. edge v7.0.12 fixes a connection bug — this is the version we swap into CIRISAgent + back the owner fed-ID up + configure replication on. re-host-VERIFIED (one-wheel Engine/Edge identity + audit_record_entry + audit_next_chain_position + serve_with_python_adapter + brain-data surface all OK on the new triple) AND CIRISServer#93 audit chain re-verified on verify v7.5.0 (log_* + audit_verify_chain outcome:ok). ZERO source changes (cargo check + default & python clippy + fmt + release-gate stage1 + wheel smoke green); ships with the --strip wheels (#101). # 0.5.51 = CLEAN RE-CUT of the edge v7.0.11 triple (same substrate as 0.5.50: persist v10.2.1 / edge v7.0.11 / verify v7.4.0) with STRIPPED wheels (PR #101: maturin --strip ~halves each wheel, ~90MB->~40MB). 0.5.50 published only PARTIALLY — the PyPI 'ciris-server' project hit its 10GB size cap (10.67GB across 45 versions) and 400'd the upload mid-stream, so only android×2 + macos×2 landed (no linux wheel, no sdist) → linux stayed on 0.5.49. Freed space (pruned old releases) + stripped wheels → 0.5.51 uploads clean on every platform. No source change vs 0.5.50. # 0.5.50 = adopt the edge v7.0.11 substrate triple (persist v10.2.0->v10.2.1 / edge v7.0.10->v7.0.11; verify family v7.4.0 + leviculum v0.7.0 unchanged); persist patch bump, re-host-VERIFIED (one-wheel Engine/Edge identity + audit_record_entry + audit_next_chain_position + serve_with_python_adapter + brain-data task_get/secrets_recall_secret/tsdb_prune_summaries/incident_list all OK on v10.2.1) AND the CIRISServer#93 audit chain re-verified end-to-end on the new persist (4× log_* + audit_verify_chain outcome:ok); ZERO source changes (cargo check + default & python clippy + fmt + release-gate stage1 + wheel smoke green). # 0.5.49 = CIRISServer#93 FIX — the LensAudit (cohabitation) audit-chain WRITE path now produces a valid persist AuditEntry over the wheel (D02/D23). Four wheel-boundary mismatches, each only visible by running the real ciris_persist Engine (all in crates/ciris-lens-core/src/audit/): (1) HEADLINE — record_event now reads the chain head via engine.audit_next_chain_position(tenant) (CIRISPersist#281) and sets sequence_number = next_sequence_number (was hard-coded 0 → "sequence_number must be >= 1") + prev_hash = the 32-byte head (was "" → "prev_hash must be 32 bytes"); persist does NOT fill these on INSERT; (2) prev_hash comes back as 64 HEX chars but the AuditEntry wire serde is base64-STANDARD (serde_bytes_b64) → hex-decode then base64-encode; (3) stamp_signature was URL_SAFE_NO_PAD but persist's verify_hybrid decodes the signature as base64-STANDARD ("ed25519_sig: Invalid symbol 45"); (4) actor_id was engine.local_key_id() (the key_id LABEL, '-' fails pubkey decode) — persist's self-signed model is "actor_id IS the pubkey", so use engine.local_public_key_b64(); (bonus) recorded_at truncated to microseconds (Postgres TIMESTAMPTZ µs) BEFORE hashing, else audit_verify_chain reports EntryHashMismatch on read-back. VERIFIED end-to-end against the freshly-built wheel: 4× LensAudit.log_* record + audit_verify_chain walks all 4 with outcome:ok. lens-core 1.4.2->1.4.3; 27 audit unit tests + clippy + fmt green. Substrate unchanged from 0.5.48 (persist v10.2.0 / edge v7.0.10 / verify v7.4.0). — the LensAudit (cohabitation) audit-chain WRITE path now produces a valid persist AuditEntry over the wheel (D02/D23). Four wheel-boundary mismatches, each only visible by running the real ciris_persist Engine (all in crates/ciris-lens-core/src/audit/): (1) HEADLINE — record_event now reads the chain head via engine.audit_next_chain_position(tenant) (CIRISPersist#281) and sets sequence_number = next_sequence_number (was hard-coded 0 → "sequence_number must be >= 1") + prev_hash = the 32-byte head (was "" → "prev_hash must be 32 bytes"); persist does NOT fill these on INSERT; (2) prev_hash comes back as 64 HEX chars but the AuditEntry wire serde is base64-STANDARD (serde_bytes_b64) → hex-decode then base64-encode; (3) stamp_signature was URL_SAFE_NO_PAD but persist's verify_hybrid decodes the signature as base64-STANDARD ("ed25519_sig: Invalid symbol 45"); (4) actor_id was engine.local_key_id() (the key_id LABEL, '-' fails pubkey decode) — persist's self-signed model is "actor_id IS the pubkey", so use engine.local_public_key_b64(); (bonus) recorded_at truncated to microseconds (Postgres TIMESTAMPTZ µs) BEFORE hashing, else audit_verify_chain reports EntryHashMismatch on read-back. VERIFIED end-to-end against the freshly-built wheel: 4× LensAudit.log_* record + audit_verify_chain walks all 4 with outcome:ok. lens-core 1.4.2->1.4.3; 27 audit unit tests + clippy + fmt green. Substrate unchanged from 0.5.48 (persist v10.2.0 / edge v7.0.10 / verify v7.4.0). # 0.5.48 = adopt the edge v7.0.10 substrate triple (persist v10.1.2->v10.2.0 / edge v7.0.8->v7.0.10; verify family v7.4.0 + leviculum v0.7.0 unchanged); persist minor bump re-host-VERIFIED (one-wheel Engine/Edge identity + audit_record_entry + serve_with_python_adapter + the brain-data surface task_get/secrets_recall_secret/tsdb_prune_summaries/incident_list all OK on v10.2.0); ZERO source changes (cargo check + default & python clippy + fmt + release-gate stage1 substrate-pins + wheel smoke all green); # 0.5.47 = republish 0.5.46 with a macOS-portable CLIENT_VERSION sed (the 0.5.46 publish-pypi auto-sync used GNU `sed -i "EXPR"` which BSD/macOS sed rejects → both macos wheel legs failed → publish skipped; fixed to `sed -i.bak` + rm); content = 0.5.46 (node-switcher A/B merge + CLIENT_VERSION sync + edge v7.0.8 triple); # 0.5.46 = node-switcher MERGE fix (NodeSwitcherViewModel.reload now MERGES stored owned profiles with the local-node owned-nodes projection instead of replacing — owned+known remote nodes like A/B were dropped because the local graph only lists nodes IT is bound to; + clear [reload] logging of stored/projected/final lists) + CLIENT_VERSION drift fix (was hardcoded 0.5.34 → false "older release" banner; now auto-synced from Cargo.toml at JAR build); ALSO adopts the edge v7.0.8 substrate triple (persist v10.1.1->v10.1.2 / verify v7.2.0->v7.4.0 / edge v7.0.6->v7.0.8; the verify family = verify-core + ciris-crypto + ciris-keyring, all co-bumped to v7.4.0; leviculum v0.7.0); # 0.5.45 = desktop launcher home fix — bare `ciris-server` (desktop mode) now resolves the home via CIRISAgent path logic (CIRIS_HOME -> ~/ciris), NOT the systemd default /var/lib/ciris (not user-writable); the wheel launcher (python/ciris_server/cli.py) and the GUI client (PythonRuntime.desktop.kt nodeHomeDir) both mirror get_ciris_home() so the node + brain + bare command share ~/ciris; # 0.5.44 = edge v7.0.5 -> v7.0.6 (edge-only bugfix bump; persist v10.1.1 / verify v7.2.0 / leviculum v0.7.0 unchanged); # 0.5.43 = adopt the v7.0.5 substrate triple (persist v10.1.1 / verify v7.2.0 / edge v7.0.5, leviculum v0.7.0) + the portable software identity occurrence feature (POST /v1/self/occurrence/portable mints a fresh SOFTWARE hybrid keyset, TPM-primary-authorized as an occurrence of the owner self, written to a chosen USB dir; POST /v1/self/associate installs it on another device; owner-gated + loopback-only; identity-page UI) — the held-for-triple cut; # 0.5.42 = CIRISServer#86 — enable the 11 persist brain-data features (cirislens_tasks/thoughts/tickets/correlations/deferral_reports/maintenance_locks/creation_ceremonies/legacy_migration + cirisincident + telemetry + secrets) so the agent re-hosts its full data layer (38 Engine methods: tasks/thoughts/tickets/secrets/correlations/deferrals/locks/telemetry) from the one wheel — same #[cfg]-gated-off-our-build root cause as #83/cirisaudit; secrets methods carry a secrets_ prefix in pyo3; completes CIRISAgent#896 Phase 0; # 0.5.41 = CIRISServer#80 — PyO3 adapter hook: ciris_server.serve_with_python_adapter(adapter, home?, key_id?) folds a Python brain into the node router via the mount-by-proxy model (src/proxy.rs reverse-proxies the adapter-declared {prefix->upstream} onto the read-API; src/py_adapter.rs bridges start/stop, lifecycle parks until shutdown) — completes the agent-adoption adapter seam (brain no longer must be a bare :8080 sidecar); # 0.5.40 = enable the persist `cirisaudit` feature so the audit-chain WRITE surface (audit_record_entry + audit_canonicalize_for_hash/_for_signing, #[cfg(cirisaudit)] PyEngine methods) compiles into the wheel and re-exports to the agent — unblocks CIRISAgent#896 Phase 0 audit migration (CIRISServer#83); the methods were feature-gated off, never removed; # 0.5.39 = one-wheel re-export COMPLETE — register_persist/register_edge now delegate to the crates' pub fn register (persist v10 #231 reset_engine + edge v7.0.2 #199 init_edge_runtime, restoring the hook that regressed in the v7.x line); the agent re-hosts the FULL persist+edge surface from the single ciris-server wheel and drops its standalone ciris_persist/ciris_edge wheels; # 0.1 = lens-only (agent ~2.9.7); 0.3 = +auth subsystem / one-wheel; 0.4 = +federation peering/identity (capacity scoring, consent:replication, register_federation_key gate, root-bootstrap, NodeCode); 0.4.1 = self-attested first-run root claim (#887); 0.4.2 = one-time claim PIN; 0.4.3 = CC-compliant ownership (infra:* responsible-party owner-binding, no agency, serve-only-until-owned); 0.4.4 = substrate-native user-signed owner-binding — 1-phase /v1/setup/root + the local node's /v1/setup/claim-remote (client is a node; crypto only in the substrate); 0.4.10 = Adapter seam (trait + AdapterContext + serve_with_adapter, mirrors CIRISAgent BaseAdapterProtocol — ciris-status = ciris-server + StatusAdapter); 0.4.11 = substrate floor edge v5.0.1 + persist v9.0.3 (wheel Requires-Dist metadata fix, #241/#242; Rust source unchanged); 0.4.12 = CEG-driven replication reconciler (consent objects are the topology; API writes CEG, runtime converges; runtime Initiator-add pending CIRISEdge#173); 0.4.13 = edge v5.1.0 runtime peer control → replication reconciler is fully no-restart (consent converges live; CIRISEdge#173 resolved); 0.4.14 = config-as-CEG foundation (config:v1 CEG schema + GraphConfig service + owner-gated /v1/config; 0.5 P1); 0.4.15 = config reconciler + migrated transport/scorer/replication-cadence/mode env→config:* (hot-applied; lens_store_min baked; 0.5 P2); 0.5 = config-as-CEG (graph config — ZERO env vars; ALL config is signed CEG objects, owner-authored, runtime-reconciled, replicated; the fabric IS the config); 0.5.1 = #27 fix — node key_id = fedcode::derive_key_id(label,pubkey) (FSD-003 label-fingerprint; keystore_alias stays raw, no re-key) + the WHEEL py_main now honors --home/--key-id (was run_default → bare label); cohort_scope consts; uuid helper; 0.5.2 = #32 fix — the wheel py_main reads Python sys.argv (not std::env::args, which under the console-script carried the interpreter+script path as a spurious positional → "unknown serve arg"); v0.5.1 wheel was unusable; 0.5.3 = #34 fix — GET /v1/identity reports the derived wire key_id (was the keystore alias; now matches federation_keys + SignedKeyRecord); 0.5.4 = node-side device-authorization grant (RFC 8628; /v1/auth/device/{code,approve,token}) — owner-approves via fed-ID (YubiKey/TPM) self-login, issues a DELEGATED token attributed to the actor (agent) on behalf of the principal (owner); SessionCaller.actor; mirrors ciris-manager-client; 0.5.5 = first-run bootstrap unblocked — fed-ID mint (/v1/self/identity) + self-claim (/v1/setup/claim-remote) OPEN during first-run (no ROOT yet ⇒ no owner session to require; mirrors the agent's require_setup_mode), owner-gated again once claimed; setup/apex routes restricted to LOOPBACK peers (per-route guard; read API still binds 0.0.0.0); + GET /v1/setup/status (first-run signal, ends the client's 404 fast-degrade); + CEG-native node list GET /v1/setup/owned-nodes (projects delegates_to(user→node) owner-bindings via ownership::nodes_owned_by — the list IS the graph, not a client store); claim-remote user-signer resolved at REQUEST time (fed-ID is minted mid-wizard) keyed by a custody-backend marker so TPM/YubiKey/software re-open correctly; self-claim loopback fallback when a local NodeCode has no transport_hint; 0.5.6 = owner login password → device-grant approval prerequisite. The claim-minted ROOT had password_hash:None ⇒ no /v1/auth/login session ⇒ /v1/auth/device/approve was unreachable (the v0.5.4 grant shipped without its approval path). Now /v1/setup/root accepts optional owner_password (threaded through claim-remote on the loopback self-claim) and sets the ROOT cert's password_hash, so the owner gets a SYSTEM_ADMIN session via /v1/auth/login (username = wa_id) → approves the agent's device grant → the agent acts on-behalf (delegated dgrant: token, owner authority + actor attribution; cannot self-amplify). Wizard account password + friendly username now flow into the self-claim; login resolves wa_id | OAuth `<provider>:<external_id>` | human name (store::resolve_login, the fabric port of the agent's multi-key _users cache). 0.5.7 = WAs-need-fed-IDs UPGRADE path (the agent team's 2.9.7 migration). POST /v1/self/upgrade-owner (owner-session-gated + loopback) re-roots an already-owned node on a fed-ID: build_signed_owner_binding(fed-ID → node) + apply_signed_owner_binding (registers the fed-ID as a `user` identity + persists delegates_to(user→node, infra:*)) — the SAME CC 3.2 owner-binding the first-run claim uses, but authorized by the EXISTING owner's session (not first-run/PIN) and applied locally (no setup/root, existing ROOT + password/OAuth login PRESERVED; non-destructive owner-binding model). Client: NodeSwitcherViewModel.upgradeToFedId (mint fed-ID → upgrade) + a ManageNodes "Upgrade this account to a Fed ID" affordance. So an existing password/OAuth-rooted WA becomes fed-ID-rooted; is_owner_bound(node) then resolves to the fed-ID + the node enters the CEG owned-nodes list. 0.5.8 = age-assurance is CEG-native + correctly sequenced. POST /v1/self/age (loopback + owner-session) records the bound owner's self-declared age as a hybrid-SIGNED federation attestation (subject signs with their fed-ID via ownership::emit_signed_attestation — the working put_attestation path; NOT the unsigned local-upsert+attestation_promote path, which is broken on real nodes by CIRISPersist#247 where promote writes scrub_key_id=signer.current_alias() not the derived key_id). Wizard now posts age AFTER the claim (owner fed-ID must exist to sign), not at band-select (which 401'd — the federation /v1/safety/age-assurance route needs an x-ciris sig the app can't produce): claimLocalNodeOwnership → owner login → set age. Filed CIRISPersist#247 (promote alias-FK bug) + #248 (Engine::emit_attestation DX helper). 0.5.9 = Delegations surface — owner lists/approves/revokes who may act on-behalf. GET /v1/auth/device/grants (list LIVE delegated grants) + POST /v1/auth/device/revoke {client_id}, owner-session-gated; over the in-memory device-grant registry (thin — the substrate-native delegation surface / CIRISPersist#104 lands later). Client: a "Delegations" card in the Manage nav group (active list + approve-by-user_code + per-row revoke). The UI for the device-code flow: agent generates a code → owner approves here → agent gets the attributed dgrant token. 0.5.10 = CIRISServer#38 — adopt the CEWP scope-native-privacy substrate triple: verify v6.3.0 + persist v9.2.0 + edge v6.1.0 (from 6.2.0/9.0.3/5.1.0). CC 1.13.3.4 anonymity-by-default below federation, ratified end-to-end (CIRISConformance#19). Pins bumped in the root + the in-tree ciris-lens-core workspace member (both, else dual-version E0308); builds + clippy + tests + runtime (boot→mint→claim→owned) all green with ZERO source changes — the edge/persist surface (PublishOutcome, crypto_tier, scope blobs) is additive. Remaining #38 items (operator dual-statement UX, archive_mode group-creation, cohort_scope audit, docs, bench) are client/docs follow-ups. 0.5.11 = CIRISServer#38 follow-ups (server/docs, unblocked): tools/audit_cohort_scope_callers.py (FSD §3.2 default-flip review aid — lists federation-scope CEG emit sites for explicit operator review; --strict gate) + docs/SCOPE_PRIVACY.md (CC 1.13.3.3 dual-statement operator guide: default anonymity-by-default-below-federation + the GPA residual needing ANONYMOUS_TIER; archive_mode; deployment guidance). The verify-6.6 accord adoption (#41) + the remaining #38 client items (dual-statement on client surfaces, archive_mode group-creation) wait on edge 6.2.0 + persist 9.3.0 (verify-6.6 pin would dual-version against edge 6.1.0/persist 9.2.0). 0.5.12 = CIRISServer#45 — adopt the ciris-persist v9.3.0 CEG-native graph DX surface (+ the substrate cascade). SUBSTRATE: persist v9.2.0→v9.3.0 + edge v6.1.0→v6.2.0 + verify family v6.3.0→v6.6.0. The verify bump is FORCED lockstep, not a choice: persist v9.3.0 transitively pins ciris-verify-core v6.6.0, so the whole verify family (verify-core/keyring/crypto) must ride v6.6.0 or cargo resolves two ciris_verify_core crates with incompatible ThresholdMember/keyring types (6.4.0/6.4.1/6.5.0/6.6.0 are HUMANITY_ACCORD + STH-stack work, orthogonal to this cascade). Pins bumped in BOTH the root + the in-tree ciris-lens-core workspace member. The pin bump surfaced (and #45 fixes) the #247 promote-FK reality: persist v9.3.0's attestation_promote now writes scrub_key_id = engine.local_derived_key_id() = derive_key_id(<alias>,<pubkey>) (the DERIVED wire key_id, never the bare alias) — so a node MUST be registered under its derived id for the promote FK to resolve (prod already does via compose::register_self_key; the safety-test fixture register_node_self was registering the literal NODE_KEY_ID → now registers engine.local_derived_key_id(), mirroring prod). COLLAPSE (Cut B, traversal): is_owner_bound + nodes_owned_by drop their hand-rolled inbound-edge walks (list_attestations_for/by + lookup_public_key + a local delegation_revoked) and consume Engine::owner_bindings_of — the purpose-built reader that folds edge-expiry + the §11.10 withdraws/recants edge-retraction in; the read-time CC 1.13.5 infra-only re-check is dropped as REDUNDANT (persist's CC 4.4.3.4.3 node-agency gate already enforces infra:* at WRITE time). nodes_owned_by reads the recipient from attested_key_id (persist's canonical field) not envelope[node_key_id], so it is correct under either envelope shape; delegation_revoked deleted (~95 LOC net). e2e reachability tests (tests/safety.rs §6) prove owner_bindings_of / owner_binding_chain / reachable_under_scope / active_{community,family}_members are wired through ciris-server's Engine for the consumers that fold on next (mirrors the edge v6.2.0 adoption's active_roster / delegation_reads proofs). KEPT hand-rolled (documented; mirrors the edge team's v6.2.0 keep-and-file discipline) + upstream gaps filed: (a) scorer.rs's capacity emit sets weight=Some(score) which persist trust_scoring/topology read via weight.unwrap_or(1.0) — #248 emit_attestation hard-codes weight:None, so collapsing would silently reweight every capacity row to 1.0 (filed CIRISPersist#252: add optional weight to EmitAttestationInput); (b) peer.rs/graph_config.rs node-self emits sign via engine.sign_hybrid on a with_hardware_signer_hybrid (TPM/SE-custodied) Engine, which exposes no LocalSigner to pass to emit_attestation/owner_bind (filed CIRISPersist#253: Engine::emit_attestation_self over the composed signer); (c) the #247 USER key_id derivation (identity.rs pins the user genesis to the literal <alias>-user; the emit_signed_attestation/emit_owner_binding user-path collapse + the derived-id flip both depend on it) is wire-changing + custody-sensitive: create_federation_identity couples the ML-DSA seal-id == the recorded key_id, so recording the derived id while keeping the seal under the stable keystore alias (no re-open/lockout migration) needs a verify-side split — filed CIRISVerify#89, with a back-compat-shim migration plan for already-claimed nodes. 0.5.13 = device-code act-on-behalf is CEG-native (unblocked by the 0.5.12 substrate). The RFC-8628 handshake (device_code↔user_code, pending/approved/denied) stays in-memory (ephemeral protocol state), but the AUTHORIZATION is now a durable, signed, revocable delegates_to(owner → actor) CEG attestation. On POST /v1/auth/device/approve the node resolves the LOCAL owner's federation signer (resolve_user_signer) and emits delegates_to(owner → actor, [owner:act-on-behalf]) via ownership::emit_signed_attestation — for a hardware-backed owner ID (YubiKey/TPM/SE) the sign_hybrid BLOCKS on insert+touch, so that physical presence IS the consent. (Emit uses the working user-signed path attester=signer.key_id()=the REGISTERED literal — NOT persist's grant_delegation, which derives attester=signer.derived_key_id() and would FK-fail until the deferred #247 user-key migration / CIRISVerify#89.) The minted dgrant: bearer is only an ephemeral session credential — resolve_bearer re-checks reachable_under_scope on EVERY use, so an owner's withdraws kills the bearer immediately (not just at TTL). GET /v1/auth/device/grants lists the LIVE delegates_to edges (the list IS the graph); POST /v1/auth/device/revoke emits a signed withdraws (hardware touch) + drops the bearer. The actor (client_id) MUST be a registered federation identity (the edge attested_key_id FK + the CC 4.4.3.4.3 node-agency gate needs a non-node identity_type for the act-on-behalf scope) → invalid_client otherwise. DeviceGrantState gained owner_key_id + seed_dir (mirrors ClaimRemoteState; compose passes <keystore_alias>-user + user_seed_dir). tests/device_grant.rs rewritten end-to-end (mint owner on disk → approve emits → reachable → token bearer → revoke withdraws → reachable false → bearer dead + list empty; unregistered-actor → invalid_client; RFC-8628 mechanics preserved). 0.5.14 = the FINAL 0.5.x substrate/identity-complete cut (Track A — the cut the agent adopts for 2.9.7 lens-core replacement). SUBSTRATE: persist v9.3.0→v9.4.0 + edge v6.2.1 + verify family v6.6.0→v6.6.1. persist v9.4.0 ships the two emit surfaces filed during the v9.3.0 adoption (CIRISPersist#252 EmitAttestationInput.weight + #253 Engine::emit_attestation_self); verify v6.6.1 (CIRISVerify#89) adds create_federation_identity's seal_alias arg (the #247 user-key-derived enabler). This closes CIRISServer#45 in full. EMIT COLLAPSE: scorer.rs / peer.rs / graph_config.rs node-self emits drop the hand-rolled canonicalize→hash→hybrid-sign→assemble→put recipe for Engine::emit_attestation_self (signs with the engine's OWN composed hardware-hybrid signer; attester/scrub = the node's #247 derived key_id == cfg.key_id — wire-preserving); scorer keeps weight=Some(score) via EmitAttestationInput.weight so the capacity band survives onto the row (trust_scoring reads weight.unwrap_or(1.0)). #247 USER-KEY: identity.rs mint_user_identity now RECORDS the user under the FSD-003 derived key_id derive_key_id(<alias>,<ed_pub>) (same scheme as the node) while passing seal_alias=<alias> so create_federation_identity seals the ML-DSA half + the Ed25519 seed under the stable keystore alias — re-open by alias reproduces it (NO custody migration / NO lockout). hardware_user_local_signer builds the user LocalSigner with key_id = the derived id (opening blobs by the alias), so EVERY downstream signer.key_id() (owner-binding attester, age subject, device-grant owner id) is the correct registered wire id with no other call-site changes. device_grant list/revoke fixed to scan the graph under the owner's derived id (resolve the signer → key_id(), not the alias) — surfaced + fixed by this migration. TEST FIXTURES: every node-self-emit fixture now registers under engine.local_derived_key_id() + threads the derived id (capacity_scorer/config_reconcile/federation_admin/graph_config/peer_replication/replication_reconcile/device_grant); identity unit tests assert the derived-id roundtrip. Full suite green (20/20), clippy + fmt clean. NOTE: the user's wire/federation key_id changes from the literal <alias>-user to the derived <alias>-user-<fp> — fresh mints are clean; an already-claimed pre-0.5.14 node would re-emit its owner-binding under the derived id on re-claim (pre-1.0, the KEY itself is not re-keyed thanks to seal_alias). 0.5.15 = CIRISServer#41 PART 1 — the HUMANITY_ACCORD server surface (the SAFE-MESH FLOOR). New src/accord.rs: (1) POST /v1/accord/holder (owner-gated) admits a holder's self-signed accord_holder SignedKeyRecord through the canonical register_federation_key gate — which ENFORCES hardware attestation_evidence (persist refuses SoftwareOnly: a software-custodied holder cannot wield the kill-switch); (2) GET /v1/accord-holders, the cold-start recognition roster (list_keys_by_identity_type, no TOFU); (3) POST /v1/accord/verify-invocation, the AUTHORITATIVE server-side 2-of-3 verification of a HUMANITY_ACCORD invocation (verify_invocation over the registered holder set + InvocationDedup anti-replay) — the operational kill-switch (CC 4.2.1 / §9.2.1). Consumes verify v6.6.x humanity_accord/threshold + persist v9.4.0 accord_holder rows. tests/accord.rs: register 3 hardware-attested holders → roster → 2/3 verifies, 1/3 fails (quorum), replay rejected (dedup); missing-attestation holder REFUSED (custody floor); non-owner register 401/403. STILL PENDING (the rest of #41, gated): the portable high-secure key mode (FIPS YubiKey + USB-held ML-DSA, both-keys+PIN+touch) the accord keys MUST be held under — filed CIRISVerify#91 — plus the guided multi-party genesis ceremony + family-mgmt UX. WHY 0.5.X HOLDS: cutting 0.6 (+registry) bakes CANONICAL_BOOTSTRAP_PEERS + bootstraps the canonical mesh; that MUST NOT happen before the accord kill-switch is enforceable AND its keys are under genuine 2-factor distributed-human custody (#91). So the project stays on 0.5.X (patch-forward) until the safe-mesh floor is complete. 0.5.16 = substrate floor bump to persist v9.4.1 + edge v6.2.2 + verify family v6.7.1 (the safe-mesh-floor verify deps land). persist 9.4.0→9.4.1 (verify-family re-pin, no persist code change) + edge 6.2.1→6.2.2 (lockstep) + verify 6.6.1→6.7.1 (ADDITIVE accord stack). v6.7.1 ships exactly what the rest of CIRISServer#41 was gated on: ciris-keyring usb_wrapped_mldsa65 + hw_token (resolve_hardware_class / FIPS classes) = the PORTABLE HIGH-SECURE KEY MODE (resolves CIRISVerify#91 — FIPS YubiKey + USB-held ML-DSA, both-keys+PIN+touch); accord_custody_attestation (produce/verify_accord_custody_attestation, verify_yubikey_piv_attestation) = the holder custody attestation that FEEDS the attestation_evidence the v0.5.15 accord-holder gate already enforces; and accord_genesis (produce_accord_holder_record, build_accord_family_envelope, co_sign/assemble_accord_family_genesis, build/co_sign/concur_accord_invocation, accord_invocation_status) = the multi-party genesis ceremony + invocation-concurrence producer. Pins bumped in root + ciris-lens-core; single-version resolve; additive (zero source changes, full suite green). NOT CONSUMED YET — the consuming PRs (portable-key-mode holder provisioning + custody attestation; the genesis ceremony orchestration; the invocation-concurrence flow + client UI) follow on this foundation. Still on 0.5.X: the safe-mesh floor is now BUILDABLE end-to-end but not yet COMPLETE; no 0.6 (+registry / mesh bootstrap) until it is. 0.5.17 = CIRISServer#41 PART 2 — the accord GENESIS CEREMONY + invocation CONCURRENCE (consuming verify v6.7.1 accord_genesis). src/accord.rs adds: POST /v1/accord/genesis/envelope (build the canonical accord_family envelope holders co-sign) + POST /v1/accord/genesis/assemble (owner-gated; assemble_accord_family_genesis runs the 2-of-3 distinct-founder quorum fail-closed, then durably RECORDS the verified accord_family_genesis as a node-authored CEG attestation — the accord family is FOUNDER-signed with no family keypair, so it is NOT stored in federation_families whose family_key_id FKs to federation_keys; the signed genesis object IS the record) + GET /v1/accord/family (projects the entrenched quorum:2/3 family). Invocation concurrence: POST /v1/accord/invocation (open a pending invocation with the initiator cosignature) + POST /v1/accord/invocation/concur (append a concurring holder cosignature, advancing toward 2/3) + GET /v1/accord/invocations (pending + advisory status; verify-invocation stays authoritative against federation_keys). tests/accord.rs (5): the holder-registry/kill-switch trio + genesis_ceremony_assembles_and_entrenches_the_family (3 holders → envelope → 2/3 co-sign → assemble+record → GET family shows 3 entrenched) + invocation_concurrence_advances_to_quorum (1/3 sub-quorum → concur → 2/3 met → listed). REMAINING #41: the holder-device portable-custody provisioning tool (UsbWrappedMlDsa65Signer + produce_accord_custody_attestation; real YubiKey token open blocked on CIRISVerify#62 get_token_signer stub) + the KMP ceremony/concurrence client UI (built in parallel, integrating). Still 0.5.X until the safe-mesh floor is COMPLETE. 0.5.18 = CIRISServer#41 PART 3 — the portable high-secure accord-holder PROVISIONING tool (src/accord_custody.rs), consuming verify v6.7.1 CIRISVerify#91 (resolved). provision_portable_holder wires UsbWrappedMlDsa65Signer::provision (ML-DSA-65 AEAD-wrapped to a USB key, unwrappable only by the YubiKey via touch+PIN) + HardwareRootedIdentity (Ed25519 in a FIPS YubiKey + the wrapped ML-DSA) + produce_accord_holder_record (the self-signed accord_holder record to register via POST /v1/accord/holder) + produce_accord_custody_attestation (the portable_2fa FIPS PIV-chain custody proof). HOLDER-DEVICE op (a library fn, not a server endpoint): the caller supplies the YubiKey Ed25519 HardwareSigner — real FIPS YubiKey token open is blocked on CIRISVerify#62 (get_token_signer stubbed NotSupported), so the wiring is exercised today with a software Ed25519 stand-in + lands on real hardware once #62 ships. Test: provision → re-open the USB-wrapped ML-DSA roundtrips (software stand-in). With this, the safe-mesh-floor SERVER surface is complete: holder registry + 2/3 kill-switch (0.5.15) + genesis ceremony + concurrence (0.5.17) + portable-custody provisioning (this) + the KMP Accord client UI. Remaining before 0.6: CIRISVerify#62 (real YubiKey token), the operational genesis CEREMONY run, then bake CANONICAL_BOOTSTRAP_PEERS. 0.5.19 = CIRISServer#41 — the accord-holder CUSTODY GATE wired (the SAFE-MESH FLOOR pin). POST /v1/accord/holder accepts an optional custody_attestation (the holder portable_2fa YubiKey PIV chain 9c→f9→…intermediates…→Yubico Attestation Root 1) and verifies it via verify_accord_custody_attestation against the PINNED DURABLE ROOT — Yubico Attestation Root 1 (developers.yubico.com/PKI/yubico-ca-1.pem, embedded src/accord_pki/yubico_attestation_root_1.der) — plus the FIPS-certified+touch-always floor + attested-key==holder bind, BEFORE admitting. Pin the DURABLE root, NOT the rotating "Yubico PIV Attestation B 1"; f9+intermediates ride in the holder attestation chain. CIRISVerify#91+#62 closed+validated on a real YubiKey 5 FIPS (fw 5.7.4; ciris_keyring::pkcs11 cryptoki live). test: non-chaining custody refused before registration. REMAINING for the floor: the foolproof holder-provisioning UI (accord_custody::provision_portable_holder; select ML-DSA USB path on an already-FIPS-approved key) + the operational genesis ceremony RUN. Still 0.5.X. 0.5.20 = CIRISServer#41 — the OPERATIONAL HALT (the kill-switch made ENFORCEABLE, not just verifiable; CC 4.2.1/4.2.3/§9.2.1). NEW POST /v1/accord/message: a node receiving an authentic accord-holder-signed message (1) replicates it to all known peers (concurrence-seeking gossip, loop-stopped by a seen-set); (2) for a verified 2-of-3 CONSTITUTIONAL quorum (the global halt) replicates to ALL peers FIRST, then latches a disk halt (src/accord_halt.rs writes HUMANITY_ACCORD_HALT under home) and terminates the process fail-secure (exit 42); (3) notify/drill flow the SAME replicate+surface path but NEVER halt (EAS-style drill of the delivery path). create_invocation/concur share the replicate+halt path so a concurring cosignature reaching 2/3 also halts. STARTUP GATE: compose.rs check_halt_gate refuses to boot while the latch exists — "not a recoverable pause", cleared only by manual latch removal; no operator/steward/WA restart overrides it. router_with_halt wires home + bootstrap_peers + exit_on_halt. tests: 2/3 CONSTITUTIONAL latches+gates startup; a 2/3 DRILL surfaces but does NOT halt; unregistered-holder message dropped (401); accord_halt gate unit test. Still 0.5.X. 0.5.21 = CIRISServer#41 — the FOOLPROOF holder-provisioning flow (the last safe-mesh floor code piece). NEW POST /v1/accord/provision-holder (src/accord_provision.rs, LOOPBACK-only, pkcs11-feature-gated): opens the holder already-FIPS-approved YubiKey via the existing ciris_keyring pkcs11 cryptoki path (identity.rs open_yubikey_ed25519_signer), shells ykman for the PIV attestation chain (9c attest + f9 device cert), and drives accord_custody::provision_portable_holder with the holder-chosen ML-DSA USB path → returns {key_id, holder_record, custody_attestation} (the holder then POSTs those to the owner-gated /v1/accord/holder custody gate). Without the pkcs11 feature → 501 NotSupported. Guided KMP desktop ProvisionAccordHolderScreen (3 steps; centerpiece = SELECT THE ML-DSA USB PATH; key assumed already FIPS-approved) + ProvisionAccordHolderViewModel + CIRISApiClient.provisionAccordHolder + nav (MANAGE group) + en-only localization (needs localize-ui fan-out for the other 28 langs). App does NO crypto. Hardware-real parts (token open, ykman chain, provision wiring) need a real YubiKey 5 FIPS to validate end-to-end at the ceremony. Still 0.5.X. 0.5.22 = CIRISServer#41 — DECOUPLE family from accord + FIX the kill-switch roster (the self-quorum hole). NEW src/family.rs: generic CEWP family ops over persist family CEG DX (create_family/add_member/active_members/revoke_member/swap_member/active_threshold_roster over put_family + add_family_member + active_family_members + put_family_membership_revocation) — NOT accord-aware. accord.rs now treats HUMANITY_ACCORD as a first-class persist family: the kill-switch roster = accord_roster() = family::active_threshold_roster("humanity-accord") (the LIVE family SEATS), NOT list_keys_by_identity_type(accord_holder) (every row). This CLOSES the self-quorum hole: a vaulted cold-spare is a registered accord_holder identity but NOT a family member, so it is never a seat — one human cannot self-satisfy 2-of-3 with their primary+spare. genesis/assemble now entrenches a real persist family: registers a CEREMONIAL family anchor key humanity-accord (fresh hybrid keypair, self-signed identity_type=family, PRIVATE HALF DISCARDED — it never signs; minted on a dedicated 16MiB-stack thread because ML-DSA keygen/sign overflows the async worker stack, which would ALSO crash prod genesis) for the federation_families FK, then put_family(members=founders, quorum:2/3, entrenched); the 2/3-founder-signed accord_family_genesis CEG attestation is kept as the signed AUTHORIZATION proof. get_family + list_holders read the persist family (holders=authoritative seats; registered=all identities incl spares). Recovery swap mechanism = family::swap_member (revoke primary + add spare; same-size roster); the accord recovery ENDPOINT (2/3-authorized) is a follow-up pending a verify-blessed swap-signing payload. tests: 11 — verify/halt/concur now establish a family first; +registered_spare_is_not_a_seat_and_cannot_help_reach_quorum (the self-quorum hole closed). Still 0.5.X. 0.5.23 = CIRISServer#41 — DESKTOP QA RUNNER (software-key end-to-end, `cargo run --example qa_runner`). examples/qa_runner: two REUSABLE modules mirroring the production decoupling — family (generic ciris_server::family ops: create→add→live-roster→remove→swap→threshold-roster) + accord (the kill-switch HTTP lifecycle: register holders→genesis/entrench family→roster=seats w/ spare-not-a-seat→invocation open/concur→2/3 verify→self-quorum REFUSED→2/3 CONSTITUTIONAL halt latched + startup gated). Boots an in-process engine with SOFTWARE hybrid signers (ed25519-dalek + ciris_keyring ML-DSA-65) so the WHOLE family+accord flow is proven before real YubiKeys are plugged in. 18 steps, all green; exits non-zero on any failure. Validates the v0.5.22 family-roster model end-to-end (spare registered but not a seat → cannot reach quorum). Still 0.5.X. 0.5.24 = CIRISServer#41 — FSD/ROSTERED_GROUP_KEY_OPS.md (the key-ops coverage spec) + the upstream asks. Establishes that self/family/community are the three persist-rostered groups on a visibility gradient (affiliations/species/biosphere/federation are audience tiers, NOT rostered); the accord = an entrenched family + kill-switch; the roster lifecycle is GENERIC to any cohort. Catalogs every key/membership op (holder-key lifecycle A1-A6, roster/membership B1-B6, spare/custody C1-C4, invocation/governance D1-D4) mapped to NIST SP 800-57 lifecycle + ICANN DNSSEC KSK ceremony + the CEG runbook, with authorization matrix (owner-gated custody vs 2/3-quorum governance) + status. The ⚠️/❌ ops collapse to supersede (buildable now) / reconstitute / reactivate. Filed the gaps: CIRISPersist#249 comment (the rostered-group WRITE/governance surface — uniform cohort dispatch, supersede_group, FINISH the deferred quorum-authorized membership gate, active_member_keys, atomic swap, forward-secrecy on remove, versioning, event hook, self+affiliations coverage Q) + CIRISVerify#95 (lifecycle InvocationKind for reactivation + a blessed membership-change/supersede builder+verifier). Docs only. Still 0.5.X. 0.5.25 = SUBSTRATE FLOOR for the rostered-ops DX — persist v9.4.1→v9.9.0 + verify family v6.7.1→v6.9.0 + edge v6.2.2→v6.2.3 (the v6.2.3 quartet; CIRISEdge#183). Lands what we filed: persist G1–G4 rostered-ops DX (uniform cohort read/write, supersede + versioning, the quorum-authorized membership gate with one-seat + M-of-N invariants enforced IN THE SUBSTRATE, rekey-on-revoke + change-events — CIRISPersist#249) + verify verify_membership_change (CIRISVerify#95). HUMANITY_ACCORD mesh genesis is unblocked at persist>=9.9.0. ADDITIVE: pins bumped in root + crates/ciris-lens-core; ZERO source changes; full suite green (lib 82, accord 11, all integration suites, qa_runner 18/18), default + pkcs11 + clippy -D warnings + fmt clean. The new surfaces are not consumed yet — the supersede/reconstitute/reactivate endpoints (now unblocked) are the next adoption cut. Still 0.5.X. 0.5.26 = CIRISServer#41/#63/#64 — accord MEMBERSHIP-CHANGE ops (supersede / reconstitute) on the persist 9.9.0 rostered-ops governance gate. NEW POST /v1/accord/family/change/envelope (owner-gated; build_membership_change_envelope → the canonical jcs payload the CURRENT roster cosigns, returned + the exact signing bytes) + POST /v1/accord/family/supersede (owner-gated submission, 2/3-authorized: supersede_family_with_quorum — persist re-verifies ≥M prior-roster hybrid cosigs via verify v6.9.0 verify_membership_change + the supersedes ANTI-REPLAY binding + ONE-SEAT key-distinctness IN THE SUBSTRATE, then re-baselines as a new version) + GET /v1/accord/family/history (the supersede audit chain). ONE primitive = replace-a-seat / recover-from-spare / expand / shrink (+ the forced threshold change: 3→5 ⇒ quorum:2/3→3/5). accord_roster + family::active_threshold_roster now ride persist active_member_keys(Cohort::Family) (substrate-native, #63 — drops the hand-rolled per-member lookup). tests: family_supersede_replaces_a_seat_under_2of3_and_rejects_sub_quorum (12 accord); qa_runner +6 membership steps (24/24: supersede a→d, reconstitute 3→5→quorum:3/5, 1-sig REJECTED by the substrate gate=409, history chain). FEATURE AUDIT: edge transport-http/reticulum + codec-fountain, persist sqlite/postgres/extract/cirislens_wa_cert/service_token_revocation, verify software/pqc-ml-dsa(+tpm/android/pkcs11-gated) — all correct + complete for the accord/family/membership surface; codec-fountain on (the holonomic/#11 swarm wiring is code activation, not a feature). reactivate (lifecycle:active) still pending CIRISVerify#95 Gap 1 (no lifecycle InvocationKind yet). Still 0.5.X. 0.5.27 = substrate-bypass-audit cleanups #31/#30/#29. #31 (P1, admission-gate hole): SignedOwnerBinding gains reg_envelope_{ed25519,ml_dsa_65}_sig_b64 (Option, the user hybrid PoP over the {key_id} registration envelope, ceg_produce_canonicalize); build_signed_owner_binding now also signs the registration envelope with the user signer; register_user_key routes through the AUTHORITATIVE Engine::register_federation_key gate (which RE-VERIFIES the scrub sig over the reg envelope → a verifiable row) when the sigs are present, falling back to put_public_key only for legacy bindings — closes the un-verifiable-user-row bypass. #30: CLOSED as already-resolved (the hand-rolled delegation_revoked was collapsed onto Engine::owner_bindings_of in #45/v0.5.12, which folds §11.10 withdraws/recants precedence — re-grant-after-withdraw reads correctly). #29: NEW nodecode↔fedcode cross-fidelity test (pins ciris-server NodeCode codec against verify fedcode, the reference codec — not just the agent Python port) + auth/bootstrap.rs NodeCode-pin decode routed through ciris_verify_core::fedcode::decode (v1 round-trips; emit stays v1 — v2 emit is a deliberate future bump). Full suite green (22 suites), qa_runner 24/24, clippy+fmt clean. Still 0.5.X. 0.5.28 = qa_runner full genesis CEREMONY scenario (the reproducible-mesh reference the guided wizard mirrors). accord::run_ceremony: 3 humans × {primary, spare} = 6 software accord_holder keys registered A1→A2→B1→B2→C1→C2; genesis assembled over the 3 PRIMARIES (family SEATS, quorum:2/3); asserts 3 seats = the primaries, 6 registered (3 seats + 3 vaulted spares), spares registered-but-NOT-seated, signed genesis emitted (the bake artifact for the cold-start recognition root, CIRISVerify#107). qa_runner 36/36. Operationally separates the canonical TRIO (nodes) from the accord HOLDERS (humans). Still 0.5.X. 0.5.29 = CIRISServer#41 — the guided GENESIS CEREMONY wizard (foolproof, reproducible mesh kill-switch setup). NEW POST /v1/accord/family/cosign (src/accord_provision.rs, LOOPBACK + pkcs11-gated): re-opens a primary holder YubiKey (open_yubikey_ed25519_signer) + the USB-wrapped ML-DSA (UsbWrappedMlDsa65Signer::open) -> HardwareRootedIdentity -> co_sign_accord_family(envelope) (touch=consent) -> returns the cosignature + the founder member together (assemble needs both signatures + founders). 501 without pkcs11; 6/6 tests. KMP AccordCeremonyScreen (under the Accord screen, shown ONLY when no family registered): intro '6 FIPS YubiKeys + 6 USB keys + 3 humans' + the 2-of-3 HUMAN kill-switch explainer (explicitly NOT node/mesh setup; the canonical-trio vs accord-holders distinction made operator-visible) -> provision A1->A2->B1->B2->C1->C2 (primaries=SEAT, spares=VAULT) -> cosign (3 primaries re-insert; assemble at >=2) -> done with the genesis surfaced as the SAVE-THIS bake artifact (CIRISVerify#107). +37 en localization keys (needs localize-ui fan-out). App does NO crypto. HW-real (token open / USB re-open / bound cosign / assemble) validates at the ceremony. default + pkcs11 builds + clippy + fmt + KMP desktop compile all green.; 0.5.30 = the v6.3.0 substrate UNLOCK (edge v6.3.0 / persist v9.10.0 / verify family v6.11.0) wired through: (a) #11 HOLONOMIC — CIRISEdge FountainSwarmRuntime installed (publisher = Engine::list_held_fountain_content; converger fed by edge's FountainHoldingClaim dispatch; two persist evict adapters), guarded on caps.lens_store, honest activation (no synthetic claims); (b) accord REACTIVATE — the constitutional way back from a halt (CC 4.2.1 §69): `ciris-server accord reactivate --proof` clears the disk latch ONLY on a verify-native accord:lifecycle:active proof (InvocationKind::LifecycleActive, CIRISVerify#95) meeting BOTH the current M-of-N quorum (M from the family's own consensus_protocol) AND the ORIGINAL-MESH FLOOR (>=1 signer from the genesis/version-1 roster) — a rotated/captured roster cannot resurrect a node the founding humanity halted; halt-gate message now points to reactivate as conformant, demotes rm to break-glass. default + pkcs11 + clippy + fmt + 22 suites green; (c) cold-start GENESIS RECOGNITION — accord_roster (and GET /v1/accord-holders) falls back to the BAKED humanity_accord_genesis() (CIRISVerify#107) resolved against the node's PINNED accord_holder keys when no persist family is entrenched (no-TOFU, never from a peer; fail-closed; inert until verify bakes the genesis).; 0.5.31 = safe-mesh red-team REMEDIATION (FSD/SAFE_MESH.md). A 4-agent adversarial review refuted the "v0.5.30 is the floor" claim; I6/I7/I8 held, I1/I2/I3/I5 had real gaps — all fixed + re-verified: B1 (custody bypass — custody_attestation now MANDATORY at /v1/accord/holder + peer::register_peer_key refuses accord_holder + genesis_assemble requires every seat be a registered accord_holder, so seat=>accord_holder=>FIPS custody); B3 (quorum-completing halt now gossips — seen-set keyed on is_global_halt); B4 (halt aborts, never clean-exits, without a durable latch — no un-gated resurrect); N1 (halt threshold derives M from the entrenched consensus_protocol, not a hard-coded 2); N2 (assert_distinct_roster at the verifier). B2 (reactivate/halt-clear rooted in operator-writable local state) MITIGATED — original-genesis check anchored to the PINNED humanity_accord_genesis() when baked + rm de-advertised; residual (current-roster + tamper-evident latch + unbaked-genesis fallback) folds into G2 (the verify genesis bake). accord 14/14, qa 36/36, suite 22/22.; 0.5.32 = desktop node-client + accord-ceremony fixes (found while running the first real genesis ceremony). SERVER HEALTH: new src/health.rs serves the node's OWN liveness (/health, /v1/health, /v1/system/health) — mandatory base health the client checks; the agent INHERITS /v1/system/health + enriches it with optional cognitive health (client now reports CONNECTED on SERVER status:ok, not on a required cognitive_state). PKCS11 IN DEFAULT: default=["pkcs11"] so the published wheel/binary carry the YubiKey path; release-safe per-target (cryptoki is linux/windows-only in keyring) — full cross-platform parity is a follow-up pending a CIRISVerify keyring change. SETUP WIZARD: /v1/setup/status now returns the {data:{…}} envelope the shared client expects (was bare → "null data"); getSelfKeyRecord maps the canonical NESTED {record:{key_id}} persist shape; the 2FA toggle routes the mint to backend=pkcs11; probe no longer mistakes the NODE steward key for the USER fed-ID (always mints a distinct user identity via the ladder pkcs11-if-2FA → HW[TPM/SE/keystore] → SW; verify resolves custody). FIRST-RUN CLAIM: the desktop reads the node's <home>/claim_pin file when stdout capture missed it (same-machine, first-run op-level access), routes first-run → claim-remote (never upgrade-owner), and the server DELETES the claim_pin file on a successful claim (one-time secret). ACCORD PROVISION: provision-holder now logs server-side (was silent — failures only showed client-side) + a clearer error (when the slot key exists, ykcs11 needs a CERTIFICATE in the slot to enumerate it). KNOWN follow-ups (not in this cut): owned-nodes client list-refresh after claim, wizard auto-generates the slot cert, pkcs11 cross-platform parity (verify keyring), login-response shape.; 0.5.33 = accord-ceremony YubiKey UX (found running the genesis ceremony). NEW GET /v1/accord/yubikey-status (loopback; shells `ykman piv info`, no cryptoki) reports detected / FIPS-approved / slot-9C key+cert / PIN+PUK tries → the ceremony UI shows a "YUBI DETECTED — FIPS COMPLIANT — 9C PROVISIONED — READY TO PROCEED" banner AUTO-FIXES the "9C key present but NO certificate" case — provision-holder generates the self-signed slot cert itself (using the PIN; ykcs11 then enumerates the key), no manual ykman step; the banner is red + a precise hint when the 9C key is present but has NO certificate — the ykcs11-can't-enumerate case). CLIENT: the PIN entry is now masked (PasswordVisualTransformation) on all 3 accord PIN fields; a prominent "👆 Touch your YubiKey now" prompt shows while a provision/cosign is in-flight (the token blocks on a physical touch); YubiKeyStatus model + getYubiKeyStatus + the banner wired into AccordCeremonyScreen (refresh on entry + Re-check).; 0.5.34 = the owner fed-ID is BOUND TO THE LOGIN (session gate). resolve_user_signer (the one path that re-opens the responsible-user/owner fed-ID signer) is now the ENFORCED CHOKE POINT: it takes a FedIdUse authority — OwnerSession (the caller proved a live owner session via require_owner → SystemAdmin+FullAccess) or FirstRunBootstrap (no owner yet; the fed-ID is minted+used to CREATE the owner) — and RE-VERIFIES is_first_run for the bootstrap arm, so the fed-ID can never be wielded on an already-owned node without a login (defense-in-depth even if a future caller forgot its gate). Threaded through all 4 callers (claim-remote = bootstrap-or-owner; upgrade-owner / self-age / device-grant approve = owner-session). Per the audit the per-endpoint owner gate already existed; this makes it un-bypassable at the function. OAuth uses the same gate (a live/valid owner session) — no password-wrap (chosen over key-binding for one consistent model; password-derived at-rest wrap remains a later defense-in-depth option). claim_remote 3/3, ownership 7/7, device_grant 10/10, clippy clean. Still 0.5.X. 0.5.35 = SUBSTRATE FLOOR bump to verify family v7.2.0 + persist v9.11.0 + edge v6.4.0 (the verify v6→v7 MAJOR — additive, no breakage) + the #268 ENTRENCHMENT UNBLOCK. v7.0 hash-commits the ML-DSA-65 pubkey inside the custody attestation (preimage stays under the EdDSA single-shot ceiling); v7.1 custody→persist BRIDGE (custody_attestation_to_platform_attestation → PlatformAttestation::ExternalSecureElement) — register_holder now packages the VERIFIED custody attestation into persist's {platform_attestation, nonce_captured_at} AttestationEvidence shape, the EXACT shape HardwareAttestationPolicy::check deserializes, with ExternalSecureElement now an accepted accord_holder hardware type (CIRISPersist#268) → the captured FIPS-YubiKey holders ADMIT and genesis ENTRENCHES (the old hand-rolled {verified,hardware_class,…} JSON did NOT match the gate — that mismatch WAS the #268 blocker); v7.2 BAKES the HUMANITY_ACCORD genesis recognition root (humanity_accord_genesis() is now Some — our 2026-06-23 ceremony genesis, quorum:2/3, 3 seats), so `accord reactivate` anchors the original-mesh floor to the PINNED baked genesis (the kill-switch is constitutionally real now, not an operator-writable fallback). NEW release-gate QA suite (tests/release_gates.rs, one module per countdown stage verify7→persist10→0.6): software-key gate tests that stay RED until each requisite clears — Stage 1 (substrate pins / baked kill-switch / 2-of-3 roster / persist accepts ExternalSecureElement / admission-evidence admitted) + Stage 3 (software delegate→claim→dgrant resolves with owner authority + actor attribution) are GREEN; Stages 2/4/5/6/7/8 red-by-design (node-upgrade /health probe, scores evidence, Node-A nodecode+PR, persist-v10 pin+bake, agent-adoption, registry-present). ADDITIVE: pins in root + crates/ciris-lens-core; ZERO regressions (lib 90, accord 14, device_grant 7, ownership 10, root_bootstrap 13, safety 11 + every integration suite green). 0.5.36 = the RNS-NATIVE cut — adopt CIRISEdge v7.0.0 + CIRISPersist v10.0.0 (leviculum/reticulum-core v0.7.0). EDGE v7.0.0 lands CIRISEdge#191 (B2): the IP/TCP Reticulum transport now registers via Destination::with_explicit_hash(reticulum_destination_for_pubkey(fed_pubkey)) — N1 "addressing IS identity" is load-bearing on BOTH transports (was packet-radio only), so the NODE CODE (federation Ed25519) determines the routable RNS destination, no DNS in the addressing path (intentional wire-break vs Python-RNS interop); + AnnounceControl (ScopePrivacyAnnouncePolicy) + 4 collapsed surfaces. ADOPTION (src/holonomic.rs): drop the FountainTierEvict + FountainEvictHardDelete shims (+ parse_tier + its test) — persist v10's FederationDirectory carries evict_fountain_content_to_tier + _hard_delete DIRECTLY, so FountainSwarmRuntime::start now takes the engine's Arc<dyn FederationDirectory> (same shape as ReplicationRuntime); FountainHoldingsSource kept. Pins bumped root + crates/ciris-lens-core (persist version 9→10, edge 6→7). Gate-suite floor → verify7.2/persist10/edge7.0; Stage-2 node target → 0.5.36. A2/A3 (reachable_under_scope_with_reasons login walk, persist ceg_produce_canonicalize) additive — deferred, not blocking. ZERO regressions (lib 89, accord 14, device_grant 7, peer_replication/replication_reconcile/safety green; fmt + clippy clean). The node-code+PIN, all-RNS claim model now has its foundation: node code → routable destination. Still 0.5.X. 0.5.37 = RELAX the first-run ROOT-claim loopback guard + a `ciris-server claim` CLI (remote/delegated claiming — the "node code + PIN" model). /v1/setup/root is no longer loopback-bound: it is gated by the one-time claim PIN (itself a host-access 0600 secret on the node) PLUS the hybrid-signed owner-binding the claim carries (the owner is cryptographically fixed to the claimer's fed-ID); the operator's firewall is the network-exposure control. The no-PIN setup READS (/v1/setup/status, /v1/setup/owned-nodes) KEEP their loopback layer — moved INSIDE bootstrap::router (compose drops the blanket layer). So a remote/delegated claim succeeds against a node's PUBLIC read-API with no SSH tunnel. NEW `ciris-server claim --home <h> --key-id <alias> --backend tpm|yubikey|software --node-code <CIRIS-V1-...> --claim-pin <PIN> --target-url <node read-API> [--cohort-scope self] [--owner-password/username]` — opens YOUR local user fed-ID (the SAME <keystore_alias>-user alias/path the node resolves) + builds+hybrid-signs delegates_to(you->node, infra:*) + POSTs the 1-phase claim via claim_remote::claim_remote. The local client that claims a node with just its NodeCode + PIN. root_bootstrap 13/13, claim_remote 3/3, lib 89 green; fmt+clippy clean. Still 0.5.X. 0.5.38 = SELF-OCCURRENCE enrollment — add/manage a SECOND device as an occurrence of your self (laptop-loss resilience; CIRISServer#76). NEW src/auth/occurrence.rs: POST /v1/self/occurrence (ADD a device — hybrid-signed by your LIVE primary occurrence via verify::verify_request + signer_acts_for; admits the new device's key through register_federation_key, writes put_identity_occurrence, cascades the Self-DEK via rekey_self_occurrence_add), POST /v1/self/occurrence/revoke (a SURVIVING occurrence revokes a lost/stolen device → put_identity_occurrence_revocation), GET /v1/self/occurrences (the device roster; unauthenticated read, same posture as self-key-record). The SIGNATURE is the gate (no loopback), so a remote/new device enrolls with no tunnel; after enrollment the new device passes signer_acts_for → it IS the self (self-login, consent, delegations, owner-of-record for claimed nodes). The clean single-purpose surface — self_login was the only prior path, shaped as a paired app+agent co-admit. CLIENT: a cross-platform Identity Management page (commonMain) — the device roster + 'Add a device' (paste/scan the new device's fedcode) + 'Log in as yourself on another device' (mint a local fed-ID key → render its fedcode + QR) + revoke; the node signs the federation request on the user's behalf (no keys in Kotlin). Rides into the wheel CIRISAgent 2.9.7 ships on the phone, so the phone enrolls as the backup occurrence. STILL missing (tracked in #76): occurrence-based owner-binding re-key/supersede after a laptop loss (ownership SURVIVES + reads recognize the occurrence; re-binding under the survivor needs an endpoint). occurrence 2/2, clippy + fmt clean, client compiles. Still 0.5.X. 0.6 = +registry (~2.9.8/9); 1.0 = +node (~2.9.10). Patch forward on breakage.
|
|
4
|
+
edition = "2021"
|
|
5
|
+
# MSRV floor is set by the substrate: ciris-verify v5.2.0 requires 1.86
|
|
6
|
+
# (persist v6.0.1 is 1.83). Build with the higher of the two.
|
|
7
|
+
rust-version = "1.86"
|
|
8
|
+
authors = ["Eric Moore <eric@ciris.ai>"]
|
|
9
|
+
description = "The fabric node — the federation's headless cohabitation runtime (registry + lens [+ node] over one shared substrate). agent = fabric node + brain. Shipped as both the ciris-server binary and a PyO3 abi3 wheel CIRISAgent consumes. See MISSION.md."
|
|
10
|
+
license = "AGPL-3.0-or-later"
|
|
11
|
+
repository = "https://github.com/CIRISAI/CIRISServer"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
publish = false
|
|
14
|
+
|
|
15
|
+
# CIRISServer is ONE cohabitation composition in TWO shapes (MISSION.md §1.2/§6):
|
|
16
|
+
# - [lib] cdylib → the PyO3 abi3 wheel CIRISAgent pip-installs (the agent is
|
|
17
|
+
# pure Python; it consumes ciris-server, not the cores).
|
|
18
|
+
# - [lib] rlib → so the ciris-server binary links the same composition.
|
|
19
|
+
# - [[bin]] → the headless fabric node deployment.
|
|
20
|
+
# The composition lives in src/lib.rs; src/main.rs is a thin entry point.
|
|
21
|
+
[workspace]
|
|
22
|
+
# lens-core is absorbed in-tree (CIRISLensCore repo retired); the root package
|
|
23
|
+
# composes it as a path dep. node-core folds in here the same way at Server 1.0.
|
|
24
|
+
members = ["crates/ciris-lens-core"]
|
|
25
|
+
resolver = "2"
|
|
26
|
+
|
|
27
|
+
[lib]
|
|
28
|
+
name = "ciris_server"
|
|
29
|
+
crate-type = ["cdylib", "rlib"]
|
|
30
|
+
path = "src/lib.rs"
|
|
31
|
+
|
|
32
|
+
[[bin]]
|
|
33
|
+
name = "ciris-server"
|
|
34
|
+
path = "src/main.rs"
|
|
35
|
+
|
|
36
|
+
[features]
|
|
37
|
+
# pkcs11 (the YubiKey / PKCS#11-PIV custody backend) ships in DEFAULT so the
|
|
38
|
+
# published wheel + the `ciris-server` binary carry the hardware fed-ID + accord
|
|
39
|
+
# custody path out of the box (no special build). `python`/`extension-module` are
|
|
40
|
+
# deliberately NOT default — the binary must never link libpython; maturin turns
|
|
41
|
+
# them on for the wheel (pyproject [tool.maturin]). TPM/postgres hardware backends
|
|
42
|
+
# are auto-on per-target on Linux (see the [target.*] tables below).
|
|
43
|
+
default = ["pkcs11"]
|
|
44
|
+
# `python` pulls the PyO3 bindings (for the wheel). The binary builds WITHOUT it,
|
|
45
|
+
# so a plain `cargo build` never links libpython.
|
|
46
|
+
# ONE-WHEEL RE-EXPORT (CIRISServer#4): `python` ALSO turns on the substrate
|
|
47
|
+
# crates' OWN pyo3 surfaces (`ciris-persist/pyo3`, `ciris-edge/pyo3`) so their
|
|
48
|
+
# `#[pyclass]`es compile into THIS cdylib — one `.so`, one PyO3 type registry,
|
|
49
|
+
# so the persist `Engine` handed to edge is the SAME type both sides see (the
|
|
50
|
+
# CIRISPersist#109 cross-wheel type-identity bug CANNOT occur). persist names its
|
|
51
|
+
# feature `pyo3` (not `python`); edge likewise, and edge's `pyo3` already pulls
|
|
52
|
+
# `ciris-persist/pyo3` transitively — both listed for explicitness. verify is
|
|
53
|
+
# deliberately ABSENT: it is a ctypes wheel (libciris_verify_ffi.so via
|
|
54
|
+
# ctypes.CDLL), not a `#[pymodule]`, so it cannot be a pyo3 submodule.
|
|
55
|
+
python = [
|
|
56
|
+
"dep:pyo3",
|
|
57
|
+
"dep:pyo3-async-runtimes",
|
|
58
|
+
"ciris-lens-core/python",
|
|
59
|
+
"ciris-persist/pyo3",
|
|
60
|
+
"ciris-edge/pyo3",
|
|
61
|
+
]
|
|
62
|
+
# `extension-module` is what maturin builds the wheel with (tells PyO3 not to
|
|
63
|
+
# link libpython). The bin must NOT enable it. See pyproject.toml [tool.maturin].
|
|
64
|
+
# Propagated to the substrate crates so THEIR pyo3 surfaces also skip linking
|
|
65
|
+
# libpython (each crate gates `extension-module` as its own feature).
|
|
66
|
+
extension-module = [
|
|
67
|
+
"python",
|
|
68
|
+
"pyo3/extension-module",
|
|
69
|
+
"ciris-persist/extension-module",
|
|
70
|
+
"ciris-edge/extension-module",
|
|
71
|
+
]
|
|
72
|
+
# `pkcs11` turns on the YubiKey (PKCS#11 / PIV) custody backend for the USER
|
|
73
|
+
# federation identity (`ciris-server identity create --backend pkcs11`). OFF by
|
|
74
|
+
# default: a plain `cargo build` never links `cryptoki`, and the Pkcs11 backend
|
|
75
|
+
# honestly returns NotSupported without it. It flips `ciris-keyring/pkcs11` on
|
|
76
|
+
# (operator hardware; Linux). The YubiKey path is hardware-validated by the
|
|
77
|
+
# operator — there is no token in CI, so it is gated + flagged, not unit-tested.
|
|
78
|
+
# Like the per-target `tpm` posture, it is NOT in `default`; build it explicitly
|
|
79
|
+
# (`--features pkcs11`) on a Linux box with a token attached.
|
|
80
|
+
# `pkcs11` (the YubiKey custody path) pulls `ciris-keyring/pkcs11` directly and
|
|
81
|
+
# GLOBALLY: CIRISVerify v6.12.0 made cryptoki build on ALL targets (feature
|
|
82
|
+
# parity), so it no longer breaks the macos/android/ios wheels. The ciris-server
|
|
83
|
+
# pkcs11 source compiles wherever this feature is on (gated on `feature = "pkcs11"`,
|
|
84
|
+
# no target_os restriction). At runtime a target with no PKCS#11 module (e.g.
|
|
85
|
+
# android, which reaches a YubiKey over NFC via YubiKit instead) returns
|
|
86
|
+
# NotSupported — present everywhere, hardware-validated where a token is attached.
|
|
87
|
+
pkcs11 = ["ciris-keyring/pkcs11"]
|
|
88
|
+
# NOTE: hardware key custody (TPM/SE/StrongBox) is wired per-TARGET below, not as
|
|
89
|
+
# a cargo feature — TPM (tss-esapi) is Linux-only, so a top-level `tpm` feature
|
|
90
|
+
# made `--all-features` drag tss-esapi onto Windows/macOS (where it can't build).
|
|
91
|
+
# The `[target.'cfg(target_os = "linux")']` table enables keyring/tpm + persist
|
|
92
|
+
# postgres on Linux only; runtime auto-detects hardware and degrades to encrypted
|
|
93
|
+
# software when absent (`is_hardware_backed()` reports the posture). This mirrors
|
|
94
|
+
# the substrate crates' per-target keyring/postgres gating.
|
|
95
|
+
|
|
96
|
+
# ----------------------------------------------------------------------------
|
|
97
|
+
# Dependencies — CIRISServer AUTHORS NO PRIMITIVES. It composes the core
|
|
98
|
+
# libraries over ONE shared persist Engine (registry + lens read/write the same
|
|
99
|
+
# corpus in-process; per-slice views via Engine::from_shared).
|
|
100
|
+
#
|
|
101
|
+
# Substrate floor (SHIPPED): persist v8.6.0 / edge v4.5.0 / verify-family v5.11.0
|
|
102
|
+
# (ciris-keyring + ciris-crypto + ciris-verify-core), CEG 1.0-RC12. The composition
|
|
103
|
+
# root pins the singleton construction; the in-tree ciris-lens-core co-bumps in
|
|
104
|
+
# lockstep (MAJOR caret pins persist "8" / edge "4"). edge v4.2.0 ships the relay
|
|
105
|
+
# outer-open primitive (`open_av_outer`, CIRISEdge#149) → multi-tier ALM chains
|
|
106
|
+
# (benches/alm_chain.rs). All additive; no composition-root API change. pyo3 0.29.
|
|
107
|
+
# ----------------------------------------------------------------------------
|
|
108
|
+
[dependencies]
|
|
109
|
+
# The composed cores (authority + observation; node folds in at Server 1.0).
|
|
110
|
+
# ciris-registry-core — re-added at Server 0.5, co-bumped to the 6.6/edge-3.2 floor
|
|
111
|
+
# (CIRISRegistry#76). Held OUT of the 0.1 graph: registry-core@main still pins the
|
|
112
|
+
# OLD floor (persist 5.5.5 / edge 2.2.2 / verify 5.1.3) and would drag a second
|
|
113
|
+
# persist+edge rev into the build. The compose_registry() scaffold stays in
|
|
114
|
+
# src/compose.rs; this dep returns once registry co-bumps.
|
|
115
|
+
ciris-lens-core = { path = "crates/ciris-lens-core" } # ABSORBED in-tree (workspace member); CIRISLensCore repo retired
|
|
116
|
+
# ciris-node-core — folds in at Server 1.0 / agent 2.9.10 (a substrate gen behind: persist 4.10).
|
|
117
|
+
|
|
118
|
+
# The substrate trio (also pulled transitively by the cores; pinned here so the
|
|
119
|
+
# composition root owns the singleton construction).
|
|
120
|
+
# sqlite on all platforms; postgres is Linux-only (libpq/openssl don't link
|
|
121
|
+
# cleanly on the macOS/Windows runners — same posture as persist's own CI). The
|
|
122
|
+
# `[target.linux]` table below adds postgres.
|
|
123
|
+
# `cirislens_wa_cert` + `cirislens_service_token_revocation` expose the auth
|
|
124
|
+
# substrate the fabric absorbs (CIRISServer#9, src/auth): the agent's `wa_cert`
|
|
125
|
+
# table (users/WA/OAuth/api-keys) + the `revoked_service_tokens` table.
|
|
126
|
+
ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v11.9.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.3.0", features = ["transport-reticulum", "transport-http", "transport-packet-radio"] }
|
|
128
|
+
# Founder-quorum verification + key-id fingerprint at the composition root
|
|
129
|
+
# (threshold:: module path — NOT re-exported at the crate root).
|
|
130
|
+
# LOCKSTEP: persist v9.4.0 transitively pins verify-core v6.6.x — the whole
|
|
131
|
+
# verify family (verify-core/keyring/crypto) MUST ride the SAME tag or cargo
|
|
132
|
+
# resolves two ciris_verify_core crates with incompatible ThresholdMember/keyring
|
|
133
|
+
# types. v6.6.1 (CIRISVerify#89) adds the create_federation_identity `seal_alias`
|
|
134
|
+
# arg the #247 user-key-derived fix consumes. (6.4–6.6 are HUMANITY_ACCORD + STH
|
|
135
|
+
# stack — the accord-genesis surface CIRISServer#41 consumes.)
|
|
136
|
+
ciris-verify-core = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v8.3.0" }
|
|
137
|
+
# The hybrid crypto primitives (Ed25519 + ML-DSA-65 software signers) — used by
|
|
138
|
+
# the portable software identity occurrence to build a `HybridSigningIdentity`
|
|
139
|
+
# over two software seeds. Same tag as the rest of the verify family.
|
|
140
|
+
ciris-crypto = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v8.3.0", version = "8", features = ["pqc-ml-dsa", "self-enc"] }
|
|
141
|
+
# Hardware-backed transport-identity keystore (verify v5.2.0 #68 / edge #99).
|
|
142
|
+
# Base = software keystore + byte-identical migration of an existing .rid (works
|
|
143
|
+
# everywhere, no libtss2). The real TPM-2.0 / SE / StrongBox backend rides the
|
|
144
|
+
# `tpm` feature; runtime auto-detects hardware and falls back to software.
|
|
145
|
+
ciris-keyring = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v8.3.0", version = "8", features = ["software", "pqc-ml-dsa"] }
|
|
146
|
+
|
|
147
|
+
# PyO3 bindings for the abi3 wheel — optional, gated behind the `python` feature
|
|
148
|
+
# so the binary never links them. 0.29 matches the persist/edge family floor.
|
|
149
|
+
pyo3 = { version = "0.29", features = ["abi3-py310"], optional = true }
|
|
150
|
+
pyo3-async-runtimes = { version = "0.29", features = ["tokio-runtime"], optional = true }
|
|
151
|
+
|
|
152
|
+
tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "time", "sync"] }
|
|
153
|
+
anyhow = "1"
|
|
154
|
+
fs2 = "0.4" # available-disk check for realistic-minimum feature gating
|
|
155
|
+
# GET /v1/identity (the fabric-node identity surface) — merged onto the lens
|
|
156
|
+
# read-API listener. axum pinned to lens-core's 0.8 so the merged Router unifies.
|
|
157
|
+
axum = "0.8"
|
|
158
|
+
base64 = "0.22"
|
|
159
|
+
serde = { version = "1", features = ["derive"] } # holonomic scoreboard model (benchmarks::)
|
|
160
|
+
serde_json = "1"
|
|
161
|
+
getrandom = "0.3" # mint the ML-DSA-65 federation seed on first boot (hybrid PQC)
|
|
162
|
+
# Cosmetic v4 attestation-ids (the content hash is the integrity anchor). Direct
|
|
163
|
+
# dep at the same major persist already pins transitively — no new resolution.
|
|
164
|
+
uuid = { version = "1", features = ["v4"] }
|
|
165
|
+
# Auth subsystem (src/auth, CIRISServer#9): timestamps on the absorbed wa_cert
|
|
166
|
+
# rows, SHA-256 for api-key / service-token hashing, hex for the digest wire form.
|
|
167
|
+
# All three already in the lock as substrate-transitive deps (no new resolution).
|
|
168
|
+
chrono = { version = "0.4", features = ["serde"] }
|
|
169
|
+
sha2 = "0.10"
|
|
170
|
+
hex = "0.4"
|
|
171
|
+
# Auth gap-close (CIRISServer#9, src/auth): the byte-compatible password KDF +
|
|
172
|
+
# the OAuth/native/device-auth outbound-HTTP + JWKS-verify halves. All already in
|
|
173
|
+
# the lock as substrate-transitive deps (reqwest/jsonwebtoken via edge+verify;
|
|
174
|
+
# pbkdf2/hmac/ed25519-dalek via the crypto family) — pinned here so the auth
|
|
175
|
+
# subsystem owns them directly, no new resolution.
|
|
176
|
+
# - pbkdf2 + hmac: reproduce the agent's PBKDF2-HMAC-SHA256(100k) password hash
|
|
177
|
+
# (auth_service.py `_hash_password`/`_verify_password`) byte-for-byte.
|
|
178
|
+
# - ed25519-dalek: verify the ROOT mint signature (the agent's `verify_root_signature`).
|
|
179
|
+
# - jsonwebtoken: Apple Sign-In RS256 JWKS verification.
|
|
180
|
+
# - reqwest (rustls): Google tokeninfo / OAuth code→token / Apple JWKS / Portal HTTP.
|
|
181
|
+
# - urlencoding: build the provider authorize-URL query string (matches urlencode).
|
|
182
|
+
pbkdf2 = { version = "0.12", default-features = false }
|
|
183
|
+
hmac = "0.12"
|
|
184
|
+
subtle = "2" # constant-time password-hash compare (the agent's hmac.compare_digest)
|
|
185
|
+
ed25519-dalek = "2"
|
|
186
|
+
jsonwebtoken = "9"
|
|
187
|
+
urlencoding = "2"
|
|
188
|
+
async-trait = "0.1" # the ProviderClient HTTP seam (async fn in trait)
|
|
189
|
+
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json"] }
|
|
190
|
+
# Mesh control-plane relay (#128 Phase D, src/mesh_relay.rs): the RNS responder
|
|
191
|
+
# dispatches a verified control op into the node's OWN axum Router in-process via
|
|
192
|
+
# `tower::ServiceExt::oneshot` (the same-handlers guarantee, RNS_CONTROL_RELAY.md
|
|
193
|
+
# §5.4). Already in the lock as axum's own dependency (and a dev-dep) — promoting
|
|
194
|
+
# it to a runtime dep adds no new resolution.
|
|
195
|
+
tower = { version = "0.5", features = ["util"] }
|
|
196
|
+
flate2 = "1" # read the gz'd legacy-trace dump (import-traces subcommand)
|
|
197
|
+
tracing = "0.1"
|
|
198
|
+
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
|
199
|
+
# Non-blocking rolling file sink for the node log (so a headless node launched by
|
|
200
|
+
# the desktop app logs RELIABLY to <home>/logs/, not just the captured console).
|
|
201
|
+
tracing-appender = "0.2"
|
|
202
|
+
|
|
203
|
+
# Linux-only hardware + Postgres: cargo UNIONS these onto the base deps above.
|
|
204
|
+
# - persist `postgres` (libpq/openssl) — Linux deployment + the postgres
|
|
205
|
+
# conformance lane; macOS/Windows stay sqlite-only.
|
|
206
|
+
# - keyring `tpm` (tss-esapi / TPM 2.0) — the real hardware backend; needs
|
|
207
|
+
# libtss2 (Linux build dep). Other targets keep the software keystore.
|
|
208
|
+
[target.'cfg(target_os = "linux")'.dependencies]
|
|
209
|
+
ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v11.9.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"] }
|
|
210
|
+
# keyring `tpm` (TPM-at-rest, Linux-only via tss-esapi). `pkcs11` is no longer
|
|
211
|
+
# per-target — it rides the global `pkcs11` feature now that cryptoki builds on all
|
|
212
|
+
# targets (CIRISVerify v6.12.0).
|
|
213
|
+
ciris-keyring = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v8.3.0", version = "8", features = ["tpm-plugin"] }
|
|
214
|
+
|
|
215
|
+
# Android (arm64/arm32/x86_64): the keyring `android` backend (JNI → Android
|
|
216
|
+
# Keystore/StrongBox); sqlite bundles, no postgres/tpm. Mirrors persist/edge.
|
|
217
|
+
[target.'cfg(target_os = "android")'.dependencies]
|
|
218
|
+
ciris-keyring = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v8.3.0", version = "8", features = ["android"] }
|
|
219
|
+
|
|
220
|
+
# serialport (the RNode LoRa driver dep, src/radio.rs) pulls libudev-sys on Linux,
|
|
221
|
+
# which only resolves where libudev exists: desktop/server Linux (gnu, x86_64 or
|
|
222
|
+
# aarch64), macOS, Windows. It does NOT cross-compile for armv7 / musl (no libudev
|
|
223
|
+
# in the cross sysroot — the release armv7+musl legs panicked on it) and isn't
|
|
224
|
+
# usable on android/ios. Gate to exactly the serial-capable targets — the SAME
|
|
225
|
+
# predicate guards `pub mod radio` (lib.rs) + the edge attach (compose.rs).
|
|
226
|
+
[target.'cfg(any(target_os = "macos", target_os = "windows", all(target_os = "linux", target_env = "gnu", any(target_arch = "x86_64", target_arch = "aarch64"))))'.dependencies]
|
|
227
|
+
serialport = "4"
|
|
228
|
+
|
|
229
|
+
# Test-only — the two-node replication integration test (tests/replication.rs)
|
|
230
|
+
# builds + signs CEG batches with the same primitives persist verifies against.
|
|
231
|
+
# ed25519-dalek MUST match persist's locked 2.x (the SigningKey type crosses the
|
|
232
|
+
# Engine::with_signer / put_public_key API boundary).
|
|
233
|
+
[dev-dependencies]
|
|
234
|
+
ed25519-dalek = "2"
|
|
235
|
+
base64 = "0.22"
|
|
236
|
+
chrono = { version = "0.4", features = ["serde"] }
|
|
237
|
+
serde_json = "1"
|
|
238
|
+
criterion = { version = "0.5", features = ["async_tokio"] }
|
|
239
|
+
# Tamper-side raw SQLite handle for the audit hash-chain conformance gate
|
|
240
|
+
# (tests/audit_chain.rs): opens the engine's file-backed DB on a SECOND
|
|
241
|
+
# connection to corrupt one stored row, the only way to land a tampered entry
|
|
242
|
+
# (record_entry validates + rejects, so a broken row can't go in through the
|
|
243
|
+
# trait). Pinned to persist's locked 0.31 + same features (NO `bundled` — links
|
|
244
|
+
# the platform libsqlite3, matching persist's non-mobile target so the two
|
|
245
|
+
# `links = "sqlite3"` crates unify to one symbol set).
|
|
246
|
+
rusqlite = { version = "0.31", features = ["chrono", "serde_json"] }
|
|
247
|
+
# Drive the merged axum Router in-process for the HTTP trace-ingest test
|
|
248
|
+
# (tests/ingest_http.rs): `ServiceExt::oneshot` + read the response body. tower
|
|
249
|
+
# 0.5 / http-body-util 0.1 match axum 0.8's floor (already in-tree transitively).
|
|
250
|
+
tower = { version = "0.5", features = ["util"] }
|
|
251
|
+
http-body-util = "0.1"
|
|
252
|
+
# The PQC primitives the realtime-A/V E2E bench drives directly: hybrid KEX
|
|
253
|
+
# (X25519 + ML-KEM-768) for the per-Link transit key, AES-256-GCM for the
|
|
254
|
+
# two-layer chunk seal. Same pin/features edge composes (tag parity).
|
|
255
|
+
ciris-crypto = { git = "https://github.com/CIRISAI/CIRISVerify", tag = "v8.3.0", version = "8", features = ["hybrid-kex", "aes-gcm", "pqc-ml-dsa", "self-enc"] }
|
|
256
|
+
# Enable edge's OWN fountain codec (`codec-fountain`, L1-A) for the survival-floor
|
|
257
|
+
# proof — dev/test ONLY (feature unification applies to test/bench builds; the
|
|
258
|
+
# shipped wheel stays codec-free, since a relay forwards sealed symbols opaquely
|
|
259
|
+
# and never encodes/decodes). This lets tests/chaos_mesh.rs exercise the SUBSTRATE
|
|
260
|
+
# codec (`fountain_encode`/`fountain_decode`) directly — a real MEASURED proof,
|
|
261
|
+
# not a reference stand-in.
|
|
262
|
+
ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "v8.3.0", features = ["codec-fountain"] }
|
|
263
|
+
|
|
264
|
+
# PQC realtime-A/V streaming E2E benchmark (CIRISEdge#62 realtime_av profile).
|
|
265
|
+
[[bench]]
|
|
266
|
+
name = "pqc_av_streaming"
|
|
267
|
+
harness = false
|
|
268
|
+
|
|
269
|
+
# Replication / corpus-ingest throughput (the CEG-RC5 receive spine).
|
|
270
|
+
[[bench]]
|
|
271
|
+
name = "replication_ingest"
|
|
272
|
+
harness = false
|
|
273
|
+
|
|
274
|
+
# Multi-tier ALM relay chain (CIRISEdge#149 open_av_outer) — per-hop + per-depth
|
|
275
|
+
# cost; the E2E byte-survival invariant is gated in tests/alm_chain.rs.
|
|
276
|
+
[[bench]]
|
|
277
|
+
name = "alm_chain"
|
|
278
|
+
harness = false
|
|
279
|
+
|
|
280
|
+
# Sustained multi-stream seal throughput — measures the actual core-fraction to
|
|
281
|
+
# seal N blob streams @30fps in a real loop (promotes the page's "2,000 blob
|
|
282
|
+
# streams ≈ 6-10% of a core" from arithmetic to MEASURED).
|
|
283
|
+
[[bench]]
|
|
284
|
+
name = "stream_fanout"
|
|
285
|
+
harness = false
|
|
286
|
+
|
|
287
|
+
# N_eff capacity-scoring microbench — the lens constraint eigenspectrum pipeline
|
|
288
|
+
# (ciris_server::scorer::n_eff). Feature-matrix build + Jacobi eigendecomposition
|
|
289
|
+
# + PR/entropy derivation: the per-agent per-cadence-tick CPU cost of
|
|
290
|
+
# `capacity:sustained_coherence:v1`. CI-runnable (pure arithmetic, no network,
|
|
291
|
+
# no database).
|
|
292
|
+
[[bench]]
|
|
293
|
+
name = "n_eff_scoring"
|
|
294
|
+
harness = false
|
|
295
|
+
|
|
296
|
+
# Erasure-survival bench — EMPIRICAL reconstruction rate against the real substrate
|
|
297
|
+
# fountain codec (edge codec-fountain / RaptorQ). Encodes a blob into H holders, drops
|
|
298
|
+
# holders by a per-availability-tier Bernoulli(q) coin, runs many real decode trials,
|
|
299
|
+
# and writes the measured p_reconstruct per tier to target/erasure_survival.json (read
|
|
300
|
+
# by the scoreboard). `harness = false` — survival is a rate, not a latency. Codec is
|
|
301
|
+
# dev-only, so this measurement lives in a bench. `cargo bench --bench erasure_survival`.
|
|
302
|
+
[[bench]]
|
|
303
|
+
name = "erasure_survival"
|
|
304
|
+
harness = false
|
|
305
|
+
|
|
306
|
+
# Signature-overhead micro-bench — per-event sign+verify latency for classical
|
|
307
|
+
# (Ed25519-only) vs hybrid (Ed25519 + ML-DSA-65, the production provenance signature),
|
|
308
|
+
# using the substrate's REAL ciris_crypto primitives. The scoreboard derives the honest
|
|
309
|
+
# "+N%" post-quantum overhead from the two criterion medians. `cargo bench --bench sig_overhead`.
|
|
310
|
+
[[bench]]
|
|
311
|
+
name = "sig_overhead"
|
|
312
|
+
harness = false
|
|
313
|
+
|
|
314
|
+
# Mesh-propagation benchmark — N in-process software-key nodes; ONE group-A
|
|
315
|
+
# publisher advertises a synthetic "video" and a FountainSwarmRuntime per node
|
|
316
|
+
# converges the holding-claim to its cohort ONLY. Measures propagation latency /
|
|
317
|
+
# fan-out / group isolation / throughput over an in-memory bus (swarm LOGIC +
|
|
318
|
+
# cohort gate, not wire transport). `cargo run --example mesh_propagation`.
|
|
319
|
+
[[example]]
|
|
320
|
+
name = "mesh_propagation"
|
|
321
|
+
path = "examples/mesh_propagation/main.rs"
|
|
322
|
+
|
|
323
|
+
[profile.release]
|
|
324
|
+
# panic strategy stays "unwind" (the Win7 build-std lane relies on this being
|
|
325
|
+
# pinned here, not on the build-std crate list — see release.yml win7 lane).
|
|
326
|
+
panic = "unwind"
|
|
327
|
+
strip = false # release workflow strips per-target after build
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ciris-server
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.72
|
|
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,21 @@
|
|
|
1
|
+
# CIRISServer opaque wire-vocabulary kinds (CC 0.7 Tier-2)
|
|
2
|
+
|
|
3
|
+
**Steward:** CIRISAI/CIRISServer.
|
|
4
|
+
**Range:** `0x0000_0000..=0x0000_FFFF` (per CIRISRegistry
|
|
5
|
+
`manifests/WIRE_VOCABULARY.md` v1.0.1 §3.1 — every ratifying repo stewards its
|
|
6
|
+
own `kind` range and publishes `kind → semantics`; edge carries the payload as
|
|
7
|
+
opaque bytes, "reach, not meaning").
|
|
8
|
+
**Cohabitation gate:** `tests/wire_vocabulary_gate.rs` pins the ratified
|
|
9
|
+
vocabulary hash `c6bd6aa44111b226a6f204801b1afaa7153fb43296652c1f7cbc23228ac9346c`
|
|
10
|
+
against `ciris_edge::WIRE_VOCABULARY_HASH`, so a drifting edge bump fails this
|
|
11
|
+
repo's build.
|
|
12
|
+
|
|
13
|
+
Adding a row here is a reviewed code change; a kind is never reused after
|
|
14
|
+
retirement.
|
|
15
|
+
|
|
16
|
+
## Allocations
|
|
17
|
+
|
|
18
|
+
| kind | envelope | semantics | inner schema (app-owned) | auth |
|
|
19
|
+
|---|---|---|---|---|
|
|
20
|
+
| `0x0000_0001` | `OpaqueRequest` / `OpaqueResponse` (Ephemeral) | **Mesh control-plane relay** (CIRISServer#128 Phase D, `FSD/RNS_CONTROL_RELAY.md` + `FSD/EDGE_8_0_OPAQUE_MIGRATION.md` §6): an owner administers an owned node by federation `key_id` over RNS — the allow-listed owner-op set (`src/mesh_relay.rs::RELAYABLE`; wipe/claim/mint/login are never relayable). | `ControlPayload { headers, envelope_b64 }` where `headers` is the fabric `x-ciris-*` signature-header trio and `envelope_b64` is base64 of the EXACT signed JSON bytes of `ControlEnvelope { v, target_key_id, method, path, body, nonce, ts }` (`src/mesh_relay.rs`). Canonicalization = **exact-bytes-signed**: the serialized envelope bytes are signed, transmitted, and verified verbatim — no re-serialization on either side. The response payload is the dispatched v1 handler's body bytes; `OpaqueResponse.status` is its HTTP status. | Inner **owner fed-ID hybrid signature** (Ed25519 + ML-DSA-65, `HybridPolicy::Strict`) verified against the TARGET node's federation directory (`verify::verify_request`), and the verified signer must act for the target's own owner-binding (`is_steward_bound` + `signer_acts_for`). The OUTER edge envelope carries the transport (node-signer) identity only — it is never the authorization principal. Replay: `nonce` + `ts` (±300 s) per signer. |
|
|
21
|
+
| `0x0000_0002+` | — | *reserved* for future control ops (e.g. a mesh health probe). | — | — |
|
|
@@ -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 = "v11.
|
|
30
|
-
ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "
|
|
29
|
+
ciris-persist = { git = "https://github.com/CIRISAI/CIRISPersist", tag = "v11.9.1", version = "11", features = ["extract", "sqlite"] }
|
|
30
|
+
ciris-edge = { git = "https://github.com/CIRISAI/CIRISEdge", tag = "v8.3.0", 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
|