Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/proposed-rust-module-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ argues for doing it where it helps and against treating it as risky.
## Where the general advice does not fit this repository

This codebase has a constraint most advice does not consider: **files are
pinned**. `docs/tally/compatibility/compatibility-surface.json` binds 218 paths
pinned**. `docs/tally/compatibility/compatibility-surface.json` binds each pinned path
by SHA-256, and the evidence receipts beneath it attest behaviour *of those
bytes*. Splitting a pinned file is not a neutral move:

Expand Down
2 changes: 1 addition & 1 deletion docs/tally/compatibility/compatibility-matrix.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schema_version": 1,
"bridge_commit_sha": "be1c20cc3fd66fa1ece196505c69f26e555e4b8e",
"compatibility_surface_sha256": "4dc0c7118372a4bc4a6b3b58346b0b113ce4b6bb07a154f208546f6cd43757a8",
"compatibility_surface_sha256": "17dcd4722234ab278f55d130b00151b71ae797f6a1a7cf18246f08ab82f21915",
"claims": [
{
"claim_id": "erp9-6-6-3-windows-education-xml-one-company",
Expand Down
28 changes: 26 additions & 2 deletions docs/tally/compatibility/compatibility-surface.json
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,14 @@
"path": "src-tauri/src/agent_catalog.rs",
"sha256": "55632c680704c2784545e422cf6847b81d2423191d651a0119d45188d9bf2671"
},
{
"path": "src-tauri/src/agent_change_parse.rs",
"sha256": "1459a3a732ed5f4e51c0b83481683ebbf26adb86b6c3cc10da8604ac03bd3823"
},
{
"path": "src-tauri/src/agent_changes.rs",
"sha256": "ce8c0ca98c2194f8ce42493a39f3a034f80418bcf4c6aa3d9fc9df30a6161f71"
},
{
"path": "src-tauri/src/agent_company.rs",
"sha256": "c719ff31cb8e14959dcaecd851156356cc7e38fe50a07aaf0dd339cfd78641dc"
Expand Down Expand Up @@ -385,6 +393,18 @@
"path": "src-tauri/src/agent_ledgers.rs",
"sha256": "a891e4ac51addc9dc17ae28ce4634bd2cfeb8f3f0df78e072290771d29a3131b"
},
{
"path": "src-tauri/src/agent_movement.rs",
"sha256": "a1ca27209a17a23db26b72d190122b8be49a930b55151ecea59913126b599185"
},
{
"path": "src-tauri/src/agent_movement_math.rs",
"sha256": "5047954d7f0e5c7adfc31241bab4108a734f1f815102e95f78f080a66228bdf9"
},
{
"path": "src-tauri/src/agent_outstandings.rs",
"sha256": "93538acb8e43a1a02891d0cc5b9e8615daf10d4493eebe18cc431cc3425c7fc3"
},
{
"path": "src-tauri/src/agent_presence.rs",
"sha256": "0bfeb05248b0d371e6a87b4b004c9c3815b5590017c6bd3231277db12b030c8d"
Expand All @@ -405,6 +425,10 @@
"path": "src-tauri/src/agent_read_validation.rs",
"sha256": "7c1bf2bc330b9703e0b2ae791ae7d777b6c64449395ff79b7ef855ee0dafdfeb"
},
{
"path": "src-tauri/src/agent_receipt_fields.rs",
"sha256": "cbdd09b7916fe5b96c7be4cecab9e0bdf2f0cdb018148c106a83e026a9128ada"
},
{
"path": "src-tauri/src/agent_responses.rs",
"sha256": "dfa582e79dab46315de88ba68c7dca069566da20b67733558a38cdd714f5c3b4"
Expand Down Expand Up @@ -895,7 +919,7 @@
},
{
"path": "tools/bridge-tally-compatibility/src/lib.rs",
"sha256": "8f9840b107e3c14290e66a7e9eeafce09930fb7d17286a35c9475d1af87b6062"
"sha256": "8ad5d452bb3f76e3d1ee69c78c0a564af2263392ffb0c47f58ed49c837eb6692"
},
{
"path": "tools/bridge-tally-compatibility/src/main.rs",
Expand Down Expand Up @@ -930,5 +954,5 @@
"sha256": "a8ac2714fecf51947f2822c8c46d7ce2e8602c732780ff60566a7771f0836f9a"
}
],
"manifest_sha256": "4dc0c7118372a4bc4a6b3b58346b0b113ce4b6bb07a154f208546f6cd43757a8"
"manifest_sha256": "17dcd4722234ab278f55d130b00151b71ae797f6a1a7cf18246f08ab82f21915"
}
48 changes: 35 additions & 13 deletions src-tauri/tests/admission_and_egress_files_stay_pinned.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! The fourteen files pinned by the raise to 232 (bridge#416) must stay pinned.
//! The files pinned by the raises to 232 and 238 (bridge#416) must stay pinned.
//!
//! The compatibility gate cannot notice a pin disappearing. `rehash-surface`
//! updates hashes and never adds paths. `docs/release-process.md` requires the
//! pin list to be merged rather than resolved by taking one side; a resolution
//! that takes the base side anyway drops every entry a branch added while
//! keeping the raised `MAX_SURFACE_FILES`, and the gate passes. So does the cap
//! assertion, which bounds headroom and would pass with all fourteen dropped.
//! assertion, which bounds headroom and would pass with all of them dropped.
//! `book_presence_tests.rs` guards its own contract's pins the same way.
//!
//! This file is deliberately not pinned itself: a guard that lived in the
Expand Down Expand Up @@ -35,6 +35,17 @@ const ADMISSION_AND_EGRESS: [&str; 14] = [
"src-tauri/src/tally/runtime_control.rs",
];

/// The six files pinned by the raise to 238: five on the read path, and the
/// egress receipt's field walker. Reasons live beside `MAX_SURFACE_FILES`.
const READ_PATH_AND_RECEIPT: [&str; 6] = [
"src-tauri/src/agent_change_parse.rs",
"src-tauri/src/agent_changes.rs",
"src-tauri/src/agent_movement.rs",
"src-tauri/src/agent_movement_math.rs",
"src-tauri/src/agent_outstandings.rs",
"src-tauri/src/agent_receipt_fields.rs",
];

fn pinned_paths(surface: &str) -> BTreeSet<String> {
let surface: serde_json::Value = serde_json::from_str(surface).expect("surface json");
surface["files"]
Expand All @@ -53,9 +64,8 @@ fn unpinned<'a>(pinned: &BTreeSet<String>, required: &[&'a str]) -> Vec<&'a str>
.collect()
}

#[test]
fn admission_and_egress_files_are_still_pinned() {
let missing = unpinned(&pinned_paths(SURFACE), &ADMISSION_AND_EGRESS);
fn assert_still_pinned(required: &[&str]) {
let missing = unpinned(&pinned_paths(SURFACE), required);
assert!(
missing.is_empty(),
"dropped from the compatibility surface: {missing:?}. A merge that took \
Expand All @@ -65,17 +75,29 @@ fn admission_and_egress_files_are_still_pinned() {
);
}

#[test]
fn admission_and_egress_files_are_still_pinned() {
assert_still_pinned(&ADMISSION_AND_EGRESS);
}

#[test]
fn read_path_and_receipt_files_are_still_pinned() {
assert_still_pinned(&READ_PATH_AND_RECEIPT);
}

/// The check above must be able to fail. Drive the same two functions over the
/// real surface with one entry removed, rather than a hand-built fixture that
/// would only prove `BTreeSet::contains` works.
#[test]
fn the_pin_check_reports_a_dropped_entry() {
let dropped = ADMISSION_AND_EGRESS[0];
let mut surface: serde_json::Value = serde_json::from_str(SURFACE).expect("surface json");
surface["files"]
.as_array_mut()
.expect("surface files")
.retain(|entry| entry["path"].as_str() != Some(dropped));
let pinned = pinned_paths(&surface.to_string());
assert_eq!(unpinned(&pinned, &ADMISSION_AND_EGRESS), vec![dropped]);
for required in [&ADMISSION_AND_EGRESS[..], &READ_PATH_AND_RECEIPT[..]] {
let dropped = required[0];
let mut surface: serde_json::Value = serde_json::from_str(SURFACE).expect("surface json");
surface["files"]
.as_array_mut()
.expect("surface files")
.retain(|entry| entry["path"].as_str() != Some(dropped));
let pinned = pinned_paths(&surface.to_string());
assert_eq!(unpinned(&pinned, required), vec![dropped]);
}
}
49 changes: 41 additions & 8 deletions tools/bridge-tally-compatibility/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@ pub const RESERVED_SURFACE_FILES: usize = 15;
/// and manifest) but makes further unreviewed additions an explicit
/// compatibility-surface decision.
///
/// **Raised six times, the first three by branches that did not see each
/// **Raised seven times, the first three by branches that did not see each
/// other.** 210 to 211 on master for `src-tauri/src/agent_ledgers.rs`, 211 to
/// 212 for `src-tauri/crates/bridge-tally-core/src/master_binding.rs`, 212 to
/// 216 in a single commit for the voucher-presence engine, its adapter, its
/// admission-contract assertion, and `agent_catalog.rs` -- the last of those
/// taking the slot a paragraph below had already reserved for it by name, which
/// is why the four pins arrive as one raise and not two -- 216 to 217 for
/// `.github/workflows/dependency-security-scheduled.yml`, 217 to 218 for
/// `src-tauri/src/agent_import_identity.rs`, and 218 to 232 for fourteen files
/// named individually below. Each reason stands; a merge that
/// `src-tauri/src/agent_import_identity.rs`, 218 to 232 for fourteen files
/// named individually below, and 232 to 238 for six more. Each reason stands; a
/// merge that
/// keeps a raise but loses its pin would pass the gate with behavior silently
/// outside the evidence boundary, which is the failure this constant exists to
/// make loud.
Expand Down Expand Up @@ -121,13 +122,45 @@ pub const RESERVED_SURFACE_FILES: usize = 15;
/// the response hash it commits to, and that only a persisted preparation
/// yields a write-completion token.
///
/// The raise to 238 binds six more files from the same bridge#416 search. Five
/// decide what a read tells a caller, or when a sync may move past rows. The
/// sixth, `agent_receipt_fields.rs`, belongs with the egress record above:
/// bridge#416 listed it as borderline rather than with the fourteen, and it
/// describes the response of any tool, not only a read. Same rule: each reason
/// says what the file holds.
///
/// What a read reports, or lets a sync skip:
/// - `agent_movement.rs` -- the ledger movement tool, and the voucher predicate
/// it applies after checking the whole window: cancelled, optional and
/// entryless vouchers are left out of the movement figures.
/// - `agent_movement_math.rs` -- one ledger's movement row: when an opening was
/// observed, closing is opening plus debit plus credit; when none was, closing
/// is left empty and the row is marked `partial` with
/// `opening_balance_not_observed`.
/// - `agent_outstandings.rs` -- the outstandings tool's receivable and payable
/// totals over open bills, and its ageing buckets (0-30, 31-60, 61-90, over 90
/// days, and unaged).
/// - `agent_change_parse.rs` -- `checkpoint_advanceable`: true when a page was
/// not truncated and its highest returned alter id, or the requested
/// checkpoint when it returned none, reaches the company's high-water mark.
/// - `agent_changes.rs` -- the changed-since tool, which applies that predicate
/// to vouchers and masters separately, reports `checkpoint_advanceable` only
/// when both hold, chooses each axis's next alter id from its own result, and
/// refuses a checkpoint past the company snapshot.
///
/// And the egress record:
/// - `agent_receipt_fields.rs` -- `released_fields`, which the egress receipt in
/// `agent_delivery.rs` uses to describe a released tool response by its JSON
/// key paths rather than its values.
///
/// Not pinned, and deliberately: files feature-gated out of every shipped build
/// (`agent_lab.rs`, `jsonex*.rs`, `india_tax_observation.rs`), operator filing
/// labels, dead or declaration-only modules, and the read-path files that
/// compute reported figures or decide when a change cursor may advance. Those
/// decide what a read says, not what is admitted or where data may go; they are
/// the next candidates if the boundary widens, and bridge#416 records why.
pub const MAX_SURFACE_FILES: usize = 232;
/// labels, dead or declaration-only modules, and `observability.rs`. Its count
/// bucketing is a real privacy reduction, and the `tally_telemetry_preview`
/// command returns what it builds, but nothing in the frontend calls that
/// command and nothing sends its result off the machine. It becomes a candidate
/// when something does. bridge#416 records the reasoning for the rest.
pub const MAX_SURFACE_FILES: usize = 238;
pub const MAX_OPERATIONS: usize = 16;
pub const MAX_CLAIMS: usize = 128;
pub const MAX_KEYS: usize = 32;
Expand Down